主要通过js、canvas、node、websocket来实现五子棋游戏。

tip:如果你想清楚的了解怎么实现,请一步步看思路流程,文章最后有项目的gitee地址、对应B站视频,可直接食用。

首先搭建一个express服务:

const express = require('express')
const path = require('path')
const app = express()
//静态资源目录
app.use(express.static(path.join(__dirname, 'public')));
let port = 3003
app.get('/home', (req, res, next) => {res.writeHead(200, { 'Content-type': 'text/html;charset=utf-8' })res.end('欢迎来到express')next()
})const server = app.listen(port, () => { console.log('成功启动express服务,端口号是' + port) })

这个时候我们可以访问静态文件里面的文件了,如:

public下面的index.html在访问3003/的时候在浏览器渲染。

这也说明了我们的node服务启动成功,接口在3003端口上。

前端页面,里面包括css\html但是不包括js,只是引入js文件:

<!-- 2021/5/15 -->
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><link rel="icon" type="image/jpg" href="./ipc.jpg"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>五子棋</title><style>* {padding: 0;margin: 0;}html,body {width: 100%;height: 100%;overflow: hidden;}canvas {margin-top: 200px;margin-left: 300px;background-color: rgb(213, 176, 146);display: inline-block;border-radius: 8px;border: 1px solid black;}.resultBox {position: absolute;text-align: center;top: 200px;left: 760px;width: 200px;height: 450px;/* background-color: #ccc; */background-color: rgb(213, 176, 146);color: 38px;line-height: 60px;font-weight: bold;}</style>
</head><body><div class="box"><canvas id="canvas"></canvas><div class="resultBox"><p class="redP">白旗已下0</p><p class="blackP">黑旗已下0</p><p class="resultP"></p></div></div><!-- 通过script的方式引入 soctke.io --><script  defer crossorigin="anonymous"integrity="sha512-PU5S6BA03fRv1Q5fpwXjg5nlRrgdoguZ74urFInkbABMCENyx5oP3hrDzYMMPh3qdLdknIvrGj3yqZ4JuU7Nag=="src="https://lib.baomitu.com/socket.io/4.1.3/socket.io.js"></script>//低版本  不再使用<!-- <script src="https://cdn.bootcss.com/socket.io/2.2.0/socket.io.js"></script> --><script defer src="./wuziqi.js"></script>
</body></html>

1:生成棋盘

2:生成棋子

3:棋子落点

4:五子成线 ?赢 :输

流程:

1.页面:渲染完成,输入房间号
2.选择白棋 、 黑棋
3.选择白棋后先下 黑棋有了白棋才能下
4.一方胜利,游戏结束。

页面加载后开始连接服务器。 控制台打印连接成功。输入房间号。

房间号里面只能容纳两个人,多余的人为观众,不可控制器盘的棋子

棋盘构造函数

  //线条构造函数//线条颜色 x yfunction Line(color, x, y) {this.color = color;this.x = xthis.y = y}//画横线Line.prototype.getXLine = function () {ctx.lineWidth = 1;ctx.beginPath();ctx.moveTo(0, this.y);ctx.lineTo(this.x, this.y);ctx.strokeStyle = this.color;ctx.closePath();ctx.fill();ctx.stroke();}//画竖线Line.prototype.getYLine = function () {ctx.lineWidth = 1;ctx.beginPath();ctx.moveTo(this.x, 0);ctx.strokeStyle = this.color;ctx.lineTo(this.x, this.y);ctx.closePath();ctx.fill();ctx.stroke();}//线条相隔大小 后面 num += flaglet num = 0//线条随机颜色数组// let colorsList = ["#33B5E5", "#0099CC", "#AA66CC", "#9933CC", "#99CC00", "#669900", "#FFBB33", "#FF8800", "#FF4444", "#CC0000"]//循环画线for (let i = 0; i <= canvas.width; i += flag) {// let colorx = colorsList[Math.floor(Math.random() * 10)]// let colory = colorsList[Math.floor(Math.random() * 10)]let colorx, colorycolorx = colory = 'black'getXLineArr.push(new Line(colorx, canvas.width, num))getYLineArr.push(new Line(colory, num, canvas.width))num += flag}//画横线getXLineArr.map(item => {item.getXLine()})//画竖线getYLineArr.map(item => {item.getYLine()})

棋子构造函数

function Chessman(x, y, color) {this.x = xthis.y = ythis.color = color
}
Chessman.prototype.update = function () {ctx.save();ctx.beginPath()ctx.fillStyle = this.color// 背景颜色为白色ctx.arc(this.x, this.y, 20, 0, Math.PI * 2, false)ctx.fill()ctx.closePath()
}

