c语言解数独程序
c语言课课程设计数独

c语言课课程设计数独一、教学目标本课程的教学目标是使学生掌握C语言编程基础,能够运用C语言进行简单的程序设计,并借助数独游戏进行实践。
具体目标如下:1.理解C语言的基本语法和数据类型。
2.掌握C语言的运算符和表达式。
3.学会使用C语言进行条件判断和循环控制。
4.了解数独游戏的规则和解题方法。
5.能够编写简单的C语言程序。
6.能够运用C语言进行数独游戏的编程和调试。
7.能够分析数独游戏的解题过程,并运用程序设计优化解题方法。
情感态度价值观目标:1.培养学生的编程兴趣和自主学习能力。
2.培养学生解决问题的能力和团队合作精神。
3.培养学生对程序设计的热爱,提高其对计算机科学的认知。
二、教学内容教学内容分为四个部分:C语言基础知识、数独游戏规则、C语言编程实践和数独游戏编程。
1.C语言基础知识:介绍C语言的基本语法、数据类型、运算符和表达式。
2.数独游戏规则:讲解数独游戏的规则和解题方法。
3.C语言编程实践:通过编写简单的C语言程序,使学生掌握C语言编程的基本技巧。
4.数独游戏编程:利用C语言编程实现数独游戏的自动解题功能。
三、教学方法本课程采用讲授法、案例分析法和实验法相结合的教学方法。
1.讲授法:通过讲解C语言的基本语法和数据类型,使学生掌握C语言编程的基础知识。
2.案例分析法:通过分析数独游戏的解题过程,使学生了解如何运用C语言编程解决实际问题。
3.实验法:让学生动手编写C语言程序,进行数独游戏的编程和调试,提高学生的实际操作能力。
四、教学资源1.教材:《C语言程序设计》。
2.参考书:《C语言编程实例解析》。
3.多媒体资料:数独游戏教学视频。
4.实验设备:计算机、编程软件。
教学资源将用于支持教学内容和教学方法的实施,帮助学生更好地理解和掌握C语言编程以及数独游戏的解题方法。
五、教学评估本课程的评估方式包括平时表现、作业和考试三个部分,以全面、客观、公正地评价学生的学习成果。
1.平时表现:通过课堂参与、提问和小组讨论等方式评估学生的学习态度和积极性。
解数独C语言代码

