HTML5小游戏之五子棋续篇

本文延续前文,介绍了如何使用HTML5、JavaScript和canvas重构五子棋游戏,采用面向对象的方式提高了代码的扩展性和可维护性。通过这种方式,棋盘大小的调整和其他功能的添加变得更加简便。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

通过上一篇的代码,我们已经实现了五子棋这个游戏,并且可以开始人机大战了。不过js的代码部分还是新手写法,扩展性也不强,也不容易修改,假如我们把棋盘大小改一下要修改很多地方,要加入别的功能也会很困难,所以后续又改成了面向对象的写法,想必这样做的有点我不用再赘述了,直接上代码:

function chess(){
    var self=this;
    this.canvas=document.getElementById("canvas");
    this.context=this.canvas.getContext('2d');
    this.bootWidth=30;
    this.bootHeight=this.bootWidth;
    this.canvasWidth=this.bootWidth*15;
    this.canvasHeight=this.bootHeight*15;
    this.me=true;
    //表示棋盘位置的二维数组
    this.chessBoard=[];
    //定义一个赢法数组
    this.wins=[];
    //赢法种类索引
    this.count=0;
    //定义我和电脑的赢法数组
    this.myWin=[];
    this.computerWin=[];
    this.over=false;
    this.canvas.width=this.canvasWidth;
    this.canvas.height=this.canvasHeight;
    this.img=new Image();
    this.img.src="Images/logo.png";
    this.img.onload=function(){
        self.context.drawImage(self.img,0,0,self.canvasWidth,self.canvasHeight);
        self.drawChessBoard(self.bootWidth,self.bootHeight);
    }
    //将棋盘位置二维数组初始化为0
    this.initChessBoard();
    //初始化赢法数组
    this.initWins();
    //初始化我和电脑的赢法数组
    this.initMeAndComputerWin();
    this.canvas.onclick=function(e){
        if(self.over){
            return;
        }
        var x= e.offsetX;
        var y= e.offsetY;
        var i=Math.floor(x/self.bootWidth);
        var j=Math.floor(y/self.bootHeight);
        if(self.chessBoard[i][j]==0){
            self.oneStep(i,j,self.me);
            //代表这个位置是我的棋子
            self.chessBoard[i][j]=1;             
            for(var k=0;k<self.count;k++){
                if(self.wins[i][j][k]){
                    self.myWin[k]++;
                    //表示这种赢法计算机不可能赢了
                    self.computerWin[k]=6;       
                    if(self.myWin[k]==5){
                        self.over=true;
                        setTimeout(function(){
                            window.alert("电脑赢了");
                            location.reload();
                        },50);
                    }
                }
            }
            //电脑落子
            if(!self.over){
                self.me=!self.me;
                self.computerAI();
            }
        }
    }
}


chess.prototype.drawChessBoard=function(bootWidth,bootHeight){
    this.context.beginPath();
    this.context.strokeStyle="#afafaf";
    for(var i=0;i<15;i++){
        this.context.moveTo(
            bootWidth/2+i*bootWidth,
            bootHeight/2);
        this.context.lineTo(
            bootWidth/2+i*bootWidth,
            this.canvasHeight-bootHeight/2);
        this.context.moveTo(
            bootWidth/2,
            i*bootHeight+bootHeight/2);
        this.context.lineTo(
            this.canvasWidth-bootWidth/2,
            i*bootHeight+bootHeight/2);
    }
    this.context.stroke();
    this.context.closePath();
}
chess.prototype.initChessBoard=function(){
    for(var i=0;i<15;i++){
        this.chessBoard[i]=[];
        for(var j=0;j<15;j++){
            this.chessBoard[i][j]=0;
        }
    }
}
chess.prototype.oneStep=function(i,j,me){
    //i、j是索引,me表示黑棋还是白棋,我方是黑棋
    this.context.beginPath();
    this.context.arc(
        this.bootWidth/2+i*this.bootWidth,
        this.bootWidth/2+j*this.bootWidth,
        13,
        0,
        2*Math.PI);
    this.context.closePath();
    var gradient=this.context.createRadialGradient(
        this.bootWidth/2+i*this.bootWidth+2,
        15+j*this.bootWidth-2,
        13,
        15+i*this.bootWidth+2,
        15+j*this.bootWidth-2,
        0);
    if(me){
        gradient.addColorStop(0,"#0a0a0a");
        gradient.addColorStop(1,"#636766");
    }else{
        gradient.addColorStop(0,"#d1d1d1");
        gradient.addColorStop(1,"#f9f9f9");
    }
    this.context.fillStyle=gradient;
    this.context.fill();
}
chess.prototype.initWins=function(){
    for(var i=0;i<15;i++){
        this.wins[i]=[];
        for(var j=0;j<15;j++){
            this.wins[i][j]=[];
        }
    }
    //所有连成竖线的赢法
    for(var i=0;i<15;i++){
        for(var j=0;j<11;j++){
            for(var k=0;k<5;k++){
                this.wins[i][j+k][this.count]=true;
            }
            this.count++;
        }
    }
    //所有连成横线的赢法
    for(var i=0;i<11;i++){
        for(var j=0;j<15;j++){
            for(var k=0;k<5;k++){
                this.wins[i+k][j][this.count]=true;
            }
            this.count++;
        }
    }
    //所有连成斜线的赢法
    for(var i=0;i<11;i++){
        for(var j=0;j<11;j++){
            for(var k=0;k<5;k++){
                this.wins[i+k][j+k][this.count]=true;
            }
            this.count++;
        }
    }
    //所有连成反斜线的赢法
    for(var i=0;i<11;i++){
        for(var j=14;j>3;j--){
            for(var k=0;k<5;k++){
                this.wins[i+k][j-k][this.count]=true;
            }
            this.count++;
        }
    }
}

chess.prototype.initMeAndComputerWin=function(){
    for(var i=0;i<this.count;i++){
        this.myWin[i]=0;
        this.computerWin[i]=0;
    }
}

chess.prototype.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(this.chessBoard[i][j]==0){
                //遍历所有赢法
                for(var k=0;k<this.count;k++){
                    if(this.wins[i][j][k]){
                        //判断我方在该位置落子好不好,加的分数越多代表越好
                        if(this.myWin[k]==1){
                            myScore[i][j]+=1;
                        }else if(this.myWin[k]==2){
                            myScore[i][j]+=100;
                        }else if(this.myWin[k]==3){
                            myScore[i][j]+=10000;
                        }else if(this.myWin[k]==4){
                            myScore[i][j]+=1000000;
                        }

                        //判断电脑在该位置落子好不好,加的分数越多代表越好
                        if(this.computerWin[k]==1){
                            computerScore[i][j]+=2;
                        }else if(this.computerWin[k]==2){
                            computerScore[i][j]+=220;
                        }else if(this.computerWin[k]==3){
                            computerScore[i][j]+=22000;
                        }else if(this.computerWin[k]==4){
                            computerScore[i][j]+=22000000;
                        }
                    }
                }
                //判断我的最高分位置
                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;
                    }
                }

            }
        }
    }
    this.oneStep(u,v,this.me);
    //代表这个位置是计算机的棋子
    this.chessBoard[u][v]=2;
    for(var k=0;k<this.count;k++){
        if(this.wins[u][v][k]){
            this.computerWin[k]++;
            //表示这种赢法我不可能赢了
            this.myWin[k]=6;
            if(this.computerWin[k]==5){
                this.over=true;
                setTimeout(function(){
                    window.alert("电脑赢了");
                    location.reload();
                },50);
            }
        }
    }
    if(!this.over){
        this.me=!this.me;
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值