Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Q
qiuxu_code
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
邱旭
qiuxu_code
Commits
718cca42
Commit
718cca42
authored
Jun 21, 2021
by
邱旭
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
默认变更列表
parent
938ee7fc
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
341 additions
and
16 deletions
+341
-16
02.井子棋对战版-联机功能.md
doc/02.井子棋对战版-联机功能.md
+340
-1
02_01.png
doc/img/02_01.png
+0
-0
井字棋对战版.html
src/client/井字棋对战版.html
+1
-5
server.js
src/server/server.js
+0
-10
No files found.
doc/02.井子棋对战版-联机功能.md
View file @
718cca42
...
@@ -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
;
}
}
```
doc/img/02_01.png
0 → 100644
View file @
718cca42
24.3 KB
src/client/井字棋对战版.html
View file @
718cca42
...
@@ -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
;
...
...
src/server/server.js
View file @
718cca42
...
@@ -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
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment