在 Java 中使用 GUI 井字游戏

问题描述 投票:0回答:1
import javax.swing.*;  //for GUI components like JFrame, JPanel, JButton
import java.awt.*; // for creating buttons and other visual components like coc=lor font etc
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;

public class GUI{  // The main class
    private JButton[] buttons;
    private char[] num = {'1','2','3','4','5','6','7','8','9'};
    private char player, computer;
    private ImageIcon playericon, computericon;
    private boolean running = true;
    public GUI() {

        JFrame frame = new JFrame("Tic tac toe");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //exits the frame when click on x

        frame.setLayout(null); //used to automatically position the components in the frame but when set to null you need to set everything manually using .setBounds()

        BackgroundPanel panel = new BackgroundPanel("ticbg.jpg");//panel is used to display buttons, label( which displays te text and images)
        frame.setExtendedState(JFrame.MAXIMIZED_BOTH);  //extend the frame to full screen
        frame.setContentPane(panel);  //add all the components(buttons) to the panel.

        JButton button = new JButton();  //creates a new button
        button.setBounds(637, 500, 89, 93);
        button.setIcon(new ImageIcon("start button.png")); //add image to button
        button.setBorder(BorderFactory.createEtchedBorder());  //for border decor
        button.setFocusable(false);  //removes the box that displays around the text in the button
        button.addActionListener(e -> {  //tells what to do when click on the button
            SelectToken();
            frame.dispose(); //used to close the window/ frame and in this code moves to another frame/screen/window
        });

        panel.add(button); // adding the button to the panel
        frame.setVisible(true);// makes the frame visible


    }
    //it is called inner class
    public class BackgroundPanel extends JPanel {  //BackgroundPanel is a custom panel that extends JPanel to display background image
        private Image backgroundImage;

        public BackgroundPanel(String imagePath) {
            backgroundImage = new ImageIcon(imagePath).getImage();
            setLayout(null);
        }

        @Override
        protected void paintComponent(Graphics g) { //overriding paintComponent that draws the bg image
            super.paintComponent(g);  //clears the background to draw the image
            g.drawImage(backgroundImage, 0, 0, getWidth(), getHeight(), this);  // draws the image
        }
    }


    public void SelectToken(){
        JFrame frame = new JFrame("Select Token");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        BackgroundPanel panel2 = new BackgroundPanel("ticbg2.png");
        frame.setContentPane(panel2);
        frame.setLayout(null);


        JButton button2 = new JButton();
        button2.setBounds(650, 210, 98, 98);
        button2.setIcon(new ImageIcon("X.png"));
        button2.setBorder(BorderFactory.createEtchedBorder());
        button2.setFocusable(false);
        button2.addActionListener(e->{
            player = 'X';
            computer = 'O';
            playericon = new ImageIcon("X.png");
            computericon = new ImageIcon("O.png");
            button2.setEnabled(false);
        });



        JButton button3 = new JButton("O");
        button3.setBounds(650, 320, 98, 98);
        button3.setIcon(new ImageIcon("O.png"));
        button3.setBorder(BorderFactory.createEtchedBorder());
        button3.setFocusable(false);
        button3.addActionListener(e->{
            player = 'O';
            computer ='X';
            playericon = new ImageIcon("O.png");
            computericon = new ImageIcon("X.png");
            button3.setEnabled(false); //disabling the button once it is clicked
        });


        JButton startgame = new JButton();
        startgame.setBounds(558, 430, 280, 60);
        startgame.setIcon(new ImageIcon("Play Now.png"));
        startgame.setBorder(BorderFactory.createEtchedBorder());
        startgame.setFocusable(false);
        startgame.addActionListener(e->{
            Gamegrid();
            frame.dispose();
        });


        //adding buttons to the panel2 (panel of the second frame)
        panel2.add(button2);
        panel2.add(button3);
        panel2.add(startgame);

        frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
        frame.setVisible(true);
    }



    public void Gamegrid(){
        JFrame frame = new JFrame("Grid");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        BackgroundPanel panel3 = new BackgroundPanel("ticbg2.png");
        frame.setContentPane(panel3);

        frame.setLayout(new GridLayout(3, 3));

        buttons = new JButton[9]; //creating array of buttons to form a grid
        for (int i = 0; i < 9; i++) {
            buttons[i] = new JButton(String.valueOf(num[i]));
            buttons[i].setFont(new Font("Arial", Font.PLAIN, 24));
            buttons[i].setBorder(BorderFactory.createEtchedBorder());
            buttons[i].setIcon(new ImageIcon("gridbg.png"));
            buttons[i].setFocusable(false);
            buttons[i].addActionListener(new ButtonListener());
            panel3.add(buttons[i]);
        }
        frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
        frame.setVisible(true);
    }
    //called inner class
    private class ButtonListener implements ActionListener { //class to tell what to do when a button is clicked

