1
0
mirror of https://github.com/thib8956/tic-tac-toe-ws.git synced 2024-09-29 06:06:37 +00:00

fix endgame condition

This commit is contained in:
Thibaud Gasser 2024-09-25 11:58:56 +02:00
parent 8333df9580
commit f56fc0a65c
3 changed files with 89 additions and 84 deletions

View File

@ -22,11 +22,11 @@ interface Shape {
time: number; time: number;
} }
let grid = [0, 0, 0, 0, 0, 0, 0, 0, 0] let grid = [0, 0, 0, 0, 0, 0, 0, 0, 0];
let circle = true;
let pendingEvts: Point[] = []; let pendingEvts: Point[] = [];
let shapes: Shape[] = []; let shapes: Shape[] = [];
let myId: number | null = null; let myId: number | null = null;
let mySymbol: "x" | "o" | null = null;
let canvasMsg: string = "Offline"; let canvasMsg: string = "Offline";
function drawGridBackground(ctx: CanvasRenderingContext2D, origin: Point) { function drawGridBackground(ctx: CanvasRenderingContext2D, origin: Point) {
@ -105,18 +105,17 @@ function updateGridState(ctx: CanvasRenderingContext2D, gridOrigin: Point) {
for (let x = 0; x < 3; ++x) { for (let x = 0; x < 3; ++x) {
switch (grid[y*3+x]) { switch (grid[y*3+x]) {
case 0: break; case 0: break;
case 1: { case myId: {
const p = gridIndexToCoords(gridOrigin, x, y); const p = gridIndexToCoords(gridOrigin, x, y);
drawCircle(ctx, p); mySymbol == "o" ? drawCircle(ctx, p) : drawCross(ctx, p);
break; break;
} }
case 2: { default: {
const p = gridIndexToCoords(gridOrigin, x, y); const p = gridIndexToCoords(gridOrigin, x, y);
drawCross(ctx, p); mySymbol == "o" ? drawCross(ctx, p) : drawCircle(ctx, p);
break; break;
} }
default: throw new Error(`unhandled grid state ${grid[y*3+x]}`);
} }
} }
} }
@ -165,7 +164,8 @@ function init() {
switch (msg.kind) { switch (msg.kind) {
case "hello": { case "hello": {
myId = (msg.data as Hello).id; myId = (msg.data as Hello).id;
canvasMsg = `connected to server with id ${myId}`; mySymbol = (msg.data as Hello).symbol;
canvasMsg = `connected to server with id ${myId}, ${mySymbol}`;
console.log(canvasMsg); console.log(canvasMsg);
break; break;
} }

View File

@ -15,7 +15,8 @@ export interface Response {
} }
export interface Hello { export interface Hello {
id: number id: number,
symbol: "x" | "o"
} }
export interface EndGame { export interface EndGame {

View File

@ -1,5 +1,5 @@
import { Message, Response, Hello, EndGame } from "common.mjs" import { Message, Response, Hello, EndGame } from "common.mjs"
import { WebSocket, WebSocketServer } from "ws"; import { WebSocket, WebSocketServer, MessageEvent } from "ws";
const port = 1234 const port = 1234
const wss = new WebSocketServer({ port }); const wss = new WebSocketServer({ port });
@ -28,27 +28,31 @@ wss.on("connection", (ws) => {
} }
const symbol = clients.length == 0 ? "o" : "x"; const symbol = clients.length == 0 ? "o" : "x";
const helloMsg: Message = {
kind: "hello",
data: { id, symbol } as Hello
}
clients.push({id, ws, symbol}); clients.push({id, ws, symbol});
ws.send(JSON.stringify({kind: "hello", data: { id } as Hello})); ws.send(JSON.stringify(helloMsg));
console.log(`player #${id} connected`); console.log(`player #${id} connected`);
ws.addEventListener("message", (event: any) => { ws.addEventListener("message", (event: MessageEvent) => {
const message = JSON.parse(event.data); const message = JSON.parse(event.data as string);
const {x, y} = message; const {x, y} = message;
const player = clients.find(x => x.ws === ws); const player = clients.find(x => x.ws === ws);
console.assert(player !== undefined); if (!player) throw new Error("player not found");
console.log(message, player!.id, currentPlayer?.id); console.log(message, player!.id, currentPlayer?.id);
if (!currentPlayer) { if (!currentPlayer) {
currentPlayer = player; currentPlayer = player;
} }
if (clients.length < 2 || player!.id != currentPlayer?.id || endGame) { if (clients.length < 2 || player.id != currentPlayer?.id || endGame) {
return; return;
} }
if (grid[y*3+x] === 0) { if (grid[y*3+x] === 0) {
grid[y*3+x] = player!.symbol == "o" ? 1 : 2; grid[y*3+x] = player.id;
for (const c of clients) { for (const c of clients) {
const msg: Message = { const msg: Message = {
kind: "update", kind: "update",
@ -69,7 +73,7 @@ wss.on("connection", (ws) => {
data: { issue: "draw" } as EndGame data: { issue: "draw" } as EndGame
}; };
c.ws.send(JSON.stringify(msg)); c.ws.send(JSON.stringify(msg));
endGame = true; endGame = true;
} }
} else { } else {
console.log(`player ${winnerId} won !`); console.log(`player ${winnerId} won !`);
@ -78,13 +82,13 @@ wss.on("connection", (ws) => {
winner?.ws?.send(JSON.stringify({ winner?.ws?.send(JSON.stringify({
kind: "endgame", kind: "endgame",
data: { issue: "win" } as EndGame data: { issue: "win" } as EndGame
} as Message)); } as Message));
const loser = clients.find(x => x.id !== winnerId); const loser = clients.find(x => x.id !== winnerId);
loser?.ws?.send(JSON.stringify({ loser?.ws?.send(JSON.stringify({
kind: "endgame", kind: "endgame",
data: { issue: "lose" } as EndGame data: { issue: "lose" } as EndGame
} as Message)); } as Message));
} }
} }
}); });
@ -96,70 +100,70 @@ wss.on("connection", (ws) => {
}); });
function checkWin(grid: number[]): number { function checkWin(grid: number[]): number {
const clone = [...grid]; const clone = [...grid];
const grid2d = []; const grid2d = [];
while(clone.length) grid2d.push(clone.splice(0,3)); while(clone.length) grid2d.push(clone.splice(0,3));
if ( if (
grid2d[0][0] !== 0 && grid2d[0][0] !== 0 &&
grid2d[0][0] === grid2d[0][1] && grid2d[0][0] === grid2d[0][1] &&
grid2d[0][1] === grid2d[0][2] grid2d[0][1] === grid2d[0][2]
) { ) {
return grid2d[0][0]; return grid2d[0][0];
} }
if ( if (
grid2d[1][0] !== 0 && grid2d[1][0] !== 0 &&
grid2d[1][0] === grid2d[1][1] && grid2d[1][0] === grid2d[1][1] &&
grid2d[1][1] === grid2d[1][2] grid2d[1][1] === grid2d[1][2]
) { ) {
return grid2d[1][0]; return grid2d[1][0];
} }
if ( if (
grid2d[2][0] !== 0 && grid2d[2][0] !== 0 &&
grid2d[2][0] === grid2d[2][1] && grid2d[2][0] === grid2d[2][1] &&
grid2d[2][1] === grid2d[2][2] grid2d[2][1] === grid2d[2][2]
) { ) {
return grid2d[2][0]; return grid2d[2][0];
} }
if ( if (
grid2d[0][0] !== 0 && grid2d[0][0] !== 0 &&
grid2d[0][0] === grid2d[1][0] && grid2d[0][0] === grid2d[1][0] &&
grid2d[1][0] === grid2d[2][0] grid2d[1][0] === grid2d[2][0]
) { ) {
return grid2d[0][0]; return grid2d[0][0];
} }
if ( if (
grid2d[0][1] !== 0 && grid2d[0][1] !== 0 &&
grid2d[0][1] === grid2d[1][1] && grid2d[0][1] === grid2d[1][1] &&
grid2d[1][1] === grid2d[2][1] grid2d[1][1] === grid2d[2][1]
) { ) {
return grid2d[0][1]; return grid2d[0][1];
} }
if ( if (
grid2d[0][2] !== 0 && grid2d[0][2] !== 0 &&
grid2d[0][2] === grid2d[1][2] && grid2d[0][2] === grid2d[1][2] &&
grid2d[1][2] === grid2d[2][2] grid2d[1][2] === grid2d[2][2]
) { ) {
return grid2d[0][2]; return grid2d[0][2];
} }
if ( if (
grid2d[0][0] !== 0 && grid2d[0][0] !== 0 &&
grid2d[0][0] === grid2d[1][1] && grid2d[0][0] === grid2d[1][1] &&
grid2d[1][1] === grid2d[2][2] grid2d[1][1] === grid2d[2][2]
) { ) {
return grid2d[0][0]; return grid2d[0][0];
} }
if ( if (
grid2d[0][2] !== 0 && grid2d[0][2] !== 0 &&
grid2d[0][2] === grid2d[1][1] && grid2d[0][2] === grid2d[1][1] &&
grid2d[1][1] === grid2d[2][0] grid2d[1][1] === grid2d[2][0]
) { ) {
return grid2d[0][2]; return grid2d[0][2];
} }
for (const row of grid2d) { for (const row of grid2d) {
if (row[0] === 0 || row[1] === 0 || row[2] === 0) { if (row[0] === 0 || row[1] === 0 || row[2] === 0) {
return -1; return -1;
} }
} }
return 0; return 0;
} }