原生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 相关文章推荐
js点击更换背景颜色或图片的实例代码
Jun 25 Javascript
jquery操作angularjs对象
Jun 26 Javascript
JavaScript获得指定对象大小的方法
Jul 01 Javascript
javascript面向对象程序设计高级特性经典教程(值得收藏)
May 19 Javascript
JS常用知识点整理
Jan 21 Javascript
jQuery插件FusionCharts绘制的3D环饼图效果示例【附demo源码】
Apr 02 jQuery
WebSocket的通信过程与实现方法详解
Apr 29 Javascript
vue实现的双向数据绑定操作示例
Dec 04 Javascript
基于mpvue的简单弹窗组件mptoast使用详解
Aug 02 Javascript
JavaScript图像放大镜效果实现方法详解
Jun 28 Javascript
js实现简单抽奖功能
Nov 24 Javascript
关于小程序优化的一些建议(小结)
Dec 10 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实现ping
2006/10/09 PHP
推荐个功能齐全的发送PHP邮件类
2007/01/03 PHP
PHPMailer安装方法及简单实例
2008/11/25 PHP
php set_magic_quotes_runtime() 函数过时解决方法
2010/07/08 PHP
Drupal7中常用的数据库操作实例
2014/03/02 PHP
php使用MySQL保存session会话的方法
2015/06/18 PHP
关于扩展 Laravel 默认 Session 中间件导致的 Session 写入失效问题分析
2016/01/08 PHP
Laravel实现构造函数自动依赖注入的方法
2016/03/16 PHP
Laravel 实现密码重置功能
2018/02/23 PHP
PHP数组遍历的几种常见方式总结
2019/02/15 PHP
自定义jQuery选项卡插件实例
2013/03/27 Javascript
js监听键盘事件示例代码
2013/07/26 Javascript
使用AngularJS中的SCE来防止XSS攻击的方法
2015/06/18 Javascript
Jquery通过ajax请求NodeJS返回json数据实例
2016/11/08 NodeJs
详解浏览器渲染页面过程
2017/02/09 Javascript
JS+HTML5 FileReader对象用法示例
2017/04/07 Javascript
Node.js引入UIBootstrap的方法示例
2018/05/11 Javascript
微信小程序复选框实现多选一功能过程解析
2020/02/14 Javascript
token 机制和实现方式
2020/12/15 Javascript
[45:15]Optic vs VP 2018国际邀请赛淘汰赛BO3 第一场 8.24
2018/08/25 DOTA
Python中查看文件名和文件路径
2017/03/31 Python
Python QQBot库的QQ聊天机器人
2019/06/19 Python
分析运行中的 Python 进程详细解析
2019/06/22 Python
python全栈要学什么 python全栈学习路线
2019/06/28 Python
Python中list循环遍历删除数据的正确方法
2019/09/02 Python
详解用Python进行时间序列预测的7种方法
2020/03/13 Python
如何基于python把文字图片写入word文档
2020/07/31 Python
中国旅游网站:途牛旅游网
2019/09/29 全球购物
什么时候需要进行强制类型转换
2016/09/03 面试题
动物科学专业毕业生的自我评价
2013/11/29 职场文书
自主实习接收函
2014/01/13 职场文书
教育技术职业规划范文
2014/03/04 职场文书
师德师风自查材料
2014/10/14 职场文书
办公室岗位职责
2015/02/04 职场文书
交心谈心活动总结
2015/05/11 职场文书
2016年10月份红领巾广播稿
2015/12/21 职场文书