【Java GUI】人机对弈五子棋

发布于:2024-04-27 ⋅ 阅读:(22) ⋅ 点赞:(0)

在学校的Java课程中,我们被分配了一项有趣的任务:开发一款能够实现人机对弈的五子棋游戏。为了更好地理解Java GUI的运用,并与大家分享学习心得,我将整个开发过程记录在这篇博客中。欢迎大家阅读并提供宝贵的意见和建议!"

python版五子棋(讲解的更详细) 

1.绘制棋盘

1.定义myPanel类。

myPanel相当于画板。

myPanel要继承 JPanel类,并要覆盖父类的paint方法,在paint方法里面写负责绘画的代码


public class myPanel extends JPanel {
    static final int start = 6;
    @Override
    public void paint(Graphics g)
    {
        //调用父类的paint初始化画笔
        super.paint(g);
       //绘制背景
        DrawBackground(g);
        //绘制外边框
        DrawBorder(g);
        //绘制棋盘
        DrawChessBoard(g);

    }
    public void DrawBackground(Graphics g)
    {    //绘制背景
        g.setColor(new Color(211, 152, 91));
        g.fillRect(0, 0, 620,620);

    }
    public void DrawBorder(Graphics g)
    {
        //绘制外边框
        g.setColor(Color.BLACK);
        g.fillRect(5,5,610,5);
        g.fillRect(610,5,5,610);
        g.fillRect(5,610,610,5);
        g.fillRect(5,5,5,610);
    }

    public void DrawChessBoard(Graphics g)
    {
        g.setColor(Color.BLACK);
        //画横线
        for (int i = 0; i < 19; i++) {
            g.drawLine(6+i*32,6,6+i*32,614);
        }
        //画竖线
        for (int i = 0; i < 19; i++) {
            g.drawLine(6,6+i*32,614,6+i*32);
        }

    }
    //画棋子
    public void DrawChess(Graphics g,int x,int y,int  type){
        switch (type){
            case 1:
                g.setColor(Color.BLACK);
                break;
            case 2:
                g.setColor(Color.WHITE);
        }
        g.fillOval(x*32+start,y*32+start,30,30);
        
    }
   

}
2.定义myFrame类。

myFrame相当于窗口,画板要放在窗口里。

myFram要继承 JFram类,在初始化函数设置窗口参数


public class MyFrame extends JFrame {
    myPanel mp  = null;
    public MyFrame() {
        mp = new myPanel();
        this.setTitle("五子棋");
        this.setSize(620, 620);
        //添加画板
        this.add(mp);
        //点击窗口叉叉退出程序
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
    }

    static public void main(String[] args) {
        MyFrame mf = new MyFrame();
    }
}

2.核心功能

1.实现下棋功能

 1.定义相关变量

    //偏移量
    static final int IndexOffset = -10;
    static final int ChessOffset = -10;
    //黑子下棋标记
    static boolean black = true;
    boolean gameIsOver = false;

    int chess[][]=new int[19][19];

2.添加事件监听

myPanel实现 MouseListener接口

重写mouseClicked方法

    @Override
    public void mouseClicked(MouseEvent e) {
        //计算棋子坐标
        //# 0表示空棋
        //# 1表示黑棋
        //# 2表示白棋

        int x = (e.getX() - IndexOffset) / 32;
        int y = (e.getY() - 32 - IndexOffset) / 32;
        System.out.println(y);
        chess[x][y] = 1;
        this.repaint();

    }

myFrame添加事件监听

    public MyFrame() {
        mp = new myPanel();
        this.setTitle("五子棋");
        this.setSize(620, 620);
        //添加画板
        this.add(mp);
        //点击窗口叉叉退出程序
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.addMouseListener(mp);
        this.setVisible(true);
    }
2.实现自动下棋

1.按照优先级从高到低枚举出所有情况


