原生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 相关文章推荐
Firefox window.close()的使用注意事项
Apr 11 Javascript
js 点击按钮弹出另一页,选择值后,返回到当前页
May 26 Javascript
jquery下将选择的checkbox的id组成字符串的方法
Nov 28 Javascript
使图片旋转的3种解决方案
Nov 21 Javascript
解决用jquery load加载页面到div时,不执行页面js的问题
Feb 22 Javascript
js实现鼠标悬停图片上时滚动文字说明的方法
Feb 17 Javascript
javascript图片切换综合实例(循环切换、顺序切换)
Jan 13 Javascript
浅析BootStrap栅格系统
Jun 07 Javascript
AngularJS constant和value区别详解
Feb 28 Javascript
JavaScript模拟文件拖选框样式v1.0的实例
Aug 04 Javascript
BootStrap modal实现拖拽功能
Dec 01 Javascript
vue canvas绘制矩形并解决由clearRec带来的闪屏问题
Sep 02 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
再次研究下cache_lite
2007/02/14 PHP
解决PHP在DOS命令行下却无法链接MySQL的技术笔记
2010/12/29 PHP
PHP数组对比函数,存在交集则返回真,否则返回假
2011/02/03 PHP
PHP Undefined index报错的修复方法
2011/07/17 PHP
php目录操作实例代码
2014/02/21 PHP
EasyUi tabs的高度与宽度根据IE窗口的变化自适应代码
2010/10/26 Javascript
用javascript添加控件自定义属性解析
2013/11/25 Javascript
基于jQuery仿淘宝产品图片放大镜特效
2020/10/19 Javascript
JS与Ajax Get和Post在使用上的区别实例详解
2016/06/08 Javascript
微信小程序实现animation动画
2018/01/26 Javascript
JavaScript设计模式之构造函数模式实例教程
2018/07/02 Javascript
js数据类型检测总结
2018/08/05 Javascript
详解vue更改头像功能实现
2019/04/28 Javascript
关于Vue中axios的封装实例详解
2019/10/20 Javascript
基于 Vue 的 Electron 项目搭建过程图文详解
2020/07/22 Javascript
vue 监听 Treeselect 选择项的改变操作
2020/08/31 Javascript
[51:29]完美世界DOTA2联赛循环赛 Matador vs Forest BO2第一场 11.05
2020/11/05 DOTA
详解字典树Trie结构及其Python代码实现
2016/06/03 Python
python使用psutil模块获取系统状态
2016/08/27 Python
python中文分词教程之前向最大正向匹配算法详解
2017/11/02 Python
python机器学习之神经网络(三)
2017/12/20 Python
python实现抽奖小程序
2020/04/15 Python
Pycharm远程调试原理及具体配置详解
2019/08/08 Python
ansible动态Inventory主机清单配置遇到的坑
2020/01/19 Python
Python调用百度OCR实现图片文字识别的示例代码
2020/07/17 Python
Python经纬度坐标转换为距离及角度的实现
2020/11/01 Python
Python Pygame实现俄罗斯方块
2021/02/19 Python
利用css3制作3D样式按钮实现代码
2013/03/18 HTML / CSS
canvas粒子动画背景的实现示例
2018/09/03 HTML / CSS
HTML5 Canvas入门学习教程
2016/03/17 HTML / CSS
泰国王权免税店官方网站:KingPower
2019/03/11 全球购物
销售助理岗位职责
2014/02/21 职场文书
《落花生》教学反思
2016/02/16 职场文书
职工趣味运动会开幕词
2016/03/04 职场文书
如何创建一个创建MySQL数据库中的datetime类型
2022/03/21 MySQL
德生TECSUN S-2000使用手册文字版
2022/05/10 无线电