五子棋5.0(完结)

增加人机对战功能,以及该功能与原程序融合。

一、创建人机AIChess类。

1、AI原理解释

使用0、1、2表示该位置不同的棋子状态,使用哈希表赋给不同的分值,用于后续计算AI下棋的位置。

2、功能实现

(1)首先创建一个AIChess类

存储AI功能的代码,同时初始化一个行列值。

package gobangv4;


import java.awt.*;
import java.util.Arrays;
import java.util.HashMap;

public class AIChess implements Data{
    int r = 0;
    int c = 0;
}

(2)创建一个哈希表存储不同情况的分值

//存储得分
    int[][] codeArr = new int[16][16];
    //定义不同情况下的分值
    HashMap<String,Integer> map =new HashMap<>();
    {
        map.put("010", 10);
        map.put("0110", 100);
        map.put("01110", 1000);
        map.put("011110", 5000);

        map.put("020", 10);
        map.put("0220", 100);
        map.put("02220", 1000);
        map.put("022220", 5000);

        map.put("01", 5);
        map.put("011", 50);
        map.put("0111", 500);
        map.put("01111", 5000);

        map.put("02", 5);
        map.put("022", 50);
        map.put("0222", 500);
        map.put("02222", 5000);

    }

(3)获取每个无棋子的位置的分值

public void getCodeArr(int[][] chessArr){
        //遍历现在的棋盘,得到每个位置的棋子状态
        for (int i = 0; i < chessArr.length; i++) {
            for (int j = 0; j < chessArr.length; j++) {
                //首先判断是否为没有棋子的位置
                int cnum = chessArr[i][j];
                if (cnum == 0){
                    //分别向八个方向遍历
                    toLeft(chessArr,i,j);
                    toRight(chessArr,i,j);
                    toUp(chessArr,i,j);
                    toDown(chessArr,i,j);
                    toTopLeft(chessArr,i,j);
                    toTopRight(chessArr,i,j);
                    toBottomLeft(chessArr,i,j);
                    toBottomRight(chessArr,i,j);
                }
            }
        }
    }
