功能模块

先看下现在做完的效果:

代码详解

人机对战功能实现

从效果图可以看到,棋盘的横竖可以放的位置为15*15,通过canvas画棋盘:

//绘画棋盘

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

}

}

根据赢法总数定义分别保存计算机和人赢法的数组:

for(var i = 0; i < count; i++){

myWin[i] = 0;

_myWin[i] = 0;

computerWin[i] = 0;

_compWin[i] = 0;

}

然后就是人开始下棋:

// 我,下棋

chess.onclick = function(e){

if(over){ // 游戏结束

return;

}

if(!me){

return;

}

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]){

myWin[k]++;

_compWin[k] = computerWin[k]; // 为悔棋做准备

computerWin[k] = 6;//这个位置对方不可能赢了

if(myWin[k] == 5){

resultTxt.innerHTML = '恭喜,你赢了!';

over = true;

}

}

}

if(!over){

me = !me;

computerAI();

}

}

// 悔棋功能可用

backbtn.className = backbtn.className.replace( new RegExp( "(\\s|^)unable(\\s|$)" )," " );

}

oneStep() 方法为落子,要在棋盘上画一个棋子:

//画棋子

var oneStep = function(i,j,me){

// debugger;

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();

}

接着看计算机怎么下棋,具体看computerAI()方法:

// 计算机下棋

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;

}

}

根据相应的权重,计算出计算机应该落子的位置。

悔棋功能

要提的是,这里暂时只能悔一步棋。悔棋功能主要关键点是:1、销毁刚刚下的棋子;2、将之前不可能赢的状态还原;看下具体的代码:

// 悔棋

backbtn.onclick = function(e){

if(!backAble) { return;}

over = false;

me = true;

// 我,悔棋

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.className = returnbtn.className.replace( new RegExp( "(\\s|^)unable(\\s|$)" )," " );

}

minusStep()为销毁棋子的方法,我们看下是怎么销毁的。

//销毁棋子

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();

}

首先通过clearRect()擦掉该圆,然后再重新画该圆周围的格子,注意相应的位置,这里花了些时间折腾。

撤销悔棋功能

悔棋过后,再撤销,相当于还原悔棋之前的状态。代码比较简单:

// 撤销悔棋

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++){

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;

}

总结

五子棋游戏的核心关键点是:1、弄清楚有多少种赢法;2、怎么判断是否已经赢了;3、计算机下棋算法。这里巧妙地运用数组存储赢法,判断是否赢了,通过权重比较,计算出计算机该下棋的位置。

过程中用到canvas,之前有学习过,虽然很久没用,查了些资料,复习了怎么画线,画圆,学会了怎么如何清除一个圆等。

然后要注意的是,用原生Js怎么为元素添加、删除class。

最后代码放到github上了,地址:https://github.com/wj704/wj704.github.io/blob/master/five_game.html

参考资料:

http://www.cnblogs.com/gdcgy/p/5379159.html

