简单AI五子棋,js,canvas

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了简单AI五子棋,js,canvas相关的知识,希望对你有一定的参考价值。

新年第一篇博客,最近几天走亲访友的没有学习。今天开始进入学习模式。

<!DOCTYPE html>
<html>
<head>
    <title>五子棋</title>
    <link rel="stylesheet" type="text/css" href="./css/style.css">
</head>
<body>
    <canvas id="chess" width="450px" height="450px">
        
    </canvas>
    <script type="text/javascript" src="./js/script.js"></script>
</body>
</html>
canvas{
    display: block;
    margin: 50px auto;
    box-shadow: -2px -2px 2px #efefef,5px 5px 5px #b9b9b9;
}

 

接下来是js代码,也是精华

技术分享
var over=false;//游戏是否结束



//构造赢法数组
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(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++;
    }
}


//赢法统计数组
var myWin=[]
var computerWin=[]
for(var i=0;i<count;i++){
    myWin[i]=0;
    computerWin=0;
}

var chessBorad=[]//标记棋盘是否使用过
for(var i=0;i<15;i++){
    chessBorad[i]=[];
    for(var j=0;j<15;j++){
        chessBorad[i][j]=0;
    }
}

var me=true;

var chess=document.getElementById(‘chess‘);
var context=chess.getContext(‘2d‘);

context.strokeStyle="#bfbfbf";

var logo=new Image();
logo.src="bg.jpg";
logo.onload=function(){
    context.drawImage(logo,0,0,450,450);
    drawChessBoard();

    // oneStep(0,0,1)
    // oneStep(0,1,0)
}
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();

}

chess.onclick=function(e){
    if(over) return;
    var x=e.offsetX;
    var y=e.offsetY;
    var i=Math.floor(x/30);
    var j=Math.floor(y/30);
    if(!chessBorad[i][j]){
        if(!me) return;
        if(me){
            oneStep(i,j,me);
            chessBorad[i][j]=1;
        }else{
            oneStep(i,j,me);
            chessBorad[i][j]=2;
        }
        for(var k=0;k<count;k++){
            if(wins[i][j][k]) {
                myWin[k]++;
                computerWin[k]=6;//表示该赢法舍弃
            }
            if(myWin[k]==5){
                window.alert(k);
                over=true;
            }
        }
        if(!over){
            me=!me;
            computerAI();
        }
    }
}

computerAI=function(){
    var myScore=[];
    var computerScore=[];
    var max=0,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(chessBorad[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]+=100000;
                        }
                        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]+=200000;
                        }
                    }
                }
                if(myScore[i][j]>max){
                    max=myScore[i][j];
                    u=i;
                    v=j;
                }else if(myScore==max){
                    if(computerScore[i][j]>max){     
                        u=i;
                        v=j;
                    }
                }
                if(computerScore[i][j]>max){
                    max=cmputerScore[i][j];
                    u=i;
                    v=j;
                }else if(computerScore==max){
                    if(myScore[i][j]>max){     
                        u=i;
                        v=j;
                    }
                }

            }
        }
    }

    //计算机落子
    oneStep(u,v,false);
    chessBorad[u][v]=2;
    for(var k=0;k<count;k++){
            if(wins[u][v][k]) {
                computerWin[k]++;
                myWin[k]=6;//表示该赢法舍弃
            }
            if(computerWin[k]==5){
                window.alert("你输了");
                over=true;
            }
        }
        if(!over){
            me=!me;
        }
}
View Code

关键是每次计算机落子的时候,遍历棋盘上的所有点,计算出该点落子的得分。

得分有两种,一种是阻击对方胜利,一种是己方胜利得分。

按代码逻辑来说,应该是计算机主动攻击,不过在实际过程中倒是计算机一直在被动防御。

 

这里有几个比较吊的地方。首先是在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 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();

}

 

然后是点击事件的捕捉和处理:

chess.onclick=function(e){
    if(over) return;
    var x=e.offsetX;
    var y=e.offsetY;
    var i=Math.floor(x/30);
    var j=Math.floor(y/30);

捕捉到canvas上面的点击事件,及鼠标点击位置,将其转化成棋盘上面的坐标。简直神奇。

 

其实我很想骂人的,但我忍住了,,

以上是关于简单AI五子棋,js,canvas的主要内容,如果未能解决你的问题,请参考以下文章

原生JS+Canvas实现五子棋游戏

原生 JS + Canvas 实现五子棋游戏

原生 JS + Canvas 实现五子棋游戏

用原生js+canvas实现五子棋

VUE+Canvas实现简单的五子棋游戏

HTML--五子棋JS