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

View File

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

View File

@@ -5,106 +5,20 @@ import (
"fmt" "fmt"
"log" "log"
b "tic-tac-toe/board" // Added for g.GameMode b "tic-tac-toe/board"
"tic-tac-toe/network" "tic-tac-toe/network"
) )
// Обрабатываем ответ на запрос на присоединение к комнате // Обрабатываем ответ сервера, содержащий никнейм игрока
func (c *Client) handleRoomJoinResponse(payload json.RawMessage) { func (c *Client) handleNickNameResponse(payload json.RawMessage) {
var res network.RoomJoinResponse // Десериализуем ответ var res network.NickNameResponse // Десериализуем ответ
if err := json.Unmarshal(payload, &res); err == nil { if err := json.Unmarshal(payload, &res); err == nil {
c.mySymbol = res.PlayerSymbol // Устанавливаем фигуру игрока fmt.Printf("\nWelcome, %s!\n> ", res.Nickname)
c.roomName = res.RoomName // Устанавливаем имя комнаты c.setNickname(res.Nickname) // Устанавливаем никнейм игрока
if res.Board.Size > 0 { // Проверяем размер поля c.setState(mainMenu) // Переходим в главное меню
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 { } 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 { } else {
log.Printf("Error unmarshalling RoomListResponse: %v", err) log.Printf("Error unmarshalling RoomListResponse: %v", err)
} }
c.setState(mainMenu) c.setState(mainMenu) // Переходим в главное меню
} }
// Обрабатываем ответ на запрос на присоединение к комнате // Обрабатываем ответ на запрос на присоединение к комнате
func (c *Client) handleNickNameResponse(payload json.RawMessage) { func (c *Client) handleRoomJoinResponse(payload json.RawMessage) {
var res network.NickNameResponse // Десериализуем ответ var res network.RoomJoinResponse // Десериализуем ответ
if err := json.Unmarshal(payload, &res); err == nil { if err := json.Unmarshal(payload, &res); err == nil {
fmt.Printf("\nWelcome, %s!\n> ", res.Nickname) c.mySymbol = res.PlayerSymbol // Устанавливаем фигуру игрока
c.setNickname(res.Nickname) // Устанавливаем никнейм игрока c.roomName = res.RoomName // Устанавливаем имя комнаты
c.setState(mainMenu) // Устанавливаем состояние клиента 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 { } 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) c.setState(waitingOpponentInRoom)
} }
@@ -175,10 +92,12 @@ func (c *Client) handleFinishedGamesResponse(payload json.RawMessage) {
} }
} }
} else { } 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() c.board.PrintBoard()
fmt.Println() fmt.Println()
} else { } 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 return false
} }
// Преобразуем в 0-индексированный для доступа к полю // Нормируем индекс для доступа к полю
if c.board.Board[row-1][col-1] != b.Empty { if c.board.Board[row-1][col-1] != b.Empty {
fmt.Println("Invalid move. Cell is already occupied.") fmt.Println("Invalid move. Cell is already occupied.")
return false return false