您好我正在为自己创建一个TicTacToe游戏,以便更好地理解Java

但是我不确定我应该在哪里输入whoWins()方法。 我是否在按钮的actionperformed方法中输入此方法,或者我需要不同的东西。 请帮忙。

public class TTT extends JFrame implements ActionListener { private JButton buttons[] = new JButton[9]; private JButton exitButton; public JLabel title; public JPanel titlePanel, panel; private int count = 0; int symbolCount = 0; private boolean win = false; public TTT() { title = new JLabel("Welcome to my Tic Tac Toe Game!"); titlePanel = new JPanel(); title.setFont(new Font(Font.SERIF, 0, 30)); titlePanel.add(title); this.add(titlePanel, BorderLayout.NORTH); panel = new JPanel(new GridLayout(3, 3)); for (int i = 0; i = buttons.length) { JOptionPane.showMessageDialog(null, "End"); } symbolCount++; } } 

如果你真的想要做到这一点,那么我建议做一些重大的改变,一些MVC类型的改变:

  • 首先,从游戏GUI中分离出游戏的逻辑。 这意味着确定谁获胜的代码不应该包含任何包含GUI类型代码的代码。 这将是你的“模特”
  • 接下来你永远不应该有GUI代码实现监听器接口,所以尝试从GUI中获取它并可能让它进入它自己的类,即“Control”类。
  • 最后,GUI或“View”类将关注显示模型的状态并从用户获取输入并将此输入传输到控件。

例如,…

 import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.GridLayout; import java.awt.Window; import java.awt.event.*; import java.awt.image.BufferedImage; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.IOException; import java.util.EnumMap; import java.util.Map; import javax.imageio.ImageIO; import javax.swing.*; import javax.swing.event.SwingPropertyChangeSupport; public class TicTacToeMain { private static void createAndShowGui() { TttView view = null; try { view = new TttView(); } catch (IOException e) { e.printStackTrace(); System.exit(-1); } TttModel model = new TttModel(); new TttControl(model, view); JFrame frame = new JFrame("Tic Tac Toe"); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frame.getContentPane().add(view.getMainPanel()); frame.pack(); frame.setLocationByPlatform(true); frame.setVisible(true); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGui(); } }); } } enum TttPiece { EMPTY, X, O } class TttView { public static final String IMAGE = "/imgFolder/TicTacToe.png"; private static final int GAP = 5; private JPanel mainPanel = new JPanel(); private JPanel tttPanel = new JPanel(); private Map iconMap = new EnumMap<>(TttPiece.class); private JLabel[][] grid = new JLabel[TttModel.ROWS][TttModel.COLS]; private TttControl control; public TttView() throws IOException { BufferedImage img = ImageIO.read(getClass().getResourceAsStream(IMAGE)); Icon[] imgIcons = splitImg(img); iconMap.put(TttPiece.X, imgIcons[0]); iconMap.put(TttPiece.O, imgIcons[1]); iconMap.put(TttPiece.EMPTY, createEmptyIcon(imgIcons[0])); tttPanel.setLayout(new GridLayout(grid.length, grid[0].length, GAP, GAP)); tttPanel.setBackground(Color.black); MyMouseAdapter mouseAdapter = new MyMouseAdapter(); for (int row = 0; row < grid.length; row++) { for (int col = 0; col < grid[row].length; col++) { grid[row][col] = new JLabel(iconMap.get(TttPiece.EMPTY)); grid[row][col].setOpaque(true); grid[row][col].setBackground(Color.LIGHT_GRAY); grid[row][col].addMouseListener(mouseAdapter); tttPanel.add(grid[row][col]); } } JPanel btnPanel = new JPanel(new GridLayout(1, 0, 5, 0)); btnPanel.add(new JButton(new ClearAction("Clear", KeyEvent.VK_C))); btnPanel.add(new JButton(new ExitAction("Exit", KeyEvent.VK_X))); int blGap = 2; mainPanel.setLayout(new BorderLayout(blGap, blGap)); mainPanel.setBorder(BorderFactory.createEmptyBorder(blGap, blGap, blGap, blGap)); mainPanel.add(tttPanel, BorderLayout.CENTER); mainPanel.add(btnPanel, BorderLayout.SOUTH); } public void setControl(TttControl control) { this.control = control; } public JComponent getMainPanel() { return mainPanel; } private Icon createEmptyIcon(Icon icon) { int width = icon.getIconWidth(); int height = icon.getIconHeight(); BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); return new ImageIcon(img); } private Icon[] splitImg(BufferedImage img) { int w = img.getWidth(); int h = img.getHeight(); int gap = 5; Icon[] icons = new ImageIcon[2]; icons[0] = new ImageIcon(img.getSubimage(0, 0, w / 2 - gap, h / 2 - gap)); icons[1] = new ImageIcon(img.getSubimage(w / 2 + gap, 0, w / 2 - gap, h / 2 - gap)); return icons; } private class MyMouseAdapter extends MouseAdapter { @Override public void mousePressed(MouseEvent e) { if (control == null) { return; } for (int row = 0; row < grid.length; row++) { for (int col = 0; col < grid[row].length; col++) { if (grid[row][col] == e.getSource()) { control.gridPress(row, col); } } } } } private class ClearAction extends AbstractAction { public ClearAction(String name, int mnemonic) { super(name); putValue(MNEMONIC_KEY, mnemonic); } @Override public void actionPerformed(ActionEvent evt) { if (control != null) { control.clear(); } } } private class ExitAction extends AbstractAction { public ExitAction(String name, int mnemonic) { super(name); putValue(MNEMONIC_KEY, mnemonic); } @Override public void actionPerformed(ActionEvent evt) { if (control != null) { control.exit(evt); } } } public void setGridIcon(int row, int col, TttPiece tttPiece) { grid[row][col].setIcon(iconMap.get(tttPiece)); } } class TttControl { private TttModel model; private TttView view; public TttControl(TttModel model, TttView view) { this.model = model; this.view = view; view.setControl(this); model.addPropertyChangeListener(new ModelListener()); } public void exit(ActionEvent evt) { Window win = SwingUtilities .getWindowAncestor((Component) evt.getSource()); win.dispose(); } public void gridPress(int row, int col) { try { model.gridPress(row, col); } catch (TttException e) { // TODO: notify user // e.printStackTrace(); } } public void clear() { model.clear(); } private class ModelListener implements PropertyChangeListener { @Override public void propertyChange(PropertyChangeEvent evt) { if (TttModel.GRID_POSITION.equals(evt.getPropertyName())) { TttPiece[][] tttGrid = model.getTttGrid(); for (int row = 0; row < tttGrid.length; row++) { for (int col = 0; col < tttGrid[row].length; col++) { view.setGridIcon(row, col, tttGrid[row][col]); } } } } } } class TttModel { public static final int ROWS = 3; public static final int COLS = ROWS; public static final String GRID_POSITION = "grid position"; private SwingPropertyChangeSupport pcSupport = new SwingPropertyChangeSupport( this); private TttPiece[][] tttGrid = new TttPiece[ROWS][COLS]; private TttPiece player = TttPiece.X; private boolean gameOver; public TttModel() { clear(); } public void setGridPosition(int row, int col, TttPiece piece) throws TttException { if (gameOver) { return; } if (tttGrid[row][col] == TttPiece.EMPTY) { tttGrid[row][col] = piece; checkForWin(row, col, piece); nextPlayer(); pcSupport.firePropertyChange(GRID_POSITION, null, tttGrid); } else { String message = "Invalid setGridPosition for row: %d, col: %d, piece: %s. " + "Spot already occupied by piece: %s"; message = String.format(message, row, col, piece, tttGrid[row][col]); throw new TttException(message); } } public TttPiece[][] getTttGrid() { return tttGrid; } public void gridPress(int row, int col) throws TttException { setGridPosition(row, col, player); } public void nextPlayer() { player = player == TttPiece.X ? TttPiece.O : TttPiece.X; } private void checkForWin(int row, int col, TttPiece piece) { // TODO finish } public void clear() { for (int row = 0; row < tttGrid.length; row++) { for (int col = 0; col < tttGrid[row].length; col++) { tttGrid[row][col] = TttPiece.EMPTY; } } player = TttPiece.X; pcSupport.firePropertyChange(GRID_POSITION, null, tttGrid); } public void addPropertyChangeListener(PropertyChangeListener listener) { pcSupport.addPropertyChangeListener(listener); } public void removePropertyChangeListener(PropertyChangeListener listener) { pcSupport.removePropertyChangeListener(listener); } } @SuppressWarnings("serial") class TttException extends Exception { public TttException() { super(); } public TttException(String message) { super(message); } } 

用于我的图像:

在此处输入图像描述

使用GUI看起来像:

在此处输入图像描述

我也有兴趣编写一个Tic Tac Toe游戏,所以我复制了你的代码,做了一些修改,然后通过测试,检查以下内容:

 package eric.j2se.swing; import java.awt.BorderLayout; import java.awt.FlowLayout; import java.awt.Font; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; /** * 

* Simple game of Tic Tac Toe. *

* * @author eric * @date Apr 16, 2014 11:03:48 AM */ @SuppressWarnings("serial") public class TicTacToe extends JFrame implements ActionListener { // 2 players public static final char playerX = 'X'; public static final char playerO = 'O'; // null player public static final char playerN = 'N'; // the winer, init to null player private Character winner = playerN; // indicate whether game over private boolean gameOver = false; // count of button used, private int count = 0; private Character buttonPlayers[] = new Character[9]; private JButton buttons[] = new JButton[9]; private JButton exitButton; public JLabel title; public JPanel titlePanel, panel; public TicTacToe() { // init buttonPlayers for (int i = 0; i < 9; i++) { buttonPlayers[i] = playerN; } // init title title = new JLabel("Welcome to Tic Tac Toe!"); titlePanel = new JPanel(); title.setFont(new Font(Font.SERIF, 0, 30)); titlePanel.add(title); this.add(titlePanel, BorderLayout.NORTH); // init 9 button panel = new JPanel(new GridLayout(3, 3)); for (int i = 0; i < buttons.length; i++) { buttons[i] = new JButton(); panel.add(buttons[i]); buttons[i].setEnabled(true); buttons[i].addActionListener(this); } // init exit button this.add(panel, BorderLayout.CENTER); JPanel panel1 = new JPanel(new FlowLayout(FlowLayout.CENTER)); exitButton = new JButton("Quit"); panel1.add(exitButton); this.add(panel1, BorderLayout.SOUTH); exitButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { System.exit(WIDTH); } }); } public void whoWins() { // determine winner - horizontal rows if (!gameOver) { for (int i = 0; i < 3; i++) { if ((buttonPlayers[0 + i * 3] != playerN) && (buttonPlayers[0 + i * 3].equals(buttonPlayers[1 + i * 3])) && buttonPlayers[1 + i * 3].equals(buttonPlayers[2 + i * 3])) { winner = buttonPlayers[0 + i * 3]; gameOver = true; break; } } } // determine winner - vertical rows if (!gameOver) { for (int i = 0; i < 3; i++) { if ((buttonPlayers[i + 0 * 3] != playerN) && (buttonPlayers[i + 0 * 3].equals(buttonPlayers[i + 1 * 3])) && buttonPlayers[i + 1 * 3].equals(buttonPlayers[i + 2 * 3])) { winner = buttonPlayers[i + 0 * 3]; gameOver = true; break; } } } // determine winner - diagonal rows if (!gameOver) { int winButtonIndex = -1; if ((buttonPlayers[0] != playerN) && (buttonPlayers[0].equals(buttonPlayers[4])) && buttonPlayers[4].equals(buttonPlayers[8])) { winButtonIndex = 0; } else if ((buttonPlayers[2] != playerN) && (buttonPlayers[2].equals(buttonPlayers[4])) && buttonPlayers[4].equals(buttonPlayers[6])) { winButtonIndex = 2; } if (winButtonIndex >= 0) { winner = buttonPlayers[winButtonIndex]; gameOver = true; } } // full if (count == 9) { gameOver = true; } if (gameOver) { String tip = ""; switch (winner) { case playerO: tip = "Player O win!"; break; case playerX: tip = "Player X win!"; break; default: tip = "Draw game!"; break; } JOptionPane.showMessageDialog(null, tip); } } @Override public void actionPerformed(ActionEvent e) { for (int i = 0; i < buttons.length; i++) { JButton button = buttons[i]; if (button == e.getSource()) { Character currentPlayer = (count % 2 == 1 ? playerX : playerO); button.setText(String.valueOf(currentPlayer)); buttonPlayers[i] = currentPlayer; button.setEnabled(false); break; } } count++; whoWins(); } public static void main(String[] args) { TicTacToe ref1 = new TicTacToe(); ref1.setTitle("Tic Tac Toe"); ref1.setVisible(true); ref1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); ref1.setSize(500, 500); ref1.setLocationRelativeTo(null); } }

关于何时拨打胜利支票:

每次单击9个按钮中的1个时检查,

关于国旗:

我使用2个标志而不是1个标志来表示游戏结束和赢家,因为在TTT游戏中,抽奖游戏很常见,经过多次游戏后,你总是得到抽奖游戏......

对您的代码提出一点建议:

  • 比较字符串时,使用equals(),而不是==,
  • 在变量中定义const值,而不是在逻辑中写入,例如'O''X',
  • 不要重复代码,尝试使用逻辑控制使其简短易读,易于维护,