//# 0表示空棋
//# 1表示黑棋
//# 2表示白棋
//# 3表示下棋的位置


  

    private static final int[][] cdata = {

            {3, 1, 1, 1, 1}, {1, 3, 1, 1, 1}, {1, 1, 3, 1, 1}, {1, 1, 1, 3, 1}, {1, 1, 1, 1, 3},

            {2, 2, 3, 2, 2}, {2, 2, 2, 3, 2}, {2, 3, 2, 2, 2}, {3, 2, 2, 2, 2}, {2, 2, 2, 2, 3},

            {3, 1, 1, 1, 0}, {1, 1, 1, 3, 0}, {1, 1, 3, 1, 0}, {1, 3, 1, 1, 0},

            {3, 2, 2, 2, 0}, {2, 3, 2, 2, 0}, {2, 2, 3, 2, 0}, {2, 2, 2, 3, 0},

            {1, 1, 3, 3, 0}, {3, 1, 1, 0, 0}, {0, 1, 3, 1, 0},

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

            {3, 1, 0, 0, 0}, {1, 3, 0, 0, 0}

    };

2.选出最佳下棋位置 

    public Point getBestPoint() {
        //记录最低分(分值越低,优先级越高)
        int score = 100;
        //最佳位置
        Point point = new Point(0, 0);
        //每次都要遍历四个方向 左下 下 右下 右
        int[] dx = {-1, 0, 1, 1};
        int[] dy = {1, 1, 1, 0};
        for (int i = 0; i < 19; i++) {

            for (int j = 0; j < 19; j++) {
                for (int k = 0; k < 4; k++) {
                    int cnt = 0;
                    for (int[] e : cdata) {
                        int m;
                        int x = i;
                        int y = j;
                        int bestX = 0;
                        int bestY = 0;
                        for (m = 0; m < 5; m++) {
                            if (e[m] == 3 && chess[x][y] == 0) {
                                bestX = x;
                                bestY = y;
                            } else {
                                if (chess[x][y] != e[m]) {
                                    break;
                                }
                            }
                            x += dx[k];
                            y += dy[k];
                            if (x < 0 || x >= 19 || y < 0 || y >= 19) {
                                break;
                            }

                        }
                        if (m == 5) {
                            if (cnt < score) {
                                score = cnt;
                                point.x = bestX;
                                point.y = bestY;
                            }
                            break;
                        }
                        cnt++;
                    }
                }

            }
        }
        if (score < 100) {
            return point;
        } else {
            int x = (int) (Math.random() * 19);
            int y = (int) (Math.random() * 19);
            while (chess[x][y] != 0) {
                x = (int) (Math.random() * 19);
                y = (int) (Math.random() * 19);
            }
            return new Point(x, y);
        }

    }
3.判断游戏是否结束

遍历棋盘

   public boolean check() {
        //每次都要遍历四个方向 左下 下 右下 右
        int[] dx = {-1, 0, 1, 1};
        int[] dy = {1, 1, 1, 0};
        for (int i = 0; i < 19; i++) {
            for (int j = 0; j < 19; j++) {
                for (int k = 0; k < 4; k++) {
                    int x = i;
                    int y = j;
                    int m;
                    boolean flag = true;
                    for (m = 0; m < 4; m++) {
                        int tx = x + dx[k];
                        int ty = y + dy[k];
                        if (tx < 0 || tx > 19 || ty < 0 || ty > 19) {
                            flag = false;
                            break;
                        }
                        if (chess[x][y] != chess[x + dx[k]][y + dy[k]]) {
                            flag = false;
                            break;
                        } else if (chess[x][y] == 0) {
                            flag = false;
                            break;
                        }
                        x = tx;
                        y = ty;
                    }
                    if (flag) {
                        gameIsOver = true;
                        return true;
                    }

                }
            }
        }
        return false;
    }
4.事件循环
   @Override
    public void paint(Graphics g) {
        //调用父类的paint初始化画笔
        super.paint(g);
        //绘制背景
        DrawBackground(g);
        //绘制外边框
        DrawBorder(g);
        //绘制棋盘
        DrawChessBoard(g);
        DrawChess(g);
        //开始游戏

            if (!gameIsOver)
                game();

        //游戏结束
        if (check()) {
            gameOver(g);
        }

    }

