热门标签 | 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;


推荐阅读
  • 本文全面解析了JavaScript中的DOM操作,并提供了详细的实践指南。DOM节点(Node)通常代表一个标签、文本或HTML属性,每个节点都具有一个nodeType属性,用于标识其类型。文章深入探讨了DOM节点的创建、查询、修改和删除等操作,结合实际案例,帮助读者更好地理解和掌握DOM编程技术。 ... [详细]
  • 本文探讨了使用JavaScript在不同页面间传递参数的技术方法。具体而言,从a.html页面跳转至b.html时,如何携带参数并使b.html替代当前页面显示,而非新开窗口。文中详细介绍了实现这一功能的代码及注释,帮助开发者更好地理解和应用该技术。 ... [详细]
  • 本文总结了JavaScript的核心知识点和实用技巧,涵盖了变量声明、DOM操作、事件处理等重要方面。例如,通过`event.srcElement`获取触发事件的元素,并使用`alert`显示其HTML结构;利用`innerText`和`innerHTML`属性分别设置和获取文本内容及HTML内容。此外,还介绍了如何在表单中动态生成和操作``元素,以便更好地处理用户输入。这些技巧对于提升前端开发效率和代码质量具有重要意义。 ... [详细]
  • JavaScript XML操作实用工具类:XmlUtilsJS技巧与应用 ... [详细]
  • javascript分页类支持页码格式
    前端时间因为项目需要,要对一个产品下所有的附属图片进行分页显示,没考虑ajax一张张请求,所以干脆一次性全部把图片out,然 ... [详细]
  • 在JavaWeb开发中,文件上传是一个常见的需求。无论是通过表单还是其他方式上传文件,都必须使用POST请求。前端部分通常采用HTML表单来实现文件选择和提交功能。后端则利用Apache Commons FileUpload库来处理上传的文件,该库提供了强大的文件解析和存储能力,能够高效地处理各种文件类型。此外,为了提高系统的安全性和稳定性,还需要对上传文件的大小、格式等进行严格的校验和限制。 ... [详细]
  • 技术分享:使用 Flask、AngularJS 和 Jinja2 构建高效前后端交互系统
    技术分享:使用 Flask、AngularJS 和 Jinja2 构建高效前后端交互系统 ... [详细]
  • 本文介绍了如何在iOS平台上使用GLSL着色器将YV12格式的视频帧数据转换为RGB格式,并展示了转换后的图像效果。通过详细的技术实现步骤和代码示例,读者可以轻松掌握这一过程,适用于需要进行视频处理的应用开发。 ... [详细]
  • 本文探讨了资源访问的学习路径与方法,旨在帮助学习者更高效地获取和利用各类资源。通过分析不同资源的特点和应用场景,提出了多种实用的学习策略和技术手段,为学习者提供了系统的指导和建议。 ... [详细]
  • HBase Java API 进阶:过滤器详解与应用实例
    本文详细探讨了HBase 1.2.6版本中Java API的高级应用,重点介绍了过滤器的使用方法和实际案例。首先,文章对几种常见的HBase过滤器进行了概述,包括列前缀过滤器(ColumnPrefixFilter)和时间戳过滤器(TimestampsFilter)。此外,还详细讲解了分页过滤器(PageFilter)的实现原理及其在大数据查询中的应用场景。通过具体的代码示例,读者可以更好地理解和掌握这些过滤器的使用技巧,从而提高数据处理的效率和灵活性。 ... [详细]
  • 重要知识点有:函数参数默许值、盈余参数、扩大运算符、new.target属性、块级函数、箭头函数以及尾挪用优化《深切明白ES6》笔记目次函数的默许参数在ES5中,我们给函数传参数, ... [详细]
  • 字节流(InputStream和OutputStream),字节流读写文件,字节流的缓冲区,字节缓冲流
    字节流抽象类InputStream和OutputStream是字节流的顶级父类所有的字节输入流都继承自InputStream,所有的输出流都继承子OutputStreamInput ... [详细]
  • 本文详细介绍了 PHP 中对象的生命周期、内存管理和魔术方法的使用,包括对象的自动销毁、析构函数的作用以及各种魔术方法的具体应用场景。 ... [详细]
  • 2.2 组件间父子通信机制详解
    2.2 组件间父子通信机制详解 ... [详细]
  • 本文介绍了UUID(通用唯一标识符)的概念及其在JavaScript中生成Java兼容UUID的代码实现与优化技巧。UUID是一个128位的唯一标识符,广泛应用于分布式系统中以确保唯一性。文章详细探讨了如何利用JavaScript生成符合Java标准的UUID,并提供了多种优化方法,以提高生成效率和兼容性。 ... [详细]
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社区 版权所有