我正在制作一个数独游戏,但我遇到了打开已保存的Sudoku文件的问题。让我们说我正在做这个谜题,并希望稍后再回过头来,我将部分完成的谜题保存到文件中,该文件有效。当我打开它时,它不起作用。
这是保存的代码(变量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());
}
}
});
以下是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++;
}
}
打开操作按钮:
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网格(使用相应的数字填充网格)。
我得到的错误是&#34;行长度%d ...&#34;错误或&#34;无效的标记%s ...&#34;错误。当我从Open函数中选择文件时,它不会将任何内容加载回网格。这就是我失去的地方。如果拼图完成并保存,那么它可以打开,因为包含拼图的外部文本文件已满,文件中的每个元素(空格)都有一个数字,因此当它遍历每个拼图时数字,它没有发现任何错误或缺少数字。但是当保存部分文件时,无法将其打开回网格以再次开始播放...
答案 0 :(得分:1)
Your representation of a (sample) row is this:
ConnectionString2
But when you split that line on 1,2,,7,6,,,,5
, you will get:
,
This is clearly not an array of length 9, so [1,2,7,6,5]
will return if (splitLine.length != 9)
. 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. 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. The key here is that the empty character is still required to maintain the topology of your data structure.
As a side note this:
false
Should probable reference if (c < ROWS - 1) {
saveFile.write(",");
}
instead.
答案 1 :(得分:0)
通过阅读您的代码,在我看来,违规行是:
if (splitLine[c].length() != 1 || !(Character.isDigit(splitLine[c].charAt(0)))) {
throw new IllegalArgumentException(...
在openPuzzle函数中。这是因为在保存部分完成的数据时,您的文件将显示为&#34; 1,2,,3,1,6,7,......&#34;现在读入时的空单元格的字符串长度为0.因此splitLine [c] .length()!= 1将失败。要解决这个问题,我建议将代码更改为:
if (splitLine[c].length() > 0 || !(Character.isDigit(...
在加载时,接受零长度字符(未填充空格)。