我会把html文件、css文件提供下载地址,文件夹路径也展示给大家。但是图片就没法一一放在博客里面了。 |
可以点击下载:https://download.csdn.net/download/qq_43592352/12367801
运行图片
目录路径
五子棋.html
<html> <head> <title>五子棋-黑子电脑</title> <link rel="stylesheet" type="text/css" href="css/style.css"/> <script src="jquery-3.3.1.js" type="text/javascript"></script> </head> <body> <div id=container> <div id=chessboard> </div> </div> </body> <script type="text/javascript"> /**********************自定义便捷函数*******************************/ function getRandom(min,max){//获取在区间[min.max]内的int数 let s; s=parseInt(Math.random()*max+1); while(s<min) { s=parseInt(Math.random()*max+1); } return s; } /**************************定义初始化数据*****************************************/ /***封装棋盘里面的点 类*****/ function Point(index,hang,lie){ this.idnex=index; this.hang=hang; this.lie=lie; this.state=0; this.pointX=-17+(this.lie-1)*52; this.pointY=-17+(14-this.hang+1)*52; } var pointsScore=new Array(226); var points=new Array(226); for(let i=1;i<=225;i++) { points[i]=new Point(i,parseInt((i-1)/15+1),i-parseInt((i-1)/15)*15); pointsScore[i]=0; } console.log(points[15].pointX); /**************************系统设置*****************************************/ /* * 封装游戏容器居中 */ (() => { let screenHeight=parseInt($(window).height()); //浏览器时下窗口可视区域高度 let screenWidth=parseInt($(window).width()); //浏览器时下窗口可视区域高度 let containerHeigth=parseInt($("#container").height());//container容器高度 let containerWidth=parseInt($("#container").width());//container容器宽度 $("#container").css({ 'marginLeft':(screenWidth-containerWidth)/2+'px', 'marginTop':(screenHeight-containerHeigth)/2+'px', }) })(); /** 根据鼠标相对于棋盘坐标轴的位置,以30*30px大小的正方形位界限, ** 搜索在矩形内是否有point点存在,然后根据坐标确定points的index */ let getPointsIndex = (movex,movey) => { let hang=-1,lie=-1; for(let i=1;i<=15;i++){ if(movex<=points[i].pointX+32&&movex>=points[i].pointX+2) lie=i; if(movey<=points[i].pointX+32&&movey>=points[i].pointX+2) hang=16-i; } if(hang==-1||lie==-1) return 0; return (hang-1)*15+lie; } addChess(1,113); /***对点击事件,获取相对于棋盘坐标轴的位置,然后根据坐标确定points的index*****/ $("#container").on("click",function(e){ console.log("--------点击了!"); e = e || window.event; if(e.pageX || e.pageY) { movex = e.pageX-parseInt($("#container").css("marginLeft"))-37; movey = e.pageY-parseInt($("#container").css("marginTop"))-12; } console.log("--------检索到坐标的index为:"+getPointsIndex(movex,movey)); addChess(-1,getPointsIndex(movex,movey)); addChess(1,computer(getPointsIndex(movex,movey))); }) /*******添加棋子********/ function addChess(state,index){//state代表状态,1黑子 -1白子 var img=$(new Image()); img.attr({ 'src':'css/img/'+(state==1?'black':'white')+'.png', 'class':'chess' }); img.css({ 'margin-left':points[index].pointX+'px', 'margin-top':points[index].pointY+'px', }); points[index].state=state; $("#chessboard").append(img); } /**************************电脑算法*****************************************/ /***评分表***/ var score1={//白子为电脑 电脑主…… 我也不知道主进攻还是防守 empty : 7, b_1 : 35, b_2 : 800, b_3 : 15000, b_4 : 80000, w_1 : 15, w_2 : 400, w_3 : 1800, w_4 : 10000, polluted : 0 } function getScore(isEmpty,isPolluted,stateNum,state,i){//白棋为电脑,主防守 let fen=score1; if(points[i].state!=0) pointsScore[i]=0; else{ if(isPolluted) pointsScore[i]+=fen.polluted; else if(isEmpty) pointsScore[i]+=fen.empty; else { if(stateNum==1&&state==1) pointsScore[i]+=fen.b_1; else if(stateNum==2&&state==1) pointsScore[i]+=fen.b_2; else if(stateNum==3&&state==1) pointsScore[i]+=fen.b_3; else if(stateNum==4&&state==1) pointsScore[i]+=fen.b_4; if(stateNum==1&&state==-1) pointsScore[i]+=fen.w_1; else if(stateNum==2&&state==-1) pointsScore[i]+=fen.w_2; else if(stateNum==3&&state==-1) pointsScore[i]+=fen.w_3; else if(stateNum==4&&state==-1) pointsScore[i]+=fen.w_4; } } } function computer(index){ for(let i=1;i<=225;i++) pointsScore[i]=0; for(let q=1;q<=225;q++){ let hangPointIndex=q;//得到此点的index for(let j=1;j<=5;j++)//遍历与此点横相关的五元组,理论上有五个五元组 { if(points[hangPointIndex].lie>=j&&points[hangPointIndex].lie<=10+j)//筛选可成立的五元组 { let isEmpty=1,isPolluted=0,isPolluted1=0,isPolluted2=0,stateNum=0,state=0; for(let k=1;k<=5;k++) { if(points[hangPointIndex+k-j].state!=0) {isEmpty=0;stateNum++;} if(points[hangPointIndex+k-j].state==1) isPolluted1=1; if(points[hangPointIndex+k-j].state==-1) isPolluted2=1; } if(isPolluted1==1&&isPolluted2==1) isPolluted=1; if(isPolluted1==1&&isPolluted2==0) state=1; if(isPolluted1==0&&isPolluted2==1) state=-1; getScore(isEmpty,isPolluted,stateNum,state,hangPointIndex); } } let liePointIndex=q;//得到此点的index for(let j=1;j<=5;j++)//遍历与此点纵相关的五元组,理论上有五个五元组 { if(points[liePointIndex].hang>=j&&points[liePointIndex].hang<=10+j)//筛选可成立的五元组 { var isEmpty=1,isPolluted=0,isPolluted1=0,isPolluted2=0,stateNum=0,state=0; for(var k=1;k<=5;k++) { if(points[liePointIndex+(k-j)*15].state!=0) {isEmpty=0;stateNum++;} if(points[liePointIndex+(k-j)*15].state==1) isPolluted1=1; if(points[liePointIndex+(k-j)*15].state==-1) isPolluted2=1; } if(isPolluted1==1&&isPolluted2==1) isPolluted=1; if(isPolluted1==1&&isPolluted2==0) state=1; if(isPolluted1==0&&isPolluted2==1) state=-1; getScore(isEmpty,isPolluted,stateNum,state,liePointIndex); } } let nowIndex=q;//获取此时point的索引index for(var j=1;j<=5;j++)//遍历与此点正斜(形如“/”)相关的五元组,理论上有五个五元组 { if(points[nowIndex].hang>=j&&points[nowIndex].hang<=10+j&&points[nowIndex].lie>=j&&points[nowIndex].lie<=10+j)//筛选可成立的五元组 { var isEmpty=1,isPolluted=0,isPolluted1=0,isPolluted2=0,stateNum=0,state=0; for(var k=1;k<=5;k++) { if(points[nowIndex+(k-j)*16].state!=0) {isEmpty=0;stateNum++;} if(points[nowIndex+(k-j)*16].state==1) isPolluted1=1; if(points[nowIndex+(k-j)*16].state==-1) isPolluted2=1; } if(isPolluted1==1&&isPolluted2==1) isPolluted=1; if(isPolluted1==1&&isPolluted2==0) state=1; if(isPolluted1==0&&isPolluted2==1) state=-1; getScore(isEmpty,isPolluted,stateNum,state,nowIndex); } } for(var j=1;j<=5;j++)//遍历与此点反斜(形如“\”)相关的五元组,理论上有五个五元组 { if(points[nowIndex].hang>=6-j&&points[nowIndex].hang<=16-j&&points[nowIndex].lie>=j&&points[nowIndex].lie<=10+j)//筛选可成立的五元组 { var isEmpty=1,isPolluted=0,isPolluted1=0,isPolluted2=0,stateNum=0,state=0; for(var k=1;k<=5;k++) { if(points[nowIndex-(k-j)*14].state!=0) {isEmpty=0;stateNum++;} if(points[nowIndex-(k-j)*14].state==1) isPolluted1=1; if(points[nowIndex-(k-j)*14].state==-1) isPolluted2=1; } if(isPolluted1==1&&isPolluted2==1) isPolluted=1; if(isPolluted1==1&&isPolluted2==0) state=1; if(isPolluted1==0&&isPolluted2==1) state=-1; getScore(isEmpty,isPolluted,stateNum,state,nowIndex); } } } let maxIndex=[],max=0; for(let val of pointsScore) if(val>max) max=val; for(let i=1;i<=225;i++) if(pointsScore[i]==max) maxIndex.push(i); return maxIndex[parseInt(Math.random()*(maxIndex.length))]; } </script> </html>
五子棋算法
五子棋有15行、15列,一共225个点。假设每个点都有自己的分数。
我们遍历每个点。
如上图,对于每个点来说,它在横、竖、正斜(“/”)、反斜(“\”)四个方向上,都会有包含此点的五元组,一共20个。
我们遍历这20个五元组。
对于每个五元组来说,如果里面有黑子有白子,我们称五元组被污染了,如果五元组是空的,或者有1个到4个白子或黑子,我们都给出相应的分数。评分表如下:
/***评分表***/ empty : 7, b_1 : 35, b_2 : 800, b_3 : 15000, b_4 : 80000, w_1 : 15, w_2 : 400, w_3 : 1800, w_4 : 10000, polluted : 0
最后20个五元组得出的分数,都加再这一点上面。
之后遍历225个点的分数,得出最大分数的点,下棋。
算法结构大致画为:
进行下一个游戏的开发!
注意事项
【1】 原创博客,转载本篇请与我联系,尊重版权。
【2】 关于阅读本篇博客的所有问题、代码源码、图片素材、编程技巧、编程经历都可联系我,与我交流讨论。
【3】 本人部分时间承接各种毕业设计、网站编写、微信小程序编写、数据库作业编写。需要请加QQ:1460787433,详聊。