mirror of
https://github.com/thib8956/tic-tac-toe-ws.git
synced 2025-01-12 04:41:06 +00:00
implement the game, more or less
This commit is contained in:
parent
be71a811d3
commit
774b193e7f
15
client.mts
15
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 ws = new WebSocket("ws://localhost:1234");
|
||||||
const grid = [0, 0, 0, 0, 0, 0, 0, 0, 0]
|
const grid = [0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||||
@ -44,6 +44,19 @@ ws.onmessage = (evt) => {
|
|||||||
}
|
}
|
||||||
break;
|
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: {
|
default: {
|
||||||
console.log(msg);
|
console.log(msg);
|
||||||
break;
|
break;
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
export type MessageKind = "hello" | "update";
|
export type MessageKind = "hello" | "update" | "endgame";
|
||||||
|
|
||||||
export interface Message {
|
export interface Message {
|
||||||
kind: MessageKind,
|
kind: MessageKind,
|
||||||
data: Response | Hello,
|
data: Response | Hello | EndGame,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Request {
|
export interface Request {
|
||||||
@ -18,3 +18,6 @@ export interface Hello {
|
|||||||
id: number
|
id: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface EndGame {
|
||||||
|
issue: "win" | "lose" | "draw"
|
||||||
|
}
|
||||||
|
122
server.mts
122
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";
|
import { WebSocket, WebSocketServer } from "ws";
|
||||||
|
|
||||||
const port = 1234
|
const port = 1234
|
||||||
@ -15,6 +15,7 @@ interface Client {
|
|||||||
|
|
||||||
let id = 1;
|
let id = 1;
|
||||||
let clients: Client[] = [];
|
let clients: Client[] = [];
|
||||||
|
let currentPlayerId: number | undefined = undefined;
|
||||||
|
|
||||||
wss.on("connection", (ws) => {
|
wss.on("connection", (ws) => {
|
||||||
id += 1;
|
id += 1;
|
||||||
@ -24,6 +25,11 @@ wss.on("connection", (ws) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!currentPlayerId) {
|
||||||
|
currentPlayerId = id;
|
||||||
|
console.log(`current player is #${currentPlayerId}`);
|
||||||
|
}
|
||||||
|
|
||||||
clients.push({id, ws});
|
clients.push({id, ws});
|
||||||
ws.send(JSON.stringify({kind: "hello", data: { id } as Hello}));
|
ws.send(JSON.stringify({kind: "hello", data: { id } as Hello}));
|
||||||
console.log(`player #${id} connected`);
|
console.log(`player #${id} connected`);
|
||||||
@ -33,16 +39,51 @@ wss.on("connection", (ws) => {
|
|||||||
const {x, y} = message;
|
const {x, y} = message;
|
||||||
const playerId = clients.find(x => x.ws === ws)?.id;
|
const playerId = clients.find(x => x.ws === ws)?.id;
|
||||||
console.assert(playerId);
|
console.assert(playerId);
|
||||||
|
console.log(message, playerId, currentPlayerId);
|
||||||
|
|
||||||
|
if (playerId != currentPlayerId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (grid[y*3+x] === 0) {
|
if (grid[y*3+x] === 0) {
|
||||||
grid[y*3+x] = playerId as number;
|
grid[y*3+x] = playerId as number;
|
||||||
for (const c of clients) {
|
for (const c of clients) {
|
||||||
const msg: Message = {
|
const msg: Message = {
|
||||||
kind: "update",
|
kind: "update",
|
||||||
data: { grid } as Response,
|
data: { grid } as Response,
|
||||||
}
|
}
|
||||||
c.ws.send(JSON.stringify(msg));
|
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", () => {
|
ws.on("close", () => {
|
||||||
@ -50,3 +91,72 @@ wss.on("connection", (ws) => {
|
|||||||
clients = clients.filter(x => x.id !== id);
|
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;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user