五子棋

该文章简要介绍java五子棋的思路。

一、画棋盘

首先在已经创建好的窗体内绘制五子棋棋盘。主要根据窗体大小来通过画直线的方式来绘制棋盘,或者可以引入已经画好棋盘的背景图。以下主要介绍通过画直线的方式来绘制棋盘的思路。

1.首先设置中间为画图面板

this.setBackground(Color.WHITE);

        frame.add(this, BorderLayout.CENTER);

    this.addMouseListener(this);

2.将绘制棋盘的代码写入重画函数中,因为每下一个棋子都得对棋盘进行重绘。

public void paint(Graphics g){

        super.paint(g);

        g.drawRect(47, 35, 750, 700);

        g.drawRect(37, 30, 770, 710);

        for(int i = 1;i<75/5;i++){

           g.drawLine(47+50*i, 35, 47+50*i, 735);

        }

        for(int i = 1;i<70/5;i++){

           g.drawLine( 47, 35+50*i, 797, 35+50*i);

        }

        if(kaiju){

           for(int i = 0;i<16;i++){

               for(int j = 0;j<15;j++){

                   if(qizi[i][j]==1){//白子

                       g.setColor(Color.WHITE);

                       g.fillOval(22+50*i, 10+50*j, 50, 50);

                       g.setColor(Color.BLACK);

                       g.drawOval(22+50*i, 10+50*j, 50, 50);

                   }

                   if(qizi[i][j]==2){//黑子

                       g.setColor(Color.BLACK);

                       g.fillOval(22+50*i, 10+50*j, 50, 50);

                   }

               }

           }

        }

}

其中设置了一个棋子数组来存储黑子、白子、空的情况。

二、下棋子

设置鼠标监听,通过获取鼠标点击的位置来判断棋子下的位置。

x = e.getX();

        y = e.getY();

        g = this.getGraphics();

        if((x-47)%50<25){

           locx = (x-47)/50;

        }

        else{

           locx = (x-47)/50+1;

        }

        if((y-35)%50<25){

           locy = (y-35)/50;

        }

        else{

           locy = (y-35)/50+1;

        }

并且下子前应判断当前位置是否能下子。可通过上面设置的棋子数组中所存储的数值来判断当前位置是否有棋子。

三、判断是否连成五子

判断棋盘中是否存在连成五子的情况,只需判断下的最后一颗棋子是否连成五子。首先应该判断最后一颗棋子四个方向(竖直、水平、左斜、右斜)上,连成的棋子个数。

//判断是否连成5

    public int checkHorizon(int x,int y){//判断水平方向

        count = 1;

        panduan = 0;

        num = 1;

        n = 1;

        for(int i = x+1;i<x+5&&i<16;i++){//向右

           if(qizi[i][y]==0){

               n++;

           }

           else if(qizi[x][y]==qizi[i][y]&&count==n){

               count++;

               n++;

           }

           else{

               panduan ++;

               break;

           }

        }

        num = n - count;

        n = count;

        for(int i = x-1;i>x-5&&i>=0;i--){//向左

            if(qizi[i][y]==0){

               n++;

           }

           else if(qizi[x][y]==qizi[i][y]&&count==n){

               count++;

               n++;

           }

           else{

               panduan ++;

               break;

           }

        }

        num+=n;

        return count;

    }

    public int checkVeritical(int x,int y){//判断竖直方向

        count = 1;

        panduan = 0;

        num = 1;

        n = 1;

        for(int i = y+1;i<y+5&&i<15;i++){//向下

           if(qizi[x][i]==0){

               n++;

           }

           else if(qizi[x][y]==qizi[x][i]&&count==n){

               count++;

               n++;

           }

           else{

               panduan ++;

               break;

           }

        }

        num = n - count;

        n = count;

        for(int i = y-1;i>y-5&&i>=0;i--){//向上

           if(qizi[x][i]==0){

               n++;

           }

           else if(qizi[x][y]==qizi[x][i]&&count==n){

               count++;

               n++;

           }

           else{

               panduan ++;

               break;

           }

        }

        num+=n;

        return count;

    }

    public int checkLeft(int x,int y){//判断左斜方向

        count = 1;

        panduan = 0;

        num = 1;

        n = 1;

        for(int i =1;i<5&&(y+i)<15&&(x+i)<16;i++){//左斜向下

           if(qizi[x+i][y+i]==0){

               n++;

           }

           else if(qizi[x][y]==qizi[x+i][y+i]&&count==n){

               count++;

               n++;

           }

           else{

               panduan ++;

               break;

           }

        }

        num = n - count;

        n = count;

        for(int i =-1;i>-5&&(y+i)>=0&&(x+i)>=0;i--){//左斜向上

           if(qizi[x+i][y+i]==0){

               n++;

           }

           else if(qizi[x][y]==qizi[x+i][y+i]&&count==n){

               count++;

               n++;

           }

           else{

               panduan ++;

               break;

            }

        }

        num+=n;

        return count;

    }

    public int checkRight(int x,int y){//判断右斜方向

        count = 1;

        panduan = 0;

        num = 1;

        n = 1;

        for(int i =1;i<5&&(y+i)<15&&(x-i)>=0;i++){//右斜向下

           if(qizi[x-i][y+i]==0){

               n++;

           }

           else if(qizi[x][y]==qizi[x-i][y+i]&&count==n){

               count++;

               n++;

           }

           else{

               panduan ++;

               break;

           }

        }

        num = n - count;

        n = count;

        for(int i =-1;i>-5&&(y+i)>=0&&(x-i)<16;i--){//右斜向上

           if(qizi[x-i][y+i]==0){

               n++;

           }

           else if(qizi[x][y]==qizi[x-i][y+i]&&count==n){

               count++;

               n++;

           }

           else{

               panduan ++;

               break;

           }

        }

        num+=n;

        return count;

}

