⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ai.java~9~

📁 j2me源代码
💻 JAVA~9~
字号:
package wzq;

/**
 * <p>Title:五子棋人工智能部分 </p>
 *
 * <p>Description:实现了最基本的人工智能 </p>
 *
 * <p>Copyright: Copyright (c) 2005</p>
 *
 * <p>Company: Star Group</p>
 *
 * @author: wangyaobsz
 * @version 1.0
 */
public class AI {
    /**
     * 找到最佳下棋点。
     * 基本思路是, 先计算每个点的权值,在权值最高的位置下棋
     */
    public static Point findBestLocation(Chesses chess) {
        //权值数组
        int[][] power = new int[Chesses.BOARD_SIZE][Chesses.BOARD_SIZE];
        for (short i = 0; i < Chesses.BOARD_SIZE; i++) {
            for (short j = 0; j < Chesses.BOARD_SIZE; j++) {
                // 当已有子时将该点的权值设为-1
                if (chess.getChess()[i][j] != 0) {
                    power[i][j] = -1;
                }
                // 否则计算该点权值
                else {
                    power[i][j] = (short) calcPower(i, j, chess.getCurrentType(),
                            chess);
                }
            }
        }
        //计算完所有点的权值后, 再找出其中权值最大的点
        Point bestLoc = calcMaxPowerLocation(power);
        power = null;
        return bestLoc;
    }

    /**
     * 遍历权值数组,找出权值最大点.
     * @param power
     * @return
     */
    private static Point calcMaxPowerLocation(int[][] power) {
        int max = 0;
        short x = 0, y = 0;
        for (short i = 0; i < Chesses.BOARD_SIZE; i++) {
            for (short j = 0; j < Chesses.BOARD_SIZE; j++) {
                if (power[i][j] > max) {
                    x = i;
                    y = j;
                    max = power[i][j];
                }
            }
        }
        return new Point(x, y);
    }

    /**
     * 检查m,n点的权值.<p>
     * 思路是, 假定在m,n位置下棋后,计算4个方向经过该点,同色相连的棋子数量, 不同的数量有不同的
     * 权值,将四个方向上权值相加即为该点的权值.计算完后恢复该点的状态.
     * @param m
     * @param n
     * @param currentType:当前棋子的类型
     * @param chess
     * @return
     */
    private static int calcPower(short m, short n, short currentType,
                                 Chesses chess) {
        int p = 0;

        //找取胜点,
        int p1 = 1000;
        //找三个相连的点
        int p3 = 60;
        //找两个相连的点
        int p5 = 20;
        //找相连的点
        int p7 = 10;

        //找对手的取胜点
        int p2 = 85;
        //找对手的三个相连的点
        int p4 = 45;
        //找对手的两个相连的点
        int p6 = 15;
        //找对方的相连的点
        int p8 = 5;

        short[] arrLinks = new short[4];
        //首先模拟我方下棋,在该点预下一子,预测棋局的权值分布,然后进行后续计算.
        chess.setChessFeeler(m, n, currentType);

        // 计算4个方向上同色相连棋子的数量.
        arrLinks = calcLinkCount(m, n, chess.getChess());

        //如果m,n是中心点, 将权值加1
        if (m == Chesses.BOARD_SIZE / 2 &&
            n == Chesses.BOARD_SIZE / 2) {
            p += 1;
        }
        //计算我方在该点四个方向的权值
        for (short i = 0; i < 4; i++) {
            if (Math.abs(arrLinks[i]) == 5) {
                p += p1;
            }
            if (arrLinks[i] == 4) {
                p += p3;
            }
            if (arrLinks[i] == 3) {
                p += p5;
            }
            if (arrLinks[i] == 2) {
                p += p7;
            }
        }
        //首先模拟我方下棋,在该点预下一子,预测棋局的权值分布,然后进行后续计算.
        if (currentType == Chesses.BLACK_CHESS) {
            //如果对方是白子,
            chess.setChessFeeler(m, n, Chesses.WHITE_CHESS);
        } else {
            //如果对方是黑子,
            chess.setChessFeeler(m, n, Chesses.BLACK_CHESS);
        }

        arrLinks = calcLinkCount(m, n, chess.getChess());
        //计算对手在该点四个方向的权值
        for (short i = 0; i < 4; i++) {
            if (Math.abs(arrLinks[i]) == 5) {
                p += p2;
            }
            if (arrLinks[i] == 4) {
                p += p4;
            }
            if (arrLinks[i] == 3) {
                p += p6;
            }
            if (arrLinks[i] == 2) {
                p += p8;
            }
        }
        //计算完后恢复该点的原来状态.
        chess.setChessFeeler(m, n, 0);
        arrLinks = null;
        return p;
    }

