1

这曾经是家庭作业,但现在它是个人的,因为学期结束了,我仍在努力学习 Swing 组件。这个程序是我尝试以最简单(看起来)的方式将程序控制台 TicTacToe 实现提升到一个小程序中,避免使用单个 JTextField 和提交按钮的传统按钮网格。

它在第一次运行良好,但是在我用 init() 函数中的一些逻辑重置游戏后(这确实有效,我很惊讶),getText() 在第 155 行返回空字符串(搜索“ARGH” )。在这一点上,我基本上是在黑暗中拍摄,所以,如果有人可以看看和批评,也许指出通过这条最短路线的方式,我真的很感激!

    /** 
     * TTTapp.java - TicTacToe
     * Implements a simple console-based version of the classic
     * game Tic Tac Toe 
     * @author  Todd Howe
     * @version 1.0
     * @since 2012-08-22
     */
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import java.util.ArrayList;
    import java.util.*;
    /**
     * Plays a simple game of Tic Tac Toe.
     * 
     * A 3x3 char array is generated to accomodate a simple Tic Tac Toe
     * game. The player picks a position, the computer picks randomly 
     * and the results are tallied in the usual manner.
     */ 
    public class TTTapp extends JApplet implements ActionListener {
        static boolean checkWin=false;              // control variable to detect wins
        static boolean boardFull=false;             // control variable to detect ties
        static String response="";                      // user input
        static int gridPos;                         // (1-9) 1D rep of position on the TTT board
        static int x, y;                                // cartesian TTT board coordinates
        static char player;                         // X or O to indicate current player
        static char[][] board = new char[3][3];     // 2d TTT board matrix
        static int[][] magicsquare = { {8, 1, 6},       // sekrit weapon
                                        {3, 5, 7},
                                        {4, 9, 2} };

        Container con=getContentPane();
        Font monoFont = new Font("Monospaced", Font.BOLD, 12);
        JLabel gameBanner1=new JLabel("Welcome to Tic Tac Toe!");
        JLabel gameBanner2=new JLabel("Player is X, Computer is O");
        JLabel spacer1=new JLabel(" ");
        JLabel spacer2=new JLabel(" ");
        JLabel spacer3=new JLabel(" ");
        JLabel board1=new JLabel(" 1 | 2 | 3 ");
        JLabel board2=new JLabel("---|---|---");
        JLabel board3=new JLabel(" 4 | 5 | 6 ");
        JLabel board4=new JLabel("---|---|---");
        JLabel board5=new JLabel(" 7 | 8 | 9 ");
        JLabel announce=new JLabel("");
        JLabel prompt=new JLabel("\nPick an available space by entering the number (1-9): ");
        JTextField promptField=new JTextField("",4);
        JButton submitButton=new JButton("Submit");
        JButton restartButton=new JButton("RESTART GAME");
        BoxLayout flow=new BoxLayout(con, BoxLayout.Y_AXIS);    

        public void init() {
            // prep the application window
            if (TTTapp.checkWin==false) {
                con.setLayout(flow);
                board1.setFont(monoFont);
                board2.setFont(monoFont);
                board3.setFont(monoFont);
                board4.setFont(monoFont);
                board5.setFont(monoFont);

                gameBanner1.setAlignmentX(Component.CENTER_ALIGNMENT);
                gameBanner2.setAlignmentX(Component.CENTER_ALIGNMENT);
                board1.setAlignmentX(Component.CENTER_ALIGNMENT);
                board2.setAlignmentX(Component.CENTER_ALIGNMENT);
                board3.setAlignmentX(Component.CENTER_ALIGNMENT);
                board4.setAlignmentX(Component.CENTER_ALIGNMENT);
                board5.setAlignmentX(Component.CENTER_ALIGNMENT);
                announce.setAlignmentX(Component.CENTER_ALIGNMENT);
                prompt.setAlignmentX(Component.CENTER_ALIGNMENT);
                promptField.setAlignmentX(Component.CENTER_ALIGNMENT);
                submitButton.setAlignmentX(Component.CENTER_ALIGNMENT);

                con.add(gameBanner1);
                con.add(gameBanner2);
                con.add(spacer1);
                con.add(board1);
                con.add(board2);
                con.add(board3);
                con.add(board4);
                con.add(board5);
                con.add(spacer2);
                con.add(announce);
                con.add(prompt);
                con.add(promptField);
                con.add(submitButton);
                promptField.requestFocus();

                System.out.println("Real INIT");
                submitButton.addActionListener(this);
                promptField.addActionListener(this);
            }
            else {
                con.setLayout(flow);
                board1.setFont(monoFont);
                board2.setFont(monoFont);
                board3.setFont(monoFont);
                board4.setFont(monoFont);
                board5.setFont(monoFont);

                gameBanner1.setAlignmentX(Component.CENTER_ALIGNMENT);
                gameBanner2.setAlignmentX(Component.CENTER_ALIGNMENT);
                board1.setAlignmentX(Component.CENTER_ALIGNMENT);
                board2.setAlignmentX(Component.CENTER_ALIGNMENT);
                board3.setAlignmentX(Component.CENTER_ALIGNMENT);
                board4.setAlignmentX(Component.CENTER_ALIGNMENT);
                board5.setAlignmentX(Component.CENTER_ALIGNMENT);
                announce.setAlignmentX(Component.CENTER_ALIGNMENT);
                prompt.setAlignmentX(Component.CENTER_ALIGNMENT);
                promptField.setAlignmentX(Component.CENTER_ALIGNMENT);
                submitButton.setAlignmentX(Component.CENTER_ALIGNMENT);
                restartButton.setAlignmentX(Component.CENTER_ALIGNMENT);

                con.add(gameBanner1);
                con.add(gameBanner2);
                con.add(spacer1);
                con.add(board1);
                con.add(board2);
                con.add(board3);
                con.add(board4);
                con.add(board5);
                con.add(spacer2);
                con.add(announce);
                con.add(spacer3);
                con.add(restartButton);

                System.out.println("Else INIT");
                restartButton.addActionListener(this);
            }
        }
        public void actionPerformed(ActionEvent e) {
            String discard="";
            // MAIN GAME LOOP (CHANGED BOTH FORMER WHILE LOOPS TO IF TO ALLOW GETTEXT REFRESH)
            // game reset
            if (TTTapp.checkWin==true) {
                TTTapp.checkWin=false;
                TTTapp.boardFull=false;
                TTTapp.response="";
                TTTapp.board = new char[3][3];
                TTTapp.gridPos=(-1);
                announce.setText("");
                con.remove(announce);
                con.remove(restartButton);
                con.remove(spacer3);
                board1.setText(" 1 | 2 | 3 ");
                board2.setText("---|---|---");
                board3.setText(" 4 | 5 | 6 ");
                board4.setText("---|---|---");
                board5.setText(" 7 | 8 | 9 ");
                promptField.requestFocus();
                init();
                TTTapp.response=promptField.getText();
                promptField.setText("");
                // ### ARGH THIS DOESN'T READ promptField IN INIT() ################
            }
            if (TTTapp.boardFull==false && TTTapp.checkWin==false) {
                // ###############################################################
                // System.out.println("boardFull: "+boardFull+" checkWin: "+checkWin);
                displayBoard(TTTapp.board);
                // player's turn
                // System.out.println("Player's turn");
                TTTapp.player='X';
                TTTapp.gridPos=(-1);
                // WAS WHILE
                while (TTTapp.gridPos==(-1)) { // this was my last attempt to capture the bad response
                    if (TTTapp.gridPos==(-1)) {
                        TTTapp.response=promptField.getText();
                        promptField.setText("");
                        // ##################################################
                        System.out.println("Got here, response is "+response);
                        TTTapp.gridPos=validateResponse(TTTapp.response, TTTapp.board); 
                        // #######################################
                        System.out.println("GridPos is "+gridPos);
                        TTTapp.boardFull=playGridPos(TTTapp.gridPos, TTTapp.board, TTTapp.player);
                        // ########################################
                        System.out.println("boardFull: "+boardFull);
                        displayBoard(TTTapp.board);
                    }
                }
                // check for player win
                TTTapp.checkWin=scanBoard(TTTapp.board, TTTapp.magicsquare, TTTapp.player);
                if (TTTapp.checkWin==true) {
                    displayBoard(TTTapp.board);
                    con.remove(prompt);
                    con.remove(promptField);
                    con.remove(submitButton);
                    announce.setText("\nPLAYER WINS");
                }
                // computer's turn
                TTTapp.player='O';
                if (TTTapp.checkWin==false) {
                    if (TTTapp.boardFull==false) {
                        TTTapp.gridPos=computerPlays(TTTapp.board);
                        TTTapp.boardFull=playGridPos(TTTapp.gridPos, TTTapp.board, TTTapp.player);
                        displayBoard(TTTapp.board);
                    }
                    //check for computer win here
                    TTTapp.checkWin=scanBoard(TTTapp.board, TTTapp.magicsquare, TTTapp.player);
                    if (TTTapp.checkWin==true) {
                        displayBoard(TTTapp.board);
                        con.remove(prompt);
                        con.remove(promptField);
                        con.remove(submitButton);
                        announce.setText("\nCOMPUTER WINS");
                    }
                }
            }
            if (TTTapp.checkWin==false && TTTapp.boardFull==true) {
                displayBoard(TTTapp.board);
                con.remove(prompt);
                con.remove(promptField);
                con.remove(submitButton);
                announce.setText("\nTIE GAME");
            }
            if (TTTapp.checkWin==true) {
                init();
            }
            repaint();
        }
        /**
         * Display the TicTacToe board as a grid
         * @param board 2D char array representing game board
         */
        public void displayBoard(char[][] board) {
            int gridPos;    // (1-9) 1d rep of position on the board
            char[] cell=new char[9];    // array of parsed TTT board elements
            char readCell;              // single TTT element
            int line;                   // printout line number
            String[] boardDisplay = new String[5];  // array for 'console printing' to applet
            // System.out.println("");
            // stores each element of the displayBoard readout in cell[]
            for (int x=0; x<3; x++) {
                for (int y=0; y<3; y++) {
                    gridPos=((x*3)+y);
                    readCell=parseCell(board[x][y]);
                    if (readCell==' ') {
                        cell[gridPos]=(char)(gridPos+49);
                    }
                    else {
                        cell[(x*3)+y]=readCell;
                    }
                }
                // constructs tic tac toe grid display line by line
                line=x*2;
                boardDisplay[line]=(" "+cell[((x*3)+0)]+" | "+cell[((x*3)+1)]+" | "+cell[((x*3)+2)]);
                if(x<2) {
                    line+=1;
                    boardDisplay[line]=("---|---|---");
                }
            }
            board1.setText(boardDisplay[0]);
            board2.setText(boardDisplay[1]);
            board3.setText(boardDisplay[2]);
            board4.setText(boardDisplay[3]);
            board5.setText(boardDisplay[4]);
        }
        /**
         * Checks desired player board position against vacancies on TTT grid
         * @param response String of user response
         * @param board 2D char array representing game board
         */
        public int validateResponse(String response,char[][] board) {
            int checkPos=(-1);  // desired TTT board position
            ArrayList emptyCells=new ArrayList();   // array of available positions
            Integer somePos;    // candidate TTT board position
            int result=(-1);    // result returns position or -1 signal to try again
            boolean contains=false; // candidate cell matches desired position
            // populate emptyCells with (1-9) positions
            emptyCells=findEmptyCells(board);
            // checks whether there's any empty cells left
            if (emptyCells.size() > 0) {
                // checks whether the input is at least one char long
                if (response.length()>0) {
                    checkPos=(int)(response.charAt(0)-48);
                    int i=0;
                    while (i<emptyCells.size()) {
                        // #########################################################
                        // System.out.println("emptyCells("+i+"): "+emptyCells.get(i));
                        // checks whether requested cell is empty or not
                        somePos=(Integer)(emptyCells.get(i));
                        // ############################################################
                        // System.out.println("somePos: "+somePos+" checkPos: "+checkPos);
                        if ((somePos.intValue())!=checkPos) {
                            i++;
                        }
                        else {
                            if ((somePos.intValue())==checkPos) {
                                contains=true;
                                i=99;
                            }
                        }
                    }
                    // if requested cell is empty, validate request
                    if (contains==true) {
                        result=checkPos;
                    }
                    // otherwise send pick again signal
                    else {
                        // #################################################################
                        // System.out.println("Contains is "+contains+" checkPos is "+checkPos);
                        result=(-1);
                    }
                }
                // if no entry detected, send pick again signal
                else {
                    result=(-1);
                }
            }
            return(result);
        }
        /**
         * Further validates and places player marker on the board
         * @param gridPos Int desired position of marker on board
         * @param board 2D char array representing game board
         * @param player Char marker representing player
         */
        public boolean playGridPos(int gridPos, char[][] board, char player) {
            int x,y;    // cartesian TTT board coordinates
            ArrayList emptyCells=new ArrayList();   // array of available positions
            boolean boardFull=false;    // control variable to detect ties
            switch (gridPos) {
                // catch invalid entry signal
                case(-1):
                    announce.setText("\nPLEASE ENTER ONE OF THE VISIBLE NUMBERS.");
                    break;
                // place the player marker on the board
                default:
                    gridPos--;
                    x=gridPos/3;
                    y=gridPos-(x*3);
                    board[x][y]=player;
            }
            emptyCells=findEmptyCells(board);
            // check to see if the board is now full
            if (emptyCells.size()==0) {
                boardFull=true;
            }
            return(boardFull);
        }
        /**
         * Determines the computer's next move
         * @param board 2D char array representing game board
         */
        public int computerPlays(char[][] board) {
            int gridPos=(-1);   // (1-9) 1d rep of position on the board
            int temp;           // random board position variable
            String response=""; // user input
            Integer availPos;   // Integer rep of board position index
            ArrayList emptyCells=new ArrayList();   // array of available positions
            boolean vacant=false;   // control variable for a position's vacancy
            boolean checkWin=false; // control variable to detect a win
            char[][] tempBoard = new char[3][3];    // board to test positions for a win
            int[][] magicsquare = { {8, 1, 6},      // sekrit weapon
                                    {3, 5, 7},
                                    {4, 9, 2} };
            emptyCells=findEmptyCells(board);
            // check to see if we have an available win and pick that
            for (int i=0; i<emptyCells.size(); i++) {
                response=(""+emptyCells.get(i));
                temp=validateResponse(response, board);
                availPos=(Integer)temp;
                temp=availPos.intValue();
                // copy board to tempBoard
                for(int x=0; x<3; x++) {
                    for(int y=0; y<3; y++) {
                        tempBoard[x][y]=board[x][y];
                    }
                }
                // if there's two adjacent Os, find the win
                if (checkWin==false) {
                    checkWin=playGridPos(temp,tempBoard,'O');
                    checkWin=scanBoard(tempBoard,magicsquare,'O');
                    if (checkWin==true) {
                        gridPos=temp;
                    }
                }
            }
            // else pick a random square
            if (checkWin==false) {
                while (vacant==false) {
                    temp=(int)(Math.random()*(emptyCells.size()-1));
                    response=(""+emptyCells.get(temp));
                    gridPos=validateResponse(response, board);
                    if (gridPos!=(-2) && gridPos!=(-1)) {
                        availPos=(Integer)gridPos;
                        gridPos=availPos.intValue();
                        vacant=true;
                    }
                }
            }
            return(gridPos);
        }
        /**
         * Detect vacant elements in TicTacToe matrix
         * @param board 2D char array representing game board
         */
        public ArrayList findEmptyCells(char[][] board) {
            ArrayList emptyCells=new ArrayList(); // array of available positions
            char readCell;  // contents of a candidate cell
            Integer availPos;   // integer rep of board position index
            for (int x=0; x<3; x++) {
                for (int y=0; y<3; y++) {
                    availPos=Integer.valueOf((x*3)+y+1);
                    readCell=parseCell(board[x][y]);
                    if (readCell==' ') {
                        emptyCells.add(availPos);
                    }
                }                       
            }
            return(emptyCells);
        }
        /**
         * Scores the TTT board using a magic square to tally row/col/diag
         * @param board 2D char array representing game board
         * @param magicsquare 2D matrix to to help score TTT board
         * @param player Char marker representing player
         */
        public boolean scanBoard(char[][] board, int[][] magicsquare, char player) {
            char readCell;  // contents of a candidate cell
            int[][] keyScores=new int[3][3]; // matrix for magicsquare scoring
            boolean checkWin=false; // control variable to detect wins
            // mask magicsquare with player's occupied cells
            for (int x=0; x<3; x++) {
                for (int y=0; y<3; y++) {
                    readCell=parseCell(board[x][y]);
                    if (readCell==player) {
                        keyScores[x][y]=magicsquare[x][y];
                    }
                    else {
                        keyScores[x][y]=0;
                    }
                }                       
            }
            // check for a win
            // horizontals
            for (int x=0; x<3; x++) {
                if ((keyScores[x][0]+keyScores[x][1]+keyScores[x][2])==15)
                    checkWin=true;
            }
            //verticals 
            for (int y=0; y<3; y++) {
                if ((keyScores[0][y]+keyScores[1][y]+keyScores[2][y])==15)
                    checkWin=true;
            }
            //diagonals
            if ((keyScores[0][0]+keyScores[1][1]+keyScores[2][2])==15)
                    checkWin=true;
            if ((keyScores[0][2]+keyScores[1][1]+keyScores[2][0])==15)
                    checkWin=true;
            return(checkWin);
        }
        /**
         * Returns a processed representation of one TTT cell element
         * @param token Char contents of a single TTT cell
         */
        public char parseCell(char token) {
            char result=' ';    // holds processed contents of cell
            switch(token) {
            case('\u0000'):
                result=(' ');
                break;
            case('x'):
            case('X'):
                result=('X');
                break;
            case('o'):
            case('O'):
                result=('O');
                break;
            default:
                result=token;
            }
            return(result);
        }
    }
4

1 回答 1

2

你的actionPerformed逻辑是错误的。

首先,您不应该将所有这些不相关的内容转储到单个actionPerformed. 每个单独的组件(文本字段、按钮)都应该有一个actionPerformed

如果你不能,那么你应该检查谁实际触发了这个事件(要么检查ActionEvent.getSource要么ActionEvent.getActionCommand

现在,我确实通过改变来纠正这个问题

if (BadApplet.checkWin == true) {
    // Stuff here
} 
if (BadApplet.boardFull == false && BadApplet.checkWin == false) {
    // more stuff here
}

if (BadApplet.checkWin == true) {
    // Stuff here
}  else if (BadApplet.boardFull == false && BadApplet.checkWin == false) {
    // more stuff here
}

我强烈建议您学习如何调试源代码;)

于 2012-08-24T04:27:53.543 回答