简体   繁体   English

将部分数独文本文件加载到2D数组中

[英]Loading partial sudoku text file into 2D array

I am making a Sudoku game and I have an issue with opening a saved Sudoku file. 我在做数独游戏,打开保存的数独文件时遇到问题。 Let's say I am doing the puzzle, and want to come back to it later, I save the partially completed puzzle to a file, which works. 假设我正在做拼图,并且想稍后再讲,我将部分完成的拼图保存到一个文件中,该文件可以正常工作。 When I go to open it, it does not work. 当我打开它时,它不起作用。

Here is the code for save (both variables ROWS and COLUMNS are equal to 9): 这是保存的代码(变量ROWS和COLUMNS都等于9):

private void savePuzzle() throws IOException {

    JFileChooser fileChooser = new JFileChooser();
    int returnVal = fileChooser.showDialog(this, "Save");

    BufferedWriter saveFile = null;
    File file;

    // If the user has canceled, no need to continue
    if (returnVal != JFileChooser.APPROVE_OPTION) {
        return;
    }

    file = fileChooser.getSelectedFile();

    saveFile = new BufferedWriter(new FileWriter(file));
    for (int r = 0; r < ROWS; r++) {
        for (int c = 0; c < COLUMNS; c++) {
            saveFile.write(inputBoxes[r][c].getText());
            if (c < ROWS - 1) {
                saveFile.write(",");
            }
        }
        saveFile.write("\n");
    }
    saveFile.close();
}

Here is the action button for save: 这是用于保存的操作按钮:

saveAction.addActionListener(new ActionListener() {

        public void actionPerformed(ActionEvent evt) {
            try {
                // call method to save puzzle by writing its contents to an external save file
                savePuzzle();
            } catch (IOException ex) {
                System.out.println(ex.toString());
            }
        }
    }); 

Here is the code for open: 这是开放的代码:

private void openPuzzle() throws FileNotFoundException, IllegalArgumentException {

    JFileChooser fileChooser = new JFileChooser();
    int returnVal = fileChooser.showDialog(this, "Open");

    File file = fileChooser.getSelectedFile();
    Scanner readFile = new Scanner(file);

    // If the user has canceled, no need to continue with open process
    if (returnVal != JFileChooser.APPROVE_OPTION) {
        return;
    }

    // Row
    int r = 0;

    // Update squares with data from file
    while (readFile.hasNextLine()) {
        String[] splitLine = readFile.nextLine().split(",");

        // Verify the length of the row
        if (splitLine.length != 9) {
            throw new IllegalArgumentException(String.format("Row length(%d) not correct in %s at row %d",
                    splitLine.length, file, r));
        }

        for (int c = 0; c < 9; c++) {
            // Verify each item in row
            if (splitLine[c].length() != 1 || !(Character.isDigit(splitLine[c].charAt(0)))) {
                throw new IllegalArgumentException(String.format("Invalid token %s in %s at row %d col %d",
                        splitLine[c], file, r, c));
            }
            // Update square
            inputBoxes[r][c].setText(splitLine[c]);
        }
        // Move to next row
        r++;
    }
}

And the open action button: 和打开动作按钮:

openAction.addActionListener(new ActionListener() {

        public void actionPerformed(ActionEvent evt) {
            try {
                // call method so that user can open their saved puzzle and populate the grid with its contents
                openPuzzle();
            } catch (FileNotFoundException ex) {
                System.out.println(ex.toString());
            } catch (IllegalArgumentException ex) {
                System.out.println(ex.toString());
            }
        }
    });

I know that the open code is finding empty values in the saved text file if it is a partially completed puzzle, and it is returning those catch statements, but I have no clue how to get it to just keep reading each element on the line (whether it's a number or empty space), and just return what's in the text file to the GUI grid (populate the grid with the corresponding numbers). 我知道,如果打开的代码是部分完成的难题,那么打开的代码会在保存的文本文件中找到空值,并且正在返回这些catch语句,但是我不知道如何获取它,而是继续读取行中的每个元素( (是数字还是空格),然后将文本文件中的内容返回到GUI网格(使用相应的数字填充网格)。

The errors I'm getting are either the "Row length %d..." error or the "Invalid token %s..." error. 我遇到的错误是“行长度%d ...”错误或“无效令牌%s ...”错误。 It loads nothing back into the grid when I select the file from the Open function. 当我从“打开”功能中选择文件时,它不会将任何内容加载回网格中。 That's where I'm lost. 那就是我迷路的地方。 If the puzzle is complete, and it is saved, then it can be open, because the external text file that contains the puzzle is full, and each element (space) in the file has a number in it, so when it iterates over each number, it does not find any errors or missing numbers. 如果拼图完成并保存,则可以将其打开,因为包含拼图的外部文本文件已满,并且文件中的每个元素(空格)中都有一个数字,因此对每个拼图进行迭代时数字,它找不到任何错误或缺少数字。 But when a partial file is saved, it cannot be opened back into the grid to start playing it again... 但是,如果保存了部分文件,则无法将其重新打开到网格中以再次开始播放...

Your representation of a (sample) row is this: 您对(样本)行的表示是这样的:

1,2,,7,6,,,,5

But when you split that line on , , you will get: 但是,当你分割该行上,你会得到:

[1,2,7,6,5]

This is clearly not an array of length 9, so if (splitLine.length != 9) will return false . 显然这不是长度为9的数组,因此, if (splitLine.length != 9)将返回false You must save a non-digit character to the text file that indicates an 'empty' space, or the split function will very rarely return a row of the correct length. 您必须将一个非数字字符保存到文本文件中,以指示“空”空间,否则split函数将很少返回正确长度的行。 It is possible to represent an entire Sodoku board with a single list of 81 characters, the digits 0 through 9 and an 'empty' character, no commas or line breaks needed. 可以用一个81个字符,从0到9的数字和一个“空”字符的单个列表来代表整个Sodoku面板,不需要逗号或换行符。 The key here is that the empty character is still required to maintain the topology of your data structure. 这里的关键是,仍然需要使用空字符来维护数据结构的拓扑。

As a side note this: 附带说明一下:

if (c < ROWS - 1) {
    saveFile.write(",");
}

Should probable reference COLS instead. 应该可能参考COLS代替。

From reading your code it would seem to me that the offending line is: 通过阅读您的代码,在我看来,令人讨厌的行是:

if (splitLine[c].length() != 1 || !(Character.isDigit(splitLine[c].charAt(0)))) {
            throw new IllegalArgumentException(...

In the function openPuzzle. 在函数openPuzzle中。 This is because when saving a partially completed sudoku your file will look like "1,2,,3,,1,6,7,....." Now the empty cells when read in will have a string length of 0. So splitLine[c].length() != 1 will fail. 这是因为当保存部分完成的数独时,您的文件将看起来像“ 1,2,,3,,1,6,7,.....”。现在,读入时的空白单元格的字符串长度为0。因此splitLine [c] .length()!= 1将失败。 To solve this i would suggest changing the code to be: 为了解决这个问题,我建议将代码更改为:

if (splitLine[c].length() > 0 || !(Character.isDigit(...

So that zero length characters (unfilled spaces) are accepted when loading it in. 以便在加载零长度字符(未填充的空格)时接受该字符。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM