当前位置: 首页 > 知识库问答 >
问题:

使用图形和java OOP的类似井字游戏的问题

黎奇思
2023-03-14

我正在开发一款我的朋友发明的游戏——tic tac toe的一个小变化:使用4x4板,一个玩家(x)需要以特定的方式获得3个x,而另一个玩家可以每回合放置一个“z”和一个“o”,并且需要填充整个板。我的问题不在于规则和算法,而在于图形:我对图形没有太多经验,只是无法让我的电路板工作(即使没有任何规则——只需根据需要显示)。

我有一个代表棋盘的棋盘类。棋盘有一个二维的细胞数组。每个Cell(Cell=我的另一个类)也是一个JButton,我希望每次单击按钮时他的图像都会改变——所以我决定使用ImageIcon。我还有一个GameMain类来控制游戏,还有一个Tools类来添加两个按钮——“退出”和“重置”。

如果你能帮我建议如何让我的板子正确加载,我将不胜感激。目前,该板根本没有显示,如果我稍微调整一下代码,它会显示出来,但按钮根本不会显示。

代码如下:GameMain。爪哇:

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

public class GameMain extends JPanel {
    private Turn _turn;
    Board _board;
    private Tools _buttons;
    private boolean isOver = false;

    public enum GameState {PLAYING, xWON, oWON};

    private GameState _currentState;

    // Name-constants for the various dimensions used for graphics drawing
    public static final int CELL_SIZE = 100; // cell width and height (square)
    public static final int CANVAS_WIDTH = CELL_SIZE * 4;  // the drawing canvas
    public static final int CANVAS_HEIGHT = CELL_SIZE * 4;
    public static final int GRID_WIDTH = 8;  // Grid-line's width
    public static final int GRID_WIDTH_HALF = GRID_WIDTH / 2; // Grid-line's half-width

    public GameMain() {
        this.addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent e) {
                if (_currentState == GameState.PLAYING) {
                    updateGame();
                } else {
                    initGame(); //game over, restart
                }
                repaint();
            }
        });

        setLayout(new BorderLayout());
        setPreferredSize(new Dimension(CANVAS_WIDTH, CANVAS_HEIGHT + 30));
        _board = new Board();
        _buttons = new Tools();
        initGame();
        _buttons.SetObject(_board);

        add(_board, BorderLayout.CENTER);
        add(_buttons, BorderLayout.SOUTH);
    }

    public void initGame() {
        _turn = Turn.X;
        _board.init();
        _currentState = GameState.PLAYING;
    }

    public void updateGame() {
        if (_board.hasWonX()) {
            _currentState = GameState.xWON;
        } else if (_board.hasWonO()) {
            _currentState = GameState.oWON;
        }
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        setBackground(Color.WHITE);

        _board.paint(g);
    }


    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JFrame frame = new JFrame("xBlock");
                frame.setSize(500, 500);
                // Set the content-pane of the JFrame to an instance of main JPanel
                frame.setContentPane(new GameMain());
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.pack();
                frame.setLocationRelativeTo(null); // center the application window
                frame.setVisible(true);            // show it
            }
        });
    }
}

董事会:

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;

public class Board extends JPanel implements ActionListener {
    private Cell[][] _cells;
    private Turn _turn;

    public Board() {
        setLayout(new GridLayout(4, 4));

        _cells = new Cell[4][4];
        _turn = Turn.X;

        for (int i = 0; i < _cells.length; i++) {
            for (int j = 0; j < _cells[0].length; j++) {
                _cells[i][j] = new Cell(i, j);
                _cells[i][j].addActionListener(this);
                add(_cells[i][j]);
            }
        }
    }

    //initiate board
    public void init() {
        _turn = Turn.X;
        for (int i = 0; i < _cells.length; i++) {
            for (int j = 0; j < _cells[0].length; j++) {
                _cells[i][j].setState(State.EMPTY);
            }
        }

    }

    public void fillCell(Cell c) {
        if (c.getState() == State.EMPTY) {
            c.setState(_turn.ordinal());
            c.setEnabled(false);
            c.draw();
            _turn = _turn.getNext();
        }
    }

    public void checkCellsAround(Cell c) {
        State state = c.getState();
        State right, left, up, down;

        if (c.getJ() < 3 && c.getJ() > 0) {
            right = _cells[c.getI()][c.getJ() + 1].getState();
            left = _cells[c.getI()][c.getJ() - 1].getState();
        } else if (c.getJ() == 0) {
            right = _cells[c.getI()][c.getJ() + 1].getState();
            left = State.EMPTY;
        } else {
            right = State.EMPTY;
            left = _cells[c.getI()][c.getJ() - 1].getState();
        }

        if (c.getI() < 3 && c.getI() > 0) {
            up = _cells[c.getI() - 1][c.getJ()].getState();
            down = _cells[c.getI() + 1][c.getJ()].getState();
        } else if (c.getI() == 0) {
            up = State.EMPTY;
            down = _cells[c.getI() + 1][c.getJ()].getState();
        } else {
            up = _cells[c.getI() - 1][c.getJ()].getState();
            down = State.EMPTY;
        }

        switch (state) {
            case EMPTY:
                break;
            case X:
                if ((left == State.O && right == State.O) || (up == State.O && down == State.O) || (left == State.Z && right == State.Z) || (up == State.Z && down == State.Z)) {
                    c.setState(State.HOURGLASS);
                }
                break;
            case O:
                if ((left == State.X && right == State.X) || (up == State.X && down == State.X)) {
                    c.setState(State.EMPTY);
                }
                break;
            case Z:
                if ((left == State.X && right == State.X) || (up == State.X && down == State.X)) {
                    c.setState(State.HOURGLASS);
                }
                break;
            case HOURGLASS:
                break;
            case SCRIBBLE:
                break;
        }

    }

    public void actionPerformed(ActionEvent E) {
        Cell c = (Cell) E.getSource();
        fillCell(_cells[c.getI()][c.getJ()]);
    }

    public boolean hasWonO() {
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                if (_cells[i][j].getState() == State.EMPTY) {
                    return false;
                }
            }
        }
        return true;
    }

    public boolean hasWonX() {
        return false;
    }


    public void paint(Graphics g) {
        g.setColor(Color.GRAY);
        for (int i = 1; i < 4; i++) {
            g.fillRoundRect(0, GameMain.CELL_SIZE * i - GameMain.GRID_WIDTH_HALF,
                    GameMain.CANVAS_WIDTH - 1, GameMain.GRID_WIDTH,
                    GameMain.GRID_WIDTH, GameMain.GRID_WIDTH);
        }
        for (int j = 1; j < 4; j++) {
            g.fillRoundRect(GameMain.CELL_SIZE * j - GameMain.GRID_WIDTH_HALF, 0,
                    GameMain.GRID_WIDTH, GameMain.CANVAS_HEIGHT - 1,
                    GameMain.GRID_WIDTH, GameMain.GRID_WIDTH);
        }
        for (int i = 0; i < 5; i++) {
            for (int j = 0; j < 5; j++) {
                _cells[i][j].draw();
            }
        }
    }
}

Cell.java:

    import javax.swing.ImageIcon;
import javax.swing.JButton;

public class Cell extends JButton {
    private int _i, _j;
    private State _state;

    ImageIcon X = new ImageIcon(this.getClass().getResource("x-icon.png"));
    ImageIcon O = new ImageIcon(this.getClass().getResource("o-icon.png"));
    ImageIcon Z = new ImageIcon(this.getClass().getResource("z-icon.png"));
    ImageIcon Hourglass = new ImageIcon(this.getClass().getResource("hourglass-icon.png"));
    ImageIcon Scribble = new ImageIcon(this.getClass().getResource("scribble-icon.png"));

    public Cell() {
        this.setEnabled(true);
        _i = 0;
        _j = 0;
        _state = State.EMPTY;

    }

    public Cell(int i, int j) {
        this.setEnabled(true);
        _i = i;
        _j = j;
        _state = State.EMPTY;
    }

    public int getI() {
        return _i;
    }

    public int getJ() {
        return _j;
    }

    public void setState(State state) {
        _state = state;
        if (state == State.EMPTY) {
            this.setEnabled(true);
        }
    }

    public void setState(int index) {
        _state = State.values()[index];
    }

    public State getState() {
        return _state;
    }

    public void draw() {
        switch (_state) {
            case EMPTY:
                this.setIcon(null);
                break;

            case X:
                this.setIcon(X);
                break;

            case O:
                this.setIcon(X);
                break;

            case Z:
                this.setIcon(X);
                break;

            case HOURGLASS:
                this.setIcon(X);
                break;

            case SCRIBBLE:
                this.setIcon(X);
                break;
        }
    }

    public void highlight() {
    }
}

工具。爪哇:

 import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;

public class Tools extends JPanel {

    private JButton _exit, _reset;
    private Board _board;

    Tools() {
        setLayout(new FlowLayout());

        _exit = new JButton("Exit");
        _reset = new JButton("Reset");

        _exit.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                System.exit(0);
            }
        });

        _reset.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                _board.init();
            }
        });
        add(_exit);
        add(_reset);
    }

    public void SetObject(Board b) {
        _board = b;
    }

}

State.java:

public enum State {
    EMPTY, X, O, Z, HOURGLASS, SCRIBBLE;


    public State getNext() {
        return State.values()[(this.ordinal() + 1) % State.values().length];
    }
}

转动爪哇:

public enum Turn {
    X, O, Z;

    public Turn getNext() {
        return Turn.values()[(this.ordinal() + 1) % Turn.values().length];
    }
}

提前谢谢!

共有1个答案

艾璞瑜
2023-03-14

因此,在运行它之后,您将在Board类的绘制方法的这一行获得ArrayIndexOutOfBoundsException

    for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 5; j++) {
            _cells[i][j].draw();       <==========
        }
    }

不知道你的游戏是如何运行的,但是通过查看之前的循环,你只能访问索引3(for(int j=1;j)

    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            _cells[i][j].draw();
        }
    }

学习读取异常和堆栈跟踪非常重要。这将为你将来省去很多麻烦。花些时间阅读什么是堆栈跟踪,以及如何使用它来调试应用程序错误?

正如我在评论中所说,

GameMain中,你似乎没有在使用paintComponent做任何事情。您应该完全去掉该类中的paintComponent方法。而不是试图调用板。油漆(g);,试着直接打电话给董事会。在鼠标侦听器中重新绘制(),而不是尝试重新绘制主游戏面板。只需在GameMain的构造函数中设置背景,而不是在paintComponent方法中设置背景。

此外,在Board类中,使用paintComponent而不是paint。别忘了给super打电话。在paintComponent方法中使用paintComponent

修复上面所有的事情,让它工作(我猜)。

更新

正如疯子在下面的评论中指出的,最好使用\u单元格。长度以避免依赖幻数。通过这种方式,您将确保不会访问不远处的索引

for (int i = 0; i < cells.length; i++) {
    for (int j = 0; j < cells[i].length; j++) {
        _cells[i][j].draw();
    }
}
 类似资料:
  • 我正在制作一个名为SOS的游戏。这是一款3x3的棋盘游戏,与Tic Tac Toe的概念相同,但在这款游戏中,玩家无法选择是以X还是O的身份进行游戏,游戏中唯一的规则是形成“SOS”。 我们的项目应该在所有职位被填补后终止,每个组成的“SOS”将被添加到组成“SOS”的玩家中。 我的问题是关于得分。在第一行输入SOS后,即,我尝试在第二行第一列输入“O”,玩家2将递增。它不应该递增,因为它不满足我

  • 我在Java中创建了一个小TicTacToe游戏,我想编写更有效的代码,我会制作一个for循环来创建9个按钮。 我现在面临的问题是如何测试按下哪个按钮以确定胜利者。我已经注释掉了我的旧测试代码,因为它不再工作。

  • 嗨,我正在编写一个井字游戏。我已经在代码中的注释中详细说明了我需要什么。我现在遇到的问题是制作一个getMobile方法。我想我需要在按下行和列后的if/else语句中调用getMobile方法? 我不确定如何从获取行/列编号并将其放入我的板上以获取用户输入的内容。 以下是我的代码:

  • 所以我为我的课做了一个抽动练习作业。我已经成功地创建了一个简单的Tic Tac Toe程序,但不知何故,检查绘制的方法有时并不正确。如果所有东西都填满了,但没有赢家,那就是平局。但如果除第0行第1列外,其他所有内容都已填满,则即使该框仍为空白,它仍将显示“Draw”。如果你不明白我的意思,就试着把所有的东西都填满,但不是赢,即使最后一个框没有填满,它也会说“平局”。我在代码中做错了什么????驱动

  • 我写的神经网络可以玩井字游戏。网络有9个输入神经元,它们描述板的状态(1-代表网络移动,1.5-代表对手移动,0-代表空单元)和9个输出神经元(具有最高值的输出神经元表示给定状态下的最佳动作)。网络没有隐藏层。激活函数-乙状结肠。学习方法--Q学习+反向传播。 网络是经过训练的,但很差(继续踩在被占用的单元格上)。所以我决定添加一个隐藏层。我想问: 在隐藏层中使用多少个神经元,在隐藏层和输出层中使

  • 我用Java写了Tic-Tac-Toe。我似乎遇到的问题是,当(人类)播放器1和(计算机)播放器2之间出现平局时,GUI会冻结。我已经在“Buttonlistener”类和“Methods”中创建了一个tieCheck,以获得一个平局。 我的程序的工作方式是,当按下一个按钮时,它会将一个值传递给methods类中的数组。在这个数组中,1=玩家1,2=玩家2。 人类玩家总是先走,所以当人类玩家走了4