java - 数组上的 Wordsearch 难题 nullpointerException

标签 java arrays wordsearch

在我已初始化的数组上收到 java.lang.NullPointerException,但我无法完全弄清楚做错了什么。错误发生在第 371 行。

下面是父类的代码,后面是初始化 letterArray ArrayList 的类:

package wordsearch;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Line2D;
import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingConstants;

/**
 *  Main class of Puzzle Program
 * @author mungaialex
 *
 */
public class WordSearchPuzzle extends JFrame {

    private static final long serialVersionUID = 1L;

    /** No. Of Columns in Wordlist*/
    private static final int WORDLISTCOLS = 1;

    static JButton[][] grid; //names the grid of buttons
    GridLayout myGridLayout = new GridLayout(1,2,3,3);

    /**Array to hold wordList*/
    ArrayList<String> wordList;

    JButton btnCheck, btnClear;

    /** Panel to hold Components to the left*/
    JPanel leftSidePanel;
    /** Panel to hold components to the right*/
    JPanel rightSidePanel;
    /**Panel to hold word List*/
    JPanel wordListPanel;
    /**Panel to hold grid buttons*/
    JPanel gridPanel;
    /**Panel to hold clear button and check button*/
    JPanel buttonsPanel;
    /**Panel to hold output textarea*/
    JPanel bottomPanel;

    private JLabel[] wordListComponents;

    @SuppressWarnings("rawtypes")
    List puzzleLines;

    //Grid Size
    private final int ROWS = 20;
    private final int COLS = 20;

    /** Output Area of system*/
    private JTextArea txtOutput;
    /**Scrollpane for Output area*/
    private JScrollPane scptxtOutput;

    private Object[] theWords;
    public String wordFromChars = new String();
    /** the matrix of the letters */
    private char[][] letterArray = null;

    /**
     * Constructor for WordSearchPuzzle
     * @param wordListFile File Containing words to Search for
     * @param wordSearhPuzzleFile File Containing the puzzle
     */
    public WordSearchPuzzle(String wordSearchFile,String wordsListFile) throws IOException {
        FileIO io = new FileIO(wordSearchFile,wordsListFile,grid);

        wordList = io.loadWordList();
        theWords = wordList.toArray();

        addComponentsToPane();
        buildWordListPanel();
        buildBottomPanel();

        io.loadPuzleFromFile();

        //Override System.out
        PrintStream stream = new PrintStream(System.out) {
            @Override
            public void print(String s) {
                txtOutput.append(s + "\n");
                txtOutput.setCaretPosition(txtOutput.getText().length());               
            }
        };
        System.setOut(stream);
        System.out.print("MESSAGES");
    }

    /**
     * Constructor two
     */

    public WordSearchPuzzle() {
    }

    /**
     * Gets the whole word of buttons clicked
     * @return
     *      Returns whole Word
     */
    public String getSelectedWord() {
        return wordFromChars;
    }

    /**
     * Adds word lists to Panel on the left
     */
    private void buildWordListPanel() {

        leftSidePanel.setBackground(Color.WHITE);

        // Build the word list
        wordListComponents = new JLabel[wordList.size()];

        wordListPanel = new JPanel(new GridLayout(25, 1));
        wordListPanel.setBackground(Color.white);

        //Loop  through list of words
        for (int i = 0; i < this.wordList.size(); i++) {

            String word = this.wordList.get(i).toUpperCase();
            wordListComponents[i] = new JLabel(word);
            wordListComponents[i].setForeground(Color.BLUE);
            wordListComponents[i].setHorizontalAlignment(SwingConstants.LEFT);
            wordListPanel.add(wordListComponents[i]);

        }

        leftSidePanel.add(wordListPanel,BorderLayout.WEST);
    }

    /**
     * Adds an output area to the bottom of 
     */
    private void buildBottomPanel() {

        bottomPanel = new JPanel();
        bottomPanel.setLayout(new BorderLayout());

        txtOutput = new JTextArea();
        txtOutput.setEditable(false);
        txtOutput.setRows(5);

        scptxtOutput = new JScrollPane(txtOutput);

        bottomPanel.add(txtOutput,BorderLayout.CENTER);
        bottomPanel.add(scptxtOutput,BorderLayout.SOUTH);
        rightSidePanel.add(bottomPanel,BorderLayout.CENTER);
    }

    /**
     * Initialize Components
     */

