gpt4 book ai didi

java - 使用图形和 java OOP 的类似于 Tic Tac Toe 的游戏的问题

转载 作者:行者123 更新时间:2023-11-30 06:17:02 26 4
gpt4 key购买 nike

我正在开发我的 friend 发明的游戏 - 井字游戏的一个小变体:使用 4x4 棋盘,一名玩家 (x) 需要以特定方式获得 3 个 x,而另一名玩家可以放置一个 'z'每回合一个“o”,需要填满整个棋盘。我的问题不在于规则和算法,而在于图形:我在图形方面没有太多经验,只是无法让我的电路板工作(即使没有任何规则 - 只需根据需要出现)。

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

如果您能帮我提出让我的板正确加载的方法,我将不胜感激。目前,看板根本不显示,如果我稍微调整一下代码,它就会显示,但按钮根本不会显示。

这是代码:GameMain.java:

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();
}
}
}
}

细胞.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() {
}
}

工具.java:

 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;
}

}

状态.java:

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


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

Turn.java:

public enum Turn {
X, O, Z;

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

提前致谢!

最佳答案

所以在运行它之后,你会得到一个 ArrayIndexOutOfBoundsExceptionBoard 的绘画方法中的这一行类:

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

不确定您的游戏是如何运行的,但通过查看之前的循环,您只能访问索引 3 ( for (int j = 1; j < 4; j++) { )。因此,如果您将循环最大值更改为 4,游戏就会启动并运行。

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

学习阅读异常和堆栈跟踪非常重要。它将为您节省很多 future 的麻烦。花点时间阅读 What is a stack trace, and how can I use it to debug my application errors?


就像我在评论中所说的那样,

It doesn't look like you're doing anything with the paintComponent in the GameMain. You should just get rid of the paintComponent method altogether in that class. Instead of trying to call board.paint(g);, try to just call board.repaint() in the mouse listener, instead of trying to repaint the main game panel. And just set the background in the constructor of the GameMain instead of in the paintComponent method.

Also in the Board class use paintComponent rather than paint. and don't forget to call super.paintComponent in the paintComponent method

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


更新

正如 MadMan 在下面的评论中指出的那样,最好使用 _cells.length避免不得不依赖魔数(Magic Number)。这样您将确保不会访问不存在的索引

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

关于java - 使用图形和 java OOP 的类似于 Tic Tac Toe 的游戏的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26323586/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com