    /**
     * 计算4个方向相连棋子的个数
     * @param m
     * @param n
     * @param arrchessboard
     * @return 返回一个4元素的数据,分别代表(m,n)点上四个方向听相连子的个数.
     */
    private static short[] calcLinkCount(short m, short n,short[][] arrchessboard)
    {
        short[] counts = new short[4];

        //检查是否无子可下(当flag=2时表示无子可下)
        short flag = 0;
        //连子个数
        short num = 1;

        //检查正东方向
        short x = (short) (m + 1);
        int y = n + 1;
        //不超出棋格
        for (; x < Chesses.BOARD_SIZE; ) {
            //如果前方的棋子与m,n点不同则跳出循环
            if (arrchessboard[x][n] == arrchessboard[m][n]) {
                num++;
                x++;
            } else {
                break;
            }
        }
        //正东方向超出棋格
        if (x == Chesses.BOARD_SIZE) {
            flag++;
        } else {
            //正东方向有别的子不可再下
            if (arrchessboard[x][n] != 0) {
                flag++;
            }
        }

        //检查正西方向
        x = (short) (m - 1);
        for (; x >= 0; ) {
            //前方的棋子与m,n点不同时跳出循环
            if (arrchessboard[x][n] == arrchessboard[m][n]) {
                num++;
                x--;
            } else {
                break;
            }
        }
        //正西方向超出棋格
        if (x == -1) {
            flag++;
        } else {
            //正西方向有别的子不可再下
            if (arrchessboard[x][n] != 0) {
                flag++;
            }
        }

        if (flag == 2) {
            counts[0] = (short) - num;
        } else {
            if (flag == 1 && num == 3) {
                //连子数为3时有一边不能下就不是活三
                counts[0] = (short) - num;
            } else {
                counts[0] = num;
            }
        }

        //检查是否无子可下(当flag=2时表示无子可下)
        flag = 0;
        //连子个数
        num = 1;
        //检查正南方向
        x = (short) (n + 1);
        for (; x < Chesses.BOARD_SIZE; ) {
            //前方的棋子与m,n点不同时跳出循环
            if (arrchessboard[m][x] == arrchessboard[m][n]) {
                num++;
                x++;
            } else {
                break;
            }
        }
        //正南方向超出棋格
        if (x == Chesses.BOARD_SIZE) {
            flag++;
        } else {
            //正南方向有别的子不可在下
            if (arrchessboard[m][x] != 0) {
                flag++;
            }
        }

        //检查正北方向
        x = (short) (n - 1);
        for (; x >= 0; ) {
            //前方的棋子与m,n点不同时跳出循环
            if (arrchessboard[m][x] == arrchessboard[m][n]) {
                num++;
                x--;
            } else {
                break;
            }
        }
        //正北方向超出棋格
        if (x == -1) {
            flag++;
        } else {
            //正北方向有别的子不可在下
            if (arrchessboard[m][x] != 0) {
                flag++;
            }
        }

        if (flag == 2) {
            counts[1] = (short) - num;
        } else {
            if (flag == 1 && num == 3) {
                //连子数为3时有一边不能下就不是活三
                counts[1] = (short) - num;
            } else {
                counts[1] = num;
            }
        }

        //检查是否无子可下(当flag=2时表示无子可下)
        flag = 0;
        //连子个数
        num = 1;

        //检查东南方向
        x = (short) (m + 1);
        //不超出棋格
        for (; x < Chesses.BOARD_SIZE && y < Chesses.BOARD_SIZE; ) {
            //前方的棋子与m,n点不同时跳出循环
            if (arrchessboard[x][y] == arrchessboard[m][n]) {
                num++;
                x++;
                y++;
            } else {
                break;
            }
        }
        //东南方向超出棋格
        if (x == Chesses.BOARD_SIZE || y == Chesses.BOARD_SIZE) {
            flag++;
        } else {
            //东南方向有别的子不可在下
            if (arrchessboard[x][y] != 0) {
                flag++;
            }
        }

        //检查西北方向
        x = (short) (m - 1);
        y = n - 1;
        //不超出棋格
        for (; x >= 0 && y >= 0; ) {
            //前方的棋子与m,n点不同时跳出循环
            if (arrchessboard[x][y] == arrchessboard[m][n]) {
                num++;
                x--;
                y--;
            } else {
                break;
            }
        }
        //西北方向超出棋格
        if (x == -1 || y == -1) {
            flag++;
        } else {
            //西北方向有别的子不可在下
            if (arrchessboard[x][y] != 0) {
                flag++;
            }
        }

        if (flag == 2) {
            counts[2] = (short) - num;
        } else {
            if (flag == 1 && num == 3) {
                //连子数为3时有一边不能下就不是活三
                counts[2] = (short) - num;
            } else {
                counts[2] = num;
            }
        }

        //检查是否无子可下(当flag=2时表示无子可下)
        flag = 0;
        //连子个数
        num = 1;

        //检查西南方向
        x = (short) (m - 1);
        y = n + 1;
        //不超出棋格
        for (; x >= 0 && y < Chesses.BOARD_SIZE; ) {
            //前方的棋子与m,n点不同时跳出循环
            if (arrchessboard[x][y] == arrchessboard[m][n]) {
                num++;
                x--;
                y++;
            } else {
                break;
            }
        }
        //西南方向超出棋格
        if (x == -1 || y == Chesses.BOARD_SIZE) {
            flag++;
        } else {
            //西南方向有别的子不可在下
            if (arrchessboard[x][y] != 0) {
                flag++;
            }
        }

        //检查东北方向(
        x = (short) (m + 1);
        y = n - 1;
        //不超出棋格
        for (; x < Chesses.BOARD_SIZE && y >= 0; ) {
            //前方的棋子与m,n点不同时跳出循环
            if (arrchessboard[x][y] == arrchessboard[m][n]) {
                num++;
                x++;
                y--;
            } else {
                break;
            }
        }
        //东北方向超出棋格
        if (x == Chesses.BOARD_SIZE || y == -1) {
            flag++;
        } else {
            //东北方向有别的子不可在下
            if (arrchessboard[x][y] != 0) {
                flag++;
            }
        }

        if (flag == 2) {
            counts[3] = (short) - num;
        } else {
            if (flag == 1 && num == 3) {
                //连子数为3时有一边不能下就不是活三
                counts[3] = (short) - num;
            } else {
                counts[3] = num;
            }
        }

        // 返回四个方向的相连子的个数。
        return counts;
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -