原生JS+Canvas实现五子棋游戏


Posted in Javascript onMay 28, 2020

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

<!DOCTYPE html> 
<html> 
 <head> 
 <meta charset="utf-8" /> 
 <title>五子棋</title> 
 <style type='text/css'> 
 canvas { 
 display: block; 
 margin: 50px auto; 
 box-shadow: -2px -2px 2px #efefef, 5px 5px 5px #b9b9b9; 
 cursor: pointer; 
 } 
 .btn-wrap { 
 display: flex; 
 flex-direction: row; 
 justify-content:center; 
 } 
 .btn-wrap div { 
 margin: 0 10px; 
 } 
 div>span { 
 display: inline-block; 
 padding: 10px 20px; 
 color: #fff; 
 background-color: #EE82EE; 
 border-radius: 5px; 
 cursor: pointer; 
 } 
 div.unable span { 
 background: #D6D6D4; 
 color: #adacaa; 
 } 
 #result-wrap {text-align: center;} 
 </style> 
 </head> 
 <body> 
 <h3 id="result-wrap">--益智五子棋--</h3> 
 <canvas id="chess" width="450px" height="450px"></canvas> 
 <div class="btn-wrap"> 
 <div id='restart' class="restart"> 
 <span>重新开始</span> 
 </div> 
 <div id='goback' class="goback unable"> 
 <span>悔棋</span> 
 </div> 
 <div id='return' class="return unable"> 
 <span>撤销悔棋</span> 
 </div> 
 </div> 
 <script type="text/javascript" charset="utf-8"> 
 var over = false; 
 var me = true; //我 
 var _nowi = 0, _nowj = 0; //记录自己下棋的坐标 
 var _compi = 0, _compj = 0; //记录计算机当前下棋的坐标 
 var _myWin = [], _compWin = []; //记录我,计算机赢的情况 
 var backAble = false, returnAble = false; 
 var resultTxt = document.getElementById('result-wrap'); 
 var chressBord = [];//棋盘 
 for(var i = 0; i < 15; i++){ 
 chressBord[i] = []; 
 for(var j = 0; j < 15; j++){ 
  chressBord[i][j] = 0; 
 } 
 } 
 //赢法的统计数组 
 var myWin = []; 
 var computerWin = []; 
 //赢法数组 
 var wins = []; 
 for(var i = 0; i < 15; i++){ 
 wins[i] = []; 
 for(var j = 0; j < 15; j++){ 
  wins[i][j] = []; 
 } 
 } 
 var count = 0; //赢法总数 
 //横线赢法 
 for(var i = 0; i < 15; i++){ 
 for(var j = 0; j < 11; j++){ 
  for(var k = 0; k < 5; k++){ 
  wins[i][j+k][count] = true; 
  } 
  count++; 
 } 
 } 
 //竖线赢法 
 for(var i = 0; i < 15; i++){ 
 for(var j = 0; j < 11; j++){ 
  for(var k = 0; k < 5; k++){ 
  wins[j+k][i][count] = true; 
  } 
  count++; 
 } 
 } 
 //正斜线赢法 
 for(var i = 0; i < 11; i++){ 
 for(var j = 0; j < 11; j++){ 
  for(var k = 0; k < 5; k++){ 
  wins[i+k][j+k][count] = true; 
  } 
  count++; 
 } 
 } 
 //反斜线赢法 
 for(var i = 0; i < 11; i++){ 
 for(var j = 14; j > 3; j--){ 
  for(var k = 0; k < 5; k++){ 
  wins[i+k][j-k][count] = true; 
  } 
  count++; 
 } 
 } 
 // debugger; 
 for(var i = 0; i < count; i++){ 
 myWin[i] = 0; 
 _myWin[i] = 0; 
 computerWin[i] = 0; 
 _compWin[i] = 0; 
 } 
 var chess = document.getElementById("chess"); 
 var context = chess.getContext('2d'); 
 context.strokeStyle = '#bfbfbf'; //边框颜色 
 var backbtn = document.getElementById("goback"); 
 var returnbtn = document.getElementById("return"); 
 window.onload = function(){ 
 drawChessBoard(); // 画棋盘 
 } 
 document.getElementById("restart").onclick = function(){ 
 window.location.reload(); 
 } 
 // 我,下棋 
 chess.onclick = function(e){ 
 if(over){ 
  return; 
 } 
 if(!me){ 
  return; 
 } 
 // 悔棋功能可用 
 backbtn.className = backbtn.className.replace( new RegExp( "(\\s|^)unable(\\s|$)" )," " ); 
 var x = e.offsetX; 
 var y = e.offsetY; 
 var i = Math.floor(x / 30); 
 var j = Math.floor(y / 30); 
 _nowi = i; 
 _nowj = j; 
 if(chressBord[i][j] == 0){ 
  oneStep(i,j,me); 
  chressBord[i][j] = 1; //我,已占位置 
   
  for(var k = 0; k < count; k++){ // 将可能赢的情况都加1 
  if(wins[i][j][k]){ 
  // debugger; 
  myWin[k]++; 
  _compWin[k] = computerWin[k]; 
  computerWin[k] = 6;//这个位置对方不可能赢了 
  if(myWin[k] == 5){ 
  // window.alert('你赢了'); 
  resultTxt.innerHTML = '恭喜,你赢了!'; 
  over = true; 
  } 
  } 
  } 
  if(!over){ 
  me = !me; 
  computerAI(); 
  } 
 } 
 } 
 // 悔棋 
 backbtn.onclick = function(e){ 
 if(!backAble) { return;} 
 over = false; 
 me = true; 
 // resultTxt.innerHTML = 'o(?□?)o,悔棋中'; 
 // 撤销悔棋功能可用 
 returnbtn.className = returnbtn.className.replace( new RegExp( "(\\s|^)unable(\\s|$)" )," " ); 
 // 我,悔棋 
 chressBord[_nowi][_nowj] = 0; //我,已占位置 还原 
 minusStep(_nowi, _nowj); //销毁棋子   
 for(var k = 0; k < count; k++){ // 将可能赢的情况都减1 
  if(wins[_nowi][_nowj][k]){ 
  myWin[k]--; 
  computerWin[k] = _compWin[k];//这个位置对方可能赢 
  } 
 } 
 // 计算机相应的悔棋 
 chressBord[_compi][_compj] = 0; //计算机,已占位置 还原 
 minusStep(_compi, _compj); //销毁棋子   
 for(var k = 0; k < count; k++){ // 将可能赢的情况都减1 
  if(wins[_compi][_compj][k]){ 
  computerWin[k]--; 
  myWin[k] = _myWin[i];//这个位置对方可能赢 
  } 
 } 
 resultTxt.innerHTML = '--益智五子棋--'; 
 returnAble = true; 
 backAble = false; 
 } 
 // 撤销悔棋 
 returnbtn.onclick = function(e){ 
 if(!returnAble) { return; } 
  // 我,撤销悔棋 
 chressBord[_nowi][_nowj] = 1; //我,已占位置 
 oneStep(_nowi,_nowj,me);  
 for(var k = 0; k < count; k++){ 
  if(wins[_nowi][_nowj][k]){ 
  myWin[k]++; 
  _compWin[k] = computerWin[k]; 
  computerWin[k] = 6;//这个位置对方不可能赢 
  } 
  if(myWin[k] == 5){ 
  resultTxt.innerHTML = '恭喜,你赢了!'; 
  over = true; 
  } 
 } 
 // 计算机撤销相应的悔棋 
 chressBord[_compi][_compj] = 2; //计算机,已占位置 
 oneStep(_compi,_compj,false);   
 for(var k = 0; k < count; k++){ // 将可能赢的情况都减1 
  if(wins[_compi][_compj][k]){ 
  computerWin[k]++; 
  _myWin[k] = myWin[k]; 
  myWin[k] = 6;//这个位置对方不可能赢 
  } 
  if(computerWin[k] == 5){ 
  resultTxt.innerHTML = 'o(?□?)o,计算机赢了,继续加油哦!'; 
  over = true; 
  } 
 } 
 returnbtn.className += ' '+ 'unable'; 
 returnAble = false; 
 backAble = true; 
 } 
 // 计算机下棋 
 var computerAI = function (){ 
 var myScore = []; 
 var computerScore = []; 
 var max = 0; 
 var u = 0, v = 0; 
 for(var i = 0; i < 15; i++){ 
  myScore[i] = []; 
  computerScore[i] = []; 
  for(var j = 0; j < 15; j++){ 
  myScore[i][j] = 0; 
  computerScore[i][j] = 0; 
  } 
 } 
 for(var i = 0; i < 15; i++){ 
  for(var j = 0; j < 15; j++){ 
  if(chressBord[i][j] == 0){ 
  for(var k = 0; k < count; k++){ 
  if(wins[i][j][k]){ 
   if(myWin[k] == 1){ 
   myScore[i][j] += 200; 
   }else if(myWin[k] == 2){ 
   myScore[i][j] += 400; 
   }else if(myWin[k] == 3){ 
   myScore[i][j] += 2000; 
   }else if(myWin[k] == 4){ 
   myScore[i][j] += 10000; 
   } 
   
   if(computerWin[k] == 1){ 
   computerScore[i][j] += 220; 
   }else if(computerWin[k] == 2){ 
   computerScore[i][j] += 420; 
   }else if(computerWin[k] == 3){ 
   computerScore[i][j] += 2100; 
   }else if(computerWin[k] == 4){ 
   computerScore[i][j] += 20000; 
   }  
  } 
  } 
  
  if(myScore[i][j] > max){ 
  max = myScore[i][j]; 
  u = i; 
  v = j; 
  }else if(myScore[i][j] == max){ 
  if(computerScore[i][j] > computerScore[u][v]){ 
   u = i; 
   v = j; 
  } 
  } 
  
  if(computerScore[i][j] > max){ 
  max = computerScore[i][j]; 
  u = i; 
  v = j; 
  }else if(computerScore[i][j] == max){ 
  if(myScore[i][j] > myScore[u][v]){ 
   u = i; 
   v = j; 
  } 
  } 
  
  } 
  } 
 } 
 _compi = u; 
 _compj = v; 
 oneStep(u,v,false); 
 chressBord[u][v] = 2; //计算机占据位置 
 for(var k = 0; k < count; k++){ 
  if(wins[u][v][k]){ 
  computerWin[k]++; 
  _myWin[k] = myWin[k]; 
  myWin[k] = 6;//这个位置对方不可能赢了 
  if(computerWin[k] == 5){ 
  resultTxt.innerHTML = 'o(?□?)o,计算机赢了,继续加油哦!'; 
  over = true; 
  } 
  } 
 } 
 if(!over){ 
  me = !me; 
 } 
 backAble = true; 
 returnAble = false; 
 var hasClass = new RegExp('unable').test(' ' + returnbtn.className + ' '); 
 if(!hasClass) { 
  returnbtn.className += ' ' + 'unable'; 
 } 
 } 
 //绘画棋盘 
 var drawChessBoard = function() { 
 for(var i = 0; i < 15; i++){ 
  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(); 
 } 
 } 
 //画棋子 
 var oneStep = function(i,j,me) { 
 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(me){ 
  gradient.addColorStop(0,'#0a0a0a'); 
  gradient.addColorStop(1,'#636766'); 
 }else{ 
  gradient.addColorStop(0,'#d1d1d1'); 
  gradient.addColorStop(1,'#f9f9f9'); 
 } 
 context.fillStyle = gradient; 
 context.fill(); 
 } 
 //销毁棋子 
 var minusStep = function(i,j) { 
 //擦除该圆 
 context.clearRect((i) * 30, (j) * 30, 30, 30); 
 // 重画该圆周围的格子 
 context.beginPath(); 
 context.moveTo(15+i*30 , j*30); 
 context.lineTo(15+i*30 , j*30 + 30); 
 context.moveTo(i*30, j*30+15); 
 context.lineTo((i+1)*30 , j*30+15); 
 
 context.stroke(); 
 } 
 </script> 
 </body> 