完整代码 

myPanel

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

/**
 * 
 *
 * @author yuwei
 * @date 23:29 2024/4/23
 */
public class myPanel extends JPanel implements MouseListener {
    //偏移量
    static final int IndexOffset = -10;
    static final int ChessOffset = -10;
    //黑子下棋标记
    static boolean black = true;
    boolean gameIsOver = false;

//# 0表示空棋
//# 1表示黑棋
//# 2表示白棋
//# 3表示下棋的位置


    private static final int[][] cdata = {

            {3, 1, 1, 1, 1}, {1, 3, 1, 1, 1}, {1, 1, 3, 1, 1}, {1, 1, 1, 3, 1}, {1, 1, 1, 1, 3},

            {2, 2, 3, 2, 2}, {2, 2, 2, 3, 2}, {2, 3, 2, 2, 2}, {3, 2, 2, 2, 2}, {2, 2, 2, 2, 3},

            {3, 1, 1, 1, 0}, {1, 1, 1, 3, 0}, {1, 1, 3, 1, 0}, {1, 3, 1, 1, 0},

            {3, 2, 2, 2, 0}, {2, 3, 2, 2, 0}, {2, 2, 3, 2, 0}, {2, 2, 2, 3, 0},

            {1, 1, 3, 3, 0}, {3, 1, 1, 0, 0}, {0, 1, 3, 1, 0},

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

            {3, 1, 0, 0, 0}, {1, 3, 0, 0, 0}

    };
    int chess[][] = new int[20][20];

    @Override
    public void paint(Graphics g) {
        //调用父类的paint初始化画笔
        super.paint(g);
        //绘制背景
        DrawBackground(g);
        //绘制外边框
        DrawBorder(g);
        //绘制棋盘
        DrawChessBoard(g);
        DrawChess(g);
        //开始游戏

            if (!gameIsOver)
                game();

        //游戏结束
        if (check()) {
            gameOver(g);
        }

    }

    public void gameOver(Graphics g) {
        Font font = new Font("Arial", Font.BOLD, 24);
        g.setColor(Color.red);
        g.setFont(font);
        g.drawString("游戏结束", 270, 270);
    }

    public void DrawBackground(Graphics g) {    //绘制背景
        g.setColor(new Color(211, 152, 91));
        g.fillRect(0, 0, 620, 620);

    }

    public void DrawBorder(Graphics g) {
        //绘制外边框
        g.setColor(Color.BLACK);
        g.fillRect(5, 5, 610, 5);
        g.fillRect(610, 5, 5, 610);
        g.fillRect(5, 610, 610, 5);
        g.fillRect(5, 5, 5, 610);
    }

    public void DrawChessBoard(Graphics g) {
        g.setColor(Color.BLACK);
        //画横线
        for (int i = 0; i < 19; i++) {
            g.drawLine(6 + i * 32, 6, 6 + i * 32, 614);
        }
        //画竖线
        for (int i = 0; i < 19; i++) {
            g.drawLine(6, 6 + i * 32, 614, 6 + i * 32);
        }

    }

    //画棋子
    public void DrawChess(Graphics g) {
        for (int i = 0; i < 19; i++) {
            for (int j = 0; j < 19; j++) {
                if (chess[i][j] == 1) {
                    g.setColor(Color.BLACK);
                } else if (chess[i][j] == 2) {
                    g.setColor(Color.WHITE);
                } else {
                    continue;
                }
                g.fillOval(i * 32 + ChessOffset, j * 32 + ChessOffset, 30, 30);
            }
        }


    }

