Защо булевата стойност не се превключва?

Първо искам да благодаря за всяка помощ. Аз съм сравнително нов в програмирането на Java. Създадох проста игра TicTacToe и имам малък проблем.

От време на време "X" или "O" ще се играят два пъти подред. Имам булева променлива, която трябва да превключи от true към false, за да промени "X" на "O", когато всеки играч вземе ход, но по някаква причина тя не се превключва на случаен принцип.

Мисля, че може да е проблем с Eclipse или нещо подобно, защото не разбирам защо иначе би направил това.

По-долу е кодът за играта:

public class gameMain {

    Boolean player = true;
    JPanel gameBoard;
    JButton[] b = new JButton[10];
    Font font = new Font("Arial", Font.BOLD, 99);
    ListenForButtons lfb = new ListenForButtons();

    public static void main(String args[]) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new gameMain();
            }
        });
    }

    public gameMain() {
        JFrame j = new JFrame("TicTacToe");
        j.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        j.setLocationRelativeTo(null);
        j.setSize(400, 400);

        gameBoard = new JPanel();
        gameBoard.setLayout(new GridLayout(3, 3));

        b[1] = new JButton("");
        b[1].addActionListener(lfb);
        b[1].setContentAreaFilled(false);
        b[1].setFont(font);
        b[1].setBorder(BorderFactory.createMatteBorder(0, 0, 2, 2, Color.BLACK));
        b[2] = new JButton("");
        b[2].addActionListener(lfb);
        b[2].setContentAreaFilled(false);
        b[2].setFont(font);
        b[2].setBorder(BorderFactory.createMatteBorder(0, 0, 2, 0, Color.BLACK));
        b[3] = new JButton("");
        b[3].addActionListener(lfb);
        b[3].setContentAreaFilled(false);
        b[3].setFont(font);
        b[3].setBorder(BorderFactory.createMatteBorder(0, 2, 2, 0, Color.BLACK));
        b[4] = new JButton("");
        b[4].addActionListener(lfb);
        b[4].setContentAreaFilled(false);
        b[4].setFont(font);
        b[4].setBorder(BorderFactory.createMatteBorder(0, 0, 0, 2, Color.BLACK));
        b[5] = new JButton("");
        b[5].addActionListener(lfb);
        b[5].setContentAreaFilled(false);
        b[5].setFont(font);
        b[5].setBorder(BorderFactory.createMatteBorder(0, 0, 0, 0, Color.BLACK));
        b[6] = new JButton("");
        b[6].addActionListener(lfb);
        b[6].setContentAreaFilled(false);
        b[6].setFont(font);
        b[6].setBorder(BorderFactory.createMatteBorder(0, 2, 0, 0, Color.BLACK));
        b[7] = new JButton("");
        b[7].addActionListener(lfb);
        b[7].setContentAreaFilled(false);
        b[7].setFont(font);
        b[7].setBorder(BorderFactory.createMatteBorder(2, 0, 0, 2, Color.BLACK));
        b[8] = new JButton("");
        b[8].addActionListener(lfb);
        b[8].setContentAreaFilled(false);
        b[8].setFont(font);
        b[8].setBorder(BorderFactory.createMatteBorder(2, 0, 0, 0, Color.BLACK));
        b[9] = new JButton("");
        b[9].addActionListener(lfb);
        b[9].setContentAreaFilled(false);
        b[9].setFont(font);
        b[9].setBorder(BorderFactory.createMatteBorder(2, 2, 0, 0, Color.BLACK));

        gameBoard.add(b[1]);
        gameBoard.add(b[2]);
        gameBoard.add(b[3]);
        gameBoard.add(b[4]);
        gameBoard.add(b[5]);
        gameBoard.add(b[6]);
        gameBoard.add(b[7]);
        gameBoard.add(b[8]);
        gameBoard.add(b[9]);

        j.add(gameBoard);
        j.setVisible(true);
    }

    public class ListenForButtons implements ActionListener {

        public void actionPerformed(ActionEvent e) {

            if (e.getSource() == b[1]) {
                setSquare(b[1]);
            }
            if (e.getSource() == b[2]) {
                setSquare(b[2]);
            }
            if (e.getSource() == b[3]) {
                setSquare(b[3]);
            }
            if (e.getSource() == b[4]) {
                setSquare(b[4]);
            }
            if (e.getSource() == b[5]) {
                setSquare(b[5]);
            }
            if (e.getSource() == b[6]) {
                setSquare(b[6]);
            }
            if (e.getSource() == b[7]) {
                setSquare(b[7]);
            }
            if (e.getSource() == b[8]) {
                setSquare(b[8]);
            }
            if (e.getSource() == b[9]) {
                setSquare(b[9]);
            }
            checkForWin();
        }
    }

    public void setSquare(JButton button) {
        if (player) {
            button.setText("X");
            player = false;
            button.removeActionListener(lfb);
        } else {
            button.setText("O");
            player = true;
            button.removeActionListener(lfb);
        }
    }

    public void checkForWin() {
        if ((b[1].getText().equals("X") && b[2].getText().equals("X") && b[3].getText().equals("X"))
                || (b[4].getText().equals("X") && b[5].getText().equals("X") && b[6].getText().equals("X"))
                || (b[7].getText().equals("X") && b[8].getText().equals("X") && b[9].getText().equals("X"))
                || (b[1].getText().equals("X") && b[4].getText().equals("X") && b[7].getText().equals("X"))
                || (b[2].getText().equals("X") && b[5].getText().equals("X") && b[8].getText().equals("X"))
                || (b[3].getText().equals("X") && b[6].getText().equals("X") && b[9].getText().equals("X"))
                || (b[1].getText().equals("X") && b[5].getText().equals("X") && b[9].getText().equals("X"))
                || (b[3].getText().equals("X") && b[5].getText().equals("X") && b[7].getText().equals("X"))) {
            JOptionPane.showMessageDialog(null, "X WINS THE GAME!", "", JOptionPane.INFORMATION_MESSAGE);
            resetBoard();
        } else if ((b[1].getText().equals("O") && b[2].getText().equals("O") && b[3].getText().equals("O"))
                || (b[4].getText().equals("O") && b[5].getText().equals("O") && b[6].getText().equals("O"))
                || (b[7].getText().equals("O") && b[8].getText().equals("O") && b[9].getText().equals("O"))
                || (b[1].getText().equals("O") && b[4].getText().equals("O") && b[7].getText().equals("O"))
                || (b[2].getText().equals("O") && b[5].getText().equals("O") && b[8].getText().equals("O"))
                || (b[3].getText().equals("O") && b[6].getText().equals("O") && b[9].getText().equals("O"))
                || (b[1].getText().equals("O") && b[5].getText().equals("O") && b[9].getText().equals("O"))
                || (b[3].getText().equals("O") && b[5].getText().equals("O") && b[7].getText().equals("O"))) {

            JOptionPane.showMessageDialog(null, "O WINS THE GAME!", "", JOptionPane.INFORMATION_MESSAGE);
            resetBoard();
        } else if (!b[1].getText().equals("") && !b[2].getText().equals("") && !b[3].getText().equals("")
                && !b[4].getText().equals("") && !b[5].getText().equals("") && !b[6].getText().equals("")
                && !b[7].getText().equals("") && !b[8].getText().equals("") && !b[9].getText().equals("")) {
            JOptionPane.showMessageDialog(null, "Cats Game!", "", JOptionPane.INFORMATION_MESSAGE);
            resetBoard();
        }
    }

    public void resetBoard() {
        for (int i = 1; i <= b.length - 1; i++) {
            b[i].setText("");
        }
        for (int i = 1; i <= b.length - 1; i++) {
            b[i].addActionListener(lfb);
        }
        player = true;
    }
 }

