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 1.4.2发布!主要是性能与API
Feb 25 Javascript
读jQuery之四(优雅的迭代)
Jun 20 Javascript
Javascript基础教程之数组 array
Jan 18 Javascript
基于JavaScript实现高德地图和百度地图提取行政区边界经纬度坐标
Jan 22 Javascript
js事件冒泡、事件捕获和阻止默认事件详解
Aug 04 Javascript
JS无缝滚动效果实现方法分析
Dec 21 Javascript
如何提高数据访问速度
Dec 26 Javascript
js图片延迟加载(Lazyload)三种实现方式
Mar 01 Javascript
JavaScript实现简单的树形菜单效果
Jun 23 Javascript
vue源码学习之Object.defineProperty对象属性监听
May 30 Javascript
代码分析vue中如何配置less
Sep 28 Javascript
js实现自定义右键菜单
May 18 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
哪吒敖丙传:新人物二哥敖乙出场 小敖丙奶气十足
2020/03/08 国漫
PHP脚本数据库功能详解(上)
2006/10/09 PHP
关于PHP的相似度计算函数:levenshtein的使用介绍
2013/04/15 PHP
将php数组输出html表格的方法
2014/02/24 PHP
PHP如何通过AJAX方式实现登录功能
2015/11/23 PHP
php 无限级分类 获取顶级分类ID
2016/03/13 PHP
Yii框架实现图片上传的方法详解
2017/05/20 PHP
php操作mongodb封装类与用法实例
2018/09/01 PHP
JavaScript 全面解析各种浏览器网页中的JS 执行顺序
2009/02/17 Javascript
Jquery显示、隐藏元素以及添加删除样式
2013/08/09 Javascript
jQuery层级选择器用法分析
2015/02/10 Javascript
JavaScript中数据结构与算法(二):队列
2015/06/19 Javascript
JS访问SWF的函数用法实例
2015/07/01 Javascript
JS实现带关闭功能的阿里妈妈网站顶部滑出banner工具条代码
2015/09/17 Javascript
javascript匀速动画和缓冲动画详解
2016/10/20 Javascript
JavaScript用JSONP跨域请求数据实例详解
2017/01/06 Javascript
bootstrap table服务端实现分页效果
2017/08/10 Javascript
vue实现仿淘宝结账页面实例代码
2017/11/08 Javascript
Vue.js搭建移动端购物车界面
2020/06/28 Javascript
学习JS中的DOM节点以及操作
2018/04/30 Javascript
微信小程序中this.data与this.setData的区别详解
2018/09/17 Javascript
vue解决弹出蒙层滑动穿透问题的方法
2018/09/22 Javascript
JS实现换肤功能的方法实例详解
2019/01/30 Javascript
微信小程序实现可长按移动控件
2020/11/01 Javascript
Python中关于Sequence切片的下标问题详解
2017/06/15 Python
Python基于列表list实现的CRUD操作功能示例
2018/01/05 Python
python获取指定字符串中重复模式最高的字符串方法
2018/06/29 Python
pygame游戏之旅 调用按钮实现游戏开始功能
2018/11/21 Python
英国品牌男装折扣网站:Brown Bag
2018/03/08 全球购物
历史系毕业生自荐信
2013/10/28 职场文书
路政管理专业个人自荐信范文
2013/11/30 职场文书
通用自荐信范文
2014/03/14 职场文书
党政领导班子四风问题对照检查材料思想汇报
2014/10/02 职场文书
导游词之吉林吉塔
2019/11/11 职场文书
jQuery class属性操作addClass()与removeClass()、hasClass()、toggleClass()
2021/03/31 jQuery
python机器学习实现oneR算法(以鸢尾data为例)
2022/03/03 Python