
让多个用户,在游戏大厅中能够进行匹配,系统会把实力相近的两个玩家凑成一桌,进行对战
匹配这样的功能,也是依赖消息推送机制的

这里就需要用到消息推送机制,也就是需要用到 websocket
websocket 来展开的websocket 可以传输文本数据,也能传输二进制数据。此处就直接设计成让 websocket 传输 JSON 格式的文本数据即可
websocket 给服务器发送一个 JSON 格式的文本数据 ws://127.0.0.1:8080/findMatch
{
message: 'startMarch' / 'stopMatch' // 开始匹配/结束匹配
}在通过 websocket 传输请求数据的时候,数据中是不必带有用户身份信息的,当前用户的身份信息,在前面登录完成后,就已经保存到 HttpSession 中了。websocket 里,也是能拿到之前登录好的 HttpSession 中的信息的
ws://127.0.0.1:8080/Match
{
ok: true, // 匹配成功
reason: ‘’, // 匹配如果失败,失败原因的信息
message: ‘startMatch’ / ‘stopMatch’,
}
这个响应,是客户端给服务器发送请求之后,服务器立即返回的匹配响应
ws://127.0.0.1:8080/findMatch
{
ok: true.
reason: ‘’,
message: ‘matchSuccess’
}
这个响应是真正匹配到对手之后,服务器主动推送回来的信息

创建 game_hall. html,主要包含
#screen 用于显示玩家的分数信息button#match-button 作为匹配按钮<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>游戏大厅</title>
<link rel="stylesheet" href="css/common.css">
<link rel="stylesheet" href="css/game_hall.css">
</head>
<body>
<div class="nav">五子棋对战</div>
<!-- 整个页面的容器元素 -->
<div class="container">
<!-- 这个 div 在 container 中是处于垂直水平居中这样的位置 -->
<div>
<!-- 展示用户信息 -->
<div id="screen"></div>
<!-- 匹配按钮 -->
<div id="match-button">开始匹配</div>
</div> </div> <script src="js/jquery.min.js"></script>
<script> $.ajax({
type: 'get',
url: '/userInfo',
success: function(body) {
// 将 user 对喜爱那个添加到页面的显示内容中
let screenDiv = document.querySelector("#screen");
screenDiv.innerHTML = '玩家: ' + body.username + '分数: ' + body.score
+ "<br> 比赛场次: " + body.totalCount + "获胜场次: " + body.winCount;
},
error: function() {
alert("获取用户信息失败!")
}
})
</script>
</body>
</html>.container {
width: 100%;
height: calc(100% - 50px);
display: flex;
align-items: center;
justify-content: center;
}
#screen {
width: 400px;
height: 200px;
font-size: 20px;
background-color: gray;
color: white;
border-radius: 10px;
text-align: center;
line-height: 100px;
}
#match-button {
width: 400px;
height: 50px;
font-size: 20px;
color: white;
background-color: orange;
border: none;
outline: none;
border-radius: 10px;
text-align: center;
line-height: 50px;
margin-top: 20px;
}
#match-button:active {
background-color: gray;
}
css 样式/ JS 文件之后,往往要在浏览器中使用 cmd+shift+R(Windows:ctrl+f5)强制刷新,才能生效编辑 game_hall.html 的 js 部分代码
匹配中...(点击取消)”字样game_room.html<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>游戏大厅</title>
<link rel="stylesheet" href="css/common.css">
<link rel="stylesheet" href="css/game_hall.css">
</head>
<body>
<div class="nav">五子棋对战</div>
<!-- 整个页面的容器元素 -->
<div class="container">
<!-- 这个 div 在 container 中是处于垂直水平居中这样的位置 -->
<div>
<!-- 展示用户信息 -->
<div id="screen"></div>
<!-- 匹配按钮 -->
<div id="match-button">开始匹配</div>
</div> </div> <script src="js/jquery.min.js"></script>
<script>
$.ajax({
type: 'get',
url: '/userInfo',
success: function(body) {
// 将 user 对喜爱那个添加到页面的显示内容中
let screenDiv = document.querySelector("#screen");
screenDiv.innerHTML = '玩家: ' + body.username + '分数: ' + body.score
+ "<br> 比赛场次: " + body.totalCount + "获胜场次: " + body.winCount;
},
error: function() {
alert("获取用户信息失败!")
}
});
// 此处进行初始化 websocket,并且实现前端匹配逻辑
// 此处的路径必须写作 /findMatch,千万不要写作 /findMatch/ let websocket = new websocket('ws://127.0.0.1:8080/findMatch');
websocket.onopen = function() {
console.log("onopen");
}
websocket.onclose = function() {
console.log("onclose");
}
websocket.onerror = function() {
console.log("onerror");
}
// 监听页面关闭事件,在页面关闭之前,手动调用这里 websocket 的 close 方法
window.onbeforeunload = function() {
websocket.close();
}
// 一会重点来实现,要处理服务器返回的响应
websocket.onmessage = function(e) {
// 处理服务器返回的响应数据,这个响应就是针对“开始匹配”/“结束匹配”来对应的
// 解析得到的响应对象,返回的数据是一个 JSON 字符串,解析成 js 对象
let resp = JSON.parse(e.data);
let match-button = document.querySelector('#match-button');
if (!resp.ok) {
console.log("游戏大厅中接收到了失败响应!" + resp.reason);
return;
}
if (resp.message == 'startMatch') {
// 开始匹配请求发送成功
console.log("进入匹配队列成功!");
matchButton.innerHTML = '匹配中...(点击停止)';
}else if(resp.message == 'stopMatch') {
// 结束匹配请求发送成功
console.log("离开匹配队列成功!");
matchButton.innerHTML = '开始匹配';
}else if(resp.message == 'matchSuccess') {
// 已经匹配到对手了
console.log("匹配到对手! 进入游戏房间!");
location.assign('/game_room.html');
}else {
console.log("收到了非法的响应! message=" + resp.message);
}
}
// 给匹配按钮添加一个点击事件
let matchButton = document.querySelector('#match-button');
matchButton.onclick - function() {
// 在触发 websocket 请求之前,先确认下 websocket 连接是否好着
if (websocket.readyState == websocket.OPEN) {
// 如果当前 redyState 处于 OPEN 状态,说明连接好着的
// 这里发送的数据有两种可能,开始匹配/停止匹配
if (matchButton.innerHTML == '开始匹配') {
console.log("开始匹配");
websocket.send(JSON.stringify({
message: 'startMatch',
}));
} else if (matchButton.innerHTML == '匹配中...(点击停止)') {
console.log("停止匹配");
websocket.send(JSON.stringify({
message: 'stopMatch',
}));
}
}else {
// 这是说明连接当前是异常状态
alert("当前您的连接已经断开!请重新登录!");
location.assign('/login.html');
}
}
</script>
</body>
</html>36 行开始
JSON字符串和JS对象的转换
JSON 字符串转换成 JS 对象:JSON.paresJS 对象转换成 JSON 对象:JSON.stringify
JSON字符串和Java对象的转换
JSON 字符串转换成 Java 对象:ObjectMapper.readValueJava 对象转成 JSON 字符串:ObjectMapper.writeValueAsString