html五子棋游戏制作原理,原生JS+Canvas实现五子棋游戏相关推荐

  1. 五子棋人机对战_原生JS+Canvas实现五子棋游戏

    原生JS+Canvas实现五子棋游戏 效果图 主要功能模块为: 1.人机对战功能 2.悔棋功能 3.撤销悔棋功能 二.代码详解 2.1 人机对战功能实现 从效果图可以看到,棋盘的横竖可以放的位置为15 ...

  2. html五子棋悔棋,原生 JS + Canvas 实现五子棋游戏

    原标题:原生 JS + Canvas 实现五子棋游戏 || 一.功能模块 先看下现在做完的效果: 线上体验: https://wj704.github.io/five_game.html 主要功能模块 ...

  3. 前端小白写了个网页版五子棋游戏,使用原生 JS + Canvas 实现绘制棋子、棋盘

    功能模块 快来体验下吧!看下你能赢得了计算机么? 主要功能模块为: 1.人机对战功能 2.悔棋功能 3.撤销悔棋功能 老规矩,源码贴上 具体代码 (1)HTML代码 <!DOCTYPE html ...

  4. 图片五子棋PHP接口,原生JS+Canvas实现五子棋游戏实例

    一.功能模块 先看下现在做完的效果: 主要功能模块为: 1.人机对战功能 2.悔棋功能 3.撤销悔棋功能 二.代码详解 2.1 人机对战功能实现 从效果图可以看到,棋盘的横竖可以放的位置为15*15, ...

  5. 记忆翻牌游戏代码html,原生JS实现记忆翻牌游戏

    本文实例为大家分享了JS实现记忆翻牌游戏的具体代码,供大家参考,具体内容如下 html代码 css代码 * { padding: 0; margin: 0; } #game { width: 600p ...

  6. 使用原生JS+Canvas实现五子棋游戏

    布局+样式部分代码 : <style type='text/css'>canvas {display: block;margin: 50px auto;box-shadow: -2px - ...

  7. php 设计五子棋游戏,基于js+canvas实现五子棋小游戏

    本文实例为大家分享了js+canvas实现五子棋小游戏的具体代码,供大家参考,具体内容如下 效果展示: 源码展示: 五子棋 * { margin: 0; padding: 0; } body { ma ...

  8. matlab 模拟心电图,使用原生js+canvas实现模拟心电图的实例

    从2015年2月转行进入IT行业,到现在也有将近两年的时间了,从最开始的java到现在的前端,前进的路上一直靠自己摸索,一路走到现在,前端大神是绝对谈不上的,最多算一只刚入门的菜鸟. 从最开始的懵懵懂 ...

  9. java心电图_使用原生js+canvas实现模拟心电图

    从2016年2月转行进入IT行业,到现在也有将近两年的时间了,从最开始的java到现在的前端,前进的路上一直靠自己摸索,一路走到现在,前端大神是绝对谈不上的,最多算一只刚入门的菜鸟. 从最开始的懵懵懂 ...

最新文章

  1. 【更新】比较智能的爬取姓名
  2. KafkaProducer初始化时涉及到哪些核心组件?
  3. 陈国良、孙永强教授获中国计算机学会「终身成就奖」,为国内并行算法和编译技术先驱...
  4. ArcGIS符号异常问题
  5. BZOJ-1009-GT考试-HNOI2008
  6. 《轩辕传奇手游》主程序带你拆解MMORPG游戏客户端
  7. kaggle中zillow比赛中模型融合的方法及其代码
  8. java校验邮箱_Java正则表达式校验邮箱和手机号 | 学步园
  9. flutter PositionedTransition 实现缩放动画
  10. jquery级试题_jQuery经典面试题及答案精选
  11. java_opts 参数与JVM内存调优
  12. Python与数据结构[4] - 散列表[1] - 分离链接法的 Python 实现
  13. opencv舌头监测模型+keras神经网络(LeNet)
  14. solr6.3与MySQL结合使用的简明教程一
  15. select命名_Maya中Pymel写个带界面的重命名工具(一)
  16. 我在这战斗的一年里(阎阳生)
  17. Linux安装GCC方法
  18. VNCTF2021[WEB]
  19. perl脚本基础总结(转)
  20. php 扑克牌洗牌算法,随机洗牌算法 | 学步园

热门文章

  1. AS使用自己的手机设备进行调试
  2. 初级算法题->有效的数独--弄清哈希表的本质
  3. 腾讯推出微信企业服务平台风铃
  4. 软件测试工具有哪些?--最全最新的软件测试工具下载地址都在这里,错过绝对后悔
  5. 【若依框架】集成JWT
  6. RT-Thread ENV工具 pkgs --upgrade 报错:open .config failed
  7. Exponetial BackOff(指数退避算法)
  8. 哈佛结构和冯诺伊曼结构
  9. Python爬取猫眼电影榜单评分,以及评论
  10. 五阶魔方公式java_五阶魔方降阶法公式是什么?