mirror of
https://github.com/MADTeacher/go_basics.git
synced 2025-11-23 21:34:47 +02:00
Крестики-нолики
Добавлен сквозной проект для 1-й главы
This commit is contained in:
14
part_1/tic_tac_toe/.vscode/launch.json
vendored
Normal file
14
part_1/tic_tac_toe/.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
|
||||
{
|
||||
"name": "Launch Package",
|
||||
"type": "go",
|
||||
"request": "launch",
|
||||
"mode": "auto",
|
||||
"program": "${fileDirname}", // <- ставим запятую
|
||||
"console": "integratedTerminal"
|
||||
}
|
||||
]
|
||||
}
|
||||
3
part_1/tic_tac_toe/go.mod
Normal file
3
part_1/tic_tac_toe/go.mod
Normal file
@@ -0,0 +1,3 @@
|
||||
module tic-tac-toe
|
||||
|
||||
go 1.24.0
|
||||
247
part_1/tic_tac_toe/main.go
Normal file
247
part_1/tic_tac_toe/main.go
Normal file
@@ -0,0 +1,247 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type GameState int
|
||||
type BoardField int
|
||||
|
||||
const (
|
||||
empty BoardField = iota
|
||||
cross
|
||||
nought
|
||||
)
|
||||
|
||||
const (
|
||||
playing GameState = iota
|
||||
draw
|
||||
crossWin
|
||||
noughtWin
|
||||
quit
|
||||
)
|
||||
|
||||
func main() {
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
boardSize := 3 // размер игрового поля по умолчанию
|
||||
state := playing
|
||||
currentPlayer := cross // текущий игрок
|
||||
|
||||
// Ввод размера доски
|
||||
for {
|
||||
fmt.Print("Enter the size of the board (3-9): ")
|
||||
input, err := reader.ReadString('\n')
|
||||
if err != nil {
|
||||
fmt.Println("Error reading input. Please try again.")
|
||||
continue
|
||||
}
|
||||
input = strings.TrimSpace(input)
|
||||
size, err := strconv.Atoi(input)
|
||||
if err != nil {
|
||||
size = boardSize
|
||||
}
|
||||
if size < 3 || size > 9 {
|
||||
fmt.Println("Invalid size, please enter again")
|
||||
continue
|
||||
}
|
||||
boardSize = size
|
||||
break
|
||||
}
|
||||
|
||||
// Инициализация доски
|
||||
board := make([][]BoardField, boardSize)
|
||||
for i := range boardSize {
|
||||
board[i] = make([]BoardField, boardSize)
|
||||
}
|
||||
|
||||
// Вывод в терминал состояния игрового поля
|
||||
fmt.Print(" ")
|
||||
for i := range boardSize {
|
||||
fmt.Printf("%d ", i+1) // вывод номера столбца
|
||||
}
|
||||
fmt.Println()
|
||||
for i := range boardSize {
|
||||
fmt.Printf("%d ", i+1) // вывод номера строки
|
||||
for j := range boardSize {
|
||||
switch board[i][j] {
|
||||
case empty:
|
||||
fmt.Print(". ")
|
||||
case cross:
|
||||
fmt.Print("X ")
|
||||
case nought:
|
||||
fmt.Print("O ")
|
||||
}
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
// Завершение вывода в терминал
|
||||
|
||||
// Основной игровой цикл
|
||||
for state == playing {
|
||||
// Вывод сообщения о ходе текущего игрока
|
||||
playerSymbol := "X"
|
||||
if currentPlayer == nought {
|
||||
playerSymbol = "O"
|
||||
}
|
||||
fmt.Printf("%s's turn. Enter row and column (e.g. 1 2): ",
|
||||
playerSymbol)
|
||||
|
||||
validInput := false
|
||||
for !validInput {
|
||||
input, err := reader.ReadString('\n')
|
||||
if err != nil {
|
||||
fmt.Println("Invalid input. Please try again.")
|
||||
continue
|
||||
}
|
||||
|
||||
input = strings.TrimSpace(input)
|
||||
if input == "q" {
|
||||
state = quit
|
||||
break
|
||||
}
|
||||
|
||||
parts := strings.Fields(input)
|
||||
if len(parts) != 2 {
|
||||
fmt.Println("Invalid input. Please try again.")
|
||||
continue
|
||||
}
|
||||
|
||||
row, err1 := strconv.Atoi(parts[0])
|
||||
col, err2 := strconv.Atoi(parts[1])
|
||||
|
||||
if err1 != nil || err2 != nil {
|
||||
fmt.Println("Invalid input. Please try again.")
|
||||
continue
|
||||
}
|
||||
|
||||
if row < 1 || row > boardSize || col < 1 || col > boardSize {
|
||||
fmt.Println("Invalid input. Please try again.")
|
||||
continue
|
||||
}
|
||||
// Приведение к 0-индексации
|
||||
row--
|
||||
col--
|
||||
|
||||
if board[row][col] != empty {
|
||||
fmt.Println("This cell is already occupied!")
|
||||
continue
|
||||
}
|
||||
// Выполнение хода
|
||||
board[row][col] = currentPlayer
|
||||
|
||||
// Проверка выигрыша по строкам и столбцам
|
||||
winFound := false
|
||||
for i := range boardSize {
|
||||
rowWin := true
|
||||
colWin := true
|
||||
for j := range boardSize {
|
||||
if board[i][j] != currentPlayer {
|
||||
rowWin = false
|
||||
}
|
||||
if board[j][i] != currentPlayer {
|
||||
colWin = false
|
||||
}
|
||||
}
|
||||
if rowWin || colWin {
|
||||
winFound = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Проверка главной диагонали
|
||||
if !winFound {
|
||||
diagWin := true
|
||||
for i := range boardSize {
|
||||
if board[i][i] != currentPlayer {
|
||||
diagWin = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if diagWin {
|
||||
winFound = true
|
||||
}
|
||||
}
|
||||
|
||||
// Проверка обратной диагонали
|
||||
if !winFound {
|
||||
antiDiagWin := true
|
||||
for i := range boardSize {
|
||||
if board[i][boardSize-i-1] != currentPlayer {
|
||||
antiDiagWin = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if antiDiagWin {
|
||||
winFound = true
|
||||
}
|
||||
}
|
||||
|
||||
if winFound {
|
||||
if currentPlayer == cross {
|
||||
state = crossWin
|
||||
} else {
|
||||
state = noughtWin
|
||||
}
|
||||
} else {
|
||||
// Проверка на ничью (заполнена ли доска)
|
||||
full := true
|
||||
for i := range boardSize {
|
||||
for j := range boardSize {
|
||||
if board[i][j] == empty {
|
||||
full = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if !full {
|
||||
break
|
||||
}
|
||||
}
|
||||
if full {
|
||||
state = draw
|
||||
}
|
||||
}
|
||||
|
||||
// Вывод текущего состояния доски
|
||||
fmt.Print(" ")
|
||||
for i := range boardSize {
|
||||
fmt.Printf("%d ", i+1)
|
||||
}
|
||||
fmt.Println()
|
||||
for i := range boardSize {
|
||||
fmt.Printf("%d ", i+1)
|
||||
for j := range boardSize {
|
||||
switch board[i][j] {
|
||||
case empty:
|
||||
fmt.Print(". ")
|
||||
case cross:
|
||||
fmt.Print("X ")
|
||||
case nought:
|
||||
fmt.Print("O ")
|
||||
}
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
// Вывод сообщения о результате, если игра окончена
|
||||
if state == crossWin {
|
||||
fmt.Println("X wins!")
|
||||
} else if state == noughtWin {
|
||||
fmt.Println("O wins!")
|
||||
} else if state == draw {
|
||||
fmt.Println("It's a draw!")
|
||||
} else {
|
||||
// Переключение игрока, если игра продолжается
|
||||
if currentPlayer == cross {
|
||||
currentPlayer = nought
|
||||
} else {
|
||||
currentPlayer = cross
|
||||
}
|
||||
}
|
||||
validInput = true
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user