C程序计算对角线数独源代码
使用简单语法编写的C程序,仅在Linux环境下运行过。
顺便问一下C语言大佬们一个问题:
在while循环中运行到scanf函数为什么循环直接就结束了?
希望大佬们提出建议!
运行原理
九宫格对应二维数组,给每个格子分类:空格、定格、虚格、暂废格。
空格:即数独中的空格子,程序中用0表示
定格:即数独中一开始就给定的格子
虚格:程序分析中已经赋予过数值的空格
暂废格:程序为空格赋予的值用尽的格子
1.用户输入九宫格
2.赋值函数将适合的数值赋予一维数组
3.格子函数将每个格子的状态赋予二维数组
4.给九宫格中的空格赋值并判断是否有重复
如果不重复进行下一个格子
否则
用虚格函数将格子中的数值更换,返回第4步
如果更换所有值仍然重复
返回上一个空格,运行第4步
结束
注意事项
程序在Windows平台下运行可能出现内存溢出的情况,我在Linux下完美运行
程序在结尾while循环中运行到scanf函数时会出现直接跳出循环的情况,不影响程序计算
在输入九宫格的时候务必准确输入,否则会计算错误,输入后无法更改
输入时空格用0代替,直接回车会卡死
源代码
#include<stdio.h>
unsigned short One_Pocket[800]={0},One_Pocket_Basic = 0,A;
unsigned short Two_Pocket[9][9]={0};//坐标值对应九宫格的坐标值,用于存入相应的九宫格是什么状态,一次函数调用,永久使用
unsigned short X = 0,Y = 0,Nine_Pocket[9][9] =
{ //申明坐标X,Y,九宫格二维数组,空值用0代替
{0 , 0 , 0 , 7 , 0 , 9 , 0 , 1 , 0},
{6 , 0 , 8 , 0 , 0 , 0 , 9 , 0 , 0},
{0 , 9 , 0 , 3 , 0 , 0 , 0 , 7 , 0},
{0 , 0 , 0 , 0 , 5 , 0 , 4 , 0 , 7},
{0 , 0 , 0 , 9 , 0 , 6 , 0 , 0 , 0},
{3 , 0 , 6 , 0 , 7 , 0 , 0 , 0 , 0},
{0 , 4 , 0 , 0 , 0 , 2 , 0 , 8 , 0},
{0 , 0 , 5 , 0 , 0 , 0 , 2 , 0 , 1},
{0 , 3 , 0 , 5 , 0 , 8 , 0 , 0 , 0}
};
short For_Gong()//判断坐标对应的相应值在第几宫格中,方法:GN=For_Gong()
{
if(Y <= 2)
{
if(X <= 2)
{
return 1;
}
if(X<= 5)
{
return 2;
}
if(X <= 8)
{
return 3;
}
}
else if(Y <= 5 )
{
if(X <= 2)
{
return 4;
}
if(X <= 5)
{
return 5;
}
if(X <= 8)
{
return 6;
}
}
else if(Y <= 8)
{
if(X <= 2)
{
return 7;
}
if(X <= 5)
{
return 8;
}else
{
return 9;
}
}
}
void Nine_Pocket_Return_For()//判断相应坐标值是什么状态,空格返回1,定格返回2,虚格返回3。存入对应的二维数组中
{
short SA,i;
for(Y = 0 ; Y <= 8 ; Y++)
{
for(X = 0 ; X <=8 ; X++)
{
if(Nine_Pocket[Y][X] != 0)//如果坐标值不等于零
{
SA = One_Pocket_Basic;//记录原始一维数组底值
for(i = 0 ; i <=8 ; i++)//逐次增加一维数组的底值并判断所有的值是否为0
{
if(One_Pocket[One_Pocket_Basic] == 0)//如果第一个一维数组值为零
{
One_Pocket_Basic = One_Pocket_Basic + 1; //将底值加1
}
if(i == 8)//如果加到到最后还是等于零,则是定格
{
Two_Pocket[Y][X] = 2;
One_Pocket_Basic = SA; //恢复一维数组的坐标底
}
One_Pocket_Basic = One_Pocket_Basic + 9;
}
}
else//否则这个是空格或者是虚格
{
Two_Pocket[Y][X] = 3;
One_Pocket_Basic = One_Pocket_Basic + 9;
}
}
}
X = 0;
Y = 0;
One_Pocket_Basic = 0;
}
short Two_Pocket_Return()//给需要的函数返回九宫格是什么状态
{
if(Nine_Pocket[Y][X] == 0)
{
return 1;
}
else
{
return Two_Pocket[Y][X];
}
}
void Pocket_Add()//增值函数,增值函数的意义在于将坐标值增加到下一位虚格中,方便分析使用。
{
short Forcast;
if(X == 8 )
{
Y = Y + 1;
X = 0;
One_Pocket_Basic = One_Pocket_Basic + 9;
for(short i = 1; i < 81 ; i++)//根据要求,增值后的坐标必须是空值
{
Forcast = Two_Pocket_Return(); //1空,2定,3虚
if(Forcast == 1 || Forcast == 3)
{
break;
}
else
{
if(X == 8 )
{
Y = Y + 1;
X = 0;
One_Pocket_Basic = One_Pocket_Basic + 9;
}
else
{
X = X + 1;
One_Pocket_Basic = One_Pocket_Basic + 9;
}
}
}
}
else
{
X = X + 1;
One_Pocket_Basic = One_Pocket_Basic + 9;
for(short i = 1 ; i < 81 ; i++)//根据要求,增值后的坐标必须是空值
{
Forcast = Two_Pocket_Return();
if(Forcast == 1)
{
break;
}
else
{
if(X == 8 )
{
Y = Y + 1;
X = 0;
One_Pocket_Basic = One_Pocket_Basic + 9;
}
else
{
X = X + 1;
One_Pocket_Basic = One_Pocket_Basic + 9;
}
}
}
}
}
void Pocket_Reduce()//降值函数
{
unsigned short Forcast;
if(X == 0 )
{
Y = Y - 1;
X = 8;
One_Pocket_Basic = One_Pocket_Basic - 9;
for(unsigned short i = 1 ; i < 81 ; i++)//根据要求,降值后的坐标必须是虚值
{
Forcast = Two_Pocket_Return();
if(Forcast == 3)
{
break;
}
else
{
if(X == 0)
{
Y = Y - 1;
X = 8;
One_Pocket_Basic = One_Pocket_Basic - 9;
}
else
{
X = X - 1;
One_Pocket_Basic = One_Pocket_Basic - 9;
}
}
}
}
else
{
X = X - 1;
One_Pocket_Basic = One_Pocket_Basic - 9;
for(unsigned short i = 1 ; i < 81 ; i++)//根据要求,降值后的坐标必须是虚值
{
Forcast = Two_Pocket_Return();
if(Forcast == 3)
{
break;
}
else
{
if(X == 0)
{
Y = Y - 1;
X = 8;
One_Pocket_Basic = One_Pocket_Basic - 9;
}
else
{
X = X - 1;
One_Pocket_Basic = One_Pocket_Basic - 9;
}
}
}
}
}
short Return_For_X()//判断坐标参数X轴是否有重复,重复返回1,不重复返回2,以下函数同理
{
for(unsigned short i = 0 ; i < 9 ; i++)
{
if( i == X)
{
continue;
}
else
{
if(Nine_Pocket[Y][i] == Nine_Pocket[Y][X])
{
return 1;
}
}
}
return 2;
}
short Return_For_Y()
{
for(unsigned short i = 0 ; i < 9 ; i++)
{
//<>判断Y轴
if(i == Y)
{
continue;
}
else
{
if(Nine_Pocket[i][X] == Nine_Pocket[Y][X])
{
return 1;
}
}
}
return 2;
}
short Return_For_L()
{
for(unsigned short i = 0 ; i < 9 ; i++)
{
if(i == X || i == Y)
{
continue;
}
else
{
if(Nine_Pocket[i][i] == Nine_Pocket[Y][X])
{
return 1;
}
}
}
return 2;
}
short Return_For_R()
{
for(unsigned short i = 0 ; i < 9 ; i++)
{
if( i == X)
{
continue;
}
else
{
if(Nine_Pocket[8-i][i] == Nine_Pocket[Y][X])
{
return 1;
}
}
}
return 2;
}
short Return_For_G(short A)
{
switch(A)
{
case 1://<代码分析> 判断此坐标在第一宫中是否有重复,以下for判断皆如此
for(unsigned short j = 0 ; j < 3 ; j++)
{
for(unsigned short i = 0 ; i < 3 ; i++)
{
if(i == X && j == Y)
{
continue;
}
if(Nine_Pocket[j][i] == Nine_Pocket[Y][X])
{
return 1;
}
}
}
break;
case 2:
for(unsigned short j = 0 ; j < 3 ; j++)
{
for(unsigned short i = 3 ; i < 6 ; i++)
{
if(i == X && j == Y)
{
continue;
}
if(Nine_Pocket[j][i] == Nine_Pocket[Y][X])
{
return 1;
}
}
}
break;
case 3:
for(unsigned short j = 0 ; j < 3 ; j++)
{
for(unsigned short i = 6 ; i < 9 ; i++)
{
if(i == X && j == Y)
{
continue;
}
if(Nine_Pocket[j][i] == Nine_Pocket[Y][X])
{
return 1;
}
}
}
break;
case 4:
for(unsigned short j = 3 ; j < 6 ; j++)
{
for(unsigned short i = 0 ; i < 3 ; i++)
{
if(i == X && j == Y)
{
continue;
}
if(Nine_Pocket[j][i] == Nine_Pocket[Y][X])
{
return 1;
}
}
}
break;
case 5:
for(unsigned short j = 3 ; j < 6 ; j++)
{
for(unsigned short i = 3 ; i < 6 ; i++)
{
if(i == X && j == Y)
{
continue;
}
if(Nine_Pocket[j][i] == Nine_Pocket[Y][X])
{
return 1;
}
}
}
break;
case 6:
for(unsigned short j = 3 ; j < 6 ; j++)
{
for(unsigned short i = 6 ; i < 9 ; i++)
{
if(i == X && j == Y)
{
continue;
}
if(Nine_Pocket[j][i] == Nine_Pocket[Y][X])
{
return 1;
}
}
}
break;
case 7:
for(unsigned short j = 6 ; j < 9 ; j++)
{
for(unsigned short i = 0 ; i < 3 ; i++)
{
if(i == X && j == Y)
{
continue;
}
if(Nine_Pocket[j][i] == Nine_Pocket[Y][X])
{
return 1;
}
}
}
break;
case 8:
for(unsigned short j = 6 ; j < 9 ; j++)
{
for(unsigned short i = 3 ; i < 6 ; i++)
{
if(i == X && j == Y)
{
continue;
}
if(Nine_Pocket[j][i] == Nine_Pocket[Y][X])
{
return 1;
}
}
}
break;
case 9:
for(unsigned short j = 6 ; j < 9 ; j++)
{
for(unsigned short i = 6 ; i < 9 ; i++)
{
if(i == X && j == Y)
{
continue;
}
if(Nine_Pocket[j][i] == Nine_Pocket[Y][X])
{
return 1;
}
}
}
break;
}
return 2;
}
short Return_For()//判断相应的坐标值是否有重复,重复返回1,不重复返回2
{
short Forcast;
Forcast = Return_For_X();
if(Forcast == 1)
{
return 1;
}
Forcast = Return_For_Y();
if(Forcast == 1)
{
return 1;
}
Forcast = For_Gong();
Forcast = Return_For_G(Forcast);
if(Forcast == 1)
{
return 1;
}
//对于斜轴的判断是有条件的,左轴条件是X=Y,右轴条件是Y==(8-X),并且要分开判断,
if(X == Y)
{
Forcast = Return_For_L(); //左右斜上轴的判断是有条件的,不是一直使用
if(Forcast == 1)
{
return 1;
}
}
if(Y == (8-X))
{
Forcast = Return_For_R();
if(Forcast == 1 )
{
return 1;
}
}
return 2;
}
void Print_Nine_Pocket()//将九宫格打印
{
for(unsigned short i=0 ; i<9 ; i++)
{
for(unsigned short j=0 ; j<9 ; j++)
{
printf(" %d ",Nine_Pocket[i][j]);
if ( j==2 || j == 5)
{
printf(" ");
}
if( i==2 && j == 8 )
{
printf("\n");
}
if( i == 5 && j == 8 )
{
printf("\n");
}
if( j == 8)
{
printf("\n");
}
}
}
}
void Give_For()//给一维数组赋预测值,自动匹配符合每个格子的数值,写入一维数组中
{
short Forcast,SA;
for(Y = 0 ; Y <= 8 ; Y++)
{
for(X = 0 ; X <= 8 ; X++)
{
if(Nine_Pocket[Y][X] == 0)
{
for(SA = 1 ; SA <= 9 ; SA++)//从1-9开始依次增加数字
{
Nine_Pocket[Y][X] = SA; //将预测数字写入九宫格
Forcast = Return_For();//判断相应的坐标值中的预测值是否重复//将是否重复的值存入变量中
if(Forcast == 2) //如果没有重复
{
One_Pocket[One_Pocket_Basic] = SA;//将预测值写入一维数组中
}
Nine_Pocket[Y][X] = 0;
One_Pocket_Basic = One_Pocket_Basic + 1;
}
}
else
{
One_Pocket_Basic = One_Pocket_Basic + 9;
}
}
}
X = 0;
Y = 0;
One_Pocket_Basic = 0;
}
short Nine_Pocket_Xu_For()//对虚格的坐标进行赋值判断,如果成功更换此格子,返回1,否则为暂废格返回2
{
short SA,Max,Forcast;
SA = One_Pocket_Basic; //记录底值原始数值
Max = One_Pocket_Basic + 9; //记录原始数值的最大值
for(One_Pocket_Basic ; One_Pocket_Basic < Max ; One_Pocket_Basic++) //判断出格子里的值在一维数组中是第几位
{
if(One_Pocket[One_Pocket_Basic] ==0)
{
}
else
{
if(One_Pocket[One_Pocket_Basic] != Nine_Pocket[Y][X])//如果此时的一维数组不等于相应格子值
{
}
else//否则格子里的值等于一维数组的值
{
break;
}
}
if(One_Pocket_Basic == (Max-1))//如果进行第八次计算还是没有结果,则是暂废格
{
One_Pocket_Basic = SA; //恢复原坐标底值,一维数组坐标底值紧跟XY变化
printf("虚格操作:此格是暂废格");
return 2;
}
}
for(One_Pocket_Basic ; One_Pocket_Basic < Max ; One_Pocket_Basic++)//以记录后的底值为开始,逐渐加1,如果一维数组为0,就加1,否则就赋值格子
{
if(One_Pocket[One_Pocket_Basic] == 0 || One_Pocket[One_Pocket_Basic]==Nine_Pocket[Y][X])
{
}
else//如果不等于0
{
Nine_Pocket[Y][X] = One_Pocket[One_Pocket_Basic]; //将不等于0的数重新赋值到原先的九宫格中
Forcast=Return_For(X ,Y); //将是否重复的值存入变量中
if(Forcast == 1)
{//如果重复
Nine_Pocket[Y][X] = 0;
}
else
{//否则没有重复,则成功更换数值
One_Pocket_Basic = SA; //恢复原坐标底值,一维数组坐标底值紧跟XY变化
return 1;
}
}
if(One_Pocket_Basic == (Max-1) || One_Pocket_Basic == Max)//如果进行最后一次判断一维数组值都还为零,则此格为暂废格,需要XY坐标底值降值函数
{
One_Pocket_Basic = SA;//恢复原坐标底值,一维数组坐标底值紧跟XY变化
return 2;
}
}
}
short Nine_Pocket_Add_For()//用一维数组的预测值给九宫格赋值并判断
{
short Forcast,SA;
for(Y = 0 ; Y <= 8 ; Y++)
{
for(X = 0 ; X <= 8 ; X++)
{
Label:
Forcast = Two_Pocket_Return(); //获取二维数组中相应的格子是什么状态,1空格,2定格,3虚格
if(Forcast == 1)//如果是空格进行赋值判断操作
{
}
if(Forcast == 2)//如果是定格跳过本次循环
{
One_Pocket_Basic = One_Pocket_Basic + 9; //一维数组底值紧跟XY坐标值变化
continue;
}
if(Forcast == 3)//如果是虚格,则进入虚格函数
{
Forcast = Nine_Pocket_Xu_For();//1为虚格并成功更换了此格预测数,2为所有预测数已用尽,需要返回上一个虚格中更换相应的虚格数,
if(Forcast == 1)
{
Pocket_Add(); //成功更换当前格子值后,应当将坐标换回原来的值
goto Label;
}
if(Forcast == 2)
{
Nine_Pocket[Y][X] = 0; //将当前的坐标值恢复成0,然后降值坐标返回上一个虚值坐标并重复本函数
Pocket_Reduce(); //将坐标值降到上一个虚格中
goto Label;
}
}
//剩余是对空格子里的值赋值并判断,如果赋值成功并不重复,此次循环顺利结束,如果重复,则使用降值函数返回上一级虚值并使用goto标签
SA = One_Pocket_Basic; //记录原始底值
for(short i = 0 ; i < 9 ; i++)
{
if(One_Pocket[One_Pocket_Basic] == 0)
{
One_Pocket_Basic = One_Pocket_Basic+1;
}
else
{
Nine_Pocket[Y][X] = One_Pocket[One_Pocket_Basic];
Forcast = Return_For(X ,Y); //将是否重复的值存入变量中
if(Forcast == 1)//返回1重复,否则不重复
{
Nine_Pocket[Y][X] = 0;
One_Pocket_Basic = One_Pocket_Basic + 1; //如果重复则把一维数组的底值加1再次进行计算
}
else
{
One_Pocket_Basic = SA;//底值归位
One_Pocket_Basic = One_Pocket_Basic + 9; //本次循环结束,一维数组底值紧跟坐标XY变化
break;
}
}
if(i == 8)//如果进行第8次计算则说明这个格子是暂废格,降值处理
{
Nine_Pocket[Y][X] = 0;
One_Pocket_Basic = SA;
Pocket_Reduce();
goto Label;
}
}
}
}
}
void inget()
{
for(short i = 0; i < 9 ; i++)
{
for(short j = 0 ; j < 9 ; j++ )
{
printf("\n请输入坐标为Y=%d,X=%d的数值:",i+1,j+1);
scanf("%d",&Nine_Pocket[i][j]);
}
}
}
void Print_Two_Pocket()//将九宫格打印
{
for(unsigned short i=0 ; i<9 ; i++)
{
for(unsigned short j=0 ; j<9 ; j++)
{
printf(" %d ",Two_Pocket[i][j]);
if ( j==2 || j == 5)
{
printf(" ");
}
if( i==2 && j == 8 )
{
printf("\n");
}
if( i == 5 && j == 8 )
{
printf("\n");
}
if( j == 8)
{
printf("\n");
}
}
}
}
void main()
{
char m;
printf("程序准备完成,请确认是否开始(y输入表格,n结束)\a\n");
scanf("%c",&m);
while(m == 'y' || m == 'Y')
{
printf("请输入新的表格:\n");
inget();//用户输入数独表格
Print_Nine_Pocket();//将九宫格打印
printf("\n请确认无误后进行下一步操作(y重新输入,n开始分析)\n");
fflush(stdin);
scanf("%c",&m);
}
Give_For();//给一维数组赋值,输入坐标参数X,Y,给一维数组返回预测值
Nine_Pocket_Return_For();
//Print_Two_Pocket();
Nine_Pocket_Add_For();//用一维数组的预测值给九宫格赋值并判断
printf("\n");
Print_Nine_Pocket();//将九宫格打印
}