热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

原生JS+Canvas完成五子棋游戏

一、功用模块先看下如今做完的结果:线上体验:https:wj704.github.iofive_…重要功用模块为:1.人机对战功用2.悔棋功用3.打消悔棋功用二、代码详解2.1人机

一、功用模块

先看下如今做完的结果:

《原生JS+Canvas完成五子棋游戏》

线上体验:https://wj704.github.io/five_…
重要功用模块为:
1.人机对战功用
2.悔棋功用
3.打消悔棋功用

二、代码详解

2.1 人机对战功用完成

从结果图能够看到,棋盘的反正能够放的位置为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 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 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 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 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;
}
}

依据响应的权重,计算出计算机应当落子的位置。

2.2 悔棋功用

要提的是,这里临时只能悔一步棋。悔棋功用重要症结点是: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 if(wins[_nowi][_nowj][k]){
myWin[k]--;
computerWin[k] = _compWin[k];//这个位置对方能够赢
}
}
// 计算机响应的悔棋
chressBord[_compi][_compj] = 0; //计算机,已占位置 复原
minusStep(_compi, _compj); //烧毁棋子
for(var k = 0; k 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()擦掉该圆,然后再从新画该圆四周的格子,注重响应的位置,这里花了些时候折腾。

2.3 打消悔棋功用

悔棋事后,再打消,相当于复原悔棋之前的状况。代码比较简单:

// 打消悔棋
returnbtn.Onclick= function(e){
if(!returnAble) { return; }
// 我,打消悔棋
chressBord[_nowi][_nowj] = 1; //我,已占位置
oneStep(_nowi,_nowj,me);
for(var k = 0; 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 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/wj70&#8230;
参考材料:
http://www.cnblogs.com/gdcgy/&#8230;


推荐阅读
author-avatar
mobiledu2502858723
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有