【前端】AI五子棋游戏186行

2024-04-18 16:04

本文主要是介绍【前端】AI五子棋游戏186行,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

这个来源于网上,不过代码改了不少,减少了些代码便于学习。 

<!DOCTYPE html>
<html><body><h3>AI五子棋游戏</h3><canvas id="chess" width="450px" height="450px"></canvas><script>var chressBord = []; //棋盘			var wins = [];  //存放所有5个棋子在一条线上所有可能性,第一维存放y, 第二维存放x,第三维存放当前的可能性编号var count = 0; //赢法总数量var myWin = []; //我们赢法的统计数组var computerWin = []; //计算机赢法的统计数组var chess = document.getElementById("chess");var context = chess.getContext('2d');for(var i = 0; i < 15; i++){chressBord[i] = [];wins[i] = [];for(var j = 0; j < 15; j++){chressBord[i][j] = 0;wins[i][j] = [];}}//横线赢法for(var i = 0; i < 15; i++)for(var j = 0; j < 11; j++,count++)for(var k = 0; k < 5; k++)wins[i][j+k][count] = true;//竖线赢法for(var i = 0; i < 15; i++)for(var j = 0; j < 11; j++,count++)for(var k = 0; k < 5; k++)wins[j+k][i][count] = true;//正斜线赢法for(var i = 0; i < 11; i++)for(var j = 0; j < 11; j++,count++)for(var k = 0; k < 5; k++)wins[i+k][j+k][count] = true;//反斜线赢法for(var i = 0; i < 11; i++)  for(var j = 14; j > 3; j--,count++)for(var k = 0; k < 5; k++)wins[i+k][j-k][count] = true;for(var i = 0; i < count; i++){myWin[i] = 0; //这个数组很精髓,记录下棋后我方每一个位置在每种赢法的得分computerWin[i] = 0;}chess.onclick = function(e) // 我,下棋{var i = Math.floor(e.offsetX / 30);var j = Math.floor(e.offsetY / 30);if(chressBord[i][j] == 0){MoveStep(i,j,"red", 1, myWin);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++){						for(var k = 0; k < count; k++) //遍历到i,j这个坐标时,计算谁的得分更高{if(chressBord[i][j] != 0 || !wins[i][j][k]) //当前i,j坐标还没落子continue;switch(myWin[k]){case 1: myScore[i][j] += 200; break;case 2: myScore[i][j] += 400; break;case 3: myScore[i][j] += 2000; break;case 4: myScore[i][j] += 10000; break;}switch(computerWin[k]){case 1: computerScore[i][j] += 220; break;case 2: computerScore[i][j] += 420; break;case 3: computerScore[i][j] += 2100; break;case 4: computerScore[i][j] += 20000; break;}}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]) //如果电脑在i,j落子的分数比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;    }}}}MoveStep(u,v,"blue", 2, computerWin);}var CheckWin = function(i, j, Role, WinArray){			for(var k = 0; k < count; k++)if(wins[i][j][k]) // 将可能赢的情况都加1{WinArray[k]++;if(WinArray[k] >= 5)alert(Role + ': 恭喜,你赢了!')}}//绘画棋盘var drawChessBoard = function() {for(var i = 0; i < 15; i++){context.moveTo(15 + i * 30 , 15);context.lineTo(15 + i * 30 , 435);context.moveTo(15 , 15 + i * 30);context.lineTo(435 , 15 + i * 30);context.stroke();}}drawChessBoard(); // 画棋盘var MoveStep = function(i,j,Role, ID, WinArray) //落子{context.beginPath();context.arc(15 + i * 30, 15 + j * 30, 13, 0, 2 * Math.PI);// 画圆context.closePath();    context.fillStyle = Role;context.fill(); //填充颜色chressBord[i][j] = ID; //玩家ID棋盘位置占位CheckWin(i,j,Role, WinArray);  //判断是否获胜,这里也很精髓,递归思想}</script></body>
</html>

