JS+Canvas实现五子棋游戏


Posted in Javascript onAugust 26, 2020

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

布局+样式部分代码 :

<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>
 
 <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>

js部分代码:

<script>
 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 = '计算机赢了,继续加油哦!';
   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 = '计算机赢了,继续加油哦!';
   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>

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

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

Javascript 相关文章推荐
js function使用心得
May 10 Javascript
js控制表单操作的常用代码小结
Aug 15 Javascript
正则表达式中特殊符号及正则表达式的几种方法总结(replace,test,search)
Nov 26 Javascript
jquery自适应布局的简单实例
May 28 Javascript
AngularJS优雅的自定义指令
Jul 01 Javascript
JavaScript使用Range调色及透明度实例
Sep 25 Javascript
利用Node.JS实现邮件发送功能
Oct 21 Javascript
BootStrap3使用错误记录及解决办法
Dec 22 Javascript
Jquery-data的三种用法
Apr 18 jQuery
node.js 发布订阅模式的实例
Sep 10 Javascript
JavaScript实现全选取消效果
Dec 14 Javascript
详解node child_process模块学习笔记
Jan 24 Javascript
Js Snowflake(雪花算法)生成随机ID的实现方法
Aug 26 #Javascript
uin-app+mockjs实现本地数据模拟
Aug 26 #Javascript
一篇文章带你搞懂Vue虚拟Dom与diff算法
Aug 25 #Javascript
微信小程序换肤功能实现代码(思路详解)
Aug 25 #Javascript
prettier自动格式化去换行的实现代码
Aug 25 #Javascript
Vue中 axios delete请求参数操作
Aug 25 #Javascript
React实现轮播效果
Aug 25 #Javascript
You might like
php基础知识:类与对象(3) 构造函数和析构函数
2006/12/13 PHP
说说PHP的autoLoad自动加载机制
2012/09/27 PHP
PHP读书笔记整理_结构语句详解
2016/07/01 PHP
PHP二维数组矩形转置实例
2016/07/20 PHP
php中错误处理操作实例分析
2019/08/23 PHP
Ext.get() 和 Ext.query()组合使用实现最灵活的取元素方式
2011/09/26 Javascript
js获取元素到文档区域document的(横向、纵向)坐标的两种方法
2013/05/17 Javascript
JQuery页面的表格数据的增加与分页的实现
2013/12/10 Javascript
Extjs grid panel自带滚动条失效的解决方法
2014/09/11 Javascript
直接拿来用的15个jQuery代码片段
2015/09/23 Javascript
js性能优化技巧
2015/11/29 Javascript
详解webpack运行Babel教程
2018/06/13 Javascript
解决vuejs项目里css引用背景图片不能显示的问题
2018/09/13 Javascript
antd配置config-overrides.js文件的操作
2020/10/31 Javascript
[01:02:34]TFT vs VGJ.T Supermajor 败者组 BO3 第二场 6.5
2018/06/06 DOTA
[42:50]NB vs VP 2018国际邀请赛小组赛BO2 第二场 8.18
2018/08/19 DOTA
Python爬虫中urllib库的进阶学习
2018/01/05 Python
利用python如何处理百万条数据(适用java新手)
2018/06/06 Python
Python如何使用turtle库绘制图形
2020/02/26 Python
python 在threading中如何处理主进程和子线程的关系
2020/04/25 Python
keras slice layer 层实现方式
2020/06/11 Python
Python Tkinter图形工具使用方法及实例解析
2020/06/15 Python
pycharm 添加解释器的方法步骤
2020/08/31 Python
Python getsizeof()和getsize()区分详解
2020/11/20 Python
pytest fixtures装饰器的使用和如何控制用例的执行顺序
2021/01/28 Python
纯CSS改变webkit内核浏览器的滚动条样式
2014/04/17 HTML / CSS
业务代表的岗位职责
2013/11/16 职场文书
幼教毕业生自我鉴定
2014/01/12 职场文书
微信营销策划方案
2014/02/24 职场文书
旅游节目策划方案
2014/05/26 职场文书
大一工商管理职业生涯规划:有梦最美,行动相随
2014/09/18 职场文书
护士年终个人总结
2015/02/13 职场文书
辞职信的写法
2015/02/27 职场文书
2016年感恩教师节活动总结
2016/04/01 职场文书
送给小学生的暑假礼物!小学生必背99首古诗
2019/07/02 职场文书
SQL 尚未定义空闲 CPU 条件 - OnIdle 作业计划将不起任何作用
2021/06/30 SQL Server