我有一项任务,创建一个解决9x9数独谜题的程序。规格如下:
argv[0]
不是必需的,只需要通过键盘输入scanf
功能)我的程序动态分配一个2D数组,然后分配空间来保存文件名,然后打开二进制文件来读取数据。使用printf
来调试我的程序似乎数据被适当地保存到importedData
数组,当在数独谜题上分配这些数据时,程序崩溃,或者没有正确地分配值。这是我的代码:
Sudoku.c
#include <stdio.h>
#include <stdlib.h>
#include "sudokulib.h"
#define MALLOC_ERROR 0xFF
#define FILE_NOT_FOUND 0xFFF
int main(int argc,char ** argv)
{
char **matrix;
int i,j;
int row,column,num;
FILE * fp;
char * filename;
char * importedData;
matrix=(char **)malloc(9*sizeof(char *));
if (!matrix)
exit(MALLOC_ERROR);
for (i=0;i<9;++i)
{
matrix[i]=(char *)malloc(9*sizeof(char));
if (!matrix[i])
exit(MALLOC_ERROR);
}
initSudoku(matrix);
printf ("Give me the name of data file: ");
filename=(char *)malloc(100*sizeof(char));
if (!filename)
exit(MALLOC_ERROR);
scanf("%s",filename);
fp=fopen(filename,"rb");
if (!fp)
{
printf ("File not found\n");
exit(FILE_NOT_FOUND);
}
importedData=(char *)malloc(sizeof(char)*81*3);
if (!importedData)
exit (MALLOC_ERROR);
fread(importedData,1,243,fp);
i=0;
while (importedData[i] != ' ' && importedData[i+1] != ' ' && importedData[i+2] != ' ' && importedData[i] >= '1' && importedData[i+1] >= '1' && importedData[i+2] >= '1' && importedData[i] <= '9' && importedData[i+1] <= '9' && importedData[i+2] <= '9')
{
row=importedData[i] - 48; /* Convert from ascii code to number */
column=importedData[i+1] - 48;
num=importedData[i+2] - 48;
matrix[row][column]=num;
i=i+3;
}
printf("Sudoku after importing data:\n\n");
printSudoku(matrix);
system("pause");
if (solvePuzzle(matrix))
{
printSudoku(matrix);
}
else
printf ("Puzzle has no solution\n");
fclose(fp);
free(filename);
for (i=0;i<9;++i)
{
free(matrix[i]);
}
free(matrix);
return 0;
}
Sudokulib.h
#include <stdlib.h>
#include <stdio.h>
/* Function Prototypes Begin Here */
void printSudoku(char **);
void initSudoku(char **);
int checkRow(char **,int,int);
int checkCol(char **,int,int);
int check3x3(char **,int,int,int);
int checkIfEmpty(char **,int*,int*);
int solvePuzzle (char **);
/* Function Prototypes End Here */
void printSudoku(char ** Mat)
{
int i,j;
for (i=0;i<9;++i)
{
printf ("-------------------\n");
printf("|");
for (j=0;j<9;++j)
{
printf("%d|",Mat[i][j]);
}
printf("\n");
}
printf ("-------------------\n");
}
void initSudoku(char ** Mat)
{
int i,j;
for (i=0;i<9;++i)
for (j=0;j<9;++j)
Mat[i][j]=0;
}
int checkRow (char ** Mat,int row, int num) // if row is free returns 1 else returns 0
{
int col;
for (col = 0; col < 9; col++)
{
if (Mat[row][col] == num-48)
return 0;
}
return 1;
}
int checkCol (char ** Mat,int col , int num) // if column is free returns 1 else returns 0
{
int row;
for (row = 0; row < 9; row++)
{
if (Mat[row][col] == num-48)
return 0;
}
return 1;
}
int check3x3 (char ** Mat, int row, int col, int num) // if number doesnt exist in the 3x3 grid returns 1 else returns 0
{
row = (row/3) * 3; // set to first row in the grid
col = (col/3) * 3; // set to first col in the grid
int i;
int j;
for (i = 0; i < 3; i++) // grid is 3x3
{
for (j = 0; j < 3; j++)
{
if (Mat[row+i][col+j] == num-48)
return 0;
}
}
return 1;
}
int checkIfEmpty(char ** Mat, int *row, int *col) // if a block of the entire puzzle is empty returns 1 else returns 0 also saves the target row and column it found empty
{
for (*row = 0; *row < 9; *row++)
{
for (*col = 0; *col < 9; *col++)
{
if (Mat[*row][*col] == 0)
return 1;
}
}
return 0;
}
int solvePuzzle (char ** Mat)
{
int num;
int row;
int col;
row = 0;
col = 0;
if (!checkIfEmpty(Mat,&row,&col)) // if puzzle is solved return 1
return 1;
for (num = 1; num < 9; num++)
{
if (checkRow (Mat,row,num) && checkCol (Mat,col,num) && check3x3 (Mat,row,col,num))
{
Mat[row][col] = num-48;
}
if (solvePuzzle (Mat))
{
return 1;
}
Mat[row][col] = 0;
}
return 0;
}
对于解决上述问题的任何帮助表示赞赏。
另请注意,int solvePuzzle()
尚未完成,欢迎任何改进此功能的建议。
编辑:以下是导致错误分配的二进制文件data2.bin
的内容
142156177191216228257289311329364375418422441484534546562579625663682698739743787794824855883896
输出:
Give me the name of data file: data2.bin
Sudoku after importing data:
-------------------
|0|0|0|0|0|0|0|0|0|
-------------------
|0|0|0|0|2|6|0|7|0|
-------------------
|0|6|8|0|0|7|0|0|9|
-------------------
|0|1|9|0|0|0|4|5|0|
-------------------
|0|8|2|0|1|0|0|0|4|
-------------------
|0|0|0|4|6|0|2|9|0|
-------------------
|0|0|5|0|0|0|3|0|2|
-------------------
|0|0|0|9|3|0|0|0|7|
-------------------
|0|0|4|0|0|5|0|0|3|
-------------------
Press any key to continue . . .
编辑2:发现如果使用包含非常少数据的非常小的二进制文件,例如123245321
工作正常,但如果数据超过9个字节,则拼图会搞砸。
答案 0 :(得分:3)
请注意,数组是零索引的。因此,您需要再减去一个以获得正确的索引,例如:
row=importedData[i] - 48 - 1;
另请注意,您的文件中的数字太少。只有96但你需要243。
...进一步
看看这个:
importedData=(char *)malloc(sizeof(char)*81*3);
...
fread(importedData,1,243,fp);
现在你在importedData
中有243个字符(你可以通过查看fread
的返回代码来检查。在你的情况下,文件只有96个字符(坏...)但是让& #39; s只是假设它有效。)
然后你做:
i=0;
while (importedData[i] != ' ' &&
importedData[i+1] != ' ' &&
importedData[i+2] != ' ' &&
importedData[i] >= '1' &&
importedData[i+1] >= '1' &&
importedData[i+2] >= '1' &&
importedData[i] <= '9' &&
importedData[i+1] <= '9' &&
importedData[i+2] <= '9')
{
....
}
因此,如果您阅读的243个字符都使条件高于真,那么您将继续阅读超出为importedData
分配的内存。所以你有不确定的行为。
您需要添加:
&& i < 243;
到了条件。
BTW:所有这些硬编码都很糟糕。请改用#define
。
顺便说一句:不要做
row=importedData[i] - 48 -1;
但
row=importedData[i] - '0' - 1;