person Discoveringmypath    schedule 09.04.2013    source източник
comment
Освен това понякога, когато се извика resetBoard, едно от квадратчетата на дъската не се нулира.   -  person Discoveringmypath    schedule 10.04.2013
comment

Тестването за номер на версия едва ли е добра идея. Винаги трябва да проверявате за функции и никога за версии, ако наистина искате стабилност (и в същото време преносимост).

Какво ще се случи, ако една от функциите, от които се нуждаете, бъде премахната от бъдеща версия на Matlab? Или начинът, по който работи, се променя? (това е много по-често, отколкото може да се очаква). Или ако някой иска да използва вашия код в система, съвместима с Matlab, която има функциите, които вашият код изисква?

Има някои autoconf макроси, свързани с Matlab (въпреки че никога не съм използвал такъв). Или можете да напишете свои собствени прости проверки на езика на Matlab.

  -  person Ken White    schedule 10.04.2013
comment
дайте System.out.println(player +); към вашия setSquare, може би бутонът удря два пъти, така че проверете това - или наистина е присвоен на вашите множество произволно добавени слушатели на действия като bmorris591, споменати в долната част...   -  person Christian 'fuzi' Orgler    schedule 10.04.2013
comment
Also, sometimes when resetBoard is called, one of the board squares doesn't reset Индексът на масива е базиран на нула в Java   -  person drzymala    schedule 10.04.2013
comment
Игнорирайте базата на индекса на масива; за това е подобреният for цикъл.   -  person Boris the Spider    schedule 10.04.2013
comment
Благодаря за съвета; @Кен Уайт. Това е първата ми публикация, мислех да публикувам всичко, за да могат хората да видят какво имам. Ще се опитам следващия път да го направя по-конкретно.   -  person Discoveringmypath    schedule 11.04.2013
comment
Моля, редактирайте въпроса си, както зададох, и поправете този, а не само следващия. Вероятно не получавате много помощ, защото има твърде много бъркотия. Както е сега, може да бъде затворен като твърде локализиран, защото сте включили твърде много допълнителни неща, за да го направите от обща стойност за бъдещите читатели тук.   -  person Ken White    schedule 11.04.2013


Отговори (1)


Когато се извика ResetBoard() и не всеки бутон е натиснат, в крайна сметка имате множество ActionListeners, присвоени на тези неизползвани бутони.

Ето примерен resetBoard() метод:

    public void resetBoard() {
        // Fixed the loop index. Was: (int i = 1; i <= b.length - 1; i++)
        for (int i = 0; i < b.length; i++) {
            b[i].setText("");
            // Adding a listener only if there isn't one already
            if (b[i].getActionListeners().length < 1) 
                b[i].addActionListener(lfb);
        }
        player = true;
    }

Както @MadProgrammer предложи, преработих и метода setSquare():

    public void setSquare(JButton button) {
        if (player) {
            button.setText("X");
        } else {
            button.setText("O");
        }
        button.removeActionListener(lfb);
        player = !player;
    }
person drzymala    schedule 09.04.2013
comment
Или просто не добавяйте произволно отново ActionListeners? - person Boris the Spider; 10.04.2013
comment
Бих добавил също, че в метода setSquare необходимостта от изрично задаване на player на true или false е ненужна, просто използването на player = !player в края на метода ще 1- намали претрупването на кода и 2- ще постигне абсолютен резултат, но вашият отговорът ще реши по-добре проблема - person MadProgrammer; 10.04.2013
comment
Благодаря ти, Мартини, не знаех, че може да има няколко слушатели, това реши проблема ми и има идеален смисъл. Също така предложението на MadProgrammer също помогна. Наистина оценявам помощта! - person Discoveringmypath; 11.04.2013