[网页五子棋][对战模块]前后端交互接口(建立连接、连接响应、落子请求/响应),客户端开发(实现棋盘/棋子绘制)

news2025/6/2 8:07:26

文章目录

  • 约定前后端交互接口
    • 建立连接
    • 建立连接响应
    • 针对"落子"的请求和响应
  • 客户端开发
    • 实现棋盘/棋子绘制
    • 部分逻辑解释

约定前后端交互接口

对战模块和匹配模块使用的是两套逻辑,使用不同的 websocket 的路径进行处理,做到更好的耦合

建立连接

ws://127.0.0. 1:8080/game

建立连接响应

服务器要生成一些游戏的初始信息,通过这个响应告诉客户端

{
	message: 'gameReady',  // 消息的类别:游戏就绪
	ok: true,
	reason: '',
	roomId: '12345678',    // 玩家所处在的房间id
	thisUserId: 1,         // 玩家自己的id
	thatUserId: 2,         // 玩家的对手的id
	whiteUser: 1           // 哪个玩家执白字(先手)
};
  • 这些都是玩家匹配成功之后,要由服务器生成的,然后把这个内容返回给浏览器

针对"落子"的请求和响应

请求:

{
	message: 'putChess',
	userId: 1,
	row: 0,        // 落子的坐标,往哪一行,哪一列来落子
}
  • 建议使用行和列,而不是 xy
    • row => ycol => x
    • 后面的代码中,需要使用二维数组来表示这个棋盘,通过下标取二维数组
    • [row] => [y][col] => [x]
    • 如果使用 xy,就很别扭,和我们日常表示相悖

响应:

{
	message: 'putChess',
	userId: 1,
	row: 0,
	col: 0,
	winner: 0
}
  • winner 表示当前是否分出胜负
    • 如果 winner0,表示胜负未分,还需要继续往下对战
    • 如果 winner0,表示当前的获胜方的用户 id

以上交互接口的设计,其实也不一定非得按照刚才这样写的这种格式来进行约定,也可以有其他的约定方式

  • 不管是哪种格式,只要能够解决我们的问题,并且编写代码的时候简单方便即可

客户端开发

实现棋盘/棋子绘制

创建 js/app.js

  • 我们不需要理解这部分内容,只需要复制粘贴即可
  • 使用一个二维数组来表示棋盘。虽然胜负是通过服务器判定的,但是客户端的棋盘可以避免“一个位置重复落子”这样的情况
  • oneStep 函数起到的效果是在一个指定的位置上绘制一个棋子,可以区分出绘制白子还是黑子,参数是横坐标和纵坐标,分别对应行和列
  • onlick 来处理用户点击事件,当用户点击的时候通过这个函数来控制绘制棋子
  • me 变量用来表示当前是否轮到我落子;over 变量用来表示游戏结束
  • 这个代码中会用到一个背景图,放到 image 目录中即可
// 定义全局变量,表示游戏初始化信息
let gameInfo = {  
    roomId: null,  
    thisUserId: null,  
    thatUserId: null,  
    isWhite: true,  
}  
  
//  
// 设定界面显示相关操作  
//  
  
function setScreenText(me) {  
    let screen = document.querySelector('#screen');  
    if (me) {  
        screen.innerHTML = "轮到你落子了!";  
    } else {  
        screen.innerHTML = "轮到对方落子了!";  
    }  
}  
  
//  
// 初始化 websocket//  
  
// TODO  
  
