Java 简易五子棋的实现 V1.0

由于这是在优化结束后再写的博客,初期版本的代码已经不在,这里用最终版的代码来讲解思路。

V1.0 登录跳转主页 与 棋盘开发&下棋

-界面类:

关于基础的JFrame 知识就不细讲了,看往期,这里主要提供如何在登录页面和棋盘页面之间跳转

-登录/注册页面

-这里没有写注册功能的代码,仅写了登录功能

public class GameUI implements GoData {
    JFrame loginJF = new JFrame();
    GameJFrame gameJF = new GameJFrame();
    GameListener gameListener = new GameListener();
    Mypanel jp1 = new Mypanel();
    JPanel jp2 = new JPanel();

    public void initLoginUI() {
        loginJF.setTitle("登录");
        loginJF.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        loginJF.setLayout(new FlowLayout());
        loginJF.setSize(400, 400);
        loginJF.setLocationRelativeTo(null);
        JLabel nameInLa = new JLabel("账号");
        JTextField nameIn = new JTextField(30);
        JButton jButton = new JButton("登录");
        loginJF.add(nameInLa);
        loginJF.add(nameIn);
        loginJF.add(jButton);
        loginJF.setVisible(true);

        jButton.addActionListener(gameListener);
        gameListener.nameIn = nameIn;
        gameListener.gameUI = this;
    }
}

比较简单,就讲解最后一句,this指的是GameUI,将GameUI传进监听器后,就能在监听器内调用GameUI内的函数,实现后面的显示和隐藏页面。

-五子棋主页

-直接提供优化后的方法,利用面板

-此处将窗口设置为边框布局(BorderLayout( ) ),将窗口分为南北 东西 中五个区域,这里将按钮区放在东区(EAST),将宽度固定,下棋区放在中心(CENTER),会随着窗口大小改变尺寸。

-关于监听器,只给面板1(下棋区)设置鼠标监听器,给面板二中的按钮设置动作监听器。

-关于按钮,这里用了单选按钮,通过按钮组实现多个按钮的单选

-在进入五子棋页面后,要直接展示棋盘,所以要重写Mypanel的paint()方法,棋盘的绘制就不细讲了就是填充一个矩形后,在上面画上数根(这里为16)直线即可

//此处创建了两个面板,面板是一个容器,其中的Mypanel中重写了重载的代码
Mypanel jp1 = new Mypanel();
JPanel jp2 = new JPanel();

public void initGameUI() {
        gameJF.setTitle("五子棋");
        gameJF.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        gameJF.setLayout(new BorderLayout()); //边框布局,一种布局方式
        gameJF.setSize(900, 900);
        gameJF.setLocationRelativeTo(null);

        jp1.setBackground(Color.white);
        jp2.setPreferredSize(new Dimension(120, 0));
        jp2.setBackground(Color.darkGray);

        gameJF.add(jp1, BorderLayout.CENTER);
        gameJF.add(jp2, BorderLayout.EAST);

        String[] strs = {"开始游戏", "人人对战", "人机对战", "悔棋", "退出"};

        JButton bt1 = new JButton(strs[0]);
        jp2.add(bt1);
        bt1.addActionListener(gameListener);

        ButtonGroup group = new ButtonGroup();
        JRadioButton jRadioButton1 = new JRadioButton(strs[1], true);
        JRadioButton jRadioButton2 = new JRadioButton(strs[2], false);
        group.add(jRadioButton1);
        group.add(jRadioButton2);
        jp2.add(jRadioButton1);
        jp2.add(jRadioButton2);
        jRadioButton1.addActionListener(gameListener);
        jRadioButton2.addActionListener(gameListener);
        gameListener.bt1 = jRadioButton1;
        gameListener.bt2 = jRadioButton2;

        JButton bt2 = new JButton(strs[3]);
        jp2.add(bt2);
        bt2.addActionListener(gameListener);

        JButton bt3 = new JButton(strs[4]);
        jp2.add(bt3);
        bt3.addActionListener(gameListener);

        jp1.gameListener = gameListener;
        jp1.addMouseListener(gameListener);
        gameListener.g = jp1.getGraphics();
    }
