vue实现五子棋游戏


Posted in Javascript onMay 28, 2020

本文实例为大家分享了vue实现五子棋游戏的具体代码,供大家参考,具体内容如下

思路

1.vue实现五子棋

空棋盘开局。

画网格:网格有 15 行 15 列,共有 225 个交叉点
黑先、白后,交替下子,每次只能下一子
胜负判定
按照简单的规则,从当前下子点位的方向判断()。如果有一个方向满足连续5个黑子或白子,游戏结束。

2.支持dom和canvas切换

判断浏览器是否支持canvas:

false: 不支持 切换dom方式
true:  支持 使用canvas

3.实现悔棋功能

4.实现撤销悔棋

例子:

为了简便,我就把所有写在一起了,按理来说是要分文件写的;

GitHub IO:链接

<!DOCTYPE html>
<html>
 <head>
 <meta charset="utf-8">
 <title>简易五子棋</title>
 <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
 <style>
 body {
 margin: 0;
 padding: 0;
 }
 #app{
 padding-left: 30%;
 width: 500px;
 }
 .h2Title{
 text-align: center;
 }
 #app h3{
 color: red;
 }
 .Fbuttons{
 margin-bottom: 1rem;
 }
 .main{
 background-color: bisque;
 width: 30rem;
 }
 .restart,.regret,.undo{
 background: bisque;
 padding: 6px 10px;
 border-radius: 6px;
 font-size: 12px;
 cursor: pointer;
 }
 #chess {
 position: relative;
 width: 440px;
 height: 450px;
 padding-left: 30px;
 padding-top: 30px;
 background-color: bisque; 
 }
 
 #chess .squre { 
 width: 28px;
 height: 28px;
 border: 1px solid #666;
 float: left;
 }
 
 #box01 .squre:hover {
 background-color: pink;
 }
 
 #box01 { 
 position: absolute;
 margin: 0 auto;
 width: 450px;
 height: 450px;
 top: 15px;
 left: 15px;
 }
 
 #box01 .qz {
 /* width: 28px;
 height: 28px; */
 width: 30px;
 height: 30px;
 border: 0px solid #C7C7C7;
 float: left;
 border-radius: 50%;
 /* margin: 1px; */
 }
 
 #box01 .qz:hover {
 background-color: pink;
 }
 .toggle{
 float: right;
 }
 
 </style>
 </head>
 <body>
 <div id="app">
 <h2 class="h2Title">五子棋</h2>
 <h3>{{victory}}</h3>
 <div class="Fbuttons">
 <input type="button" value="重新开始" class="restart" @click="restartInit()" />
 <input type="button" value="悔棋" class="regret" @click="regret()" />
 <input type="button" value="撤销悔棋" class="undo" @click="undo()" />
 <input type="button" :value="toggle?'切换dom':'切换canvas'" class="toggle" @click="toggleF()" />
 </div>
 <div class="main">
 <canvas v-show="toggle" id="myCanvas" ref="canvas" width="480" height="480">当前浏览器不支持Canvas</canvas>
 <div v-show="!toggle" id="chess" ref="chessBox">
 <!-- <div id="box01"></div>
 <div id="box02"></div> -->
 </div>
 </div>

 </div>
 <!-- -->
 <script>
 var app = new Vue({
 el: "#app",
 data: {
 pieceMapArr: [], //记录棋盘落子情况
 pieceColor: ["black", "white"], //棋子颜色
 step: 0, //记录当前步数
 checkMode: [ //输赢检查方向模式
 [1, 0], //水平
 [0, 1], //竖直
 [1, 1], //左斜线
 [1, -1], //右斜线
 ],
 flag: false,
 victory: '',
 history: [], //历史记录位置
 historyVal: [], //历史记录不被删除数组
 stepHistory: 0,
 domPiece:[], //
 toggle: true //true为canvas,false为dom
 },
 mounted(){
 const myCanvas = document.getElementById("myCanvas");
 if (!myCanvas.getContext) {
 alert("当前浏览器不支持Canvas.");
 this.toggle = false;
 this.drawpieceBoardDom();
 } else {
 console.log("当前浏览器支持Canvas", this.toggle)
 this.drawpieceBoard();
 const canvas = this.$refs.canvas;
 // 添加点击监听事件 
 canvas.addEventListener("click", e => {
 if (this.flag) {
 alert("游戏结束,请重新开始~");
 return;
 }
 //判断点击范围是否越出棋盘
 if (e.offsetX < 25 || e.offsetX > 450 || e.offsetY < 25 || e.offsetY > 450) {
 return;
 }
 let dx = Math.floor((e.offsetX + 15) / 30) * 30;
 let dy = Math.floor((e.offsetY + 15) / 30) * 30;
 console.log('this.pieceMapArr 数组', this.pieceMapArr)
 if (this.pieceMapArr[dx / 30 - 1][dy / 30 - 1] == 0) {
 console.log('落下棋子', dx, dy, this.pieceColor[this.step % 2])
 this.drawPiece(dx, dy, this.pieceColor[this.step % 2]); //落下棋子
 this.pieceMapArr[dx / 30 - 1][dy / 30 - 1] = this.pieceColor[this.step % 2];

 //历史记录位置
 this.history.length = this.step;
 this.history.push({
  dx,
  dy,
  color: this.pieceColor[this.step % 2]
 });
 this.historyVal.push({
  dx,
  dy,
  color: this.pieceColor[this.step % 2]
 });
 this.stepHistory++
 console.log('this.history', this.history);
 //检查当前玩家是否赢了游戏
 for (var i = 0; i < 4; i++) {
  this.checkWin(dx / 30 - 1, dy / 30 - 1, this.pieceColor[this.step % 2], this.checkMode[i]);
 }
 this.step++;
 } else {
 alert("不能落在有棋子的地方!");
 }
 });


 }
 },
 methods: {
 toggleF() {
 this.toggle = !this.toggle;
 if (!this.toggle) {
 // console.log("当前---------------1")
 // let elem = document.getElementById('box01');
 // if (elem !== null) {
 // elem.parentNode.removeChild(elem);
 // let elem02 = document.getElementById('box02');
 // elem02.parentNode.removeChild(elem02);
 // }
 // this.drawpieceBoardDom();
 this.restartInit()
 } else {
 this.restartInit()
 // this.drawpieceBoard();
 }
 },
 //初始化棋盘数组
 pieceArr() {
 for (let i = 0; i < 15; i++) {
 this.pieceMapArr[i] = [];
 for (let j = 0; j < 15; j++) {
 this.pieceMapArr[i][j] = 0;
 }
 }
 },
 //重新开始
 restartInit() {
 if (!this.toggle) {
 // console.log("-----dom-------")
 var elem = document.querySelector('#box01');
 // console.log("elem",elem)
 if (elem != null ) {
 elem.parentNode.removeChild(elem);
 let elem02 = document.querySelector('#box02');
 elem02.parentNode.removeChild(elem02);
 }
 this.drawpieceBoardDom();
 this.flag = false;
 this.step = 0;
 this.stepHistory = 0;
 this.historyVal = [];
 this.history = [];
 } else {
 //重画
 this.repaint();
 // 绘制棋盘
 this.drawpieceBoard();
 this.flag = false;
 this.step = 0;
 this.stepHistory = 0;
 this.historyVal = [];
 this.history = [];
 }
 },
 //---------canvas----------
 // 绘制棋盘
 drawpieceBoard() {
 //初始化棋盘数组
 this.pieceArr();
 //canvas 绘制
 let canvas = this.$refs.canvas
 // 调用canvas元素的getContext 方法访问获取2d渲染的上下文
 let context = canvas.getContext("2d");
 context.strokeStyle = '#666'
 for (let i = 0; i < 15; i++) {
 //落在方格(canvas 的宽高是450)
 // context.moveTo(15 + i * 30, 15)
 // context.lineTo(15 + i * 30, 435)
 // context.stroke()
 // context.moveTo(15, 15 + i * 30)
 // context.lineTo(435, 15 + i * 30)
 // context.stroke()
 //落在交叉点(480)
 context.beginPath();
 context.moveTo((i + 1) * 30, 30);
 context.lineTo((i + 1) * 30, canvas.height - 30);
 context.closePath();
 context.stroke();
 context.beginPath();
 context.moveTo(30, (i + 1) * 30);
 context.lineTo(canvas.width - 30, (i + 1) * 30);
 context.closePath();
 context.stroke();
 }
 },
 //绘制棋子
 drawPiece(x, y, color) {
 let canvas = this.$refs.canvas
 let context = canvas.getContext("2d");
 context.beginPath(); //开始一条路径或重置当前的路径
 context.arc(x, y, 15, 0, Math.PI * 2, false);
 context.closePath();
 context.fillStyle = color;
 context.fill();
 },
 //胜负判断函数
 checkWin(x, y, color, mode) {
 let count = 1; //记录
 for (let i = 1; i < 5; i++) {
 if (this.pieceMapArr[x + i * mode[0]]) {
 if (this.pieceMapArr[x + i * mode[0]][y + i * mode[1]] == color) {
  count++;
 } else {
  break;
 }
 }
 }
 for (let j = 1; j < 5; j++) {
 if (this.pieceMapArr[x - j * mode[0]]) {
 if (this.pieceMapArr[x - j * mode[0]][y - j * mode[1]] == color) {
  count++;
 } else {
  break;
 }
 }
 }
 // console.log('胜负判断函数', count)
 // console.log('color', color)
 if (count >= 5) {
 if (color == 'black') {
 this.victory = "黑子棋方胜利!";
 } else {
 this.victory = "白子棋方胜利!";
 }
 // 游戏结束
 // console.log('游戏结束')
 this.flag = true;
 }
 },
 //重画函数
 repaint() {
 //重画
 let canvas = this.$refs.canvas;
 let context = canvas.getContext("2d");
 context.fillStyle = "bisque";
 context.fillRect(0, 0, canvas.width, canvas.height);
 context.beginPath();
 context.closePath();
 },

 //悔棋: 
 // canvas 创建一个二维数组,下棋或者悔棋都操作这个数组。操作完数据,把画布全清,重新用数据画一个棋盘。
 // dom 二维数组删除数组最后一项, 先清空棋子的填充颜色,在渲染上颜色
 regret() {
 if (!this.toggle) {
 // console.log("-----dom------this.domPiece",this.domPiece)
 if (this.history.length && !this.flag) {
 this.history.pop(); //删除数组最后一项 
 console.log("-----dom------this.history", this.history)
 //重画
 this.pieceArr();
 // let elem = document.getElementById('box01');
 // if (elem !== null) {
 // elem.parentNode.removeChild(elem);
 // let elem02 = document.getElementById('box02');
 // elem02.parentNode.removeChild(elem02);
 // } //这个太耗性能了
 // this.drawpieceBoardDom();
 // 清空棋子的填充颜色
 this.domPiece.forEach(e => { 
  e.forEach(qz => {
  qz.style.backgroundColor = '';
  })  
 });
 // 渲染棋子颜色
 this.history.forEach(e => {
  this.domPiece[e.m][e.n].style.backgroundColor = e.color
  this.pieceMapArr[e.m][e.n] = e.color;
 });
 this.step--
 } else {
 alert("已经不能悔棋了~")
 }

 } else {
 if (this.history.length && !this.flag) {
 this.history.pop(); //删除数组最后一项 
 //重画
 this.repaint();
 // 绘制棋盘
 this.drawpieceBoard();
 //绘制棋子
 this.history.forEach(e => {
  this.drawPiece(e.dx, e.dy, e.color)
  this.pieceMapArr[e.dx / 30 - 1][e.dy / 30 - 1] = e.color;
 });
 this.step--
 } else {
 alert("已经不能悔棋了~")
 }
 }
 },
 //撤销悔棋 
 undo() {
 if (!this.toggle) {
 // console.log("-----dom------this.domPiece",this.domPiece)
 if ((this.historyVal.length > this.history.length) && !this.flag) {
 this.history.push(this.historyVal[this.step])
 console.log("-----dom------this.history", this.history)
 // 清空棋子的填充颜色
 this.domPiece.forEach(e => { 
  e.forEach(qz => {
  qz.style.backgroundColor = '';
  })  
 });
 // 渲染棋子颜色
 this.history.forEach(e => {
  this.domPiece[e.m][e.n].style.backgroundColor = e.color
  this.pieceMapArr[e.m][e.n] = e.color;
 });
 this.step++
 } else {
 alert("不能撤销悔棋了~")
 }
 
 } else {
 if ((this.historyVal.length > this.history.length) && !this.flag) {
 this.history.push(this.historyVal[this.step])
 //重画
 this.repaint();
 // 绘制棋盘
 this.drawpieceBoard();
 this.history.forEach(e => {
  this.drawPiece(e.dx, e.dy, e.color)
  this.pieceMapArr[e.dx / 30 - 1][e.dy / 30 - 1] = e.color;
 });
 this.step++
 } else {
 alert("不能撤销悔棋了~")
 }
 }
 },
 
 // -----------dom-----------
 drawpieceBoardDom() {
 // console.log("this", this)
 let that = this;
 //调用初始化棋盘数组函数
 that.pieceArr();
 //创建一个容器
 const box = document.querySelector("#chess");
 const box01 = document.createElement("div");
 box01.setAttribute("id", "box01");
 box.appendChild(box01);
 //画棋盘
 const chess01 = document.querySelector("#box01");
 const box02 = document.createElement("div");
 box02.setAttribute("id", "box02");
 box.appendChild(box02);
 let arr = new Array();
 for (let i = 0; i < 14; i++) {
 arr[i] = new Array();
 for (let j = 0; j < 14; j++) {
 arr[i][j] = document.createElement("div");
 arr[i][j].setAttribute("class", "squre");
 box02.appendChild(arr[i][j]);
 }
 }
 //画棋子
 let arr01 = this.domPiece; 
 for (let i = 0; i < 15; i++) {
 arr01[i] = new Array();
 for (let j = 0; j < 15; j++) {
 arr01[i][j] = document.createElement("div");
 arr01[i][j].setAttribute("class", "qz");
 chess01.appendChild(arr01[i][j]);
 }
 }
 // console.log("this.domPiece",this.domPiece)
 // 填充颜色和判断
 for (let m = 0; m < 15; m++) {
 for (let n = 0; n < 15; n++) {
 arr01[m][n].onclick = function() {
  //判断游戏是否结束
  if (!that.flag) {
  if (that.pieceMapArr[m][n] == 0) {
  //黑白交换下棋
  // console.log(this);
  // console.log('落下棋子', that.pieceColor[that.step % 2])
  //确保填充颜色正确进行了判断
  if (this.className == "qz" && that.step % 2 == 0 && this.style.backgroundColor == "") {
  //下棋填充黑颜色
  this.style.backgroundColor = that.pieceColor[that.step % 2];
  //写入棋盘数组
  that.pieceMapArr[m][n] = that.pieceColor[that.step % 2];
  //历史记录位置
  that.history.length = that.step;
  that.history.push({
  m,
  n,
  color: that.pieceColor[that.step % 2]
  });
  that.historyVal.push({
  m,
  n,
  color: that.pieceColor[that.step % 2]
  });
  that.stepHistory++
  console.log('this.history', that.history);
  } else if (this.className == "qz" && that.step % 2 != 0 && this.style.backgroundColor == "") {
  //下棋填充白颜色
  this.style.backgroundColor = that.pieceColor[that.step % 2];
  //写入棋盘数组
  that.pieceMapArr[m][n] = that.pieceColor[that.step % 2];
  //历史记录位置
  that.history.length = that.step;
  that.history.push({
  m,
  n,
  color: that.pieceColor[that.step % 2]
  });
  that.historyVal.push({
  m,
  n,
  color: that.pieceColor[that.step % 2]
  });
  that.stepHistory++
  console.log('this.history', that.history);
  }
  //检查当前是否赢了
  for (var i = 0; i < 4; i++) {
  that.checkWin(m, n, that.pieceColor[that.step % 2], that.checkMode[i]);
  }
  that.step++;
  // console.log('that.step', that.step);
  } else {
  alert("不能落在有棋子的地方!");
  return;
  }
  } else {
  // that.flag = true;
  alert("游戏结束,请重新开始~");
  return;
  }
 }
 }
 }
 
 },

 }
 });
 </script>
 </body>
