
给,注释改一改,有台湾风格了:
#include < stdioh >
#include < stdlibh >
int sudoku[81] ; // 数独题目阵列
int tempNum[81] ; // 上一次填数位置
int tempSp= 0 ; // 上一次填数位置指标
int startH[81] ; // 列位置的起点
int startV[81] ; // 行位置的起点
int startB[81] ; // 九宫格位置的起点
int addH[9] ; // 列位置的加值
int addV[9] ; // 行位置的加值
int addB[9] ; // 九宫格位置的加值
void init() {
// 参数设定(设定这些参数之后,无论检查行、列、九宫格都方便多了)
int i ;
for(i=0; i<81; i++) {
startH[i]= i/9 9 ; // 列位置的起点
startV[i]= i% 9 ; // 行位置的起点
startB[i]= ((i/9)/3)27+ ((i%9)/3)3 ; // 九宫格位置的起点
}
for(i=0; i<9; i++) {
addH[i]= i ; // 列位置的加值
addV[i]= i9 ; // 行位置的加值
addB[i]= (i/3)9+ (i%3) ; // 九宫格位置的加值
}
}
void printSudoku(int prn) {
// 印出数独题目(阵列内容)
int i ;
for(i=0; i<81; i++) {
printf( "%2d", prn[i]);
if(i%9==8) printf("\n");
}
}
int getNextBlank(int sp) {
// 取得下一个空白的位置
do {
sp++ ;
} while(sp<81 && sudoku[sp]>0) ;
return(sp) ;
}
int check1(int sp, int start, int addnum) {
// 检查指定的行、列、九宫格有没有相同的数字,若有传回 1
int fg= 0, i, sp1 ;
for(i=0; i<9; i++) {
sp1= start+ addnum[i] ;
if(sp!=sp1 && sudoku[sp]==sudoku[sp1]) fg++ ;
}
return(fg) ;
}
int check(int sp) {
// 检查同行、列、九宫格有没有相同的数字,若有传回 1
int fg= 0 ;
if(!fg) fg= check1(sp, startH[sp], addH) ; // 检查同列有没有相同的数字
if(!fg) fg= check1(sp, startV[sp], addV) ; // 检查同行有没有相同的数字
if(!fg) fg= check1(sp, startB[sp], addB) ; // 检查同九宫格有没有相同的数字
return(fg) ;
}
void push(int sp) {
// 将指定的位置放入堆叠中
tempNum[tempSp++]= sp ;
}
int pop() {
// 取出堆叠中的上一个位置
if(tempSp<0) return(-1) ;
else return(tempNum[--tempSp]) ;
}
void tryAns() {
// 测试求解
int sp=getNextBlank(-1) ; // 取得第一个空白的位置开始填入数字
do {
sudoku[sp]++ ; // 将本位置数字加 1
if(sudoku[sp]>9) { // 如果本位置的数字已大於 9 时则回到上一个位置继续测试
sudoku[sp]= 0 ;
sp= pop() ;
} else {
if(check(sp)==0) { // 如果同行、列、九宫格都没有相同的数字,则到下一个空白处继续
push(sp) ; // 当然,如果发现有相同的数字时,就需把原位置的数字加 1(所以本处什麼都不做)
sp= getNextBlank(sp) ;
}
}
} while(sp>=0 && sp<81) ;
}
int main(int argc, char argv[]) {
int j ;
printf( "----------\n");
printSudoku(sudoku) ;
init() ; // 参数设定
tryAns() ; // 测试求解
printf( "----------\n");
printSudoku(sudoku) ;
printf( "----------\n");
}
回溯法(探索与回溯法)是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。
#include<stdioh>
int map[9][9];
bool isPlace(int count){
int row = count / 9;
int col = count % 9;
int j;
//同一行
for(j = 0; j < 9; ++j){
if(map[row][j] == map[row][col] && j != col){
return false;
}
}
//同一列
for(j = 0; j < 9; ++j){
if(map[j][col] == map[row][col] && j != row){
return false;
}
}
//同一小格
int tempRow = row / 3 3;
int tempCol = col / 3 3;
for(j = tempRow; j < tempRow + 3;++j){
for(int k = tempCol; k < tempCol + 3; ++k){
if(map[j][k] == map[row][col] && j != row && k != col){
return false;
}
}
}
return true;
}
void backtrace(int count){
if(count == 81){
for(int i = 0; i < 9; ++i){
for(int j = 0; j < 9; ++j){
printf("%d ",map[i][j]);
}
printf("\n");
}
return;
}
int row = count / 9;
int col = count % 9;
if(map[row][col] == 0){
for(int i = 1; i <= 9; ++i){
map[row][col] = i;//赋值
if(isPlace(count)){//可以放
backtrace(count+1);//进入下一层
}
}
map[row][col] = 0;//回溯
}else{
backtrace(count+1);
}
}
int main()
{
char c;
for(int i=0;i<9;i++)
{
for(int j=0;j<9;j++)
{
scanf("%c",&c);
if(c=='')map[i][j]=0;
else map[i][j]=c-'0';
}
scanf("%c",&c);//接收换行符
}
backtrace(0);
return 0;
}
check()函数的dowhile循环有深层次逻辑错误:当if((rawflag==1)||(colflag==1))为“真”后的某种情况就出现rawflag和colflag不可能同时出现0而导致死循环。写法上if((rawflag==1)||(colflag==1))
{
a[raw][col]=rand()%9+1;
}
else
break;
}
和while((rawflag==1)||(colflag==1));就不协调,好像把if语句删除,把它的体a[raw][col]=rand()%9+1;直接写在do{后才在逻辑上清晰……
我用EXCEL的宏编过,但是算法不太好,简单得可以作出,难得的就不行了
想法如下:
建立一个X(a,b,c,d)的列阵,4个数为(1,2,3)中的一个
a,b表示大的33阵(就是你所说的"区")的位置
c,d表示在特定33阵(特定"区")中的位置
那么每个特定的X表示特定的空格位置
每个X初始都=123456789
X的值表示这个空格可能取的数
然后已经给出的条件的X改为条件给出的数
现在我虽然不知道剩下的空格是哪个数,但是我可以知道特定的空格中不可以是哪个数(按规则)
step1
所以分别检查每个空格
将不可能出现的数字从123456789中删去(比如这个区已经存在1,4,5那么我们把区中其他的空格的1,4,5去掉,变成2,3,6,7,8,9)
这样X的位数就越来越小了
当X的长度等于1的时候那么这个空格就是唯一的了
step2
检查每一个区中的9个数中含有几个1,如果只有1个,那么含有1的哪个空格就是1了,(1-9,依次检验),(行或者列也要分别检验)
step3
检查是不是每个数都小于10,如果不是
检查经过step1和step2后,各个数字有没有变化,如果有,那么重复step1,step2没有的话(说明按刚刚的步骤只能解到这样了)结束循环
我编的只是为了方便帮我解题,太难的做不出,但是用的话可以解出很多数了,人在看一下,很快就解出了
如果一定要编到底的话,我也想过
然后在X中寻找1个2位数,假定2位数中的一个是正确的,然后在按刚刚的步骤,如果结果有矛盾则就是另一个数
希望对你有帮助
哈哈,这简单!数独生成算法?这个还真不好搞,不过我当初写数独游戏的时候随便捣鼓出来过一个,你自己去改改吧,至于这个算法能不能生成所有的数独,我还真没论证过。原理:对一个给出的数独棋盘的所有行或列交换给出的两个数X、Y,数组仍满足数独规则。如给出1、2,则对所有列交换1、2的位置,数组仍满足数独规则。由于对棋盘的演进是随机的,所以相当于随机生成数独棋盘啦。每次演进的次数最好大一点,10次以上吧,以保证每个数都被换过位置。具体代码就不用我写了吧,嘎嘎……追问不用生成所有数独。。只要生成一个唯一解的就好。。。
如果按照您这个算法,交换所有列任意两个数或者多组数就可以生成新的数独了吧。
void readGame (sudukoGrid game) {
cell currentCell = 0;
int inChar = getchar();
while (inChar != EOF) {
if (
((inChar >= MIN_VALUE) && (inChar <= MAX_VALUE)) ||
(inChar == EMPTY_VALUE)
) {
assert (currentCell <= MAX_CELL);
game [currentCell] = inChar;
currentCell++;
}
inChar = getchar();
}
assert (currentCell == (MAX_CELL+1));
}
第一个readgame,谁会别的?
#include<stdioh>
#define N 3
bool rowtest(int n[])
{
int i,j;
int num;
int no_exist=0;
for(i=0;i<NN;i+=N)
{
for(num=1;num<N+1;num++)
{
for(j=i;j<i+N;j++)
{
if(num!=n[j])
no_exist++;
if(no_exist==N)
return 0;
}
no_exist=0;
}
}
return 1;
}
bool coltest(int n[])
{
int i,j;
int num;
int no_exist=0;
for(i=0;i<N;i++)
{
for(num=1;num<N+1;num++)
{
for(j=i;j<i+NN;j+=N)
{
if(num!=n[j])
no_exist++;
if(no_exist==N)
return 0;
}
no_exist=0;
}
}
return 1;
}
void main()
{
int n;
int i;
int j;
char c;
int finish=0;
int realnum=0;
int num[NN]={0};
printf("\n请输入测试的数据组数:\n\n");
scanf("%d",&n);
getchar();
printf("输入的数据只能是1-%d,输入只取前%d个数\n\n",N,NN);
for(i=1;i<=n;i++)
{
printf("第%d组数据如下:\n\n",i);
while(1)
{
c=getchar();
if(c>='1'&&c<=(char)(N+48))
{
num[finish]=c-48;
finish++;
}
realnum++;
if(realnum==N(N+1))
break;
}
for(j=0;j<NN;j++)
{
if(!num[j])
{
printf("输入有误!\n\n");
return;
}
}
if(rowtest(num)&&coltest(num))
printf("yes\n\n");
else
printf("no\n\n");
}
}
由于输入81个数进行检测很麻烦,所以只用了33的数据。你可以将N改为9,即可满足要求。
以上就是关于数独C代码 Microsoft Visual C++ 6.0 //不胜感激(一定要C程序的不要C++)全部的内容,包括:数独C代码 Microsoft Visual C++ 6.0 //不胜感激(一定要C程序的不要C++)、求解数独题,用C语言实现、c语言 随机生成数独等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)