    public  void addComponentsToPane() {

        //      buttonsPanel = new JPanel(new BorderLayout(3,5)); //Panel to hold Buttons
        buttonsPanel = new JPanel(new GridLayout(3,1));

        leftSidePanel = new JPanel(new BorderLayout());

        rightSidePanel = new JPanel(new BorderLayout());

        btnCheck = new JButton("Check Word");
        btnCheck.setActionCommand("Check");
        btnCheck.addActionListener(new ButtonClickListener());

        btnClear = new JButton("Clear Selection");
        btnClear.setActionCommand("Clear");
        btnClear.addActionListener(new ButtonClickListener());

        buttonsPanel.add(btnClear);//,BorderLayout.PAGE_START);
        buttonsPanel.add(btnCheck);//,BorderLayout.PAGE_END);

        leftSidePanel.add(buttonsPanel,BorderLayout.SOUTH);
        this.getContentPane().add(leftSidePanel,BorderLayout.LINE_START);

        gridPanel = new JPanel();
        gridPanel.setLayout(myGridLayout);

        myGridLayout.setRows(20);
        myGridLayout.setColumns(20);

        grid = new JButton[ROWS][COLS]; //allocate the size of grid
        //theBoard = new char[ROWS][COLS];

        for(int Row = 0; Row < grid.length; Row++){
            for(int Column = 0; Column < grid[Row].length; Column++){

                grid[Row][Column] = new JButton();//Row + 1 +", " + (Column + 1));

                grid[Row][Column].setActionCommand(Row + "," + Column);

                grid[Row][Column].setActionCommand("gridButton");

                grid[Row][Column].addActionListener(new ButtonClickListener());

                gridPanel.add(grid[Row][Column]);
            }
        }

        rightSidePanel.add(gridPanel,BorderLayout.NORTH);
        this.getContentPane().add(rightSidePanel, BorderLayout.CENTER);
    }

    public static void main(String[] args)  {
        try {
            if (args.length !=2) { //Make sure we have both the puzzle file and word list file
                JOptionPane.showMessageDialog(null, "One or All Files are Missing");
            } else { //Files Found
                WordSearchPuzzle puzzle = new WordSearchPuzzle(args[0],args[1]);
                puzzle.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                puzzle.setSize(new Dimension(1215,740));

                //Display the window.
                puzzle.setLocationRelativeTo(null); // Center frame on screen
                puzzle.setResizable(false); //Set the form as not resizable
                puzzle.setVisible(true);    
            }
        } catch (Exception e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
        }
    }

    public int solvePuzzle( ){
        int matches = 0;
        for( int r = 0; r < ROWS; r++ )
            for( int c = 0; c < COLS; c++ )
                for( int rd = -1; rd <= 1; rd++ )
                    for( int cd = -1; cd <= 1; cd++ )
                        if( rd != 0 || cd != 0 )
                            matches += solveDirection( r, c, rd, cd );
        return matches;
    }

    private int solveDirection( int baseRow, int baseCol, int rowDelta, int colDelta ){
        String charSequence = "";
        int numMatches = 0;
        int searchResult;

        FileIO io = new FileIO();

        charSequence += io.theBoard[ baseRow ][ baseCol ];
        for( int i = baseRow + rowDelta, j = baseCol + colDelta;
                i >= 0 && j >= 0 && i < ROWS && j < COLS;
                i += rowDelta, j += colDelta )
        {
            charSequence += io.theBoard[ i ][ j ];
            searchResult = prefixSearch( theWords, charSequence );
            if( searchResult == theWords.length )
                break;
            if( !((String)theWords[ searchResult ]).startsWith( charSequence ) )
                break;
            if( theWords[ searchResult ].equals( charSequence ) )
            {
                numMatches++;
                System.out.println( "Found " + charSequence + " at " +
                        baseRow + " " + baseCol + " to " +
                        i + " " + j );
            }
        }
        return numMatches;
    }

    private static int prefixSearch( Object [ ] a, String x ) {
        int idx = Arrays.binarySearch( a, x );
        if( idx < 0 )
            return -idx - 1;
        else
            return idx;
    }

    class ButtonClickListener implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {

            String command = ((JButton)e.getSource()).getActionCommand();
            if (command == "Clear") {
                //Enable the buttons that have been disabled and not form a whole word
                //JOptionPane.showMessageDialog(null, "Cooming Soon");

                for (String word : wordList) {
                    System.out.print(word);
                }

            } else if (command == "Check") {

                String selectedWord = getSelectedWord();

                if (!selectedWord.equals("")){

                    System.out.print("Selected word is " + getSelectedWord());
                    //First check if selected word exits in wordList

                    if (ifExists(selectedWord)) {
                        if(searchWord(selectedWord)){
                            JOptionPane.showMessageDialog(null, "Success");
                            wordFromChars = ""; //Reset the selected Word
                        }
                    } else {
                        JOptionPane.showMessageDialog(null, "[" + selectedWord + "] " +
                                "Does Not Belong to Word list");
                        wordFromChars = ""; //Reset the selected Word
                    }

                } else {

                    JOptionPane.showMessageDialog(null, "No Buttons on Grid have been clicked");

                }
            } else if (command == "gridButton") {
                getSelectedCharacter(e);
                ((JButton)e.getSource()).setEnabled(false);         
            }
        }

