软件编程
位置:首页>> 软件编程>> java编程>> Java实现在线五子棋对战游戏(人机对战)

Java实现在线五子棋对战游戏(人机对战)

作者:独一无二的哈密瓜  发布时间:2023-01-10 19:07:29 

标签:Java,五子棋,游戏

1. 人机对战

要增添一个人机对战的模块, 最大的难点就是如何让人机知道下在什么位置是最好的, 不仅要具备进攻的能力, 还需要具备防守的能力.

这里当人机第一次走的时候, 采用标准开局, 下子在最中间.

当玩家走了之后, 人机就需要去判定下在什么位置合理.

这里采用的是评分表的方法来计算落子在每一个位置的分数, 根据最高分数来进行下子.

1.1 演示

Java实现在线五子棋对战游戏(人机对战)

1.2 评分表

分析棋形的几种情况.

例如, 自己是黑子.

"_" 代表 没有子, "1" 代表 黑子 , "0" 代表 白子

当落子只有一颗子的情况

  • ① _ 1 _

  • ② _ 1 0

  • ③ 0 1 _

  • ④ 0 1 0

当落子有两颗子的情况

  • ① _ 1 1 _

  • ② _ 1 1 0

  • ③ 0 1 1 _

  • ④ 0 1 1 0

当落子有三颗子的情况

  • ① _ 1 1 1 _

  • ② _ 1 1 1 0

  • ③ 0 1 1 1 _

  • ④ 0 1 1 1 0

当落子有四颗子的情况

  • ① _ 1 1 1 1 _

  • ② _ 1 1 1 1 0

  • ③ 0 1 1 1 1 _

  • ④ 0 1 1 1 1 0

当落子有五颗子的情况

  • ① _ 1 1 1 1 1 _

  • ② _ 1 1 1 1 1 0

  • ③ 0 1 1 1 1 1 _

  • ④ 0 1 1 1 1 1 0

这里大概的情况分为这几种, 分别对这几种情况进行一个分数的设定, 让机器人根据分数的高低优先去处理某种情况.

这里设计一种分数表

一子情况

Java实现在线五子棋对战游戏(人机对战)

二子情况

Java实现在线五子棋对战游戏(人机对战)

三子情况

Java实现在线五子棋对战游戏(人机对战)

四子情况

Java实现在线五子棋对战游戏(人机对战)

五子情况

Java实现在线五子棋对战游戏(人机对战)

1.3 算法思路

使用暴力搜索的方法, 将棋盘中每个空格的子, 当下子的时候, 去判定下子之后, 横向得分情况, 竖向得分情况, 左斜得分情况, 右斜的得分情况.

例如, 下子是黑子.

  • 横向, 去看左边有多少个黑子, 多少白子, 去看右边有多少个黑子, 多少白子. 然后根据评分表, 算得分数.

  • 纵向, 去看上方有多少黑子, 多少白子, 再去下方看有多少个黑子, 多少白子, 然后根据评分表, 算得分数.

  • 左斜, 去左下方看有多少黑子, 多少白子, 再去右上方看有多少黑子, 多少白子, 然后根据评分表, 算得分数.

  • 右斜. 去左上方看有多少黑子,多少白子, 再去右下方看有多少黑子, 多少白子, 然后根据评分表, 算得分数.

将四个方向的得分加起来, 算得分数, 进行下子.

这里这种算法, 只具备了进攻, 不具备防守的能力. 要想人机下棋具备防守的能力, 还需要让人机对玩家落子的分数进行评估, 如果玩家落子得分更高, 就需要考虑去防守了.

这里就让, 对每个位置, 机器人落子, 和玩家落子, 算得机器人落子的得分, 和玩家落子的得分, 对分数进行相加, 然后再去比较, 当前是最大的得分情况, 就去当前位置落子.

这里进行测试的时候, 发现出现四子的时候, 会出现不进攻 或者不防守的情况. 所以在判定的时候, 如果出现了五子连珠的情况, 首先进攻. 如果对方有四子, 自己没法五子, 首先防守.

1.4 具体代码

1.4.1 评分表方法

根据评分表来分配分数, my表示我下的棋子, his表示他下的棋子

public int score(int my,int his){
       if(my > 5) return 200000;
       if(my == 5 && his == 0) return 200000;
       if(my == 5 && his == 1) return 200000;
       if(my == 5 && his == 2) return 200000;
       if(my == 4 && his == 1) return 3000;
       if(my == 4 && his == 0) return 50000;
       if(my == 4 && his == 2) return 1000;
       if(my == 3 && his == 0) return 3000;
       if(my == 3 && his == 1) return 1000;
       if(my == 3 && his == 2) return 500;
       if(my == 2 && his == 0) return 500;
       if(my == 2 && his == 1) return 200;
       if(my == 2 && his == 2) return 100;
       if(my == 1 && his == 0) return 100;
       if(my == 1 && his == 1) return 50;
       if(my == 1 && his == 2) return 30;
       return 0;
   }