</html>

更多有趣的经典小游戏实现专题,分享给大家:

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

Javascript 相关文章推荐
jQuery实现的导航条切换可显示隐藏
Oct 22 Javascript
JavaScript中setUTCMilliseconds()方法的使用详解
Jun 12 Javascript
webpack入门+react环境配置
Feb 08 Javascript
浅谈js中的变量名和函数名重名
Feb 13 Javascript
基于vue-cli配置lib-flexible + rem实现移动端自适应
Dec 26 Javascript
详解如何用typescript开发koa2的二三事
Nov 13 Javascript
js实现下拉框二级联动
Dec 04 Javascript
Vue开发之封装上传文件组件与用法示例
Apr 25 Javascript
JavaScript的Proxy可以做哪些有意思的事儿
Jun 15 Javascript
Vue 的双向绑定原理与用法揭秘
May 06 Javascript
解决vue scoped html样式无效的问题
Oct 24 Javascript
一道JS算法面试题——冒泡、选择排序
Apr 21 Javascript
React-router v4 路由配置方法小结
Aug 08 #Javascript
用Vue.extend构建消息提示组件的方法实例
Aug 08 #Javascript
基于Vue实现页面切换左右滑动效果
Jun 29 #Javascript
VUE实现表单元素双向绑定(总结)
Aug 08 #Javascript
ES6模块化的import和export用法方法总结
Aug 08 #Javascript
Vue项目中quill-editor带样式编辑器的使用方法
Aug 08 #Javascript
webpack 2.x配置reactjs基本开发环境详解
Aug 08 #Javascript
You might like
浅析PHP程序防止ddos,dns,集群服务器攻击的解决办法
2013/06/18 PHP
使用php测试硬盘写入速度示例
2014/01/27 PHP
php获取文件后缀的9种方法
2016/03/22 PHP
PHP实现json_decode不转义中文的方法
2017/05/20 PHP
类似CSDN图片切换效果脚本
2009/09/17 Javascript
javascript中的数字与字符串相加实例分析
2011/08/14 Javascript
Ubuntu 11.10 安装Node.js的方法
2011/11/30 Javascript
js 控制下拉菜单刷新的方法
2013/03/03 Javascript
node.js中的buffer.toString方法使用说明
2014/12/14 Javascript
Javascript技术栈中的四种依赖注入小结
2016/02/27 Javascript
详解Vue.js 2.0 如何使用axios
2017/04/21 Javascript
JS 中document.write()的用法和清空的原因浅析
2017/12/04 Javascript
使用vue实现各类弹出框组件
2019/07/03 Javascript
详解从vue-loader源码分析CSS Scoped的实现
2019/09/23 Javascript
Taro UI框架开发小程序实现左滑喜欢右滑不喜欢效果的示例代码
2020/05/18 Javascript
快速解决Vue、element-ui的resetFields()方法重置表单无效的问题
2020/08/12 Javascript
vue-calendar-component 封装多日期选择组件的实例代码
2020/12/04 Vue.js
详解Python编程中time模块的使用
2015/11/20 Python
python基于隐马尔可夫模型实现中文拼音输入
2016/04/01 Python
Python中在脚本中引用其他文件函数的实现方法
2016/06/23 Python
Python中xrange与yield的用法实例分析
2017/12/26 Python
使用python装饰器计算函数运行时间的实例
2018/04/21 Python
Python基于OpenCV库Adaboost实现人脸识别功能详解
2018/08/25 Python
在Python中表示一个对象的方法
2019/06/25 Python
python中tkinter的应用:修改字体的实例讲解
2019/07/17 Python
Python字符串和正则表达式中的反斜杠('\')问题详解
2019/09/03 Python
python生成requirements.txt的两种方法
2019/09/18 Python
Django 自动生成api接口文档教程
2019/11/19 Python
浅析pip安装第三方库及pycharm中导入第三方库的问题
2020/03/10 Python
Numpy 多维数据数组的实现
2020/06/18 Python
HTML5应用之文件上传
2016/12/30 HTML / CSS
台湾最大网路书店:博客来
2018/03/18 全球购物
农村党员学习党的群众路线教育实践活动心得体会
2014/11/04 职场文书
详解Python生成器和基于生成器的协程
2021/06/03 Python
Python实现简繁体转换
2021/06/07 Python
python使用BeautifulSoup 解析HTML
2022/04/24 Python