五子棋html游戏代码与算法介绍
我会把html文件、css文件提供下载地址,文件夹路径也展示给大家。但是图片就没法一一放在博客里面了。 大家有需要的话,加博主QQ:2864144286,全天在线。 |
运行图片
目录路径
五子棋.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】 原创博客,转载本篇请与我联系,尊重版权。QQ:2864144286
【2】 关于阅读本篇博客的所有问题、代码源码、图片素材、编程技巧、编程经历都可联系我,与我交流讨论。
【3】 本人部分时间承接各种毕业设计、网站编写、微信小程序编写、数据库作业编写。需要请加QQ:2864144286,详聊。