1.4.2 横向得分方法

算得横向自己棋子数, 和他的棋子数

如果遇到空格就不计算了, 遇到别人的棋子也不计算了

public int getXScore(int x,int y, int chess){
       int my = 1;
       int his = 0;
       for(int i = x-1; i >= 0; i--){
           if(chess == board[i][y]){
               my++;
           }else if(board[i][y] == 0){
               break;
           }else{
               his++;
               break;
           }
       }
       for(int i = x+1; i<board.length; i++) {
           if(chess == board[i][y]){
               my++;
           }else if(board[i][y] == 0){
               break;
           }else{
               his++;
               break;
           }
       }
       return score(my,his);
   }

1.4.3 纵向得分方法

算得纵向自己棋子数, 和他的棋子数

如果遇到空格就不计算了, 遇到别人的棋子也不计算了

private int getYScore(int x, int y, int chess) {
       int my = 1;
       int his = 0;
       for(int i = y-1; i >= 0; i--){
           if(chess == board[x][i]){
               my++;
           }else if(board[x][i] == 0){
               break;
           }else{
               his++;
               break;
           }
       }
       for(int i = y+1; i < board.length; i++){
           if(chess == board[x][i]){
               my++;
           }else if(board[x][i] == 0){
               break;
           }else{
               his++;
               break;
           }
       }
       return score(my,his);
   }

1.4.4 左斜得分方法

算得左斜向自己棋子数, 和他的棋子数

如果遇到空格就不计算了, 遇到别人的棋子也不计算了

private int getSkewScore2(int x, int y, int chess) {
       int my = 1;
       int his = 0;
       for(int i = x+1,j=y-1; i<board.length && j >=0; i++,j--){
           if(chess == board[i][j]){
               my++;
           }else if(board[i][j] == 0){
               break;
           }else{
               his++;
               break;
           }
       }
       for(int i = x-1,j=y+1; i>=0 && j<board.length; i--,j++){
           if(chess == board[i][j]){
               my++;
           }else if(board[i][j] == 0){
               break;
           }else{
               his++;
               break;
           }
       }
       return score(my,his);
   }

1.4.5 右斜得分方法

算得右斜向自己棋子数, 和他的棋子数

如果遇到空格就不计算了, 遇到别人的棋子也不计算了

private int getSkewScore1(int x, int y, int chess) {
       int my = 1;
       int his = 0;
       for(int i = x-1,j =y-1; i >=0 && j>=0; i--,j--){
           if(chess == board[i][j]){
               my++;
           }else if(board[i][j] == 0){
               break;
           }else{
               his++;
               break;
           }
       }
       for(int i = x+1,j=y+1; j<board.length && i < board.length; i++,j++){
           if(chess == board[i][j]){
               my++;
           }else if(board[i][j] == 0){
               break;
           }else{
               his++;
               break;
           }
       }
       return score(my,his);
   }

1.4.6 落子总得分方法

这里如果自己下的子可以优先五子连珠就直接下棋.

如果没有这种情况, 再去判定是否他可以五子连珠, 如果有直接堵住

其他就计算总分数

public int getScore(int x,int y) {
       int numX1 = getXScore(x,y,1);
       int numX2 = getXScore(x,y,2);
       int numY1 = getYScore(x,y,1);
       int numY2 = getYScore(x,y,2);
       int skew1 = getSkewScore1(x,y,1);
       int skew2 = getSkewScore1(x,y,2);
       int skew3 = getSkewScore2(x,y,1);
       int skew4 = getSkewScore2(x,y,2);
       if(numX2 >= 200000 || numY2 >= 200000 || skew2 >= 200000 || skew4 >= 200000) {
           return Integer.MAX_VALUE;
       }
       if(numX1 >= 200000 || numY1 >= 200000 || skew1 >= 200000 || skew3 >= 200000){
           return Integer.MAX_VALUE;
       }
       int xScore = getXScore(x,y,1)+getXScore(x,y,2);
       int yScore = getYScore(x,y,1)+getYScore(x,y,2);
       int skewScore1 = getSkewScore1(x,y,1)+getSkewScore1(x,y,2);
       int skewScore2 = getSkewScore2(x,y,1)+getSkewScore2(x,y,2);
       return xScore + yScore + skewScore1 + skewScore2;
   }

1.4.7 确认落子位置的方法

public int[] concluate() {
       int[] res = new int[2];
       int max = 0;
       for(int i = 0; i < Constant.ROW; i++) {
           for(int j = 0; j < Constant.COL; j++) {
               if(board[i][j] != 0) {
                   continue;
               }
               int num = getScore(i,j);
               if(num == 200000){
                   res[0] = i;
                   res[1] = j;
                   return res;
               }
               if(num > max) {
                   max = num;
                   res[0] = i;
                   res[1] = j;
               }
           }
       }
       return res;
   }

来源:https://blog.csdn.net/wwzzzzzzzzzzzzz/article/details/127061995

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com