//  
// 初始化一局游戏  
//  
function initGame() {  
    // 是我下还是对方下. 根据服务器分配的先后手情况决定  
    let me = gameInfo.isWhite;  
    // 游戏是否结束  
    let over = false;  
    let chessBoard = [];  
    //初始化chessBord数组(表示棋盘的数组)  
    for (let i = 0; i < 15; i++) {  
        chessBoard[i] = [];  
        for (let j = 0; j < 15; j++) {  
            chessBoard[i][j] = 0;  
        }  
    }  
    let chess = document.querySelector('#chess');  
    let context = chess.getContext('2d');  
    context.strokeStyle = "#BFBFBF";  
    // 背景图片  
    let logo = new Image();  
    logo.src = "image/五子棋棋盘.jpg"  
    logo.onload = function () {  
        context.drawImage(logo, 0, 0, 450, 450);  
        initChessBoard();  
    }  
  
    // 绘制棋盘网格  
    function initChessBoard() {  
        for (let i = 0; i < 15; i++) {  
            context.moveTo(15 + i * 30, 15);  
            context.lineTo(15 + i * 30, 430);  
            context.stroke();  
            context.moveTo(15, 15 + i * 30);  
            context.lineTo(435, 15 + i * 30);  
            context.stroke();  
        }  
    }  
  
    // 绘制一个棋子, me 为 true    function oneStep(i, j, isWhite) {  
        context.beginPath();  
        context.arc(15 + i * 30, 15 + j * 30, 13, 0, 2 * Math.PI);  
        context.closePath();  
        var gradient = context.createRadialGradient(15 + i * 30 + 2, 15 + j * 30 - 2, 13, 15 + i * 30 + 2, 15 + j * 30 - 2, 0);  
        if (!isWhite) {  
            gradient.addColorStop(0, "#0A0A0A");  
            gradient.addColorStop(1, "#636766");  
        } else {  
            gradient.addColorStop(0, "#D1D1D1");  
            gradient.addColorStop(1, "#F9F9F9");  
        }  
        context.fillStyle = gradient;  
        context.fill();  
    }  
  
    chess.onclick = function (e) {  
        if (over) {  
            return;  
        }  
        if (!me) {  
            return;  
        }  
        let x = e.offsetX;  
        let y = e.offsetY;  
        // 注意, 横坐标是列, 纵坐标是行  
        let col = Math.floor(x / 30);  
        let row = Math.floor(y / 30);  
        if (chessBoard[row][col] == 0) {  
            // 发送坐标给服务器, 服务器要返回结果  
            send(row, col);  
  
            // 留到浏览器收到落子响应的时候再处理(收到响应再来画棋子)  
            oneStep(col, row, gameInfo.isWhite);  
            chessBoard[row][col] = 1;  
        }  
    }  
  
    // TODO 实现发送落子请求逻辑和处理落子响应逻辑  
}  
  
initGame();

canvasHTML5 引入的一个标签,画布

  • “可以在画布上画画”
  • 此处棋盘和棋子,都是画上去的。canvas 这个标签有一组配套的 jscanvas api,通过这个 api 就可以实现一些“画画”的效果
    • 例如,展示一个棋盘,就画很多的直线,就能构成棋盘的网格
    • 表示一个棋子,就画一个圆圈,并填充上颜色
    • 还需要响应点击事件,在鼠标落子的地方来画圆圈
  • canvas api 里面能做的事情比较多,比较复杂,不是重点

部分逻辑解释

image.png|337

  • 表示当前游戏中的棋盘,通过这个棋盘来表示当前哪个位置上有子了
  • 当玩家点击的时候,如果有子的位置就不能再继续落子了
  • 0 用来表示是空闲位置,非 0 表示已经有子了

image.png|334

  • 针对 chess (棋盘 canvas) 设定了点击回调
  • e 是点击回调中的事件参数,这里就会记录点击的实际位置 (坐标)
  • Math.floor(x/30) 是为了让点击操作能够对应到网格线上
    • 总体的棋盘尺寸是 450px * 450px,整个棋盘上面是 15行15列
    • 每一行每一列占用的尺寸就是 30px
  • oneStep 就是走一步 (里面绘制一个棋子)
  • 标记为 1,就是这个位置有子,不能落子了

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

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

相关文章

【ArcGIS Pro微课1000例】0071:将无人机照片生成航线、轨迹点、坐标高程、方位角

文章目录 一、照片预览二、生成轨迹点三、照片信息四、查看方位角五、轨迹点连成线一、照片预览 数据位于配套实验数据包中的0071.rar,解压之后如下: 二、生成轨迹点 地理标记照片转点 (数据管理),用于根据存储在地理标记照片文件(.jpg 或 .tif)元数据中的 x、y 和 z 坐…

