1
0
mirror of https://github.com/MADTeacher/go_basics.git synced 2025-11-23 21:34:47 +02:00

добавлены более подробные комментарии

This commit is contained in:
Stanislav Chernyshev
2025-06-23 20:59:15 +03:00
parent d0f3bff57d
commit 8ea10ef2b1
4 changed files with 144 additions and 140 deletions

View File

@@ -14,24 +14,15 @@ import (
// Объявление структуры клиента
type Client struct {
// подключение к серверу
conn net.Conn
// игровое поле
board *b.Board
// фигура игрока
mySymbol b.BoardField
// фигура игрока, ход которой сейчас
currentPlayer b.BoardField
// никнейм игрока
playerName string
// имя комнаты
roomName string
// текущее состояние клиента
state State
// мьютекс для защиты доступа к данным
mutex sync.RWMutex
// время последнего сообщения
lastMsgTime time.Time
conn net.Conn // подключение к серверу
board *b.Board // игровое поле
mySymbol b.BoardField // фигура игрока
currentPlayer b.BoardField // фигура игрока, чей сейчас ход
playerName string // имя комнаты
roomName string // имя комнаты
state State // текущее состояние клиента
mutex sync.RWMutex // мьютекс для защиты доступа к данным
lastMsgTime time.Time // время последнего сообщения
}
// Констукторная функция для создания клиента
@@ -51,7 +42,7 @@ func NewClient(addr string) (*Client, error) {
}, nil
}
// Устанавливаем никнейм игрока
// Устанавливаем никнейма игрока
func (c *Client) setNickname(nickname string) {
c.playerName = nickname
}
@@ -88,7 +79,7 @@ func (c *Client) Start() {
// Запускаем горутину для чтения сообщений от сервера
go c.readFromServer()
// Запускаем меню клиента для взаимодействия с пользователем
c.menu()
c.handleUserFlow()
}
// Читаем сообщения от сервера

View File