        /**
         * Gets the character of each button and concatenates each character to form a whole word
         * @param e     The button that received the Click Event
         * @return      Whole word 
         */
        private String getSelectedCharacter (ActionEvent e) {
            String character; 

            character = ((JButton) e.getSource()).getText();

            wordFromChars = wordFromChars + character;

            return wordFromChars;
        }       
    }
    /**
     * Checks if selected word is among in wordlist
     * @param selectedWord
     * @return      The word to search for
     */
    private boolean ifExists(String selectedWord) {
        if (wordList.contains(selectedWord)) {
            return true;
        }
        return false;
    }

    public boolean searchWord(String word) {
        if (!wordList.contains(word)) {
            return false;
        }
        //int index = wordList.indexOf(word);
        Line2D.Double line = new Line2D.Double();
        //System.out.print("LetterArray is " + letterArray.length);
        for (int x = 0; x < letterArray.length; x++) {
            for (int y = 0; y < letterArray[x].length; y++) {
                // save start point
                line.x1 = y; // (y + 1) * SCALE_INDEX_TO_XY;
                line.y1 = x; // (x + 1) * SCALE_INDEX_TO_XY;
                int pos = 0; // current letter position
                if (letterArray[x][y] == word.charAt(pos)) {
                    // first letter correct -> check next
                    pos++;
                    if (pos >= word.length()) {
                        // word is only one letter long
                        // double abit = SCALE_INDEX_TO_XY / 3;
                        line.x2 = y; // (y + 1) * SCALE_INDEX_TO_XY + abit;
                        line.y2 = x; // (x + 1) * SCALE_INDEX_TO_XY + abit;
                        return true;
                    }
                    // prove surrounding letters:
                    int[] dirX = { 1, 1, 0, -1, -1, -1, 0, 1 };
                    int[] dirY = { 0, -1, -1, -1, 0, 1, 1, 1 };

                    for (int d = 0; d < dirX.length; d++) {
                        int dx = dirX[d];
                        int dy = dirY[d];

                        int cx = x + dx;
                        int cy = y + dy;

                        pos = 1; // may be greater if already search in another
                        // direction from this point
                        if (insideArray(cx, cy)) {
                            if (letterArray[cx][cy] == word.charAt(pos)) {
                                // 2 letters correct
                                // -> we've got the direction
                                pos++;
                                cx += dx;
                                cy += dy;
                                while (pos < word.length() && insideArray(cx, cy)
                                        && letterArray[cx][cy] == word.charAt(pos)) {
                                    pos++;
                                    cx += dx;
                                    cy += dy;
                                }

                                if (pos == word.length()) {
                                    // correct end if found
                                    cx -= dx;
                                    cy -= dy;
                                    pos--;
                                }
                                if (insideArray(cx, cy) && letterArray[cx][cy] == word.charAt(pos)) {
                                    // we've got the end point
                                    line.x2 = cy; // (cy + 1) *
                                    // SCALE_INDEX_TO_XY;
                                    line.y2 = cx; // (cx + 1) *
                                    // SCALE_INDEX_TO_XY;
                                    /*
                                     * System.out.println(letterArray[x][y] +
                                     * " == " + word.charAt(0) + " (" + line.x1
                                     * + "," + line.y1 + ") ->" + " (" + line.x2
                                     * + "," + line.y2 + "); " + " [" + (line.x1
                                     * / SCALE_INDEX_TO_XY) + "," + (line.y1 /
                                     * SCALE_INDEX_TO_XY) + "] ->" + " [" +
                                     * (line.x2 / SCALE_INDEX_TO_XY) + "." +
                                     * (line.y2 / SCALE_INDEX_TO_XY) + "]; ");
                                     */

                                    //result[index] = line;
                                    // found
                                    return true;
                                }
                                // else: try next occurence
                            }
                        }

                    }

                }
            }
        }
        return false;
    }

    private boolean insideArray(int x, int y) {
        boolean insideX = (x >= 0 && x < letterArray.length);
        boolean insideY = (y >= 0 && y < letterArray[0].length);
        return (insideX && insideY);
    }

    public void init(char[][] letterArray) {
        try {
            for (int i = 0; i < letterArray.length; i++) {
                for (int j = 0; j < letterArray[i].length; j++) {
                    char ch = letterArray[i][j];
                    if (ch >= 'a' && ch <= 'z') {
                        letterArray[i][j] = Character.toUpperCase(ch);
                    }
                }
            }   
        } catch (Exception e){
            System.out.println(e.toString());
        }

        //System.out.println("It is " + letterArray.length);
        this.letterArray = letterArray;
    }
}

这是初始化 letterArray 数组的类:

package wordsearch;

import java.awt.Color;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;

import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.SwingConstants;