    public Point getBestPoint() {
        //记录最低分(分值越低,优先级越高)
        int score = 100;
        //最佳位置
        Point point = new Point(0, 0);
        //每次都要遍历四个方向 左下 下 右下 右
        int[] dx = {-1, 0, 1, 1};
        int[] dy = {1, 1, 1, 0};
        for (int i = 0; i < 19; i++) {

            for (int j = 0; j < 19; j++) {
                for (int k = 0; k < 4; k++) {
                    int cnt = 0;
                    for (int[] e : cdata) {
                        int m;
                        int x = i;
                        int y = j;
                        int bestX = 0;
                        int bestY = 0;
                        for (m = 0; m < 5; m++) {
                            if (e[m] == 3 && chess[x][y] == 0) {
                                bestX = x;
                                bestY = y;
                            } else {
                                if (chess[x][y] != e[m]) {
                                    break;
                                }
                            }
                            x += dx[k];
                            y += dy[k];
                            if (x < 0 || x >= 19 || y < 0 || y >= 19) {
                                break;
                            }

                        }
                        if (m == 5) {
                            if (cnt < score) {
                                score = cnt;
                                point.x = bestX;
                                point.y = bestY;
                            }
                            break;
                        }
                        cnt++;
                    }
                }

            }
        }
        if (score < 100) {
            return point;
        } else {
            int x = (int) (Math.random() * 19);
            int y = (int) (Math.random() * 19);
            while (chess[x][y] != 0) {
                x = (int) (Math.random() * 19);
                y = (int) (Math.random() * 19);
            }
            return new Point(x, y);
        }

    }

    public boolean check() {
        //每次都要遍历四个方向 左下 下 右下 右
        int[] dx = {-1, 0, 1, 1};
        int[] dy = {1, 1, 1, 0};
        for (int i = 0; i < 19; i++) {
            for (int j = 0; j < 19; j++) {
                for (int k = 0; k < 4; k++) {
                    int x = i;
                    int y = j;
                    int m;
                    boolean flag = true;
                    for (m = 0; m < 4; m++) {
                        int tx = x + dx[k];
                        int ty = y + dy[k];
                        if (tx < 0 || tx > 19 || ty < 0 || ty > 19) {
                            flag = false;
                            break;
                        }
                        if (chess[x][y] != chess[x + dx[k]][y + dy[k]]) {
                            flag = false;
                            break;
                        } else if (chess[x][y] == 0) {
                            flag = false;
                            break;
                        }
                        x = tx;
                        y = ty;
                    }
                    if (flag) {
                        gameIsOver = true;
                        return true;
                    }

                }
            }
        }
        return false;
    }

    public void game()  {

        if (check()) {
            return;
        }
        if (black) {
            Point point = getBestPoint();
            chess[point.x][point.y] = 1;
            black = false;
            this.repaint();
        }


    }


    @Override
    public void mouseClicked(MouseEvent e) {
        //计算棋子坐标
        //# 0表示空棋
        //# 1表示黑棋
        //# 2表示白棋
        if (!black&&!gameIsOver) {
            int x = (e.getX() - IndexOffset) / 32;
            int y = (e.getY() - 32 - IndexOffset) / 32;
            chess[x][y] = 2;
            black = true;
            this.repaint();

        }

    }

    @Override
    public void mousePressed(MouseEvent e) {

    }

    @Override
    public void mouseReleased(MouseEvent e) {

    }

    @Override
    public void mouseEntered(MouseEvent e) {

    }

    @Override
    public void mouseExited(MouseEvent e) {

    }
}

myFrame

import javax.swing.*;

/**
 * 用户服务
 *
 * @author yuwei
 * @date 23:42 2024/4/23
 */
public class MyFrame extends JFrame {
    myPanel mp  = null;
    public MyFrame() {
        mp = new myPanel();
        this.setTitle("五子棋");
        this.setSize(620, 620);
        //添加画板
        this.add(mp);
        //点击窗口叉叉退出程序
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.addMouseListener(mp);
        this.setVisible(true);
    }

    static public void main(String[] args) {
        MyFrame mf = new MyFrame();
    }
}

感谢阅读,希望本文对你有所帮助 


网站公告

今日签到

点亮在社区的每一天
去签到