//toLeft向左遍历
    public void toLeft(int[][] chessArr,int r,int c){
        if (c == 0) {
            //处于棋盘最左侧,无需向左遍历
            return;
        }
        int cn1 = chessArr[r][c-1];
        if (cn1 == 0) {
            //左侧第一位没有棋子
            return;
        }
        String codeStr = "0"+cn1;
        for (int i = c-2; i >= 0 ; i--) {
            if (chessArr[r][i] == cn1) {
                //左侧为相同颜色棋子
                codeStr += cn1;
            }else {
                if (chessArr[r][i] == 0){
                    //左侧一位没有棋子
                    codeStr += "0";
                }
                break;
            }
        }
        //根据哈希表获得该位置的分数
        int code = map.get(codeStr);
        System.out.println(codeStr + ":" + code);
        codeArr[r][c] += code;
    }
    //toright向右遍历
    public void toRight(int[][] chessArr,int r,int c){
        if (c == chessArr.length-1){
            //处于棋盘最右侧,无需向右遍历
            return;
        }
        int cn1 = chessArr[r][c+1];
        if (cn1 == 0) {
            //右侧第一位没有棋子
            return;
        }
        String codeStr = "0" + cn1;
        for (int i = c+2; i < chessArr.length ; i++) {
            if (chessArr[r][i] == cn1) {
                //右侧为相同颜色棋子
                codeStr += cn1;
            }else {
                if (chessArr[r][i] == 0){
                    //右侧一位没有棋子
                    codeStr += "0";
                }
                break;
            }
        }
        //根据哈希表获得该位置的分数
        System.out.println(codeStr);
        int code = map.get(codeStr);
        System.out.println(codeStr + ":" + code);
        codeArr[r][c] += code;
    }
    //toup向上遍历
    public void toUp(int[][] chessArr,int r,int c){
        if (r == 0){
            //处于棋盘最上侧,无需向上遍历
            return;
        }
        int cn1 = chessArr[r-1][c];
        if (cn1 == 0){
            //上侧第一位没有棋子
            return;
        }
        String codeStr = "0" + cn1;
        for (int i = r-2; i >= 0 ; i--) {
            if (chessArr[i][c] == cn1){
                //上侧为相同颜色棋子
                codeStr += cn1;
            }else {
                if (chessArr[i][c] == 0){
                    //上侧一位没有棋子
                    codeStr += "0";
                }
                break;
            }
        }
        int code = map.get(codeStr);
        System.out.println(codeStr + ":" + code);
        codeArr[r][c] += code;
    }
    //todown向下遍历
    public void toDown(int[][] chessArr,int r,int c){
        if (r == chessArr.length-1){
            //处于棋盘最下侧,无需向下遍历
            return;
        }
        int cn1 = chessArr[r+1][c];
        if (cn1 == 0){
            //下侧第一位没有棋子
            return;
        }
        String codeStr = "0" + cn1;
        for (int i = r+2; i < chessArr.length ; i++) {
            if (chessArr[i][c] == cn1){
                //下侧为相同颜色棋子
                codeStr += cn1;
            }else {
                if (chessArr[i][c] == 0){
                    //下侧一位没有棋子
                    codeStr += "0";
                }
                break;
            }
        }
        int code = map.get(codeStr);
        System.out.println(codeStr + ":" + code);
        codeArr[r][c] += code;
    }
    //totopLeft左上侧遍历
    public void toTopLeft(int[][] chessArr,int r,int c){
        if (r == 0 || c == 0){
            //棋子在最左侧、最上侧和左上角顶点
            return;
        }
        int cn1 = chessArr[r-1][c-1];
        if (cn1 == 0){
            //左上侧一位无棋子
            return;
        }
        String codeStr = "0" + cn1;
        int i = r-2;
        int j = c-2;
        while(i >= 0 && j >= 0){
            if (chessArr[i][j] == cn1){
                //左上侧为相同颜色棋子
                codeStr += cn1;
                i--;
                j--;
            }else {
                if (chessArr[i][j] == 0){
                    //左上侧一位没有棋子
                    codeStr += "0";
                }
                break;
            }
        }
        int code = map.get(codeStr);
        System.out.println(codeStr + ":" + code);
        codeArr[r][c] += code;
    }
    //totopRight右上侧遍历
    public void toTopRight(int[][] chessArr,int r,int c){
        if (r == 0 || c == chessArr.length-1){
            //棋子在最右侧、最上侧和右上角顶点
            return;
        }
        int cn1 = chessArr[r-1][c+1];
        if (cn1 == 0){
            //右上侧一位无棋子
            return;
        }
        String codeStr = "0" + cn1;
        int i = r-2;
        int j = c+2;
        while(i >= 0 && j < 16){
            if (chessArr[i][j] == cn1){
                //右上侧为相同颜色棋子
                codeStr += cn1;
                i--;
                j++;
            }else {
                if (chessArr[i][j] == 0){
                    //右上侧一位没有棋子
                    codeStr += "0";
                }
                break;
            }
        }
        int code = map.get(codeStr);
        System.out.println(codeStr + ":" + code);
        codeArr[r][c] += code;
    }
    //toBottomLeft左下侧遍历
    public void toBottomLeft(int[][] chessArr,int r,int c){
        if (r == chessArr.length-1 || c == 0){
            //棋子在最左侧、最下侧和左下角顶点
            return;
        }
        int cn1 = chessArr[r+1][c-1];
        if (cn1 == 0){
            //左下侧一位无棋子
            return;
        }
        String codeStr = "0" + cn1;
        int i = r+2;
        int j = c-2;
        while(i < 16 && j >= 0){
            if (chessArr[i][j] == cn1){
                //左下侧为相同颜色棋子
                codeStr += cn1;
                i++;
                j--;
            }else {
                if (chessArr[i][j] == 0){
                    //左下侧一位没有棋子
                    codeStr += "0";
                }
                break;
            }
        }
        System.out.println(codeStr);
        int code = map.get(codeStr);
        System.out.println(codeStr + ":" + code);
        codeArr[r][c] += code;
    }
    //toBottomRight右下侧遍历
    public void toBottomRight(int[][] chessArr,int r,int c){
        if (r == chessArr.length-1 || c == chessArr.length-1){
            //棋子在最右侧、最下侧、右下角顶点
            return;
        }
        int cn1 = chessArr[r+1][c+1];
        if (cn1 == 0){
            //右下侧一位无棋子
            return;
        }
        String codeStr = "0" + cn1;
        int i = r+2;
        int j = c+2;
        while(i < 16 && j < 16){
            if (chessArr[i][j] == cn1){
                //右下侧为相同颜色棋子
                codeStr += cn1;
                i++;
                j++;
            }else {
                if (chessArr[i][j] == 0){
                    //右下侧一位没有棋子
                    codeStr += "0";
                }
                break;
            }
        }
        int code = map.get(codeStr);
        System.out.println(codeStr + ":" + code);
        codeArr[r][c] += code;
    }