棋子落在棋盘

选择白棋 黑棋,每点击一次棋盘会进行判断是否是该你下棋子

     //当前点击的坐标  相对于canvas的坐标let arr = [e.clientX - MarginLeftNum, e.clientY - MarginTopNum]//当前点击坐标到 棋盘 0,0 的距离// let newArrLong = Math.sqrt((0 - arr[0]) * (0 - arr[0]) + (0 - arr[1]) * (0 - arr[1]))//25let newArrLong = flag / 2newARR = []//循环判断当前点击坐标到哪个棋盘坐标的距离最短,棋子放置到该坐标点lineXAndlineYArr.map((item, index) => {let newArrLongA = Math.sqrt((item[0] - arr[0]) * (item[0] - arr[0]) + (item[1] - arr[1]) * (item[1] - arr[1]))if (newArrLongA <= newArrLong) {newARR = item; newArrLong = newArrLongA}})

//看能不能落子

     //白if (redOrBlackFlag === 1) {if (blackOrRedChessman % 2 !== 0) {return false}console.log("%c当前点击棋子坐标:", "color:red;font-size:20px;", newARR)} else {//黑if (blackOrRedChessman % 2 == 0) {return false}console.log("%c当前点击棋子坐标:", "color:red;font-size:20px;", newARR)}

随后查看该点是否已经有了棋子

    //判断该点是否已经有棋子let hasYesOrNo = JSON.stringify(hasChessmanArrList).includes(JSONstringify(newARR))if (!hasYesOrNo) {//没有的话加入棋子数组hasChessmanArrList.push(newARR)}else {alert('已经有棋子')return}

棋子落子后触发服务器棋子位子更新

//lineXAndlineYArrRed 白棋
//lineXAndlineYArrBlack 黑棋
//lineXAndlineYArrBlack 黑棋
//blackOrRedChessman 棋子数量

 const sendItemsArr = JSON.stringify({ lineXAndlineYArrRed, lineXAndlineYArrBlack, hasChessmanArrList, blackOrRedChessman })mySocket.emit('sendItemsArr', sendItemsArr)