Ubuntu Zabbix 钉钉报警

文章目录 概要Zabbix警监控脚本技术细节配置zabbix告警 概要 提示&#xff1a;本教程用于Ubuntu &#xff0c;zabbix7.0 Zabbix警监控脚本 提示&#xff1a;需要创建一个脚本 #检查是否有 python3 和版本 rootzabbix:~# python3 --version Python 3.12.3在/usr/lib/zabbix/…

threejs顶点UV坐标、纹理贴图

1. 创建纹理贴图 通过纹理贴图加载器TextureLoader的load()方法加载一张图片可以返回一个纹理对象Texture&#xff0c;纹理对象Texture可以作为模型材质颜色贴图.map属性的值。 const geometry new THREE.PlaneGeometry(200, 100); //纹理贴图加载器TextureLoader const te…

STM32 RTC实时时钟\BKP备份寄存器\时间戳

一、Unix时间戳 想要计算当地北京时间&#xff0c;需要根据经度和闰年之类的运算得到(c语言里面可以调用time.h的函数) 二、UTC/GMT&#xff08;科普&#xff09; 三、时间戳转化 C语言的time.h模块提供了时间获取和时间戳转换的相关函数&#xff0c;可以方便的进行秒计数器、…

Axure设计案例——科技感立体柱状图

想让你的数据展示告别平淡无奇&#xff0c;成为吸引全场目光的焦点吗&#xff1f;快来瞧瞧这个Axure设计的科技感立体柱状图案例&#xff01;科技感设计风格借助逼真的立体效果打破传统柱状图的平面感&#xff0c;营造出一种令人眼前一亮的视觉震撼。每一个柱状体都仿佛是真实存…

app获取相册权限是否意味着所有相片都可随时读取?

针对安卓手机相册的隐私安全问题&#xff0c;我也比较好奇&#xff0c;App授予了相册权限&#xff0c;真的能自动读取用户的照片吗&#xff1f;最近做了一个小实验&#xff0c;我开发了2个小App&#xff0c;这2个App安装的时候只授予了相册权限&#xff0c;没有授予其他任何权限…

2025年05月29日Github流行趋势

项目名称&#xff1a;agenticSeek 项目地址url&#xff1a;https://github.com/Fosowl/agenticSeek项目语言&#xff1a;Python历史star数&#xff1a;11898今日star数&#xff1a;2379项目维护者&#xff1a;Fosowl, steveh8758, klimentij, ganeshnikhil, apps/copilot-pull-…

第十一节:第一部分:正则表达式:应用案例、爬取信息、搜索替换

正则表达式介绍 String提供的正则表达式的方法的书写规则 正则表达式总结 正则表达式作用&#xff1a; 作用三&#xff1a;搜索替换 案例分析及代码&#xff08;图片解析&#xff09; 代码&#xff1a; 代码一&#xff1a;校验手机号和邮箱格式是否正确 package com.itheima.…

新能源集群划分+电压调节!基于分布式能源集群划分的电压调节策略!

适用平台&#xff1a;MatlabYalmip Cplex (具体操作已在程序文件中说明) 参考文献&#xff1a;基于分布式能源集群化分的电压调节策略[D]. 一、文献解读 1. 主要内容/创新点 提出了一种基于分布式能源集群化的电压调节策略&#xff0c;计及分布式能源的有功、无功调节能力&a…

端午安康 | 以匠心,致长远

端午节快乐 值此端午佳节&#xff0c;数图衷心感谢每一位合作伙伴与客户的信任相伴。 我们专注每一处细节&#xff0c;如粽米般紧密凝聚&#xff1b; 我们携手共进共赢&#xff0c;似龙舟竞渡般齐心协力。 未来&#xff0c;我们愿继续以创新为桨&#xff0c;与您共划时代新篇…

漫画Android:事件分发的过程是怎样的?

当用户触摸屏幕时&#xff0c;硬件层会捕获触摸信号&#xff0c;并将其转化为内核事件。 Android系统会通过InputManagerService和WindowManagerService等服务将这些事件包装成MotionEvent对象&#xff0c;并将其传递给Activity的dispatchTouchEvent()方法中&#xff0c;Activi…