(4)创建主函数进行测试

public static void main(String[] args) {
        GameListener gameListener;
        //模拟测试棋盘
        int[][] chessArr = {

                {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                {0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                {0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                {0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                {0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                {0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                {0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                {0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                {0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                {0, 0, 1, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                {0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                {2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},


        };
        AIChess aiChess = new AIChess();
        aiChess.getCodeArr(chessArr);

    }

3、AI功能与源代码适配

(1)源代码优化

1>创建一个ChessUtils类,将人机对战、人人对战、悔棋以及新增的一些优化功能加入其中
public class ChessUtils implements Data {

    int chessStatus = 0;
    Graphics g;
    int[][] chessArr = new int[ROW + 1][COL + 1];
    ToWin toWin = new ToWin();
    int chessSize = 0;
    Chess[] chessList = new Chess[256];
    String gameModel = "人人对战";
    int agame = 0;
}
2>添加前置条件的检查
public boolean check(int x, int y) {
        // 计算行列值
        int r = (y - Y + SIZE / 2) / SIZE;
        int c = (x - X + SIZE / 2) / SIZE;

        if (chessStatus == 0) {
            JOptionPane.showMessageDialog(null,
                    "请先开始新的对局~");
            return false;
        }

        if (r > ROW || c > COL || x < X - SIZE / 2 || y < Y - SIZE / 2) {
            JOptionPane.showMessageDialog(null,
                    "请在棋盘内落子~");
            return false;
        }
        if (chessArr[r][c] != 0) {
            JOptionPane.showMessageDialog(null, "此处已有棋子~");
            return false;
        }
        return true;
    }
3>人人对战
// 人人对战
    public void pvpPlay(int x, int y) {
        // 计算行列值
        int r = (y - Y + SIZE / 2) / SIZE;
        int c = (x - X + SIZE / 2) / SIZE;

        if (!check(x, y)) {
            return;
        }
        chessArr[r][c] = chessStatus;
        Chess chess = new Chess(chessStatus,r,c);
        chessList[chessSize] = chess;
        chessSize++;
        // 判断落子颜色
        if (chessStatus == 1) {
            g.setColor(Color.BLACK);
            chessStatus = 2;
        } else if (chessStatus == 2) {
            g.setColor(Color.WHITE);
            chessStatus = 1;
        }
        // 根据行列值还原标准坐标
        int chessX = c * SIZE + X - SIZE / 2;
        int chessY = r * SIZE + Y - SIZE / 2;
        // 绘制棋子
        g.fillOval(chessX, chessY, SIZE, SIZE);
        if (toWin.isWin(chessArr,r, c)) {
            JOptionPane.showMessageDialog(null, chessStatus== 1 ? "白棋胜利" : "黑棋胜利");
            //将棋子状态归为0,使得后续不能再下棋。
            chessStatus = 0;
        }
    }
4>人机对战
// 人机对战
    public void pvAPlay(int x, int y) {
        //人落子
        if (!check(x, y)) {
            return;
        }
        // 计算行列值
        int r = (y - Y + SIZE / 2) / SIZE;
        int c = (x - X + SIZE / 2) / SIZE;
        chessArr[r][c] = 1;
        Chess chess = new Chess(1, r, c);
        chessList[chessSize] = chess;
        // 根据行列值还原标准坐标
        int chessX = c * SIZE + X - SIZE / 2;
        int chessY = r * SIZE + Y - SIZE / 2;
        // 绘制棋子
        g.setColor(Color.BLACK);
        g.fillOval(chessX, chessY, SIZE, SIZE);
        chessSize++;
        //判断输赢
        if (toWin.isWin(chessArr, r, c)) {
            JOptionPane.showMessageDialog(null, "玩家胜利");
            //将棋子状态归为0,使得后续不能再下棋。
            chessStatus = 0;
        }

        //AI落子
        AIChess aiChess = new AIChess();
        aiChess.playAI(chessArr, g);
        int ar = aiChess.r;
        int ac = aiChess.c;
        chessArr[ar][ac] = 2;
        Chess achess = new Chess(2, ar, ac);
        chessList[chessSize] = achess;
        chessSize++;

        if (toWin.isWin(chessArr, ar, ac)) {
            JOptionPane.showMessageDialog(null, "AI胜利");
            //将棋子状态归为0,使得后续不能再下棋。
            chessStatus = 0;
        }
    }
5>悔棋功能
public void goBack() {

        if (chessSize <= 0) {
            return;
        }
        int count = 1;
        if (gameModel.equals("人机对战")) {
            count = 2;
        }
        for (int i = 0; i < count; i++) {
            //获取最后一个棋子
            Chess chess = chessList[chessSize - 1];
            //将悔棋去除的棋子位置设置为无棋子
            chessArr[chess.r][chess.c] = 0;
            //表明这个位置现在没有棋子对象
            chessList[chessSize - 1] = null;
            //确保下次落子棋子的颜色正确
            chessStatus = chess.chessflag;
            //去除悔棋的棋子的数量
            chessSize--;
            //重绘棋盘
            drawChessPad();
            //按照悔棋后的棋子位置画出棋子
            drawChess();
        }

    }
6>赋予开局和结束对局条件
public void initGame() {
        chessStatus = 1;
        agame = 1;
        chessArr = new int[ROW + 1][COL + 1];
    }

    public void end() {
        chessStatus = 0;
        agame = 0;
    }
7>人人对战和人机对战的切换
GameLietener中mousePressed部分优化为以下代码:
@Override
    public void mousePressed(MouseEvent e) {
        super.mousePressed(e);

        //得到点击坐标
        int x = e.getX();
        int y = e.getY();
        chessUtils.play(x,y);
    }
play部分代码如下:
public void play(int x, int y) {
        if (gameModel.equals("人人对战")) {
            pvpPlay(x, y);
        } else if (gameModel.equals("人机对战")) {
            pvAPlay(x, y);
        }
    }
8>控制对局期间无法切换人人对战和人机对战功能

GameLietener中actionPerformed部分改动为:

else if (ac.equals("人机对战")) {
            //获取按下的按钮,将其文本内容改为“结束对局”,背景色改为粉色
            JButton btn = (JButton) e.getSource();
            btn.setText("人人对战");
            btn.setBackground(Color.pink);
//            将棋盘中每个位置的状态归为0
//            chessUtils.chessArr = new int[16][16];
            chessUtils.setGameModel(ac);
        }else if (ac.equals("人人对战")) {
            //获取按下的按钮,将其文本内容改为“开始游戏”,背景色改为天蓝色
            JButton btn = (JButton) e.getSource();
            btn.setText("人机对战");
            btn.setBackground(Color.cyan);
            chessUtils.setGameModel(ac);
        }

ChessUtils部分为:

public void setGameModel(String gameModel) {
        if (agame == 0) {
            this.gameModel = gameModel;
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值