日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

数独九宫格

發布時間:2023/12/14 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数独九宫格 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

數獨九宮格游戲

一.題目說明?

數獨的游戲規則:

1、在9×9的大九宮格內,已給定若干數字,其他宮位留白,玩???? 家需要自己按照邏輯推敲出剩下的空格里是什么數字。
?? 2、必須滿足的條件:每一行與每一列都有1到9的數字,每個小??? 九宮格里也有1到9的數字,并且一個數字在每行、每列及每?? 個小九宮格里只能出現一次,既不能重復也不能少。
?? 3、每個數獨游戲都可根據給定的數字為線索,推算解答出來。

按照數獨的游戲規則,用計算機實現已知數獨的求解和數獨題目的出題。

二.數據結構說明

數據結構一維數組、二維數組以及類似于“棧”的數據結構。

主要操作有:進棧,出棧,棧頂元素的操作等等

三.抽象數據類型

五個全局變量數組,其中兩個二維數組,三個一維數組。

int a[10][10]

int sd[82]

int fix[82]

int possible[82][10]

int stack[82]

四.算法設計

程序可以考慮人工智能的算法。采用人機的游戲方式,這里采用“回溯”的方法解決數獨問題。

基本框架如下:

?

?圖片粘貼不了

?

?

五.數獨程序代碼:

?? #include"stdio.h" //標準輸入輸出頭文件

#include"conio.h" //包含getch()的頭文件

#include"stdlib.h" //包含rand()的頭文件

#include"assert.h" //包含assert()的頭文件

#include"time.h" //包含srand()的頭文件

int a[10][10];//用來接收輸入數據的數組

int sd[82];//處理題目以及保存最終結果

int fix[82];//記錄哪些位置是確定的,確定為1,否則為0

int possible[82][10];//記錄所有未確定數字的可能性

int stack[82];//用來放置填入的數的棧

int t;

void clssd()//初始化函數,所有位置設為0

{

?? int i,j,k;

?? for(i=0;i<9;i++)

????? for(j=0;j<9;j++)

???????? a[i][j]=0;

?? for(k=1;k<=81;k++)

????? sd[k]=0;

}

int line(int line,int value)//檢驗行

{

?? int i;

?? for(i=1;i<=9;i++)

?? {

????? if(a[line][i]==value) return 0;

?? }

?? return 1;

}

int row(int row,int value)//檢驗列

{

?? int i;

?? for(i=1;i<=9;i++)

?? {

????? if(a[i][row]==value) return 0;

?? }

?? return 1;

}

int square(int line,int row,int value)//檢驗3*3的九宮

{

?? int L,R,i,j;

?? L=(line%3!=0)+line/3;//L表示所在九宮的行數

?? R=(row%3!=0)+row/3;//R表示所在九宮的列數

?? for(i=(L-1)*3+1;i<=L*3;i++)

?? {

????? for(j=(R-1)*3+1;j<=R*3;j++)

???????? if(a[i][j]==value) return 0;

?? }

?? return 1;

}

?? int transform_to_line(int i)

?? {

????? int line;

????? line=i/9+(i%9!=0);

????? return line;

?? }

?? int transform_to_row(int i)

?? {

????? int row;

????? row=i%9+9*(i%9==0);

????? return row;

?? }

void transform_to_a(int i)

{

????? int l,r;

????? l=transform_to_line(i);

????? r=transform_to_row(i);

????? a[l][r]=sd[i];

}

void transform_to_sd()

{

?? int line,row,i=1;

??

?? for(line=1;line<=9;line++)

????? for(row=1;row<=9;row++)

???????? do

???????? {

??????????? sd[i]=a[line][row];

??????????? i++;???????

??????????? break;

???????? }while(i<=81);

?

}

//輸出函數

void printAll()

{

?? int i;

?? for(i=0;i<81;i++)

?? {?

????? if(i%9==0)

???????? printf("\n\n\t\t");

????? printf("%4d",sd[i+1]);

??

?? }

?? printf("\n\n\n");

}

void input()//輸入數據到a[10][10]

{

?? system("cls");//清屏

?? int b[3]={0,0,0},i,j;

?? printf("請輸入已知數據");

?? printf("\n\n例如輸入7 8 9,表示第8行 第9列的數值為7,以此類推。\n\n\n");

?? do

?? {???????

????? printf("\n輸入數據:按照 值 / 行 / 列的順序,以0結束");

????? for(i=0;i<3;i++)

????? {

???????? j=getch()-48;

???????? if(j==0&&i==0) break;//實現按0結束語句

???????? if(j>0&&j<10)

???????? {

??????????? b[i]=j;

??????????? printf("%3d",b[i]);

???????? }

???????? else i--;

????? }

????? a[b[1]][b[2]]=b[0];??

?? }while(j);?

?? transform_to_sd();

?? printf("\n\n\n\t您輸入的題目為:\n\n");//打印輸入的數獨

?? printAll();

}

//三個重要函數

bool beExist(int i,int j)//判斷 sd 數組中位置為 i 的元素是否存在

{

?? int l,r;

?? l=transform_to_line(i);

?? r=transform_to_row(i);

?? //if(sd[i]!=0) return 1; 關鍵的錯誤所在!!!?

?? if(line(l,j)*row(r,j)*square(l,r,j)==0) return 1;

?? else return 0;

}

void setPb()//控制possible數組

{

??

?? int i,j;

?? for(i=1;i<=81;i++)

?? {????

????? for(j=1;j<=9;j++)

????? {

???????? if(sd[i]!=0) possible[i][j]=-1;

???????? else if( beExist(i,j))

???????? {possible[i][j]=-1;}

???????? else

???????? {possible[i][j]=j;}

????? }

?? }

?

}

bool fixAll(int sd[],int fix[],int possible[82][10])//控制fix數組

{

?? int i,j;

?? int k[82];?

?? for(i=1;i<=81;i++)

?? {

????? if(sd[i]!=0)

????? {fix[i]=1;}

????? else

????? {fix[i]=0;}

?? }?

?? for(i=1;i<=81;i++)

?? {

????? if(sd[i]!=0) continue;

????? if(fix[i]==0)

????? {

???????? for(j=1;j<=9;j++)

???????? if(possible[i][j]!=-1)

??????????? k[i]++;

????? }

????? if(k[i]==1)//如果存在只有一種可能的位置則將fix[i]改為1

???????? fix[i]=1;

???????? sd[i]=possible[i][j];

?? }?

?? for(i=1;i<=81;i++)//判斷是否存在只有一種可能的位置,若沒有返回0

?? {

????? if(k[i]==1) return 1;

????? else return 0;

?? }

}

//判斷是否完成

int isFull(int sd[])

{

?? int i;

?? for(i=1;i<=81;i++)

????? if(sd[i]==0) return 0;??

?? return 1;

}

void preDo()//預處理

{

?? while(1)

?? {

????? setPb();

????? if(!fixAll(sd,fix,possible)) //即不存在只有一種可能性的位置

???????? break;

????? if(isFull(sd)) //若已經推出全部結果

???????? break;

?? }

?? if(isFull(sd))

????? printAll();//打印結果

?

}

int calculate()//填數獨 (關鍵算法!!!)

{

?? preDo();//預處理,找出所有的位置的可能數值

?? if(isFull(sd)) return 1;

?? int top=0;

?? //將所有為0的位置入棧

?? for(int i=1;i<82;i++)

?? {?

????? if(fix[i]==0)

???????? stack[top++]=i;

?? }

?? int max=top;//記錄最大數目加1

?? top=0;//指向棧頂

?? int temp;

?? bool flag=true;//該標志位說明了當前是正常入棧

?? while(1)

?? {

????? assert(top>=0);

????? if(flag)

????? {

???????? int j;

???????? for(j=1;j<=9;j++)

??????????? if(possible[stack[top]][j]!=-1&&!beExist(stack[top],j))

??????????? //若top所示的位置上,可以安插j這個數值,則

??????????? {

??????????????? fix[stack[top]]=1;

??????????????? sd[stack[top]]=j;

??????????????? transform_to_a(stack[top]);

??????????????? ++top;

??????????????? if(top>=max) return 1;

??????????????? break;

??????????? }

???????? if(j>9)//該空所有可能值都不可以,則退一格

???????? {

????????

??????????? --top;

??????????? if(top<0) {printAll(); return 0;}

??????????? flag=false;

???????? }

????? }????

????? else

????? {

???????? if(sd[stack[top]]==9)

???????? {

??????????? fix[stack[top]]=0;

??????????? sd[stack[top]]=0;

??????????? transform_to_a(stack[top]);

??????????? --top;

??????????? if(top<0) {printAll(); return 0;}

???????? }

???????? else

???????? {

??????????? temp=sd[stack[top]];????

??????????? temp++;

??????????? while(possible[stack[top]][temp]==-1||beExist(stack[top],temp))

??????????? {

??????????????? temp++;

??????????????? if(temp>9)

??????????????? break;

??????????? }

??????????? if(temp>9)//當前節點沒有更換的可能性,繼續退回

??????????? {

??????????????? fix[stack[top]]=0;

??????????????? sd[stack[top]]=0;

??????????????? transform_to_a(stack[top]);

??????????????? --top;

??????????????? if(top<0) {printAll(); return 0;}

??????????? }

??????????? else

??????????? {

??????????????? sd[stack[top]]=temp;

??????????????? transform_to_a(stack[top]);

??????????????? ++top;

??????????????? flag=true;

??????????? }

???????? }

?????

????? }

?? }

??

}