2022 RoboCom 世界机器人开发者大赛-本科组(省赛)解题报告 | 珂学家

前言 题解 2022 RoboCom 世界机器人开发者大赛-本科组&#xff08;省赛&#xff09;。 感觉T5是最简单的&#xff0c;其他都不好做。 RC-u5 树与二分图 分值: 30分 思路: 容斥原理 树天然就是二分图&#xff0c;按深度d归类(偶数深度为S1&#xff0c;奇数深度为S2)&#x…

如何用ChatGPT提升学术长文质量

目录 一、关于让人工智能充当评审专家 二、关于分批次输入论文内容 三、来看看提示词 大家好这里是学术Anan&#xff0c;官网&#x1f449;AIWritePaper~ 论文完成初稿之后&#xff0c;一般情况下&#xff0c;宝子们还需要找专家给我们提出评审意见。找专家评审其实并不容易…

BKP(备份寄存器)和 RTC(实时时钟)

什么是BKP&#xff1f; 备份寄存器&#xff08;BackupRegister&#xff09;是42个16位的寄存器&#xff08;不同设备存在差异&#xff1a;20字节&#xff08;中容量和小容量&#xff09;/84字节&#xff08;大容量和互联型&#xff09;&#xff09;&#xff0c;可用来存储 最多…

【EdgeYOLO】《EdgeYOLO: An Edge-Real-Time Object Detector》

Liu S, Zha J, Sun J, et al. EdgeYOLO: An edge-real-time object detector[C]//2023 42nd Chinese Control Conference (CCC). IEEE, 2023: 7507-7512. CCC-2023 源码&#xff1a;https://github.com/LSH9832/edgeyolo 论文&#xff1a;https://arxiv.org/pdf/2302.07483 …

调试技巧总结

目录 一.调试1.什么是调试2.调试语义的分类2.1 静态语义2.2 动态语义 二.实用的调试技巧1.屏蔽代码2.借助打印3.查看汇编代码4.调试技巧总结 一.调试 1.什么是调试 调试&#xff0c;通俗易懂地说就是不断排查代码的错误&#xff0c;进行修正的过程&#xff0c;在写代码的时候…

ubuntu安装blender并配置应用程序图标

ubuntu安装blender并配置应用程序图标 下载blender安装包解压缩并安装启动blender添加应用程序启动图标 下载blender安装包 blender中文服务站的下载网址 这里选择Linux 64位的Blender 4.2.4 LTS。下载速度很快。下载得到 解压缩并安装 将下载的压缩包放在/opt目录下&#…

基于LBS的上门代厨APP开发全流程解析

上门做饭将会取代外卖行业成为新一轮的创业风口吗&#xff1f;杭州一位女士的3菜一汤88元套餐引爆社交网络&#xff0c;这个包含做饭、洗碗、收拾厨房的全套服务&#xff0c;正在重新定义"到家经济"的边界。当25岁的研究生系着围裙出现在客户厨房&#xff0c;当年轻姑…

Redisson学习专栏(三):高级特性与实战(Spring/Spring Boot 集成,响应式编程,分布式服务,性能优化)

文章目录 前言一、Spring Boot深度整合实战1.1 分布式缓存管理1.2 声明式缓存1.3 响应式编程 二、分布式服务治理2.1 服务端实现2.2 客户端调用2.3 高级特性2.4 服务治理功能 三、分布式任务调度引擎四、连接池配置与网络参数调优4.1 连接池配置4.2 网络参数调优4.3 集群模式特…

华为欧拉系统中部署FTP服务与Filestash应用:实现高效文件管理和共享

华为欧拉系统中部署FTP服务与Filestash应用:实现高效文件管理和共享 前言一、相关服务介绍1.1 Huawei Cloud EulerOS介绍1.2 Filestash介绍1.3 华为云Flexus应用服务器L实例介绍二、本次实践介绍2.1 本次实践介绍2.2 本次环境规划三、检查云服务器环境3.1 登录华为云3.2 SSH远…