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 相关文章推荐
json-lib出现There is a cycle in the hierarchy解决办法
Feb 24 Javascript
关于jQuery参考实例 1.0 jQuery的哲学
Apr 07 Javascript
JavaScript限定复选框的选择个数示例代码
Aug 25 Javascript
JS常用字符串处理方法应用总结
May 22 Javascript
jQuery关键词说明插件cluetip使用指南
Apr 21 Javascript
JavaScript中for循环的几种写法与效率总结
Feb 03 Javascript
JavaScript控制输入框中只能输入中文、数字和英文的方法【基于正则实现】
Mar 03 Javascript
jQuery中each遍历的三种方法实例分析
Sep 07 jQuery
2种在vue项目中使用百度地图的简单方法
Sep 28 Javascript
js使用formData实现批量上传
Mar 27 Javascript
vue中通过使用$attrs实现组件之间的数据传递功能
Sep 01 Javascript
js实现简易计算器功能
Oct 18 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
漫荒推荐:画风超赞的国风漫画推荐 超长假期不无聊
2020/03/08 国漫
php面向对象全攻略 (六)__set() __get() __isset() __unset()的用法
2009/09/30 PHP
使用php判断网页是否gzip压缩
2013/06/25 PHP
php中通过数组进行高效随机抽取指定条记录的算法
2013/09/09 PHP
php获取、检查类名、函数名、方法名的函数方法
2015/06/25 PHP
微信支付开发维权通知实例
2016/07/12 PHP
PHP中OpenSSL加密问题整理
2017/12/14 PHP
PHP给源代码加密的几种方法汇总(推荐)
2018/02/06 PHP
用Div仿showModalDialog模式菜单的效果的代码
2007/03/05 Javascript
Mootools 1.2教程 Tooltips
2009/09/15 Javascript
JavaScript中yield实用简洁实现方式
2010/06/12 Javascript
JavaScript类和继承 this属性使用说明
2010/09/03 Javascript
js登录弹出层特效
2014/03/07 Javascript
JQuery遍历json数组的3种方法
2014/11/08 Javascript
JQuery DIV 动态隐藏和显示的方法
2016/06/23 Javascript
jQuery表单事件实例代码分享
2016/08/18 Javascript
Vue.js实现在下拉列表区域外点击即可关闭下拉列表的功能(自定义下拉列表)
2017/05/30 Javascript
vue使用vue-i18n实现国际化的实现代码
2018/04/08 Javascript
使用JavaScript中的lodash编写双色球效果
2018/06/24 Javascript
layui 设置table 行的高度方法
2018/08/17 Javascript
node 文件上传接口的转发的实现
2019/09/23 Javascript
微信小程序商品详情页底部弹出框
2019/11/22 Javascript
Vue中nprogress页面加载进度条的方法实现
2020/11/13 Javascript
Python中AND、OR的一个使用小技巧
2015/02/18 Python
详解Python爬虫的基本写法
2016/01/08 Python
win8.1安装Python 2.7版环境图文详解
2019/07/01 Python
Python 3.8 新功能全解
2019/07/25 Python
浅析Windows 嵌入python解释器的过程
2019/07/26 Python
python 命令行传入参数实现解析
2019/08/30 Python
python3常用的数据清洗方法(小结)
2019/10/31 Python
Opencv 图片的OCR识别的实战示例
2021/03/02 Python
《玩具柜台前的孩子》教学反思
2014/02/13 职场文书
跳槽求职信范文
2014/05/26 职场文书
公司收款委托书范本
2014/09/20 职场文书
物流业务员岗位职责
2015/04/03 职场文书
使用Python+OpenCV进行卡类型及16位卡号数字的OCR功能
2021/08/30 Python