服务器派发另一个人更新棋子位置

    websocketObj.on('sendItemsArr', (sendItemsArr) => {itemsArr = sendItemsArr//触发所以的 sendFunEventCallBack 事件  让前端监听io.sockets.emit("getItemsArr", itemsArr);})

前端接受最新的棋子位置:

//websocket
mySocket.on('getItemsArr', (getItemsArr) => {const ItemsArr = JSON.parse(getItemsArr)lineXAndlineYArrRed = ItemsArr.lineXAndlineYArrRedlineXAndlineYArrBlack = ItemsArr.lineXAndlineYArrBlackhasChessmanArrList = ItemsArr.hasChessmanArrListblackOrRedChessman = ++ItemsArr.blackOrRedChessman// 判断这次点击棋子颜色//生成棋子 放置棋盘中lineXAndlineYArrRed.map(i => {new Chessman(i[0], i[1], color1).update()})lineXAndlineYArrBlack.map(i => {new Chessman(i[0], i[1], color2).update()})//改变页面上的信息redP.innerHTML = '白旗已下' + lineXAndlineYArrRed.lengthblackP.innerHTML = '黑旗已下' + lineXAndlineYArrBlack.length
})

再而判断下的这枚棋子,白棋或者黑棋棋子是否已经有了五个:

  //判断棋子数量是否已经大于5  没到5 决对赢不了的 ~if (newlineXAndlineYArr.length >= 5) {//向右向左倾斜判断、横向纵向判断leftRightFangXiang()// //向右倾斜function leftRightFangXiang() {// 深拷贝一份数据let newlineXAndlineYArrR = JSON.parse(JSON.stringify(newlineXAndlineYArr))let newRightArrList = []for (let i = 0; i < 5; i++) {//xif (1) {newRightArrList = []for (let j = 0; j < i; j++) {newRightArrList.push([newARR[0] - flag * (j + 1), newARR[1]])}for (let k = i; k < 4; k++) {newRightArrList.push([newARR[0] + flag * (k - i + 1), newARR[1]])}if (rightOrRight(newRightArrList, newlineXAndlineYArrR, newARR) == 'win') {console.log("%c横向赢了哦~", "color:red;font-size:30px;");break}}//yif (1) {newRightArrList = []for (let j = 0; j < i; j++) {newRightArrList.push([newARR[0], newARR[1] - flag * (j + 1)])}for (let k = i; k < 4; k++) {newRightArrList.push([newARR[0], newARR[1] + flag * (k - i + 1)])}if (rightOrRight(newRightArrList, newlineXAndlineYArrR, newARR) == 'win') {console.log("%c纵向赢了哦~", "color:red;font-size:30px;");break}}// //左下   // 前 + -     张俊卿    - +if (1) {newRightArrList = []for (let j = 0; j < i; j++) {newRightArrList.push([newARR[0] + flag * (j + 1), newARR[1] - flag * (j + 1)])}for (let k = i; k < 4; k++) {newRightArrList.push([newARR[0] - flag * (k - i + 1), newARR[1] + flag * (k - i + 1)])}if (rightOrRight(newRightArrList, newlineXAndlineYArrR, newARR) == 'win') {console.log("%c左下赢了哦~", "color:red;font-size:30px;");break}}//右下   // 前 - -     张俊卿    + +  后if (1) {newRightArrList = []for (let j = 0; j < i; j++) {newRightArrList.push([newARR[0] - flag * (j + 1), newARR[1] - flag * (j + 1)])}for (let k = i; k < 4; k++) {newRightArrList.push([newARR[0] + flag * (k - i + 1), newARR[1] + flag * (k - i + 1)])}if (rightOrRight(newRightArrList, newlineXAndlineYArrR, newARR) == 'win') {console.log("%c右下赢了哦~", "color:red;font-size:30px;");break}}}}}

胜利

**有5个连成了一条线,服务器更新棋子位置 **

  //初始化函数mySocket.emit('clearItemsArr')

node

    websocketObj.on('clearItemsArr', () => {let clearItemsArr = JSON.parse(itemsArr)clearItemsArr.lineXAndlineYArrRed = []clearItemsArr.lineXAndlineYArrBlack = []clearItemsArr.hasChessmanArrList = []clearItemsArr.blackOrRedChessman = 0// websocketObj.emit('getItemsArr',itemsArr )//触发所以的 sendFunEventCallBack 事件  让前端监听io.sockets.emit("clearItemsArrAll", JSON.stringify(clearItemsArr));})

前端接受重置位置,页面重置:

//websocket
mySocket.on('clearItemsArrAll', (getItemsArr) => {const ItemsArr = JSON.parse(getItemsArr)lineXAndlineYArrRed = ItemsArr.lineXAndlineYArrRedlineXAndlineYArrBlack = ItemsArr.lineXAndlineYArrBlackhasChessmanArrList = ItemsArr.hasChessmanArrListblackOrRedChessman = ++ItemsArr.blackOrRedChessman//赢了resultP.innerHTML = blackOrRedChessman % 2 == 0 ? '黑棋子方胜利' : '白棋子方胜利'var r = window.confirm(resultP.innerHTML + ",是否重新开始!");if (r == true) {redP.innerHTML = '白旗已下0'blackP.innerHTML = '黑旗已下0'againInit()}
})

重置画布:

//重新开始
function againInit() {// window.history.go(0)//横线对象数组getXLineArr = []//竖线对象数组getYLineArr = []//偶数白色 基数 黑色blackOrRedChessman = 0//所有棋子数组hasChessmanArrList = []//坐标点数组//白旗坐标数组lineXAndlineYArrRed = []//黑棋坐标数组lineXAndlineYArrBlack = []ctx.clearRect(0, 0, canvas.width, canvas.height)init()
}

主要是使用html、js、node、websocket完成了一个可以分多个房间的双人五子棋游戏,其他人可以观战。

git地址:

五子棋分房间双人战斗

  1. git clone https://gitee.com/zhang745929987/gobang-room-two-fight.git
  2. cd 进去 npm i
  3. node或者nodemon test.js

完整代码在git上,有兴趣可以玩一玩,提出一些改进意见。

B站视频

javascript五子棋讲解
javascript五子棋演示

演示:

五子棋小游戏(JS+Node+Websocket)可分房间对战相关推荐

  1. 前端实现五子棋小游戏2(AI实现人机对战)

    通过一个简单的算法,来实现AI智能对弈的五子棋小游戏 AI难点解析 赢法数组 赢法的统计数组 判断胜负 计算机的落子规则 代码实现 赢法数组 赢法种类的索引 横线赢法 竖线赢法 横线赢法 斜线赢法 反 ...

  2. 【Verilog】基于FPGA的五子棋小游戏(VGA显示、双人对战、胜负判别、附完整代码)

    基于FPGA的五子棋小游戏 有一些说明: 1.本文是基于VGA的显示小游戏,主要为VGA显示的拓展应用: 2.为适应不同显示屏的分辨率,棋盘确定为10X10的黑线白底的方格: 3.下棋主要用棋格颜色变 ...

  3. Android Studio实现五子棋小游戏

    项目目录 一.项目概述 二.开发环境 三.详细设计 1.布局设计 2.验证码 3.AI人机 4.背景音乐 四.运行演示 五.项目总结 六.源码获取 一.项目概述 五子棋是一种两人对弈的策略型棋类游戏, ...

  4. php 设计五子棋游戏,基于js+canvas实现五子棋小游戏

    本文实例为大家分享了js+canvas实现五子棋小游戏的具体代码,供大家参考,具体内容如下 效果展示: 源码展示: 五子棋 * { margin: 0; padding: 0; } body { ma ...

  5. js实现五子棋小游戏

    试玩 试玩网址:http://42.194.221.6:8014/ 效果 html及js <!DOCTYPE html> <html lang="en">& ...

  6. php五子棋,JS实现五子棋小游戏

    这次给大家带来JS实现五子棋小游戏,JS实现五子棋小游戏的注意事项有哪些,下面就是实战案例,一起来看一下. 思路: 1.先用canvas画五子棋的棋盘 2.获取鼠标点击的位置 3.根据鼠标点击的位置判 ...

  7. JavaScript id_JavaScript实现五子棋小游戏_javascript技巧

    更新时间:2020年10月26日 11:39:33   作者:布伽思索 这篇文章主要为大家详细介绍了JavaScript实现五子棋小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴 ...

  8. 基于flask的五子棋小游戏

    基于flask的五子棋小游戏 前言 ​ 首先说明一下,本人方向是java后端,只因老师布置了一个作业,要用flask来做一个五子棋,没办法被逼上梁山,程序不太美观,但是应付作业还是够了的. ​ 废话不 ...

  9. 前端实现五子棋小游戏1(本地双人对战)

    运用canvas写一个本地五子棋小游戏 HTML部分 JS 部分 CSS 部分 实现效果 HTML部分 <!DOCTYPE html> <html lang="en&quo ...

  10. Java编写的五子棋小游戏

    看书的时候看到一个不完整的Java编写的一个五子棋小游戏,为了恢复一下编程能力刚刚把这个小程序完成了. 实现的功能很简单,两人对下五子棋,程序自动回判断输赢.在ubuntu下搞得,没有装什么高端的输入 ...

最新文章

  1. 回望2018,展望2019
  2. 【JavaScript】 Webpack安装及文件打包
  3. 统计函数——汇总统计时间类数据
  4. audio 上一首 下一首 自定义样式_总有一首网易云,藏着你忘不掉的人。
  5. 服务器删除网站文章,如何一次性删除wordpress所有文章
  6. python函数注释,参数后面加冒号:,函数后面的箭头→是什么?
  7. Delphi动态数组详解
  8. 小a的计算器(牛客签到题A)-简单模拟
  9. 微信小程序——云服务环境的配置
  10. unity读取Text
  11. java.util接口_Java 8中java.util.function包中的谓词和使用者接口
  12. C++ STL 初步介绍01
  13. 目标检测论文阅读:Multi-scale Location-aware Kernel Representation for Object Detection(CVPR2018)
  14. jQuery版三级联动案例
  15. 对天敏电视精灵I老版播放器的修改和分析
  16. 【软件测试】学习路线资料整理摆脱迷茫,突破瓶颈(送给我迷茫的朋友)
  17. OS-练习题(10~13)
  18. 今日错题(10.6)
  19. 如何选择合适的CDN加速合作?关键在于这三个方面!
  20. idea项目相关错误与常用操作教程

热门文章

  1. iframe相关case之allowTransparency属性
  2. python爬取中国大学(高校)基本信息
  3. 阿里大鱼短信平台使用-Java版
  4. 【腾讯优测干货分享】使用多张图片做帧动画的性能优化 1
  5. 王教授是哪里人代码实现
  6. NX二次开发 判断外挂是否需要更新,从PTF下载文件(从服务器下载文件)
  7. mysql支持事务的储存引擎_「mysql事务与mysql储存引擎」- 海风纷飞Blog
  8. Unity3D可用性评估报告
  9. Win10突然卡死的原因调查
  10. Cisco 与 Intel路由器的对连配置实例