@Override
    public void paint(Graphics g) {
        super.paint(g);

        BufferedImage img = new BufferedImage(X + COL * SIZE + SIZE, Y + ROW * SIZE + SIZE, 2);
        Graphics imgG = img.getGraphics();

        imgG.setColor(Color.white);

        GoData.drawChessPad(imgG);
        GoData.drawChesses(imgG, gameListener.chessList);

        g.drawImage(img, 0, 0, null);
    }
public static void drawChessPad(Graphics g) { //绘制棋盘
        g.setColor(Color.orange);
        g.fillRect(X - 20, Y - 20, SIZE * (COL + 1), SIZE * (ROW + 1));

        g.setColor(Color.black);
        for (int i = 0; i <= 15; i++) {
            g.drawLine(X, Y + (i * SIZE), X + (ROW * SIZE), Y + (i * SIZE));
            g.drawLine(X + (i * SIZE), Y, X + (i * SIZE), Y + (COL * SIZE));
        }
    }

-显示/隐藏页面

-其实就是利用 setVisible(true/false) 来实现显示和隐藏,不可视(即隐藏)时是无法操作的。

    public void showLoginUI() {
        loginJF.setVisible(true);
    }

    public void showGameUI() {
        gameJF.setVisible(true);
        Graphics g = jp1.getGraphics();
        gameListener.g = g;
    }

    public void hideLoginUI() {
        loginJF.setVisible(false);
    }

    public void hideGameUI() {
        gameJF.setVisible(false);
    }

-主函数 启动程序

-因为五子棋页面的可视化没放在init中,所以只显示登录页面,但五子棋页面的初始化已经完成。

    public static void main(String[] args) {
        GameUI gameUI = new GameUI();
        gameUI.initLoginUI();
        gameUI.initGameUI();
    }

-监听器类:按钮监听 动作监听

-按钮与落子之间逻辑的处理

-1.点击“开始游戏”后才可以落子,并将“开始游戏”转变为“结束游戏”

        isGoing 判断对局是否开始,此时cl里为“开始游戏”,后续通过cl实现对开始结束的判断

-2.落子期间无法切换对战模式

        两个按钮设置为false时是不可操作的

    public void actionPerformed(ActionEvent e) {
        String ac = e.getActionCommand();
        cl = ac;
        switch (ac) {
            case "开始游戏" -> {
                isGoing = true;
                GoData.drawChessPad(g);
                bt1.setEnabled(!isGoing);
                bt2.setEnabled(!isGoing);
                //获取事件对象,因为是按钮,所以强制转换成按钮
                JButton button = (JButton) e.getSource(); 
                button.setText("结束游戏");
            }
        }
    }

-3.悔棋后可以直接落子,不用额外操作

        再写一个悔棋的判断即可,此时cl里为“悔棋”

if (cl.equals("开始游戏") && !isAI || cl.equals("悔棋") && !isAI)

-4.一方获胜后,无法继续落子,除非悔棋

        设置一个参数判断是否已经胜利,默认false,在任意一方胜利后,改为true,落子时先判断,如果为true,此次落子无效

Boolean isWin = false;
        case "悔棋" -> {
                if (isWin){
                    isWin = false;
                }
        }
    if (GoData.win(chessList, GoData.calC(x), GoData.calR(y))) {
        JOptionPane.showMessageDialog(null, chessFlag == 1 ? "白棋胜利~" : "黑棋胜利~");
        chessFlag = 0;
        isWin = true;
    }
    if(isWin){
            return;
        }

-5.点击结束对局不会立即清空棋盘,而是再次点击“开始游戏”才清空棋盘,方便复盘

        drawChessPad(g) 是绘制棋盘的代码,在点击“开始游戏”后才会调用,还要将单选按钮恢复

    case "开始游戏" -> {
                isGoing = true;
                GoData.drawChessPad(g);
                bt1.setEnabled(!isGoing);
                bt2.setEnabled(!isGoing);
                JButton button = (JButton) e.getSource();
                button.setText("结束游戏");
            }
    case "结束游戏" -> {
                isGoing = false;
                bt1.setEnabled(true);
                bt2.setEnabled(true);
                JButton button = (JButton) e.getSource();
                button.setText("开始游戏");
            }

-数据接口

-定义存储 棋盘上的固定数据

-初始仅存储棋盘的大小之类的数据

-后续将各种通用方法放在其中,可以通过GoData.  来直接调用其中的静态方法,上面有使用到

public interface GoData {
    int X = 70, Y = 70, SIZE = 40, COL = 15, ROW = 15;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值