使用 ImageIcons 在 Java 中编程 Tic Tac Toe - winningCondition

Programming Tic Tac Toe in Java with ImageIcons - winningCondition

我需要帮助,因为我是 Java 编程的初学者。 我目前正在为大学编程 Tic Tac Toe,我遇到了一些问题,因为我想使用一些笑脸而不是 X 和 O。但我不知道如何通过搜索获胜者来比较它们,所以我使用了字母。但是你可以在操场上看到字母和笑脸,我认为这不是最好的解决方案。也许你们中的一些人对我的程序有更好的建议和评论。我在我的 TicTacToe src 文件夹中复制了图像 devil.png 和 sun.png。

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

public class Gui implements ActionListener {

    // Variables
    private static int[][] winCombos = new int[][] //Possible win combinations
            {
                {0, 1, 2}, {3, 4, 5}, {6, 7, 8}, //horizontal wins
                {0, 3, 6}, {1, 4, 7}, {2, 5, 8}, //vertical wins
                {0, 4, 8}, {2, 4, 6}             //diagonal wins
            };

    static JButton btn[] = new JButton[9];
    private int count = 0;
    private int xscore = 0;
    private int oscore = 0;
    private String letter = "";
    private boolean win = false;
    private ImageIcon devil; // devil= spieler X
    private ImageIcon sun; // sun = spieler O

    public Gui() {

        // Create Window
        JFrame jf = new JFrame();

        jf.setSize(400, 400);
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jf.setLocationRelativeTo(null);
        jf.setResizable(false);
        jf.setTitle("Tic-Tac-Toe Playfield");
        jf.setLayout(new GridLayout(3, 3));
        devil = new ImageIcon(getClass().getResource("devil.png")); //X
        sun = new ImageIcon(getClass().getResource("sun.png")); //O

        // Add Buttons to the Window
        for (int i = 0; i < btn.length; i++) {
            btn[i] = new JButton();
            btn[i].setVisible(true);
            btn[i].setFocusPainted(false);
            btn[i].addActionListener(this);
            jf.add(btn[i]);
        }
        jf.setVisible(true);
    }

    public void actionPerformed(ActionEvent a) 
    {
            count++;

            //Who's turn is it 
            if(count % 2 == 0)
            {
                letter = "O";
                oscore++;
            }
            else
            {
                letter = "X";
                xscore++;
            }

            //Change button to letter
            if(letter == "X")
            {
                JButton pressedButton = (JButton)a.getSource();
                pressedButton.setIcon(devil);
                pressedButton.setEnabled(false);
            }
            else if(letter == "O")
            {
                JButton pressedButton = (JButton)a.getSource();
                pressedButton.setIcon(sun);
                pressedButton.setEnabled(false);
            }

            //Search for Winner
            for(int i=0; i<=7; i++)
            {
               if(btn[winCombos[i][0]].getIcon() !=null &&
                       btn[winCombos[i][0]].getIcon().equals(btn[winCombos[i][1]].getIcon()) && 
                       btn[winCombos[i][1]].getIcon() !=null && 
                               btn[winCombos[i][1]].getIcon().equals(btn[winCombos[i][2]].getIcon())

                       )

                {
                    win = true;
                }
            }


            //Dialog at the end of the game
            if(win)
            {
                JOptionPane.showMessageDialog(null, letter + " wins the game");
                System.exit(0);
            }
            else if(count == 9 && !win)
            {
                JOptionPane.showMessageDialog(null, "There is no winner.");
                System.exit(0);
            }               
    }}

MadProgrammers 建议在这里

Step back for a moment. You need to do is separate the logic from the presentation, this allows you to consistently model the logic and allow the presentation to present in whatever form it wants to. This is the basic functionality of the "model-view-controller" paradigm. With this, you model your data (the game and it's state) and then allow the view (the UI) to present it in what ever manager it wants to. This means the logic for determining when a player wins a game is determined by the model

绝对是正确的方法,也是您应该如何考虑设计未来的项目。但是,我假设您可能尚未在课程中涵盖 MVC 和其他设计模式。

您现在遇到的问题将是 NullPointerException 在您的循环中,因为在第一次点击时大多数按钮都没有分配图标,因此当您尝试调用 .equals() 时空对象发生异常。

所以简单的解决方法是您需要先检查空图标,然后才能进行相等性检查。

编辑 在你称呼平等之前!

if(btn[winCombinations[i][0]].getIcon() != null && 
   btn[winCombinations[i][0]].getIcon().equals(....

您还需要为 btn[winCombinations[i][1]].getIcon()

执行此操作

结束编辑

更简洁的方法可能是使用 Objects.equals() 方法,如果可以

解释更多:当异常发生时,方法中断 - 所以它发生在你的 for 循环中,所以下面的代码将不会被执行。尝试在你的循环下面添加这个:

System.out.println("Reached here!");

你会注意到只有在按下所有按钮后才会打印它。

为了帮助您更直观地检查,您可以在循环周围添加一个 try catch - 请注意,这不是理想的操作 - 但会帮助您更直观地诊断问题。

try
{
    // your win check loop
}
catch (Exception e)
{
    e.printStackTrace();
    JOptionPane.showMessageDialog(null, "Oh no!:\n" + e);
}