mirror of
https://github.com/MADTeacher/go_basics.git
synced 2025-11-23 21:34:47 +02:00
добавлены более подробные комментарии
This commit is contained in:
@@ -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()
|
||||
}
|
||||
|
||||
// Читаем сообщения от сервера
|
||||
|
||||
@@ -12,8 +12,8 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// Метод для взаимодействия с пользователем
|
||||
func (c *Client) menu() {
|
||||
// Метод управления всем пользовательским потоком
|
||||
func (c *Client) handleUserFlow() {
|
||||
// Создаем буфер для чтения ввода
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
// Создаем энкодер для отправки сообщений
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user