其中,num为连成棋子的个数,n为可下棋子空间的个数(即空子加上连子的个数)。

四、人人对战

人人对战较为简单,只需判断最后一颗棋子是否连成五子,再设置一个boolean变量来记录当前棋子的黑白即可。

五、人机对战

人机对战较人人对战而言需要设置电脑的AU算法来计算当前落子的最佳位置。

1、首先电脑可以遍历棋盘可下子的位置来判断当前落子的最佳位置。

2、可以设置一个较为合理的估分函数,对每个可落子的位置进行评分,最后选出分值最大的位置落子。

估分函数如下:

public void score(int count,int x,int y){

        if(qizi[x][y]==1){

           if(count==2){

               score[x][y] += 1;//堵人一子

           }

           else if(count==3){

               if(panduan==0){

                   score[x][y] += 10;//堵人活二

               }

               else if(panduan==1){

                   score[x][y] += 5;//堵人死二

               }

           }

           else if(count==4){

               if(panduan==0){

                   score[x][y] += 300;//堵人活三

               }

               else if(panduan==1){

                   score[x][y] += 30;//堵人死三

               }

           }

           else if(count==5){

               score[x][y] += 1000;//堵人四子

           }

        }

        else if(qizi[x][y]==2){

           if(count==2){

               if(panduan==0){

                   score[x][y] += 8;//电脑活一转活二

               }

               else if(panduan==1){

                   score[x][y] += 2;//电脑死一转死二

               }

           }

           else if(count==3){

               if(panduan==0){

                   score[x][y] += 50;//电脑活二转活三

               }

               else if(panduan==1){

                   score[x][y] += 25;//电脑死二转死三

               }

           }

           else if(count==4){

               if(panduan==0){

                   score[x][y] += 500;//电脑活三转活四

               }

               else if(panduan==1){

                   score[x][y] += 100;//电脑死三转死四

               }

           }

           else if(count==5){

               score[x][y]+=10000;//连成五子

               co = false;//黑子

           }

        }

       

}

也可以利用哈希表来记录分值情况,哈希表较以上而言较为复杂但是可以记录多种情况,甚至可以通过哈希表录入棋盘,以达到优化AU算法的目的。

对算法的优化也可以通过剪枝,剪去不必要遍历的位置,以提高算法运行速度。

六、悔棋

悔棋较为简单,只需要把棋子数组中存储的情况进行修改再重画棋盘即可。

if(!cho){//人人

               qizi[locx][locy]=0;

               this.paint(g);

               co = !co;

           }

           else{//人机

               qizi[locx][locy]=0;

               qizi[maxx][maxy]=0;

               this.paint(g);

        }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值