mirror of
https://github.com/MADTeacher/go_basics.git
synced 2025-11-23 21:34:47 +02:00
159 lines
3.9 KiB
Go
159 lines
3.9 KiB
Go
package client
|
|
|
|
import (
|
|
"bufio"
|
|
"encoding/json"
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
"tic-tac-toe/network"
|
|
"time"
|
|
)
|
|
|
|
func (c *Client) menu() {
|
|
reader := bufio.NewReader(os.Stdin)
|
|
encoder := json.NewEncoder(c.conn)
|
|
|
|
fmt.Print("Enter your nickname: ")
|
|
input, _ := reader.ReadString('\n')
|
|
input = strings.TrimSpace(input)
|
|
c.playerName = input
|
|
var msg network.Message
|
|
|
|
msg.Cmd = network.CmdNickname
|
|
payloadData := network.NicknameRequest{Nickname: c.playerName}
|
|
jsonPayload, err := json.Marshal(payloadData)
|
|
if err != nil {
|
|
log.Printf("Error marshalling payload for command %s: %v", msg.Cmd, err)
|
|
return
|
|
}
|
|
msg.Payload = jsonPayload
|
|
if err := encoder.Encode(msg); err != nil {
|
|
log.Printf("Failed to send message to server: %v. Disconnecting.", err)
|
|
return // Exit if we can't send to server
|
|
}
|
|
|
|
for {
|
|
switch c.getState() {
|
|
case waitNickNameConfirm:
|
|
time.Sleep(100 * time.Millisecond)
|
|
continue
|
|
case mainMenu:
|
|
c.mainMenu(reader, encoder)
|
|
case playerMove:
|
|
c.playing(reader, encoder)
|
|
case opponentMove:
|
|
// Just wait silently for opponent's move
|
|
time.Sleep(1000 * time.Millisecond)
|
|
continue
|
|
case endGame:
|
|
fmt.Println("\nGame has ended. Restarting in 10 seconds...")
|
|
time.Sleep(10 * time.Second)
|
|
continue
|
|
case waitResponseFromServer:
|
|
time.Sleep(100 * time.Millisecond)
|
|
continue
|
|
case waitingOpponentInRoom:
|
|
// Rate-limit messages to once every 3 seconds
|
|
now := time.Now()
|
|
if now.Sub(c.lastMsgTime) > 3*time.Second {
|
|
c.lastMsgTime = now
|
|
fmt.Println("\nWaiting for opponent to join...")
|
|
fmt.Println("Press 'q' and Enter to return to main menu")
|
|
fmt.Print("> ")
|
|
}
|
|
|
|
// Poll for input every cycle but don't block
|
|
var buffer [1]byte
|
|
n, _ := os.Stdin.Read(buffer[:])
|
|
if n > 0 && (buffer[0] == 'q' || buffer[0] == 'Q') {
|
|
fmt.Println("Leaving room...")
|
|
var msg network.Message
|
|
msg.Cmd = network.CmdLeaveRoomRequest
|
|
payload := network.LeaveRoomRequest{
|
|
RoomName: c.roomName,
|
|
PlayerName: c.playerName,
|
|
}
|
|
jsonPayload, _ := json.Marshal(payload)
|
|
msg.Payload = jsonPayload
|
|
encoder.Encode(msg)
|
|
c.setState(mainMenu)
|
|
continue
|
|
}
|
|
|
|
// Short sleep to avoid CPU spinning
|
|
time.Sleep(100 * time.Millisecond)
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
func (c *Client) mainMenu(reader *bufio.Reader, encoder *json.Encoder) {
|
|
var msg network.Message
|
|
|
|
fmt.Println("Enter command:")
|
|
fmt.Println("1 - Get room list")
|
|
fmt.Println("2 - Join room")
|
|
fmt.Println("3 - Get finished games")
|
|
fmt.Println("4 - Get finished game by id")
|
|
fmt.Println("5 - Exit")
|
|
fmt.Print("> ")
|
|
input, _ := reader.ReadString('\n')
|
|
input = strings.TrimSpace(input)
|
|
|
|
command, err := strconv.Atoi(input)
|
|
if err != nil {
|
|
fmt.Println("Invalid command.")
|
|
return
|
|
}
|
|
|
|
switch command {
|
|
case 1:
|
|
msg.Cmd = network.CmdListRoomsRequest
|
|
encoder.Encode(msg)
|
|
c.setState(waitResponseFromServer)
|
|
case 2:
|
|
fmt.Print("Enter room name: ")
|
|
input, _ := reader.ReadString('\n')
|
|
input = strings.TrimSpace(input)
|
|
c.roomName = input
|
|
msg.Cmd = network.CmdJoinRoomRequest
|
|
payload := network.JoinRoomRequest{
|
|
RoomName: c.roomName,
|
|
PlayerName: c.playerName,
|
|
}
|
|
jsonPayload, _ := json.Marshal(payload)
|
|
msg.Payload = jsonPayload
|
|
encoder.Encode(msg)
|
|
c.setState(waitResponseFromServer)
|
|
case 3:
|
|
msg.Cmd = network.CmdFinishedGamesRequest
|
|
encoder.Encode(msg)
|
|
c.setState(waitResponseFromServer)
|
|
case 4:
|
|
fmt.Print("Enter game id: ")
|
|
input, _ := reader.ReadString('\n')
|
|
input = strings.TrimSpace(input)
|
|
|
|
gameId, err := strconv.Atoi(input)
|
|
if err != nil {
|
|
fmt.Println("Invalid game id.")
|
|
return
|
|
}
|
|
|
|
msg.Cmd = network.CmdFinishedGameByIdRequest
|
|
payload := network.GetFinishedGameByIdRequest{GameID: gameId}
|
|
jsonPayload, _ := json.Marshal(payload)
|
|
msg.Payload = jsonPayload
|
|
encoder.Encode(msg)
|
|
c.setState(waitResponseFromServer)
|
|
case 5:
|
|
os.Exit(0)
|
|
default:
|
|
fmt.Println("Unknown command.")
|
|
return
|
|
}
|
|
}
|