[网页五子棋][匹配模块]前后端交互接口(消息推送机制)、客户端开发(匹配页面、匹配功能)

news2025/6/3 12:11:11

让多个用户,在游戏大厅中能够进行匹配,系统会把实力相近的两个玩家凑成一桌,进行对战

约定前后端交互接口

消息推送机制

匹配这样的功能,也是依赖消息推送机制的

image.png

  • 玩家 1 点击开始匹配按钮,就会告诉服务器:我要开始进行匹配
  • 玩家发送匹配请求,这个事情是确定(点击了匹配按钮,就会发送匹配请求),服务器什么时候告知玩家匹配结果(你到你排到了谁),就需要等待匹配结束的时候才能告知
  • 正是因为服务器自己也不确定,什么时候能告知玩家匹配的结果,因此就需要依赖消息推送机制
    • 当服务器这里匹配成功之后,就主动的告诉当前排到的所有玩家,“你排到了”

这里就需要用到消息推送机制,也就是需要用到 websocket

  • 接下来约定和前后端交互接口,也都是基于 websocket 来展开的
  • 和前面的 HTTP 还是有点区别的

交互接口约定

websocket 可以传输文本数据,也能传输二进制数据。此处就直接设计成让 websocket 传输 JSON 格式的文本数据即可

匹配请求

  • 客户端通过 websocket 给服务器发送一个 JSON 格式的文本数据
    • ws://127.0.0.1:8080/findMatch
      {
      message: 'startMarch' / 'stopMatch' // 开始匹配/结束匹配
      }

在通过 websocket 传输请求数据的时候,数据中是不必带有用户身份信息的,当前用户的身份信息,在前面登录完成后,就已经保存到 HttpSession 中了。websocket 里,也是能拿到之前登录好的 HttpSession 中的信息的

匹配响应 1

ws://127.0.0.1:8080/Match
{
ok: true, // 匹配成功
reason: ‘’, // 匹配如果失败,失败原因的信息
message: ‘startMatch’ / ‘stopMatch’,
}

这个响应,是客户端给服务器发送请求之后,服务器立即返回的匹配响应

匹配响应 2

ws://127.0.0.1:8080/findMatch
{
ok: true.
reason: ‘’,
message: ‘matchSuccess’
}

这个响应是真正匹配到对手之后,服务器主动推送回来的信息

  • 匹配到的对手不需要在这个响应中体现,仍然都放到服务器这边来保存即可

客户端开发

匹配页面

image.png|508

game_hall. html

创建 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>

game_hall.css

.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;  
}

image.png|233

  • 当我们修改了 css 样式/ JS 文件之后,往往要在浏览器中使用 cmd+shift+R(Windows:ctrl+f5)强制刷新,才能生效
  • 否则浏览器可能仍然在执行旧版本的代码(浏览器自带缓存)

匹配功能

编辑 game_hall.htmljs 部分代码

  • 点击匹配按钮,就会进入匹配逻辑,同时按钮上提示“匹配中...(点击取消)”字样
  • 再次点击匹配按钮,则会取消匹配
  • 当匹配成功后,服务器会返回匹配成功的响应,页面跳转到 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.pares
  • JS 对象转换成 JSON 对象:JSON.stringify

JSON 字符串和 Java 对象的转换

  • JSON 字符串转换成 Java 对象:ObjectMapper.readValue
  • Java 对象转成 JSON 字符串:ObjectMapper.writeValueAsString

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2395457.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【数据分析】Matplotlib+Pandas+Seaborn绘图

【数据分析】MatplotlibPandasSeaborn绘图 &#xff08;一&#xff09;Matplotlib绘图1.1 matplotlib绘图方式1: 状态接口1.2 matplotlib绘图方式2: 面向对象1.3 通过安斯科姆数据集, 说明可视化的重要性1.4 MatPlotlib绘图-单变量-直方图1.5 MatPlotlib绘图-双变量-散点图1.6 …

NLP学习路线图(十五):TF-IDF(词频-逆文档频率)

