繁体   English   中英

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

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

我在做数独游戏,打开保存的数独文件时遇到问题。 假设我正在做拼图,并且想稍后再讲,我将部分完成的拼图保存到一个文件中,该文件可以正常工作。 当我打开它时,它不起作用。

这是保存的代码(变量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();
}

这是用于保存的操作按钮:

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());
            }
        }
    }); 

这是开放的代码:

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++;
    }
}

和打开动作按钮:

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());
            }
        }
    });

我知道,如果打开的代码是部分完成的难题,那么打开的代码会在保存的文本文件中找到空值,并且正在返回这些catch语句,但是我不知道如何获取它,而是继续读取行中的每个元素( (是数字还是空格),然后将文本文件中的内容返回到GUI网格(使用相应的数字填充网格)。

我遇到的错误是“行长度%d ...”错误或“无效令牌%s ...”错误。 当我从“打开”功能中选择文件时,它不会将任何内容加载回网格中。 那就是我迷路的地方。 如果拼图完成并保存,则可以将其打开,因为包含拼图的外部文本文件已满,并且文件中的每个元素(空格)中都有一个数字,因此对每个拼图进行迭代时数字,它找不到任何错误或缺少数字。 但是,如果保存了部分文件,则无法将其重新打开到网格中以再次开始播放...

您对(样本)行的表示是这样的:

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

但是,当你分割该行上,你会得到:

[1,2,7,6,5]

显然这不是长度为9的数组,因此, if (splitLine.length != 9)将返回false 您必须将一个非数字字符保存到文本文件中,以指示“空”空间,否则split函数将很少返回正确长度的行。 可以用一个81个字符,从0到9的数字和一个“空”字符的单个列表来代表整个Sodoku面板,不需要逗号或换行符。 这里的关键是,仍然需要使用空字符来维护数据结构的拓扑。

附带说明一下:

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

应该可能参考COLS代替。

通过阅读您的代码,在我看来,令人讨厌的行是:

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

在函数openPuzzle中。 这是因为当保存部分完成的数独时,您的文件将看起来像“ 1,2,,3,,1,6,7,.....”。现在,读入时的空白单元格的字符串长度为0。因此splitLine [c] .length()!= 1将失败。 为了解决这个问题,我建议将代码更改为:

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

以便在加载零长度字符(未填充的空格)时接受该字符。

暂无
暂无

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

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