使用图形和java OOP的类似于Tic Tac Toe的游戏的问题
我正在做一个我的朋友发明的游戏——tic-tac-toe的一个小变化:使用4x4板,一个玩家(x)需要以特定的方式获得3个x,而另一个玩家可以每回合放置一个“z”和一个“o”,并且需要填充整个板。我的问题不在于规则和算法,而在于图形:我对图形没有太多的经验,只是无法让我的电路板正常工作(即使没有任何规则-只要根据需要显示) 我有一个Board类,它代表一个Board。电路板具有二维单元阵列。每个单元格(Cell=我的另一个类)也是一个JButton,我希望每次单击按钮时,他的图像都会发生变化——因此我决定使用ImageIcon。我还有一个GameMain类来控制游戏,还有一个Tools类来添加两个按钮——“退出”和“重置” 如果你能帮我建议如何让我的板子正确加载,我将不胜感激。目前,该董事会没有显示在所有,如果我调整代码一点,它会显示出来,但按钮不会显示在所有 代码如下:GameMain.java:使用图形和java OOP的类似于Tic Tac Toe的游戏的问题,java,swing,oop,graphics,Java,Swing,Oop,Graphics,我正在做一个我的朋友发明的游戏——tic-tac-toe的一个小变化:使用4x4板,一个玩家(x)需要以特定的方式获得3个x,而另一个玩家可以每回合放置一个“z”和一个“o”,并且需要填充整个板。我的问题不在于规则和算法,而在于图形:我对图形没有太多的经验,只是无法让我的电路板正常工作(即使没有任何规则-只要根据需要显示) 我有一个Board类,它代表一个Board。电路板具有二维单元阵列。每个单元格(Cell=我的另一个类)也是一个JButton,我希望每次单击按钮时,他的图像都会发生变化——
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();
}
}
}
}
Tools.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;
}
}
State.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];
}
}
提前谢谢 因此,在运行它之后,您将在
Board
类的绘制方法的这一行获得ArrayIndexOutOfBoundsException
:
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
_cells[i][j].draw(); <==========
}
}
在
GameMain
中,您似乎没有对paintComponent
执行任何操作。您应该在该类中完全去掉paintComponent
方法。而不是试图调用board.paint(g)
,尝试在鼠标侦听器中调用board.repaint()
,而不是尝试重新绘制主游戏面板。在board
类中,也可以使用paintComponent
而不是paint
。别忘了打电话给super.paintComponent谢谢你的快速回复!我改了,但面板还是无法加载!需要注意的是,目前我更关心的是让电路板显示在屏幕上,而不是让整个程序根据需要运行,因此有些事情没有完成(例如,wonX返回false,因为我稍后会更新它,现在我只想加载电路板,以便我可以继续)。如果您可以访问单元格
,使用单元格.length
和单元格[i].length
…挑剔;)不是更好吗@是的老兄,我为错过这个感到羞愧。这是因为一开始我想把电路板做成5x5。非常感谢你们!我按照您所说的做了修复+成功地解决了ImageIcon的一些问题(通过读取堆栈跟踪),现在板已经启动并运行-现在剩下的就是让规则正常工作:)现在我可以给+1;)1+但是@Trouble也覆盖了paint(…)
而不是paintComponent(…)
,并且没有调用任何超级绘制方法,这是一种为麻烦设置的方法。
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
_cells[i][j].draw(); <==========
}
}
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
_cells[i][j].draw();
}
}
for (int i = 0; i < cells.length; i++) {
for (int j = 0; j < cells[i].length; j++) {
_cells[i][j].draw();
}
}