@@ -12,8 +12,8 @@ import (
"time"
)
// Метод для взаимодействия с пользователем
func (c *Client) menu() {
// Метод управления всем пользовательским потоком
func (c *Client) handleUserFlow() {
// Создаем буфер для чтения ввода
reader := bufio.NewReader(os.Stdin)
// Создаем энкодер для отправки сообщений

View File

@@ -5,106 +5,20 @@ import (
"fmt"
"log"
b "tic-tac-toe/board" // Added for g.GameMode
b "tic-tac-toe/board"
"tic-tac-toe/network"
)
// Обрабатываем ответ на запрос на присоединение к комнате
func (c *Client) handleRoomJoinResponse(payload json.RawMessage) {
var res network.RoomJoinResponse // Десериализуем ответ
// Обрабатываем ответ сервера, содержащий никнейм игрока
func (c *Client) handleNickNameResponse(payload json.RawMessage) {
var res network.NickNameResponse // Десериализуем ответ
if err := json.Unmarshal(payload, &res); err == nil {
c.mySymbol = res.PlayerSymbol // Устанавливаем фигуру игрока
c.roomName = res.RoomName // Устанавливаем имя комнаты
if res.Board.Size > 0 { // Проверяем размер поля
c.board = &res.Board // Устанавливаем игровое поле
fmt.Printf(
"\nSuccessfully joined room '%s' as %s.\n",
res.RoomName, res.PlayerSymbol,
)
c.board.PrintBoard()
} else {
fmt.Printf(
"\nSuccessfully joined room '%s' as %s. "+
"Waiting for game to start...\n",
res.RoomName, res.PlayerSymbol,
)
}
fmt.Printf("\nWelcome, %s!\n> ", res.Nickname)
c.setNickname(res.Nickname) // Устанавливаем никнейм игрока
c.setState(mainMenu) // Переходим в главное меню
} else {
log.Printf("Error unmarshalling RoomJoinResponse: %v", err)
log.Printf("Error unmarshalling NickNameResponse: %v", err)
}
// Устанавливаем состояние клиента
c.setState(waitingOpponentInRoom)
}
// Обрабатываем ответ на запрос на инициализацию игры
func (c *Client) handleInitGame(payload json.RawMessage) {
var res network.InitGameResponse // Десериализуем ответ
if err := json.Unmarshal(payload, &res); err == nil {
c.board = &res.Board // Устанавливаем игровое поле
c.currentPlayer = res.CurrentPlayer // Устанавливаем фигуру игрока
fmt.Println("\n--- Game Started ---")
c.board.PrintBoard() // Выводим игровое поле
c.printTurnInfo() // Выводим информацию о ходе игрока
// Устанавливаем состояние клиента
if res.CurrentPlayer == c.mySymbol {
c.setState(playerMove)
} else {
c.setState(opponentMove)
}
} else {
log.Printf("Error unmarshalling InitGameResponse: %v", err)
}
}
// Обрабатываем сообщение об обновлении состояния игры
func (c *Client) handleUpdateState(payload json.RawMessage) {
var res network.GameStateUpdate // Десериализуем ответ
if err := json.Unmarshal(payload, &res); err == nil {
c.board = &res.Board // Устанавливаем игровое поле
c.currentPlayer = res.CurrentPlayer // Устанавливаем фигуру игрока
fmt.Println("\n--- Game State Update ---")
c.board.PrintBoard() // Выводим игровое поле
c.printTurnInfo() // Выводим информацию о ходе игрока
// Устанавливаем состояние клиента
if res.CurrentPlayer == c.mySymbol {
c.setState(playerMove)
} else {
c.setState(opponentMove)
}
} else {
log.Printf("Error unmarshalling GameStateUpdate: %v", err)
}
}
// Обрабатываем сообщение об окончании игры
func (c *Client) handleEndGame(payload json.RawMessage) {
var res network.EndGameResponse // Десериализуем ответ
if err := json.Unmarshal(payload, &res); err == nil {
c.board = &res.Board // Устанавливаем игровое поле
fmt.Println("\n--- Game Over ---")
c.board.PrintBoard() // Выводим игровое поле
// Выводим информацию о победителе
if res.CurrentPlayer == b.Empty {
fmt.Println("It's a Draw!")
} else {
fmt.Printf("Player %s wins!\n", res.CurrentPlayer)
}
c.setState(endGame) // Устанавливаем состояние клиента
fmt.Print("> ")
} else {
log.Printf("Error unmarshalling EndGameResponse: %v", err)
}
}
// Обрабатываем сообщение об ошибке
func (c *Client) handleError(payload json.RawMessage) {
var errPayload network.ErrorResponse // Десериализуем ответ
if err := json.Unmarshal(payload, &errPayload); err == nil {
fmt.Printf("\nServer Error: %s\n> ", errPayload.Message)
} else {
log.Printf("Error unmarshalling ErrorResponse: %v", err)
}
c.setState(mainMenu)
}
// Обрабатываем сообщение о списке комнат
@@ -130,30 +44,33 @@ func (c *Client) handleRoomListResponse(payload json.RawMessage) {
} else {
log.Printf("Error unmarshalling RoomListResponse: %v", err)
}
c.setState(mainMenu)
c.setState(mainMenu) // Переходим в главное меню
}
// Обрабатываем ответ на запрос на присоединение к комнате
func (c *Client) handleNickNameResponse(payload json.RawMessage) {
var res network.NickNameResponse // Десериализуем ответ
func (c *Client) handleRoomJoinResponse(payload json.RawMessage) {
var res network.RoomJoinResponse // Десериализуем ответ
if err := json.Unmarshal(payload, &res); err == nil {
fmt.Printf("\nWelcome, %s!\n> ", res.Nickname)
c.setNickname(res.Nickname) // Устанавливаем никнейм игрока
c.setState(mainMenu) // Устанавливаем состояние клиента
c.mySymbol = res.PlayerSymbol // Устанавливаем фигуру игрока
c.roomName = res.RoomName // Устанавливаем имя комнаты
if res.Board.Size > 0 { // Проверяем размер поля
c.board = &res.Board // Устанавливаем игровое поле
fmt.Printf(
"\nSuccessfully joined room '%s' as %s.\n",
res.RoomName, res.PlayerSymbol,
)
c.board.PrintBoard()
} else {
fmt.Printf(
"\nSuccessfully joined room '%s' as %s. "+
"Waiting for game to start...\n",
res.RoomName, res.PlayerSymbol,
)
}
} else {
log.Printf("Error unmarshalling NickNameResponse: %v", err)
log.Printf("Error unmarshalling RoomJoinResponse: %v", err)
}
}
// Обрабатываем сообщение об отключении оппонента
func (c *Client) handleOpponentLeft(payload json.RawMessage) {
var res network.OpponentLeft // Десериализуем ответ
if err := json.Unmarshal(payload, &res); err == nil {
fmt.Printf("\nPlayer '%s' has left the game.\n> ", res.Nickname)
} else {
log.Printf("Error unmarshalling OpponentLeft: %v", err)
}
// Устанавливаем состояние клиента
// переходим в состояние ожидания присоединения оппонента к комнате
c.setState(waitingOpponentInRoom)
}
@@ -175,10 +92,12 @@ func (c *Client) handleFinishedGamesResponse(payload json.RawMessage) {
}
}
} else {
log.Printf("Error unmarshalling FinishedGamesResponse: %v", err)
log.Printf(
"Error unmarshalling FinishedGamesResponse: %v",
err,
)
}
// Устанавливаем состояние клиента
c.setState(mainMenu)
c.setState(mainMenu) // Переходим в главное меню
}
// Обрабатываем ответ на запрос на получение данных
@@ -197,7 +116,101 @@ func (c *Client) handleFinishedGameResponse(payload json.RawMessage) {
c.board.PrintBoard()
fmt.Println()
} else {
log.Printf("Error unmarshalling FinishedGameResponse: %v", err)
log.Printf(
"Error unmarshalling FinishedGameResponse: %v",
err,
)
}
c.setState(mainMenu) // Устанавливаем состояние клиента
c.setState(mainMenu) // Переходим в главное меню
}
// Обрабатываем ответ на запрос на инициализацию игры
func (c *Client) handleInitGame(payload json.RawMessage) {
var res network.InitGameResponse // Десериализуем ответ
if err := json.Unmarshal(payload, &res); err == nil {
c.board = &res.Board // Устанавливаем игровое поле
c.currentPlayer = res.CurrentPlayer // Устанавливаем фигуру игрока
fmt.Println("\n--- Game Started ---")
c.board.PrintBoard() // Выводим игровое поле
c.printTurnInfo() // Выводим информацию о ходе игрока
if res.CurrentPlayer == c.mySymbol {
// Устанавливаем состояние, что ходит игрок
c.setState(playerMove)
} else {
// Устанавливаем состояние, что ходит оппонент
c.setState(opponentMove)
}
} else {
log.Printf(
"Error unmarshalling InitGameResponse: %v",
err,
)
}
}
// Обрабатываем сообщение об обновлении состояния игры
func (c *Client) handleUpdateState(payload json.RawMessage) {
var res network.GameStateUpdate // Десериализуем ответ
if err := json.Unmarshal(payload, &res); err == nil {
c.board = &res.Board // Устанавливаем игровое поле
c.currentPlayer = res.CurrentPlayer // Устанавливаем фигуру игрока
fmt.Println("\n--- Game State Update ---")
c.board.PrintBoard() // Выводим игровое поле
c.printTurnInfo() // Выводим информацию о ходе игрока
if res.CurrentPlayer == c.mySymbol {
// Устанавливаем состояние, что ходит игрок
c.setState(playerMove)
} else {
// Устанавливаем состояние, что ходит оппонент
c.setState(opponentMove)
}
} else {
log.Printf("Error unmarshalling GameStateUpdate: %v", err)
}
}
// Обрабатываем сообщение об окончании игры
func (c *Client) handleEndGame(payload json.RawMessage) {
var res network.EndGameResponse // Десериализуем ответ
if err := json.Unmarshal(payload, &res); err == nil {
c.board = &res.Board // Устанавливаем игровое поле
fmt.Println("\n--- Game Over ---")
c.board.PrintBoard() // Выводим игровое поле
// Выводим информацию о победителе
if res.CurrentPlayer == b.Empty {
fmt.Println("It's a Draw!")
} else {
fmt.Printf("Player %s wins!\n", res.CurrentPlayer)
}
c.setState(endGame) /// Переходи состояние завершения игры
fmt.Print("> ")
} else {
log.Printf("Error unmarshalling EndGameResponse: %v", err)
}
}
// Обрабатываем сообщение об ошибке
func (c *Client) handleError(payload json.RawMessage) {
var errPayload network.ErrorResponse // Десериализуем ответ
if err := json.Unmarshal(payload, &errPayload); err == nil {
fmt.Printf("\nServer Error: %s\n> ", errPayload.Message)
} else {
log.Printf("Error unmarshalling ErrorResponse: %v", err)
}
c.setState(mainMenu) // Переходим в главное меню
}
// Обрабатываем сообщение об отключении оппонента
func (c *Client) handleOpponentLeft(payload json.RawMessage) {
var res network.OpponentLeft // Десериализуем ответ
if err := json.Unmarshal(payload, &res); err == nil {
fmt.Printf(
"\nPlayer '%s' has left the game.\n> ",
res.Nickname,
)
} else {
log.Printf("Error unmarshalling OpponentLeft: %v", err)
}
// Переходим в состояние ожидания присоединения оппонента к комнате
c.setState(waitingOpponentInRoom)
}

View File

@@ -36,7 +36,7 @@ func (c *Client) validateMove(row, col int) bool {
)
return false
}
// Преобразуем в 0-индексированный для доступа к полю
// Нормируем индекс для доступа к полю
if c.board.Board[row-1][col-1] != b.Empty {
fmt.Println("Invalid move. Cell is already occupied.")
return false