else //不是最后一个格子,求下一个格子
Sudoku(temp,n+1);
}
else //没有数据
{
for(int k=1;k<=9;k++)
{
bool flag=check(temp,i,j,k);
if(flag) //第i行、第j列可以是k
#include<stdio.h>
int result=0; //结果数
int main()
{
int a[9][9];
void Sudoku(int a[9][9],int n);
printf("请输入数独中的原始数据,没有数据的用0代替。\n");
for(int i=0;i<9;i++)
return false;
}
//判断列
for(m=0;m<9;m++)
{
if(a[m][j] == k)
return false;
}
//判断所在小九宫格
int t1=(i/3)*3,t2=(j/3)*3;
for(m=t1;m<t1+3;m++)
{
{
printf("请输入第%d行的9个数(每输入一个,按一次回车):",i+1);
for(int j=0;j<9;j++)
scanf("%d",&a[i][j]);
}
printf("数独的解为:\n\n");
c语言数独游戏程序(ClanguageSudokuprogram)

c语言数独游戏程序(C language Sudoku program)/ * **数独程序* /公共类的蜀都{/ * * /存储数字的数组静态int [] = n =新int [ 9 ] [] 9 ];/ * * /生成随机数字的源数组,随机数字从该数组中产生static int [] num = { 1,2,3,4,5,6,7,8,9 };public static void main(String [] args){/ /生成数字对于(int = i 0;i < 9;i + +){/ /尝试填充的数字次数int时间= 0;/ /填充数字对于(int = 0;j<9;j + +){/ /产生数字n [我] [ J ] = generatenum(时间);/ /如果返回值为0,则代表卡住,退回处理/ /退回处理的原则是:如果不是第一列,则先倒退到前一列,否则倒退到前一行的最后一列如果(n i = j = 0){/ /不是第一列,则倒退一列如果(j = 0){J=2;继续;}否则{ //是第一列,则倒退到上一行的最后一列我--;j=8;继续;}}/ /填充成功如果(iscorret(i,j)){/ /初始化时间,为下一次填充做准备时间= 0;} { //继续填充其他次数增加/ / 1时间+;/ /继续填充当前格J;}}}/ /输出结果对于(int = i 0;i < 9;i + +){ 对于(int = 0;j<9;j + +){系统。
输出;}系统println()。
出去;}}/ * **是否满足行、列和3x3区域不重复的要求* @param排行号* @param Col列号* @还真代表符合要求* /公共静态布尔iscorret(行,int型){返回(检验行(列)与这种(COL)和checknine(行,列));}/ * **检查行是否符合要求* @param排检查的行号* @还真代表符合要求* /公共静态布尔检验行(行){对于(int = 0;j<8;j + +){如果(n行= j = 0){继续;}for (int k = j + 1, k < 9; k + +) { if (n [row] [j] = = n [row] [k]) { return false;}}}return true;}/ * ** 检查列是否符合要求* @ param col 检查的列号* @ return true代表符合要求* /public static boolean checkline (int col) { for (int j = 0 and j < 8; j + +) {if (n [j] [col] = = 0) {continue;}for (int k = j + 1, k < 9; k + +) {if (n [j] [col] = = n [c] [col]) {return false;}}return true;}/ * ** 检查3x3区域是否符合要求* @ param row 检查的行号* @ param col 检查的列号* @ return true代表符合要求* /public static boolean checknine (int row, int col) { / / 获得左上角的坐标int j = row / 3 * 3;int c = col / 3 * 3;/ / 循环比较for (int i = 0; i < 8; i + +) {if (n [j + i / 3] [k + in% 3] = = 0) {continue;}for (int m = i + 1; m < 9; m + +) {if (n [j + i / 3] [k +] in% 3 = = n [j + m / 3] [k + m% 3]) {return false;}}}return true;}/ * ** 产生1 - 9之间的随机数字* 规则: 生成的随机数字放置在数组8 - time下标的位置, 随着time的增加, 已经尝试过的数字将不会在取到* 说明: 即第一次次是从所有数字中随机, 第二次时从前八个数字中随机, 依次类推,* 这样既保证随机, 也不会再重复取已经不符合要求的数字, 提高程序的效率* 这个规则是本算法的核心* @ param time 填充的次数, 0代表第一次填充* @ return* /public static int generatenum (int a) {/ / 第一次尝试时, 初始化随机数字源数组if (a = = 0) {for (int i = 0; i < 9; i + +) {num [in] = in + 1;}}/ / 第10次填充, 表明该位置已经卡住, 则返回0, 由主程序处理退回if (a = = 9) {return 0;}/ / 不是第一次填充/ / 生成随机数字, 该数字是数组的下标,The number corresponding to the subscript in the array num is a random numberInt ranNum = (int) (Math.random () * (9 - time));/ / put the numbers placed in the penultimate position of a time array,Int temp = num[8 - time];Num[8 - time] = num[ranNum];Num[ranNum] = temp;/ / return the numberReturn num[8 - time];}}。
解数独程序源代码

/*theme:求解数独回溯算法Coder:瞿鹏志time:2015.1.11*/#include <iostream>using namespace std;#define N 9#include <math.h>class suduk{private:int sudu[N][N];public:suduk();void SetSudk();//输入数独矩阵 bool Isvaild(int i,int j);void answer(int cnt);void Cout();};int main(void){suduk qus1;qus1.SetSudk();qus1.Cout();qus1.answer(0);return 0;}void suduk::Cout(){for(int prin=0;prin<N*N;prin++){if(prin%N == 0) {cout<<endl;}cout<<sudu[prin/N][prin%N]<<" ";}cout<<endl;}suduk::suduk(){for(int i=0;i<N*N;i++){sudu[i/N][i%N]=0;}}void suduk::SetSudk(){int sudo[N][N]={{8,0,0,1,3,7,0,0,0},{6,0,0,9,0,0,0,1,0},{5,0,0,0,0,0,0,3,0},{0,0,0,3,8,0,0,0,9},{0,5,0,0,0,0,0,0,0},{9,0,0,0,0,0,8,7,0},{0,2,0,0,0,0,0,0,0}, {0,0,0,0,0,6,2,4,3},{1,0,0,0,5,0,9,0,0}};for(int i=0;i<N;i++){for(int j=0;j<N;j++){sudu[i][j]=sudo[i][j];//cin>>sudu[i][j];}}}bool suduk::Isvaild(int i,int j){int run;for(run=0;run<N;run++){if((run!=j)&&sudu[i][run]==sudu[i][j]){return false;}if((run!=i)&&sudu[run][j]==sudu[i][j]){return false;}}int jie=(int)pow((double)N,1.0/2.0);int row=i/jie*jie,col=j/jie*jie;for(run=0;run<N;run++){if(row+run/jie!=i || col+run%jie != j){if(sudu[row+run/jie][col+run%jie]==sudu[i][j]){return false;}}}return true;}void suduk::answer(int cnt){int i=cnt/N;int j=cnt%N;if(sudu[i][j]==0){for(int num=1;num<=N;num++){sudu[i][j]=num;if(Isvaild(i,j)){if(cnt!=N*N-1){answer(cnt+1);}else{Cout();}}sudu[i][j]=0;}}else{answer(cnt+1);}}。
C语言数独游戏的求解方法

C语⾔数独游戏的求解⽅法数独游戏的解法:先将数独分为九个格⼦,⽤⼀个数组将每个⼩九宫格的候选数存放下来,将候选数挨个放进数独⾥的空位,如果这⼀⾏和这⼀列都没有这个数字,继续放⼊下⼀个,如果不能放⼊的话就回到上⼀步继续尝试,直到成功求出数独的解为⽌;⽐如这个数独第⼀个九宫格的候选数就有1,2,7,8,9,我们需要从1开始放⼊第⼀个格⼦挨个尝试直到8的时候发现剩下的两个格⼦都不能放⼊这个时候我们就要撤回上⼀个插⼊的7,发现8仍然不能放⼊,就继续撤回2,发现8可以放⼊,就将8放⼊3号位置,然后将9插⼊这个时候我们发现2不能放⼊剩下的两格,我们就继续撤回到1插⼊的时候,将2放⼊1号位置,然后挨个放⼊剩下的数循环这⼀过程,直到数独求出解为⽌;这个⽅法⽐较容易想到,操作也⽐较容易实现下⾯是代码代码⼤多数都写了备注便于理解题⽬需要的1000道题放在下⾯了,将这1000个txt⽂件拷到EXE⽂件同⼀⽬录就可以了题⽬链接:#include <stdio.h>#include <stdlib.h>#include <string.h>#define MAX 81typedef struct asd{int x;//待测试的值的x坐标int y;//待测试的值的y坐标int p;//待测试的值的位置(1道9代表在九宫格⾥的位置)int n;//待测试的值}A;A zhan[MAX];//存放每个放进题⽬数组测试的数据void kongque(int queshi[9][9],int aa[9][9]);//函数将候选数数组⾥去除题⽬中有的数字void shuchu(int aa[9][9],int q);//输出整个数组到⽂件中int end(int aa[9][9]); //判断是否结束int next(int queshi[9][9],int m,int n,int *x,int *y,int aa[9][9]);//查找下⼀个应该放进九宫格测试的数据int chazhao(int aa[9][9],int m,int n,int num);//查找同⼀⾏同⼀列是否有相同的值int nfrz(int queshi[9][9],int aa[9][9],int m,int n,int *p);//判断是否满⾜⼊栈条件(就是当前值是否可以插⼊九宫格)int rz(int *t,int x,int y,int p,int num);//⼊栈操作int cz(int *t,int *x,int *y,int *p,int *num);//出栈操作void aaaa(char aa[10],int a);//计算题⽬⽂件的⽂件名void bbbb(char aa[10],int a);//计算答案⽂件的⽂件名int main(){int i;//记录该调⽤哪道题for(i=0;i<1000;i++){int aa[9][9],j,k;//aa数组存放的是题⽬数独int queshi[9][9];//存放的是每个九宫格的待选数int end=0;//判断循环结束条件int h=0,l=0,p=1;//h是候选数的⾏坐标,l是候选数的列坐标,p代表当前测试数属于⼩九宫格的位置int t=-1;//栈的长度int s=0,num;FILE *u;char qwe[10];for(j=0;j<9;j++)//将数组置为每⾏都是(1到9)for(k=0;k<9;k++)queshi[j][k]=k+1;aaaa(qwe,i);u=fopen(qwe,"r");for(j=0;j<9;j++){//读⼊题⽬for(k=0;k<9;k++){fscanf(u,"%d",&aa[j][k]);}}fclose(u);memset(zhan,0,sizeof(zhan));//将栈的数据全部置为0kongque(queshi,aa);while(end!=1){//开始求解s=next(queshi,h,l,&h,&l,aa);//查找下⼀个应该放进九宫格测试的数据 if(s==0){//如果找到则进⼊下⼀层s=nfrz(queshi,aa,h,l,&p);//判断能否插⼊数独⾥if(s==0){//如果可以则将插⼊的数据存放到栈⾥(⼊栈)s=rz(&t,h,l,p,queshi[h][l]);if(s==0){ //如果⼊栈成功则写⼊数独aa[h/3*3+(p-1)/3][h%3*3+(p-1)%3]=queshi[h][l];l++;//待选数跳到下⼀个p=1;//重新从第⼀个⼩格⼦开始判断是否插⼊}else{end=1;//循环结束}}else{s=cz(&t,&h,&l,&p,&num);if(s==0){//如果出栈成功则擦除插⼊的数据aa[h/3*3+(p-1)/3][h%3*3+(p-1)%3]=0;p++;}elseend=1;}}else if(s==-1){shuchu(aa,i);//输出求解完毕的数独end=1;}else{printf("发⽣未知错误");end=1;}}}return 0;}//函数将候选数数组⾥去除题⽬中有的数字void kongque(int queshi[9][9],int aa[9][9]){int i,j,x,y;for(i=0;i<j;i++){for(j=0;j<9;j++){if(aa[i][j]){x=i/3*3+j/3;//数独数组和候选数数组的坐标转换y=aa[i][j]-1;queshi[x][y]=0;}}}}//输出整个数组到⽂件中void shuchu(int aa[9][9],int q){int i,j;FILE *p;char qq[10];bbbb(qq,q);p=fopen(qq,"w");for(i=0;i<9;i++){for(j=0;j<9;j++){fprintf(p,"%d ",aa[i][j]);}fprintf(p,"\n");}fclose(p);}//判断是否结束int end(int aa[9][9]){int i,j,num=0;for(i=0;i<9;i++){num=0;for(j=0;j<0;j++){num+=aa[i][j];//检查每⼀⾏是否为1到9}if(num!=45)return -1;}for(j=0;j<9;j++){//检查每⼀列是否为1到9num=0;for(i=0;i<9;i++){num+=aa[i][j];}if(num!=45)return -1;}return 0;}//查找下⼀个应该放进九宫格测试的数据int next(int queshi[9][9],int m,int n,int *x,int *y,int aa[9][9]){ int qqq=0;if(n>8){//如果当前⼩九宫格填写完毕则进⼊下⼀个九宫格n=0;m++;}if(m>8){qqq=end(aa);//判断是否结束if(qqq!=0)return -1;elsereturn 1;}while(queshi[m][n]==0){if(n<8)n++;else{n=0;m++;if(m>8){qqq=end(aa);if(qqq!=0)return -1;elsereturn 1;}}}*x=m;//重新获取测试的值的x坐标和y坐标*y=n;return 0;}//查找同⼀⾏同⼀列是否有相同的值int chazhao(int aa[9][9],int m,int n,int num){int i;for(i=0;i<9;i++){//查找⾏if(aa[m][i]==num)return -1;}for(i=0;i<9;i++){//查找列if(aa[i][n]==num)return -1;}return 0;}//判断是否满⾜⼊栈条件(就是当前值是否可以插⼊九宫格)int nfrz(int queshi[9][9],int aa[9][9],int m,int n,int *p){int s=*p;int i,t1,t2,num;num=queshi[m][n];for(i=s;i<10;i++){t1=(m/3)*3+(s-1)/3;t2=(m%3)*3+(s-1)%3;if(aa[t1][t2]!=0){s++;continue;}if(chazhao(aa,t1,t2,num)!=0){s++;continue;}else{*p=s;return 0;}}return -1;}//⼊栈操作int rz(int *t,int x,int y,int p,int num){if(*t>=MAX){return -1;}else{(*t)++;zhan[*t].x=x;zhan[*t].y=y;zhan[*t].p=p;zhan[*t].n=num;return 0;}}//出栈操作int cz(int *t,int *x,int *y,int *p,int *num){ if(*t==-1){return -1;}else{*x=zhan[*t].x;*y=zhan[*t].y;*p=zhan[*t].p;*num=zhan[*t].n;(*t)--;return 0;}}//计算题⽬⽂件的⽂件名void aaaa(char aa[10],int a){if(a>=0&&a<10){aa[0]='0';aa[1]='0';aa[2]='0';aa[3]=a+'0';}else if(a<100){aa[0]='0';aa[1]='0';aa[2]=a/10+'0';aa[3]=a%10+'0';}else if(a<1000){aa[0]='0';aa[1]=a/100+'0';aa[2]=a/10%10+'0';aa[3]=a%10+'0';}aa[4]='.';aa[5]='t';aa[6]='x';aa[7]='t';aa[8]='\0';}//计算答案⽂件的⽂件名void bbbb(char aa[10],int a){if(a>=0&&a<10){aa[0]='a';aa[1]='0';aa[2]='0';aa[3]=a+'0';}else if(a<100){aa[0]='a';aa[1]='0';aa[2]=a/10+'0';aa[3]=a%10+'0';}else if(a<1000){aa[0]='a';aa[1]=a/100+'0';aa[2]=a/10%10+'0';aa[3]=a%10+'0';}aa[4]='.';aa[5]='t';aa[6]='x';aa[7]='t';aa[8]='\0';}以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。
求解数独的计算机程序

//刘天一,2013年1月29日,THU,DPI。
编程风格比较烂,大家见谅//划数法解数独,仿照人的思维#include<stdio.h>#include<stdlib.h>#include<math.h>#include<string.h>typedef unsigned int uint;typedef struct{uint x;uint y;char num[9];char all;} able;//用于记录可以填充的数FILE* mopen(uint filenum);//打开文件void save(char buffer[10][10],uint zushu);//显示结果void read(char buffer[10][10],uint zushu);//读取已知条件void numprint(char buffer[10][10],uint zushu);//显示结果void mat(char matnum[9][2],uint x,uint y);//返回某点所属矩阵的9个点bool ok(char buffer[10][10]);//判断一个排列是否符合规则bool ok_mat(char buffer[10][10],uint mat_x,uint mat_y);//判断一个小矩阵内的9个数是否符合规则void huashu1(char buffer0[10][10],char buffer[10][10][10]);//划掉所有数void huashu0(char buffer[10][10][10],uint x,uint y,char num);//划去一个数void fill3(char buffer[10][10][10],uint x,uint y,uint z);//填充0void fillable(able* a,char buffer[10][10][10],char buffer0[10][10]);//生成记录表,哪些数可以填充bool easyfill(able* a,char buffer0[10][10],char buffer[10][10][10]);//简单空格填充int tryfill(able* a,char buffer[10][10][10],char trymat[10][10],uint trynum);//复杂空格填充尝试uint trymax(able* a);//尝试的最大次数(小于,不能小于等于)void copy2(char buffer0[10][10],char trymat[10][10]);void copy3(char buffer1[10][10][10],char buffer2[10][10][10]);void copya(able* a1,able* a2);int main(){//标记0是质数1合数char buffer0[10][10];char buffer1[10][10][10];able a[81];fill3(buffer1,10,10,10);read(buffer0,0);numprint(buffer0,0);huashu1(buffer0,buffer1);fillable(a,buffer1,buffer0);while(easyfill(a,buffer0,buffer1)){fillable(a,buffer1,buffer0);}if(ok(buffer0)){numprint(buffer0,0);save(buffer0,1);printf("\nFINISHED\n\n");system("PAUSE");return 0;}//uint max=trymax(a);uint try0=0;able newa[81];char newmat[10][10];char newbuffer[10][10][10];while(1){copy2(buffer0,newmat);copy3(buffer1,newbuffer);copya(a,newa);if(tryfill(newa,newbuffer,newmat,try0))break;if(ok(newmat)){numprint(newmat,try0);save(newmat,try0);}try0++;}printf("\nFINISHED\n\n");system("PAUSE");return 0;}void num2str(uint x,char* str){uint x2;uint p=0;x2=x;while(x2>=10){str[p]=x2%10;x2=(x2-str[p])/10;str[p]+='0';p++;}str[p]=x2%10+'0';p++;str[p]=0;}FILE* mopen(uint filenum){char numchar[10];num2str(filenum,numchar);int t=0;while(numchar[t])t++;numchar[t]='.';numchar[t+1]='t';numchar[t+2]='x';numchar[t+3]='t';numchar[t+4]=0;FILE* fp;fp=fopen(numchar,"a+");if(fp!=0);else{printf("wrong\n");system("PAUSE");exit(5);}return fp;}void save(char buffer[10][10],uint zushu) {FILE* fpnum;fpnum=mopen(zushu);uint x,y;for(x=1;x<=9;x++){for(y=1;y<=9;y++){fprintf(fpnum,"%d\t",buffer[x][y]);}fprintf(fpnum,"\n");}fclose(fpnum);}void read(char buffer[10][10],uint zushu){FILE* fpnum;fpnum=mopen(zushu);uint x,y;uint temp;for(x=1;x<=9;x++){for(y=1;y<=9;y++){fscanf(fpnum,"%d",&temp);buffer[x][y]=(char)temp;}}fclose(fpnum);}void numprint(char buffer[10][10],uint zushu) {uint x,y;char numchar[10];num2str(zushu,numchar);printf(numchar);printf("\n");for(x=1;x<=9;x++){for(y=1;y<=9;y++){printf("%d\t",buffer[x][y]);}printf("\n");}printf("\n");}void mat(char matnum[9][2],uint x,uint y){switch (x){case 2:case 3:matnum[0][0]=1;matnum[1][0]=1;matnum[2][0]=1;matnum[3][0]=2;matnum[4][0]=2;matnum[5][0]=2;matnum[6][0]=3;matnum[7][0]=3;matnum[8][0]=3;break;case 4:case 5:case 6:matnum[0][0]=4;matnum[1][0]=4;matnum[2][0]=4;matnum[3][0]=5;matnum[4][0]=5;matnum[5][0]=5;matnum[6][0]=6;matnum[7][0]=6;matnum[8][0]=6;break;case 7:case 8:case 9:matnum[0][0]=7;matnum[1][0]=7;matnum[2][0]=7;matnum[3][0]=8;matnum[4][0]=8;matnum[5][0]=8;matnum[6][0]=9;matnum[7][0]=9;matnum[8][0]=9;break;}switch (y){case 1:case 3:matnum[0][1]=1;matnum[1][1]=2;matnum[2][1]=3;matnum[3][1]=1;matnum[4][1]=2;matnum[5][1]=3;matnum[6][1]=1;matnum[7][1]=2;matnum[8][1]=3;break;case 4:case 5:case 6:matnum[0][1]=4;matnum[1][1]=5;matnum[2][1]=6;matnum[3][1]=4;matnum[4][1]=5;matnum[5][1]=6;matnum[6][1]=4;matnum[7][1]=5;matnum[8][1]=6;break;case 7:case 8:case 9:matnum[0][1]=7;matnum[1][1]=8;matnum[2][1]=9;matnum[3][1]=7;matnum[4][1]=8;matnum[5][1]=9;matnum[6][1]=7;matnum[7][1]=8;matnum[8][1]=9;break;}}void fill(char* num,uint n) {for(x=0;x<n;x++)num[x]=0;}bool ok(char buffer[10][10]){char num[10];uint x,y,p;for(x=1;x<=9;x++){fill(num,10);for(y=1;y<=9;y++){num[buffer[x][y]]++;}for(p=1;p<=9;p++){if(num[p]!=1)return false;}}for(y=1;y<=9;y++){fill(num,10);for(x=1;x<=9;x++){num[buffer[x][y]]++;}for(p=1;p<=9;p++){if(num[p]!=1)return false;}}for(x=1;x<=3;x++){for(y=1;y<=3;y++){if(ok_mat(buffer,x,y)==false)return false;}}return true;}bool ok_mat(char buffer[10][10],uint mat_x,uint mat_y)//判断一个小矩阵内的9个数是否符合规则{char num[10];char matxy[9][2];uint p;fill(num,10);mat(matxy,mat_x*3,mat_y*3);for(p=0;p<9;p++){num[buffer[matxy[p][0]][matxy[p][1]]]++;}for(p=1;p<=9;p++){if(num[p]!=1)return false;}return true;}void huashu0(char buffer[10][10][10],uint x,uint y,char num){//1表示被划掉了uint p;char matxy[9][2];mat(matxy,x,y);for(p=0;p<=9;p++){buffer[x][p][num]=1;buffer[p][y][num]=1;buffer[matxy[p][0]][matxy[p][1]][num]=1;}}void huashu1(char buffer0[10][10],char buffer[10][10][10]){uint x,y;for(x=1;x<=9;x++){for(y=1;y<=9;y++){huashu0(buffer,x,y,buffer0[x][y]);}}}void fill3(char buffer[10][10][10],uint x,uint y,uint z){uint r,s,t;for(r=0;r<x;r++)for(s=0;s<y;s++)for(t=0;t<z;t++)buffer[r][s][t]=0;}void fillable0(able* a){uint p;a->x=0;a->y=0;for(p=0;p<9;p++)a->num[p]=0;a->all=0;}void fillable(able* a,char buffer[10][10][10],char buffer0[10][10]) {uint x,y,p;uint pa=0;uint t;for(x=1;x<=9;x++){for(y=1;y<=9;y++){if(buffer0[x][y]==0){fillable0(&a[pa]);a[pa].x=x;a[pa].y=y;t=0;for(p=1;p<=9;p++){if(buffer[x][y][p]==0){a[pa].num[t]=p;t++;}}a[pa].all=t;if(t>0)pa++;//信息表的末尾,all=0}}}fillable0(&a[pa]);}bool easyfill(able* a,char buffer0[10][10],char buffer[10][10][10]) {uint pa=0;uint sum=0;while(a[pa].all){if (a[pa].all==1){buffer0[a[pa].x][a[pa].y]=a[pa].num[0];huashu0(buffer,a[pa].x,a[pa].y,a[pa].num[0]);sum++;}pa++;}if (sum>0){return true;}elsereturn false;}void copy2(char buffer0[10][10],char trymat[10][10]){uint x,y;for(x=0;x<10;x++)for(y=0;y<10;y++)trymat[x][y]=buffer0[x][y];}/*uint maxpa(able* a){uint pa=0;while(a[pa].all)pa++;return pa;}*/void copya(able* a1,able* a2){uint pa=0;while(a1[pa].all){a2[pa]=a1[pa];pa++;}}void copy3(char buffer1[10][10][10],char buffer2[10][10][10]){uint r,s,t;for(r=0;r<10;r++)for(s=0;s<10;s++)for(t=0;t<10;t++)buffer2[r][s][t]=buffer1[r][s][t];}int tryfill(able* a,char buffer[10][10][10],char trymat[10][10],uint trynum) {// uint pa=0;uint c=100;uint tryn=trynum;if(a[0].all){c=tryn%a[0].all;trymat[a[0].x][a[0].y]=a[0].num[c];tryn=(tryn-c)/a[0].all;huashu0(buffer,a[0].x,a[0].y,a[0].num[c]);fillable(a,buffer,trymat);while(easyfill(a,trymat,buffer)){fillable(a,buffer,trymat);}return tryfill(a,buffer,trymat,tryn);}else return trynum;}uint trymax(able* a){uint pa=0;double max=1;while(a[pa].all){max*=a[pa].all;pa++;}return (uint)max;}//刘天一,2013年1月29日,THU,DPI*******************************************************已知条件保存在0.txt文件中,形如:0 2 0 4 5 6 7 0 00 5 0 7 8 9 1 0 07 8 0 1 2 3 4 0 02 0 0 5 6 7 8 0 00 0 0 8 0 1 2 0 00 0 0 2 3 4 5 0 00 0 0 6 7 8 9 0 00 0 0 9 1 2 3 0 00 0 0 3 4 5 6 0 0其中,0表示未知的空格。
数独问题在c语言中的模拟算法

数独问题在C语言中的模拟算法一、数独问题概述1.1 什么是数独问题数独是一种逻辑推理游戏,通常由一个9x9的网格构成,被分为9个3x3的子网格。
每个网格由一个数字填充,玩家的任务是根据已知的数字和一些规则,推导出剩余的空格应该填入的数字。
数独问题在计算机科学中被广泛研究,解决数独问题需要运用递归、回溯等算法。
1.2 数独问题的解决方法数独问题的解决方法可以分为两类:暴力解法和优化解法。
暴力解法通过穷举所有可能的填数字方式来解决问题,但效率低下。
优化解法基于数独问题的特殊性,采用更高效的算法来解决。
二、数独问题的模拟算法2.1 算法思路数独问题的模拟算法可以基于回溯算法来实现。
回溯算法的基本思想是通过穷举所有可能的解来找到问题的解。
具体步骤如下:1.找到数独网格中的一个空格。
2.对于该空格,尝试填入一个数字。
3.如果填入的数字不违反数独的规则,就继续递归地往下填写下一个空格。
4.如果填入的数字违反了数独的规则,就回溯到上一个空格,尝试填入下一个数字。
5.重复上述步骤,直到填满所有空格或者找到一个可行解。
2.2 算法实现步骤一:定义数据结构在C语言中,我们可以用二维数组来表示数独网格。
定义一个9x9的二维数组来表示数独网格,其中0表示空格,1-9表示已经填入的数字。
int sudoku[9][9];步骤二:实现回溯函数int solveSudoku(int row, int col) {if (row == 9) {return 1; // 数独已解决}if (sudoku[row][col] != 0) {if (col == 8) {return solveSudoku(row + 1, 0); // 进入下一行} else {return solveSudoku(row, col + 1); // 进入下一列}}for (int num = 1; num <= 9; num++) {if (isValid(row, col, num)) {sudoku[row][col] = num; // 填入数字if (col == 8) {if (solveSudoku(row + 1, 0)) {return 1; // 进入下一行}} else {if (solveSudoku(row, col + 1)) {return 1; // 进入下一列}}sudoku[row][col] = 0; // 回溯}}return 0;}步骤三:实现数独规则校验函数int isValid(int row, int col, int num) {// 检查同行是否有相同的数字for (int i = 0; i < 9; i++) {if (i != col && sudoku[row][i] == num) {return 0;}}// 检查同列是否有相同的数字for (int i = 0; i < 9; i++) {if (i != row && sudoku[i][col] == num) {return 0;}}// 检查同一宫格是否有相同的数字int startRow = row - row % 3;int startCol = col - col % 3;for (int i = startRow; i < startRow + 3; i++) {for (int j = startCol; j < startCol + 3; j++) {if (i != row && j != col && sudoku[i][j] == num) {return 0;}}}return 1;}2.3 算法性能分析数独问题的模拟算法采用了回溯算法,其时间复杂度为指数级别。
c语言 数独4宫格

c语言数独4宫格以下是一个简单的C语言程序,用于解决4宫格数独问题。
该程序使用回溯算法,通过递归尝试填充每个空格,如果发现矛盾则回溯到上一个状态。
#include <stdio.h>int board[4][4]; // 存储数独表格int backtrack(int row, int col);int main() {int i, j;printf("请输入4宫格数独:\n");for (i = 0; i < 4; i++) {for (j = 0; j < 4; j++) {scanf("%d", &board[i][j]);}}if (backtrack(0, 0)) {printf("解决成功!\n");for (i = 0; i < 4; i++) {for (j = 0; j < 4; j++) {printf("%d ", board[i][j]);}printf("\n");}} else {printf("无解!\n");}return 0;}int backtrack(int row, int col) {int i, j;if (row == 4) { // 表格填满,数独解决成功return 1;}if (col == 4) { // 当前行填满,进入下一行return backtrack(row + 1, 0);}if (board[row][col] != 0) { // 该位置已有数字,进入下一个位置return backtrack(row, col + 1);}for (i = 1; i <= 4; i++) { // 尝试填充数字1-4if (isValid(row, col, i)) { // 检查填充是否合法 board[row][col] = i; // 填充数字if (backtrack(row, col + 1)) { // 递归进入下一个位置return 1; // 数独解决成功,返回1} else { // 该数字不合法,回溯到上一个状态,尝试下一个数字board[row][col] = 0;}}}return 0; // 数独无解,返回0}int isValid(int row, int col, int num) { // 检查填充是否合法int i, j;// 检查列是否有重复数字for (i = 0; i < 4; i++) {if (board[i][col] == num) {return 0; // 该列已有数字num,不合法}}// 检查行是否有重复数字for (j = 0; j < 4; j++) {if (board[row][j] == num) {return 0; // 该行已有数字num,不合法}}// 检查3x3方格是否有重复数字for (i = 0; i < 3; i++) {for (j = 0; j < 3; j++) {if (board[row - i][col - j] == num) {return 0; // 该3x3方格已有数字num,不合法}}}return 1; // 该位置可以填充数字num,合法返回1,否则返回0。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
一.绪论
本课题的内容是解数独,数独作为一种经典的数字类游戏,具有很强的逻辑性和趣味性,效率高的解题方法对于程序算法的逻辑要求较高。
而试填入法方法简单,只是操作繁琐,但适合计算机进行。
我们小组采用的就是回溯法,利用栈和找出很明显的可唯一填入数使得运算更快一些,普通计算机解最难的17位数独题目一般不会超过5秒钟。
组内分工大致为:程序主体一起完成,另外一人负责文件导入的部分,一人负责美化,两人负责找唯一可填入数的部分。
二.数学模型
们采用的数独解决的方法是直接填入加上回溯法,而主要使用回溯法。
对整个算法来说,首先输入待求解的九宫格矩阵,空白位置用0表示。
然后定义一个AlterArr二维数组,原数独的每一个小九宫格对应新数组的每一行,将已有的数字的项替换成0。
接着进行直接填入部分,对原数独逐九宫格进行查找数据。
这部分首先检索新数组,当为非零项时,开始对数独中对应九宫格的空缺部位进行检验,当发现某个空位行与列不冲突时,计算该位置能填入数的个数,若唯一则直接填入,不回溯,并回到开头位置重新检索以防遗漏;若否,则判断下一位置。
当直接填入完成后若仍有未填的就进入回溯部分。
该部分准备工作一样,当进行到某个空位可以填入时,将此位置记录储存,用以回溯。
当之后赋值错误时,可以返回原始位置,将数字清零,并对下一位置进行赋值。
如此循环直至结束。
三.程序设计
确定了算法后,我们就开始程序的设计。
为了整个功能的实现,我们定义了许多函数来解决不同的部分。
ChangeAlter用来将新数组中已有位置的数变为零;Input函数导入题目;Count函数用来计算每一个能填数字的个数,若唯一返回0;反之返回1;CheckData函数雨来检查填入数字与每行每列数字是否重复,不重复返回0;ScanData函数用来检索新数组中需要填入的数及其位置;ScanPosition函数用来确定数据能够填入的位置;CheckEnd函数检查数独是否完成,完成就返回0。
对回溯算法,还要加入Push和Pop函数来进行数字位置的储存与释放。
整个程序就由这几个部分组合而成,通过if函数来对是否进行下一步做出判断。
同时,回溯用来储存位置的栈我们选用了结构体数组来实现;函数间参数的传值也通过指针来实现。
整个代码大致完成目标后,我们又加入了报错部分,分别使每个if判断后出现相应错误的提示,同时也对栈溢出的情况作了标示。
最后我们为整个代码添加注释,使其易懂,并进行不断的调试,完善程序。
四.撰写实现与调试
相比于上次的加密算法而言,这次我们的算法可以说是更上了一个层次,所以也变得更加复杂了。
所以我们选择采取分块的方式将其写为一个个函数,然后再在main函数中调用来完成这个高端的任务。
对于实现的方法,我们选择了回溯法这一粗暴有效的方式,这是根据计算机计算能力强这一特点,通过填入并在出错时返回的方法进行循环,以达到解决题目的目的。
我们撰写这个函数的一个优点就是网上有大量的资料可以参考,甚至还有许多学语言的同好者在网上可以进行现场的答疑,所以我们在写这个程序的时候就是是根据网上现有的一些函数,因此某个函数模块在调试过程中不会出现一个太大的问题,但是我们自己改进所加的函数就不同了,在第一次项目报告后,老师根据我们所将的内容提出了我们存在的不足和需要改进的点,而我们根据这个就在原有基础上增加一次填入过程,即当填入的数唯一时,跳过回溯步骤,减少运算时间。
添加了这个部分后,我们程序的运算也显得更有效率了。
相
比较原来的计算时间可以说有了一个质的飞跃。
五.程序结果的展示与分析
1、如下图所示首先是解一个简单的数独:
第一次填充就解开了:
所用时间大概不到一秒。
2、换一个更难的数独:
第一次填充:
最终结果:
这次用时较长,需半分钟左右。
虽然我们的算法是回溯法,原理简单而代码繁琐,但是由多次实验结果证明对于简单的数独第一次填充就会结束,而换用其它难度较大的数独的话填充次数可能会多几次,但是时间上不会延长太多,经过多次试验后我们可以大概确认时间的范围最长约为半分钟,绝大多数数独的解决时间在十秒以内,这说明了程序的性能良好。
但是,这是在数独有解的情况下,如果数独无解,程序会陷入死循环,最后自行结束,这是程序的缺陷之一。
以上实验结果的展示可以直观的说明程序的一些具体的优缺点。
六.总结与展望
第二次项目在短短的6个周内很顺利的完成了,有了第一次的磨合,这一次分工更加明确,效率更高,只用了一半的时间就完成了程序的大部分。
为了项目,每个人都学会了数独,一次次在草稿纸上涂改的方案,最终成为代码呈现在眼前,虽然经常熬夜到很晚,但看看最终的成果,这一切也都是值得的。
通过第二个任务的学习我们又学到了很多东西,包括对讲过知识的熟练应用和对未讲过知识的探索。
这次基本上实现了我们的预想,而且因为早早完成了任务,所以有时间去做一些原计划之外的部分,也使得我们小组在数独小组中独树一帜,这得益于每个小组成员的努力。
我们都对C语言的基本知识都做到了了然于胸,打好了基础,准备好了应对下学期的C++的新的挑战。