        public void actionPerformed(ActionEvent e) {
            if (running) {
                JButton button = (JButton) e.getSource();   //e.getSource(): This part retrieves the thing that caused the action, like clicking a button.
                //(JButton): This part converts whatever e.getSource() returns into a type called JButton.
                //button: This part assigns the result of the conversion to a variable called button, so you can work with it later, like changing its text or appearance.

                int index = Integer.parseInt(button.getText()) - 1;  //first it gets what is written on the button then converts it to integer and then decreases it by 1 to match with the num array indexes
                if (num[index] == player || num[index] == computer) {
                    JOptionPane.showMessageDialog(null, "Invalid move! Please choose an empty cell.");
                } else {
                    num[index] = player;
                    button.setIcon(playericon);
                    if (checkWinner()) {
                        running = false;
                        JOptionPane.showMessageDialog(null, "You win!");
                    } else if (checkTie()) {
                        running = false;
                        JOptionPane.showMessageDialog(null, "Game Draw :(");
                    } else {
                        ComputerMove();
                    }
                }
            } else {
                JOptionPane.showMessageDialog(null, "Game over! Please restart to play again.");
            }

        }
    }


    public void ComputerMove() {
        // Check for a winning move
        for (int i = 0; i < 9; i++) {
            if (num[i] >= '1' && num[i] <= '9') {
                char original = num[i];
                num[i] = computer;
                if (checkWinner()) {
                    buttons[i].setIcon(computericon);
                    return; // Computer wins
                }
                num[i] = original; // Undo the move
            }
        }

        if (num[4] >= '1' && num[4] <= '9') {
            num[4] = computer;
            buttons[4].setIcon(computericon);
            return;
        }

        for (int i : new int[] { 0, 2, 6, 8 }) {
            if (num[i] >= '1' && num[i] <= '9') {
                num[i] = computer;
                buttons[i].setIcon(computericon);
                return;
            }
        }

        for (int i : new int[] { 1, 3, 5, 7 }) {
            if (num[i] >= '1' && num[i] <= '9') {
                num[i] = computer;
                buttons[i].setIcon(computericon);
                return;
            }
        }

        // If no winning move, make a random move
        Random r = new Random();
        int j;
        do {
            j = r.nextInt(9);
        } while (num[j] == 'X' || num[j] == 'O');

        num[j] = computer;
        buttons[j].setIcon(computericon);
    }

    public boolean checkWinner() {
        // Check rows, columns, and diagonals
        for (int i = 0; i < 3; i++){
            // Check rows
            if (num[i * 3] == num[i * 3 + 1] && num[i * 3 + 1] == num[i * 3 + 2]){
                if (num[i * 3] == player){
                    return true;
                } else if( num[i * 3] == computer){
                    return true;
                }
            }

            // Check columns
            if (num[i] == num[i + 3] && num[i + 3] == num[i + 6]){
                if (num[i * 3] == player){
                    JOptionPane.showMessageDialog(null, "You win :)");
                    return true;
                } else if( num[i * 3] == computer){
                    JOptionPane.showMessageDialog(null, "Computer Wins >_<");
                    return true;
                }
            }

            // Check diagonals
            if ((num[0] == num[4] && num[4] == num[8]) || (num[2] == num[4] && num[4] == num[6])){
                if (num[i * 3] == player){
                    JOptionPane.showMessageDialog(null, "You win :)");
                    return true;
                } else if( num[i * 3] == computer){
                    JOptionPane.showMessageDialog(null, "Computer Wins >_<");
                    return true;
                }
            }
        }

        return false;
    }

    // Check if the game is tied
    private boolean checkTie(){
        for (int i = 0; i < 9; i++){
            if (num[i] != 'X' && num[i] != 'O'){
                return false;
            }
        }
        JOptionPane.showMessageDialog(null, "Game Draw :(");
        return true;
    }

}

我想改进“ComputerMove”和“CheckWinner”逻辑。

我使用 Java 中的 GUI 制作了 tic_tac_toe 游戏作为学期项目的结束。 “CheckWInner”和“ComputerMove”方法中存在逻辑错误。我想改进这些方法的逻辑。您的帮助将不胜感激。我将在下周提交此代码。 我刚刚开始使用 java GUI,并且由于这段代码的长度而感到困惑。 我重用了上学期的 tic tac toe 代码(用 C++ 编写)。 问题: 主要问题是;

  1. 在计算机执行获胜动作之前,它会显示“计算机获胜”消息
  2. 有时,用户获胜后不会显示“你赢了”消息
  3. 计算机获胜后,它不会结束游戏,而是继续进行用户移动,并显示不需要的“你赢了”消息 TT
java swing logic tic-tac-toe
1个回答
0
投票

获胜条件后“谁是获胜者”检查的按钮索引是错误的。

// check rows
下面的 if 子句没问题,但是
// Check columns
Check diagonals
会考虑不包含获胜条件的单元格(
num[i * 3]
而不是
num[i]
num[0]
)。

© www.soinside.com 2019 - 2024. All rights reserved.