在自然语言处理&#xff08;NLP&#xff09;的浩瀚宇宙中&#xff0c;TF-IDF&#xff08;词频-逆文档频率&#xff09; 犹如一颗恒星&#xff0c;虽古老却依然璀璨。当ChatGPT、BERT等大模型光芒四射时&#xff0c;TF-IDF作为传统方法的代表&#xff0c;其简洁性、高效性与可解…

[Redis] Redis命令在Pycharm中的使用

初次学习&#xff0c;如有错误还请指正 目录 String命令 Hash命令 List命令 set命令 SortedSet命令 连接pycharm的过程见&#xff1a;[Redis] 在Linux中安装Redis并连接桌面客户端或Pycharm-CSDN博客 redis命令的使用见&#xff1a;[Redis] Redis命令&#xff08;1&#xf…

openpnp - 给M4x0.7mm的直油嘴加油的工具选择

文章目录 openpnp - 给M4x0.7mm的直油嘴加油的工具选择概述如果换上带卡口的M4x0.7直油嘴END openpnp - 给M4x0.7mm的直油嘴加油的工具选择 概述 X导轨用了一个HG15的滑块 滑块上的注油口的黄油嘴是M4x0.7mm的直油嘴。 外表面是6边形的柱子&#xff0c;没有可以卡住加油嘴工…

EasyExcel复杂Excel导出

效果图展示 1、引入依赖 <!-- easyExcel --> <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>4.0.2</version> </dependency>2、实体类 import com.alibaba.excel.annotatio…

1,QT的编译教程

目录 整体流程: 1,新建project文件 2,编写源代码 3,打开QT的命令行窗口 4,生成工程文件(QT_demo.pro) 5,生成Make file 6,编译工程 7,运行编译好的可执行文件 整体流程: 1,新建project文件 新建文本文件,后缀改为.cpp 2,编写源代码

【笔记】在 MSYS2(MINGW64)中安装 Python 工具链的记录

#工作记录 &#x1f4cc; 安装背景 操作系统&#xff1a;MSYS2 MINGW64当前时间&#xff1a;2025年6月1日Python 版本&#xff1a;3.12&#xff08;默认通过 pacman 安装&#xff09;目标工具链&#xff1a; pipxnumpypipsetuptoolswheel &#x1f6e0;️ 安装过程与结果记录…

Linux 学习-模拟实现【简易版bash】

1、bash本质 在模拟实现前&#xff0c;先得了解 bash 的本质 bash 也是一个进程&#xff0c;并且是不断运行中的进程 证明&#xff1a;常显示的命令输入提示符就是 bash 不断打印输出的结果 输入指令后&#xff0c;bash 会创建子进程&#xff0c;并进行程序替换 证明&#x…

【中国・珠海】2025 物联网与边缘计算国际研讨会(IoTEC2025)盛大来袭!

2025 物联网与边缘计算国际研讨会&#xff08;IoTEC2025&#xff09;盛大来袭&#xff01; 科技浪潮奔涌向前&#xff0c;物联网与边缘计算已成为驱动各行业变革的核心力量。在此背景下&#xff0c;2025 物联网与边缘计算国际研讨会&#xff08;IoTEC2025&#xff09;即将震撼…

中国高分辨率高质量地面CO数据集(2013-2023)

时间分辨率&#xff1a;日空间分辨率&#xff1a;1km - 10km共享方式&#xff1a;开放获取数据大小&#xff1a;9.83 GB数据时间范围&#xff1a;2013-01-01 — 2023-12-31元数据更新时间&#xff1a;2024-08-19 数据集摘要 ChinaHighCO数据集是中国高分辨率高质量近地表空气污…

GO——内存逃逸分析

一、可能导致逃逸的5中情况 package mainimport "fmt"func main() {f1()f2()f3()f4()f5() }type animal interface {run() }type dog struct{}func (d *dog) run() {fmt.Println("狗在跑") }// 指针、map、切片为返回值的会发生内存逃逸 func f1() (*int,…