void solve_problem()//解題

{

?? int p;

?? system("cls"); //清屏

?? clssd(); //賦初值為0

?? input(); //輸入數據

?? transform_to_sd(); //轉換為sd[i]數組

?? p=calculate(); //計算數獨

?? if(p==0)

????? printf("\t題目有誤!!! ");

????? printf("\n\n\t答案為:\n");

?? printAll();

}?

void random()//從1-9中隨機產生幾個值輸入sd[1]至sd[9]

?? {?

????? int i,j,r;

????? int change=1;

????? int b[10]={0,0,0,0,0,0,0,0,0,0};

????? ?for(i=1;i<=9;)//從1-9中隨機產生幾個值

????? ?{?

???????? change=1;

???????? j=1+rand()%9;

???????? for(r=1;r<=9;r++)

???????? ?? if(b[r]==j) change=0;

???????? if(change==1)

???????? {b[i]=j;? i++;}

????? ?}

????? ?

????? ?for(i=1;i<=9;i++)

????? ?{

???????? sd[i]=b[i];

???????? transform_to_a(i);

????? ?}

?? }

void hide()

?? {

????? int i,f;

????? printf("請輸入難度:\n\n1.Easy\n\n2.Normal\n\n3.Hard\n\n4.So Hard\n\n5.Terrible Hard\n\n");

????? do

????? {

?? ????? f=getch()-48;

????? }while(f>5||f<1);//一共5個級別

??

????? for(i=1;i<=81;i++)

????? {?

???????? if(rand()%6>=f)//利用隨機數出現的概率出題

???????? printf("%4d",sd[i]);

???????? else

??????????? printf("?? 0");

???????? if(i%9==0)

??????????? printf("\n\n");

????? }

?? }

void make_problem()//出題函數

{?

?? system("cls");//初始化

?? clssd();

?? random();//填9個隨機值

?? calculate();//算出答案

?? hide();

?? printf("\t\t\t注意:題目中0代表待填數據\n\n\t\t?? 按空格鍵輸出答案,其他鍵退出程序\n");

?? int f;

?? do

?? {

????? f=getch()-32;

????? if(!f)

???????? printAll();

????? else break;

?? }while(f);

}

void quit()

{

int i;

for(i=0;i<100;i++)

{

?printf("%d\n",i);

?if (i>2||i<1)

?{

? exit(1);

?}

}

}

void main()//主函數

{

?? srand((unsigned)time(0));//設置時間種子為0

?? system("cls");//清屏

?? clssd();

?? printf("\n\t數獨游戲\n\n\t1.你出題,電腦來解\n\n\t2.電腦出題,你來解\n\n\t3.退出游戲");

?? int i;

?? do

?? {

????? i=getch()-48;

????? switch(i)

????? {

????? case 1:solve_problem();

???????? break;

????? case 2:make_problem();

???????? break;

????? case 3:quit();

???????? break;

????? }

?? }while(i>2||i<1);

}

六.調試報告

1.整個程序最麻煩的地方是二維數組a[10][10]與一 維數組sd[82]之間的轉換。因為輸入數據為了方便 和符合人類的思維采用了與數獨相似的二維數組?? 進行輸入。但是回溯算法要求轉換成一維數組進行? 操作。

2.調試過程中,用到了一個宏命令assert(top>=0)? top是棧頂元素的“指針”,用來操控棧中元素。正? 常情況下top>=0的。如果出現異常情況,則assert 函數會彈出對話框報錯。這表示calculate函數在 回溯的時候top值總是會回到棧底元素之前。事實? 上,開始因為在beExist()函數中用了錯誤的判斷 方 式,運行程序時總是會使得top<0。

3.上一條中的錯誤之所以會出現,是因為在設計程序 之初沒有想好,不夠完善。于是出現了,自己設計 的判斷方法與計算數獨矛盾的結果。得到的教訓?? 是,動手之前應該先考慮清楚完整的架構和應該考 慮到的細節.

?

七.測試結果分析

下面為規定測試數據:

?圖片粘貼不了

?

?

?

?

?

?

?

?

?

?

?

?

?

轉載于:https://www.cnblogs.com/wanghongcai/p/4839090.html

總結

以上是生活随笔為你收集整理的数独九宫格的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。