附原来的代码:

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title>AI五子棋游戏</title><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></head><body><h3 id="result-wrap">AI五子棋</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><script type="text/javascript" charset="utf-8">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++){ // 将可能赢的情况都加1if(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++){ // 将可能赢的情况都减1if(wins[_nowi][_nowj][k]){myWin[k]--;computerWin[k] = _compWin[k];//这个位置对方可能赢}}// 计算机相应的悔棋chressBord[_compi][_compj] = 0; //计算机,已占位置 还原minusStep(_compi, _compj); //销毁棋子                                  for(var k = 0; k < count; k++){ // 将可能赢的情况都减1if(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++){ // 将可能赢的情况都减1if(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;}// 计算机下棋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;}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></body>
</html>

这篇关于【前端】AI五子棋游戏186行的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/915235

相关文章

前端如何通过nginx访问本地端口

《前端如何通过nginx访问本地端口》:本文主要介绍前端如何通过nginx访问本地端口的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、nginx安装1、下载(1)下载地址(2)系统选择(3)版本选择2、安装部署(1)解压(2)配置文件修改(3)启动(4)

HTML中meta标签的常见使用案例(示例详解)

《HTML中meta标签的常见使用案例(示例详解)》HTMLmeta标签用于提供文档元数据,涵盖字符编码、SEO优化、社交媒体集成、移动设备适配、浏览器控制及安全隐私设置,优化页面显示与搜索引擎索引... 目录html中meta标签的常见使用案例一、基础功能二、搜索引擎优化(seo)三、社交媒体集成四、移动

HTML input 标签示例详解

《HTMLinput标签示例详解》input标签主要用于接收用户的输入,随type属性值的不同,变换其具体功能,本文通过实例图文并茂的形式给大家介绍HTMLinput标签,感兴趣的朋友一... 目录通用属性输入框单行文本输入框 text密码输入框 password数字输入框 number电子邮件输入编程框

HTML img标签和超链接标签详细介绍

《HTMLimg标签和超链接标签详细介绍》:本文主要介绍了HTML中img标签的使用,包括src属性(指定图片路径)、相对/绝对路径区别、alt替代文本、title提示、宽高控制及边框设置等,详细内容请阅读本文,希望能对你有所帮助... 目录img 标签src 属性alt 属性title 属性width/h

CSS3打造的现代交互式登录界面详细实现过程

《CSS3打造的现代交互式登录界面详细实现过程》本文介绍CSS3和jQuery在登录界面设计中的应用,涵盖动画、选择器、自定义字体及盒模型技术,提升界面美观与交互性,同时优化性能和可访问性,感兴趣的朋... 目录1. css3用户登录界面设计概述1.1 用户界面设计的重要性1.2 CSS3的新特性与优势1.

HTML5 中的<button>标签用法和特征

《HTML5中的<button>标签用法和特征》在HTML5中,button标签用于定义一个可点击的按钮,它是创建交互式网页的重要元素之一,本文将深入解析HTML5中的button标签,详细介绍其属... 目录引言<button> 标签的基本用法<button> 标签的属性typevaluedisabled

HTML5实现的移动端购物车自动结算功能示例代码

《HTML5实现的移动端购物车自动结算功能示例代码》本文介绍HTML5实现移动端购物车自动结算,通过WebStorage、事件监听、DOM操作等技术,确保实时更新与数据同步,优化性能及无障碍性,提升用... 目录1. 移动端购物车自动结算概述2. 数据存储与状态保存机制2.1 浏览器端的数据存储方式2.1.

基于 HTML5 Canvas 实现图片旋转与下载功能(完整代码展示)

《基于HTML5Canvas实现图片旋转与下载功能(完整代码展示)》本文将深入剖析一段基于HTML5Canvas的代码,该代码实现了图片的旋转(90度和180度)以及旋转后图片的下载... 目录一、引言二、html 结构分析三、css 样式分析四、JavaScript 功能实现一、引言在 Web 开发中,

CSS place-items: center解析与用法详解

《CSSplace-items:center解析与用法详解》place-items:center;是一个强大的CSS简写属性,用于同时控制网格(Grid)和弹性盒(Flexbox)... place-items: center; 是一个强大的 css 简写属性,用于同时控制 网格(Grid) 和 弹性盒(F

CSS实现元素撑满剩余空间的五种方法

《CSS实现元素撑满剩余空间的五种方法》在日常开发中,我们经常需要让某个元素占据容器的剩余空间,本文将介绍5种不同的方法来实现这个需求,并分析各种方法的优缺点,感兴趣的朋友一起看看吧... css实现元素撑满剩余空间的5种方法 在日常开发中,我们经常需要让某个元素占据容器的剩余空间。这是一个常见的布局需求