MinVerse 3D触觉鼠标的技术原理与创新解析

MinVerse3D触觉鼠标通过三维交互和触觉反馈技术&#xff0c;彻底颠覆了传统二维鼠标的操作方式。用户在操作虚拟物体时&#xff0c;可以真实感知表面质感、重量和阻力。这种技术不仅为数字环境注入了深度与临场感&#xff0c;还在3D设计、游戏开发和工程仿真等领域展现了广泛潜…

乾元通渠道商中标青海省自然灾害应急能力提升工程基层防灾项目

近日&#xff0c;乾元通渠道商中标青海省自然灾害应急能力提升工程基层防灾项目&#xff0c;乾元通作为设备厂家&#xff0c;为项目提供通信指挥类装备&#xff08;多链路聚合设备&#xff09;QYT-X1。 青岛乾元通数码科技有限公司作为国家应急产业企业&#xff0c;深耕于数据调…

openssl-aes-ctr使用openmp加速

openssl-aes-ctr使用openmp加速 openssl-aes-ctropenmp omp for openssl-aes-ctr 本文采用openssl-1.1.1w进行开发验证开发&#xff1b;因为aes-ctr加解密模式中&#xff0c;不依赖与上一个模块的加/解密的内容&#xff0c;所以对于aes-ctr加解密模式是比较适合进行并行加速的…

PHP+MySQL开发语言 在线下单订水送水小程序源码及搭建指南

随着互联网技术的不断发展&#xff0c;在线下单订水送水服务为人们所需要。分享一款 PHP 和 MySQL 搭建一个功能完善的在线订水送水小程序源码及搭建教程。这个系统将包含用户端和管理端两部分&#xff0c;用户可以在线下单、查询订单状态&#xff0c;管理员可以处理订单、管理…

计算机网络第1章(上):网络组成与三种交换方式全解析

目录 一、计算机网络的概念二、计算机网络的组成和功能2.1 计算机网络的组成2.2 计算机网络的功能 三、电路交换、报文交换、分组交换3.1 电路交换&#xff08;Circuit Switching&#xff09;3.2 报文交换&#xff08;Message Switching&#xff09;3.3 分组交换&#xff08;Pa…

Android studio进阶开发(七)---做一个完整的登录系统(前后端连接)

我们已经讲过了okhttp和登录系统的使用&#xff0c;我们今天做一个完整的登录系统&#xff0c;后端用springmybatis去做 数据库内容 -- 创建学生信息表 CREATE TABLE student_info (id SERIAL PRIMARY KEY, -- 添加自增主键name VARCHAR(255) NOT NULL,number INT NOT NULL,…

计算机网络第1章(下):网络性能指标与分层模型全面解析

目录 一、计算机网络的性能指标1.1 性能指标1&#xff1a;速率1.2 性能指标2&#xff1a;带宽1.3 性能指标3&#xff1a;吞吐量1.4 性能指标4&#xff1a;时延1.5 性能指标5&#xff1a;时延带宽积1.6 性能指标6&#xff1a;往返时延1.7 性能指标7&#xff1a;信道利用率 二、计…

恶意软件清理工具,让Mac电脑安全更简单

​你的Mac最近是不是开始表演"电子迷惑行为"&#xff1f;浏览器主页突然变成澳门赌场&#xff0c;风扇转得比直升机螺旋桨还猛......恭喜你&#xff01;可能中奖获得"恶意软件大礼包"&#xff01;别慌&#xff0c;今天就教你用恶意软件清理工具化身数字特工…

HackMyVM-Jabita

信息搜集 主机发现 ┌──(kali㉿kali)-[~] └─$ nmap -sn 192.168.43.0/24 Starting Nmap 7.95 ( https://nmap.org ) at 2025-06-01 05:20 EDT Nmap scan report for 192.168.43.1 Host is up (0.020s latency). MAC Address: C6:45:66:05:91:88 (Unknown) Nmap scan repo…