</html>

更多文章可以点击《Vue.js前端组件学习教程》学习阅读。

关于vue.js组件的教程,请大家点击专题vue.js组件学习教程进行学习。

更多vue学习教程请阅读专题《vue实战教程》

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JQuery 返回布尔值Is()条件判断方法代码
May 14 Javascript
JS增加行复制行删除行的实现代码
Nov 09 Javascript
js获取url中指定参数值的示例代码
Dec 14 Javascript
jquery默认校验规则整理
Mar 24 Javascript
JS实现自定义简单网页软键盘效果代码
Nov 05 Javascript
学习使用jquery iScroll.js移动端滚动条插件
Mar 24 Javascript
详解Javascript中DOM的范围
Feb 13 Javascript
JavaScrpt的面向对象全面解析
May 09 Javascript
聊聊那些使用前端Javascript实现的机器学习类库
Sep 18 Javascript
尝试自己动手用react来写一个分页组件(小结)
Feb 09 Javascript
详解通过源码解析Node.js中cluster模块的主要功能实现
May 16 Javascript
详解wepy开发小程序踩过的坑(小结)
May 22 Javascript
用vue 实现手机触屏滑动功能
May 28 #Javascript
Jquery高级应用Deferred对象原理及使用实例
May 28 #jQuery
JQuery插件tablesorter表格排序实现过程解析
May 28 #jQuery
JS替换字符串中指定位置的字符(多种方法)
May 28 #Javascript
js实现九宫格布局效果
May 28 #Javascript
微信小程序实现电子签名并导出图片
May 27 #Javascript
JS 逻辑判断不要只知道用 if-else 和 switch条件判断(小技巧)
May 27 #Javascript
You might like
wamp下修改mysql访问密码的解决方法
2013/05/07 PHP
web站点获取用户IP的安全方法 HTTP_X_FORWARDED_FOR检验
2013/06/01 PHP
PHP实现采集抓取淘宝网单个商品信息
2015/01/08 PHP
在openSUSE42.1下编译安装PHP7 的方法
2015/12/24 PHP
php+redis实现消息队列功能示例
2019/09/19 PHP
Thinkphp框架+Layui实现图片/文件上传功能分析
2020/02/07 PHP
javascript实用方法总结
2015/02/06 Javascript
浅谈jQuery中height与width
2015/07/06 Javascript
jQuery垂直多级导航菜单代码分享
2015/08/18 Javascript
jQuery实现简洁的导航菜单效果
2015/11/23 Javascript
基于javascript实现图片切换效果
2016/04/17 Javascript
AngularJs  Creating Services详解及示例代码
2016/09/02 Javascript
node实现简单的反向代理服务器
2017/07/26 Javascript
JavaScript中字符串的常用操作方法及特殊字符
2018/03/18 Javascript
深入理解JavaScript的async/await
2018/08/05 Javascript
vue-router源码之history类的浅析
2019/05/21 Javascript
layui 解决form表单点击无反应的问题
2019/10/25 Javascript
js实现简单的秒表
2020/01/16 Javascript
Angular利用HTTP POST下载流文件的步骤记录
2020/07/26 Javascript
[02:23]DOTA2英雄基础教程 幻影长矛手
2013/12/09 DOTA
Python爬虫_城市公交、地铁站点和线路数据采集实例
2018/01/10 Python
python学习笔记--将python源文件打包成exe文件(pyinstaller)
2018/05/26 Python
python print输出延时,让其立刻输出的方法
2019/01/07 Python
对pytorch的函数中的group参数的作用介绍
2020/02/18 Python
在Python中用GDAL实现矢量对栅格的切割实例
2020/03/11 Python
Pytorch通过保存为ONNX模型转TensorRT5的实现
2020/05/25 Python
Python Opencv图像处理基本操作代码详解
2020/08/31 Python
学生宿舍管理制度
2014/01/30 职场文书
机械制造毕业生求职信
2014/03/03 职场文书
大学新闻系求职信
2014/06/03 职场文书
大学团日活动新闻稿
2014/09/10 职场文书
教师先进事迹材料
2014/12/16 职场文书
2015年纪委工作总结
2015/05/13 职场文书
Python常用配置文件ini、json、yaml读写总结
2021/07/09 Python
从结婚开始的恋爱故事。小说《我的美好婚事》TV动画化决定
2022/04/07 日漫
Android Studio实现带三角函数对数运算功能的高级计算器
2022/05/20 Java/Android