Commit 718cca42 authored by 邱旭's avatar 邱旭

默认变更列表

parent 938ee7fc
...@@ -65,7 +65,6 @@ ws.onerror = (event) => { ...@@ -65,7 +65,6 @@ ws.onerror = (event) => {
} }
``` ```
WebSocket 基本事件: WebSocket 基本事件:
| 事件名 | 意义 | | 事件名 | 意义 |
...@@ -74,3 +73,343 @@ WebSocket 基本事件: ...@@ -74,3 +73,343 @@ WebSocket 基本事件:
| message | 收到消息 | | message | 收到消息 |
| close | 关闭 | | close | 关闭 |
| error | 异常关闭 | | error | 异常关闭 |
## 预制一些方法
在服务器中写一些变量,用于保存我们的数据
```javascript
/**
* 棋盘
* @type {number}
*/
const mapData = [
[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
];
/**
* 当前颜色,0 啥也没有, 1 白棋, 2 黑棋
*/
let curColor = 1;
let whitePlayer = null; // 白棋玩家
let blackPlayer = null; // 黑棋玩家
```
因为WebSocket只能发送String或Buffer,所以我们可以创建一个函数来方便发送Json格式的数据
服务端中,如下:
```javascript
/**
* 发送Json格式的消息
* @param conn
* @param {Object} data
*/
function sendJson(conn, data) {
conn.send(JSON.stringify(data));
}
```
客户端中,如下:
```javascript
/**
* 发送json格式数据
* @param {Object} data
*/
function sendJson(data) {
ws.send(JSON.stringify(data));
}
```
## 完成如下UI
- 1.上坐按钮:在无座时显示"点击上坐",自己的时候显示"点击站起",别人在座的时候不显示
- 2.在线人数:显示在线人数
![img.png](img/02_01.png)
## 广播房间
写一个广播函数和广播房间信息函数,用于在局面变化时广播给所有客户端
`server.connections`中存储的是所有连接的客户端,长度就是个数
```javascript
/**
* 广播JSON格式数据
* @param data
*/
function broadcastJson(data) {
const msg = JSON.stringify(data);
server.connections.forEach((conn) => {
conn.sendText(msg);
});
}
function broadcastRoom() {
broadcastJson({
type: "roomData", // type
onlineCount: server.connections.length, // 在线人数
white: whitePlayer ? whitePlayer.key : null, // 白棋玩家
black: blackPlayer ? blackPlayer.key : null, // 黑棋玩家
mapData, curColor, // 地图数据,当前期权颜色
});
}
```
修改客户端中`WebSocket`客户端的`onmessage`函数 并创建`updateData`函数,处理界面展示
```javascript
/**
* 用户ID
*/
let userId = "";
/**
* 用户身份 0 观战 1 白棋 2 黑棋
* @type {number}
*/
let identity = 0;
let whitePlayer = null;
let blackPlayer = null;
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
const type = data.type;
console.log(data);
switch (type) {
case "init":
userId = data.userId;
break;
case "roomData":
updateData(data);
break;
}
}
function updateData(data) {
const {
onlineCount, mapData, curColor,
white, black
} = data;
color = curColor;
whitePlayer = white;
blackPlayer = black;
// 设置用户身份
if (white === userId) {
identity = 1; // 代表白棋玩家
} else if (black === userId) {
identity = 2; // 代表黑棋玩家
} else {
identity = 0; // 观战
}
// TODO 更新在线人数
// TODO 更新棋盘显示
// TODO 更新玩家区域显示
}
```
在客户端连接时 发送客户的UserID并广播当前房间信息
```javascript
const server = ws.createServer((conn) => {
console.log(conn.key + "建立连接");
sendJson(conn, { type: "init", userId: conn.key });
broadcastRoom();
/* ... */
});
```
客户端中点击上下座按钮,根据黑白方发送消息给服务端
```javascript
/**
* 坐下
* @param color 颜色
*/
function sitDown(color) {
sendJson({ type: "sitDown", color, });
}
// 站起
function standUp(color) {
sendJson({ type: "standUp", color });
}
```
在服务端中收到消息根据type执行上下坐逻辑
```javascript
conn.on("text", (msg) => {
const data = JSON.parse(msg);
const type = data.type;
switch (type) {
case "sitDown":
sitDown(conn, data);
break;
case "standUp":
standUp(conn, data);
break;
}
});
// 坐下
function sitDown(conn, data) {
const { color } = data;
if (color !== 1 && color !== 2) return;
// 已经有人了啥也不做
if (
(color === 1 && whitePlayer)
|| (color === 2 && blackPlayer)
) return;
// 已经有人了啥也不做 如果已经在座位则先下座
conn === whitePlayer && (whitePlayer = null);
conn === blackPlayer && (blackPlayer = null);
color === 1 ? (whitePlayer = conn) : (blackPlayer = conn);
broadcastRoom(); // 广播新的房间信息
}
// 坐下
function standUp(conn, data) {
const { color } = data;
if (color !== 1 && color !== 2) return;
color === 1 ? (whitePlayer = null) : (blackPlayer = null);
broadcastRoom(); // 广播新的房间信息
}
```
修改客户端之前的下棋函数, 点击下棋,给服务端发送消息,将行和列和自己的身份传送给后端
```javascript
/**
* 点击格子
* @param {MouseEvent} e
*/
function clickGrid(e) {
const grid = e.target;
if (identity !== color) return;
if (grid.color === 0) { // 如果是空白的
const { row, col } = grid;
sendJson({
type: "chess",
color: identity,
row, col,
});
}
}
```
在服务端同样根据type去更新局面信息,并将之前客户端的检查输赢函数放到服务端稍作修改
如果落完子之后判定游戏结束,则执行gameOver将结果传给客户端,并重置棋盘
```javascript
function chess(conn, data) {
const { color, row, col } = data;
if (color !== curColor) return;
if ((conn === whitePlayer && color !== 1)) return;
if ((conn === blackPlayer && color !== 2)) return;
mapData[row][col] = curColor;
curColor = 3 - curColor;
judge(); // 执行检查输赢
broadcastRoom();
}
/**
* 判断输赢和
*/
function judge() {
let draw = mapData[0][0];
for (let i = 0; i < 3; i++) {
let rowColor = mapData[i][0]; // 计算横竖输赢
let colColor = mapData[0][i];
draw *= mapData[i][0] * mapData[0][i]; // 计算和棋
for (let j = 1; j < 3; j++) {
rowColor &= mapData[i][j]; // 计算横竖输赢
colColor &= mapData[j][i];
draw *= mapData[i][j] * mapData[j][i]; // 计算和棋
}
if (rowColor || colColor) {
return gameOver(rowColor || colColor);
}
}
// 计算斜线输赢
const x1 = mapData[0][0] & mapData[1][1] & mapData[2][2];
const x2 = mapData[2][0] & mapData[1][1] & mapData[0][2];
if (x1 || x2) {
return gameOver(x1 || x2);
}
// 判断是否和棋
draw && gameOver(0);
}
/**
* 游戏结束
* @param {number} flag 结束标志 0 和棋, 1 白棋赢, 2 黑棋赢
*/
function gameOver(flag) {
broadcastJson({ type: "gameOver", flag });
reset();
}
/**
* 重设
*/
function reset() {
for (let row = 0; row < 3; row++) {
for (let col = 0; col < 3; col++) {
mapData[row][col] = 0;
}
}
curColor = 1;
}
```
在客户端中处理gameOver, 显示结束面板
```javascript
ws.onmessage = (event) => {
/* ... */
switch (type) {
/* ... */
case "gameOver":
gameOver(data.flag);
break;
}
}
```
...@@ -342,7 +342,7 @@ ...@@ -342,7 +342,7 @@
} else if (black === userId) { } else if (black === userId) {
identity = 2; identity = 2;
} else { } else {
identity = 3; identity = 0;
} }
updateMap(mapData); updateMap(mapData);
...@@ -385,10 +385,6 @@ ...@@ -385,10 +385,6 @@
updateData(data); updateData(data);
break; break;
case "onlineCount":
onlineUser.innerText = `${data.onlineCount}人在线`;
break;
case "gameOver": case "gameOver":
gameOver(data.flag); gameOver(data.flag);
break; break;
......
...@@ -183,16 +183,6 @@ const server = ws.createServer((conn) => { ...@@ -183,16 +183,6 @@ const server = ws.createServer((conn) => {
}); });
/**
* 广播在线人数
*/
function broadcastOnlineCount() {
broadcastJson({
type: "onlineCount",
onlineCount: server.connections.length
});
}
/** /**
* 广播JSON格式数据 * 广播JSON格式数据
* @param data * @param data
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment