From 774b193e7f6726d643e1e68700d0ad153724614f Mon Sep 17 00:00:00 2001 From: Thibaud Date: Mon, 9 Sep 2024 14:09:00 +0200 Subject: [PATCH] implement the game, more or less --- client.mts | 15 ++++++- common.mts | 7 ++- server.mts | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 135 insertions(+), 9 deletions(-) diff --git a/client.mts b/client.mts index a364a8c..ab20fce 100644 --- a/client.mts +++ b/client.mts @@ -1,4 +1,4 @@ -import { Request, Response, Message, Hello } from "common.mjs"; +import { Request, Response, Message, Hello, EndGame } from "common.mjs"; const ws = new WebSocket("ws://localhost:1234"); const grid = [0, 0, 0, 0, 0, 0, 0, 0, 0] @@ -44,6 +44,19 @@ ws.onmessage = (evt) => { } break; } + case "endgame": { + const h1 = document.getElementById("title") as HTMLHeadingElement | null; + if (h1) { + const issue = (msg.data as EndGame).issue; + switch (issue){ + case "win": h1.innerText = "you won"; break; + case "lose": h1.innerText = "you lose"; break; + case "draw": h1.innerText = "it's a draw!"; break; + default: throw new Error(`unexpected ${issue}`); + } + } + break; + } default: { console.log(msg); break; diff --git a/common.mts b/common.mts index 2afc014..a755e79 100644 --- a/common.mts +++ b/common.mts @@ -1,8 +1,8 @@ -export type MessageKind = "hello" | "update"; +export type MessageKind = "hello" | "update" | "endgame"; export interface Message { kind: MessageKind, - data: Response | Hello, + data: Response | Hello | EndGame, } export interface Request { @@ -18,3 +18,6 @@ export interface Hello { id: number } +export interface EndGame { + issue: "win" | "lose" | "draw" +} diff --git a/server.mts b/server.mts index 0f6e11d..50821ff 100644 --- a/server.mts +++ b/server.mts @@ -1,4 +1,4 @@ -import { Message, Response, Hello } from "common.mjs" +import { Message, Response, Hello, EndGame } from "common.mjs" import { WebSocket, WebSocketServer } from "ws"; const port = 1234 @@ -15,6 +15,7 @@ interface Client { let id = 1; let clients: Client[] = []; +let currentPlayerId: number | undefined = undefined; wss.on("connection", (ws) => { id += 1; @@ -24,6 +25,11 @@ wss.on("connection", (ws) => { return; } + if (!currentPlayerId) { + currentPlayerId = id; + console.log(`current player is #${currentPlayerId}`); + } + clients.push({id, ws}); ws.send(JSON.stringify({kind: "hello", data: { id } as Hello})); console.log(`player #${id} connected`); @@ -33,16 +39,51 @@ wss.on("connection", (ws) => { const {x, y} = message; const playerId = clients.find(x => x.ws === ws)?.id; console.assert(playerId); + console.log(message, playerId, currentPlayerId); + + if (playerId != currentPlayerId) { + return; + } + if (grid[y*3+x] === 0) { grid[y*3+x] = playerId as number; for (const c of clients) { const msg: Message = { kind: "update", - data: { grid } as Response, - } - c.ws.send(JSON.stringify(msg)); - } - } + data: { grid } as Response, + } + c.ws.send(JSON.stringify(msg)); + } + + const winnerId = checkWin(grid); + if (winnerId == -1) { + currentPlayerId = clients.find(x => x.id !== currentPlayerId)?.id; // change player + console.assert(currentPlayerId); + console.log(`current player is #${currentPlayerId}`); + } else if (winnerId == 0) { + for (const c of clients) { + const msg: Message = { + kind: "endgame", + data: { issue: "draw" } as EndGame + }; + c.ws.send(JSON.stringify(msg)); + } + } else { + console.log(`player ${winnerId} won !`); + + const winner = clients.find(x => x.id === winnerId); + winner?.ws?.send(JSON.stringify({ + kind: "endgame", + data: { issue: "win" } as EndGame + } as Message)); + + const loser = clients.find(x => x.id !== winnerId); + loser?.ws?.send(JSON.stringify({ + kind: "endgame", + data: { issue: "lose" } as EndGame + } as Message)); + } + } }); ws.on("close", () => { @@ -50,3 +91,72 @@ wss.on("connection", (ws) => { clients = clients.filter(x => x.id !== id); }); }); + +function checkWin(grid: number[]): number { + const clone = [...grid]; + const grid2d = []; + while(clone.length) grid2d.push(clone.splice(0,3)); + + if ( + grid2d[0][0] !== 0 && + grid2d[0][0] === grid2d[0][1] && + grid2d[0][1] === grid2d[0][2] + ) { + return grid2d[0][0]; + } + if ( + grid2d[1][0] !== 0 && + grid2d[1][0] === grid2d[1][1] && + grid2d[1][1] === grid2d[1][2] + ) { + return grid2d[1][0]; + } + if ( + grid2d[2][0] !== 0 && + grid2d[2][0] === grid2d[2][1] && + grid2d[2][1] === grid2d[2][2] + ) { + return grid2d[2][0]; + } + if ( + grid2d[0][0] !== 0 && + grid2d[0][0] === grid2d[1][0] && + grid2d[1][0] === grid2d[2][0] + ) { + return grid2d[0][0]; + } + if ( + grid2d[0][1] !== 0 && + grid2d[0][1] === grid2d[1][1] && + grid2d[1][1] === grid2d[2][1] + ) { + return grid2d[0][1]; + } + if ( + grid2d[0][2] !== 0 && + grid2d[0][2] === grid2d[1][2] && + grid2d[1][2] === grid2d[2][2] + ) { + return grid2d[0][2]; + } + if ( + grid2d[0][0] !== 0 && + grid2d[0][0] === grid2d[1][1] && + grid2d[1][1] === grid2d[2][2] + ) { + return grid2d[0][0]; + } + if ( + grid2d[0][2] !== 0 && + grid2d[0][2] === grid2d[1][1] && + grid2d[1][1] === grid2d[2][0] + ) { + return grid2d[0][2]; + } + for (const row of grid2d) { + if (row[0] === 0 || row[1] === 0 || row[2] === 0) { + return -1; + } + } + return 0; +}