/**
 * Reads wordlist file and puzzle file
 * @author mungaialex
 *
 */

public class FileIO {

    String _puzzleFile, _wordListFile;
    /**ArrayList to hold words*/
    ArrayList<String> wordList;
    /** No. Of Columns in Wordlist*/
    private static final int WORDLISTCOLS = 1;
    List puzzleLines;
    JButton[][] _grid;

    char theBoard[][];

    private final int _rows = 20;
    private final int _columns = 20;

    WordSearchPuzzle pz = new WordSearchPuzzle();
    /**
     * Default Constructor
     * @param puzzleFile
     * @param wordListFile
     */

    public FileIO(String puzzleFile, String wordListFile,JButton grid[][]){
        _puzzleFile = new String(puzzleFile);
        _wordListFile = new String(wordListFile);
        _grid = pz.grid;
    }

    public FileIO() {
    }

    /**
     * Reads word in the wordlist file and adds them to an array
     * @param wordListFilename
     *      File Containing Words to Search For
     * @throws IOException
     */

    protected ArrayList<String> loadWordList()throws IOException {
        int row = 0;

        wordList = new ArrayList<String>();
        BufferedReader reader = new BufferedReader(new FileReader(_wordListFile));

        String line = reader.readLine();
        while (line != null) {
            StringTokenizer tokenizer = new StringTokenizer(line, " ");
            if (tokenizer.countTokens() != WORDLISTCOLS) {
                JOptionPane.showMessageDialog(null, "Error: only one word per line allowed in the word list",
                        "WordSearch Puzzle: Invalid Format", row);//, JOptionPane.OK_CANCEL_OPTION);
                //"Error: only one word per line allowed in the word list");
            }
            String tok = tokenizer.nextToken();
            wordList.add(tok.toUpperCase());
            line = reader.readLine();
            row++;
        }
        reader.close();
        return wordList;
    }
    /**
     * Reads the puzzle file line by by line
     * @param wordSearchFilename
     *      The file containing the puzzle
     * @throws IOException
     */
    protected void loadPuzleFromFile() throws IOException {
        int row = 0;
        BufferedReader reader = new BufferedReader(new FileReader(_puzzleFile));
        StringBuffer sb = new StringBuffer();
        String line = reader.readLine();

        puzzleLines = new ArrayList<String>();

        while (line != null) {
            StringTokenizer tokenizer = new StringTokenizer(line, " ");
            int col = 0;

            sb.append(line);
            sb.append('\n');

            while (tokenizer.hasMoreTokens()) {
                String tok = tokenizer.nextToken();

                WordSearchPuzzle.grid[row][col].setText(tok);

                pz.grid[row][col].setForeground(Color.BLACK);

                pz.grid[row][col].setHorizontalAlignment(SwingConstants.CENTER);

                puzzleLines.add(tok);
                col++;
            }
            line = reader.readLine();
            row++;

            theBoard = new char[_rows][_columns];
            Iterator itr = puzzleLines.iterator();

            for( int r = 0; r < _rows; r++ )
            {
                String theLine = (String) itr.next( );
                theBoard[ r ] = theLine.toUpperCase().toCharArray( );
            }
        }

        String[] search = sb.toString().split("\n");

        initLetterArray(search);

        reader.close();
    }

    protected void initLetterArray(String[] letterLines) {
        char[][] array = new char[letterLines.length][];
        System.out.print("Letter Lines are " +letterLines.length );
        for (int i = 0; i < letterLines.length; i++) {
            letterLines[i] = letterLines[i].replace(" ", "").toUpperCase();
            array[i] = letterLines[i].toCharArray();
        }
        System.out.print("Array inatoshana ivi " + array.length);
        pz.init(array); 
    }

}

提前致谢。

最佳答案

就是这里!

char[][] array = new char[letterLines.length][];

您仅初始化一个轴。 当您将此数组传递给 init() 并设置 this.letterArray = letterArray; 时,letterArray 也未完全初始化。

尝试为两个轴添加长度:

char[][] array = new char[letterLines.length][LENGTH];

关于java - 数组上的 Wordsearch 难题 nullpointerException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21405134/

相关文章:

java - 使用 Puzzle 并弄清楚如何修复越界错误

c - 尝试用C语言编写单词搜索程序

java - 如何将自定义 jar 文件添加到 pom.xml 中

java - JScrollPane 中的 JTable : Detect if mouse is over table header

c++ - 头文件中的全局数组...是否必须指定大小?

php - 如何在数组中查找一个值并使用 PHP 数组函数将其删除?

java - 在 Java 中将 1D 字符串数组转换为 2D Char 数组的最佳方法 (Eclipse)

java - 我的 while 循环做错了什么?

java - 当客户端和实际应用程序位于不同的容器中时配置事务管理器?

c - C程序中的"Array subscript is not an integer"