數獨游戲代碼


//數獨游戲c++
class CSudoku 
{ 
int map[9][9]; 
int blanks; 
int smod; 
int solves; 
int check(int,int,int*); 
void dfs(); 

public: 
enum{ANY=0,ALL=1}; 
CSudoku(int); 
CSudoku::CSudoku(int *data); 
void SudokuGenerator(int); //隨機生成數獨,n越大越難
void SudokuGenerator(int *data);//人工指定數獨
//virtual ~CSudoku(); 
void display();//顯示數獨
int resolve(int mod=ALL);//解數獨
void analyze(); 
}; 
#include "stdio.h" 
#include "stdlib.h"  
#include "time.h" 
#include "iostream"  
#include "iomanip" //要用到格式控制符

using namespace std;

 CSudoku::CSudoku(int n){
int j; 
j=rand()%3; 
blanks=n+j; 
SudokuGenerator(blanks);  
cout<<endl<<"隨機數獨:  --->(Y軸)[x,y坐標均從0開始]"<<endl;
cout<<endl<<"填數請按Enter鍵,按指示操作"<<endl;
//cout<<(空格子數為"<<blanks<<")"<<endl; 
display(); 
cout<<"press enter to continue! "<<endl; 
getchar(); 
getchar(); 
while(1){ 
cout<<"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "<<endl; 
cout<<"%%請選擇您的操作:%% "<<endl; 
cout<<"%%============================%% "<<endl;
cout<<"%%%% "<<endl; 
cout<<"%%1.顯示當前數獨%% "<<endl; 
cout<<"%%2.分析求解%% "<<endl; 
cout<<"%%3. 查看結果%% "<<endl; 
cout<<"%%4.返回%% "<<endl; 
cout<<"%%%% "<<endl; 
cout<<"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "<<endl; 
int select; 
cin>>select; 
switch (select){ 
case 1:{ 
    cout<<endl<<"當前隨機數獨: "<<endl; 
    display(); 
    cout<<"press enter to continue! "<<endl; 
    getchar(); 
    getchar(); 
    break; 
} 
case 2:{ 
    analyze(); 
    break; 
} 
case 3:{ 
    cout<<endl<<"顯示結果: "<<endl; 
    resolve(); 
    cout<<"press enter to continue! "<<endl<<endl;
    getchar(); 
    getchar(); 
    break; 
}  
case 4: return; 
    default:{ 
    cout<<"輸入錯誤,請重新輸入."<<endl; 
    break; 
} 
} 
    } 
} 


 CSudoku::CSudoku(int *data){ 
    SudokuGenerator(data); 
    cout<<endl<<"已知數獨為: "<<endl; 
    display(); 
    cout<<"press enter to continue! "<<endl; 
    getchar(); 
    getchar(); 
    analyze(); 
} 


void CSudoku::SudokuGenerator(int n){
    int i,j; 
    int mark[10]; 
    srand(time(0)); 
    //每一行i產生一個隨機位置(列j)並置為當前行值i+1,0=<i,j<=8。
    do{
    for(i=0;i<9;++i){
        for(j=0;j<9;++j) 
        map[i][j]=0; 
        j=rand()%9; 
        map[i][j]=i+1; 
     } 
    //display(); 
    } 
    while(!resolve(ANY));//生成完整的隨機Sudoku表格
//挖窟窿
for(int k=0;k<n;++k){
int tmp,flag=0,sum=1; 
do{ 
//cout<<"sum="<<sum<<endl; 
if (sum++>81){ 
    SudokuGenerator(n); 
    return; 
} 
if (flag==1) 
    map[i][j]=tmp; 
do{
    i=rand()%81; 
    j=i%9; 
    i=i/9; 
}  
    while (map[i][j]==0); 
    tmp=map[i][j]; 
    map[i][j]=0; 
    flag=1; 
} 
    while(check(i,j,mark)>1); 
    } 
} 


void CSudoku::SudokuGenerator(int *data){ 
    int *pm=(int*)map; 
    for(int i=0;i<81;++i)
    pm[i]=data[i]; 
} 


void CSudoku::display(){ 
    int count=0;
    printf("┏━┯━┯━┳━┯━┯━┳━┯━┯━┓\n");//最開始的一行

for(int i=0;i<9;++i){
    for(int j=0;j<9;++j){ 
    if(j%3==0){
        printf("");//先輸出加粗制表符
        printf(" ");
        if(map[i][j]>0){
            printf("%d",map[i][j]);
        }
        else{
            printf(" ");
        }
        //printf(" ");//把光標移到下一個格子對應的起始位置
        //printf(" ");
    }
    else{
        printf("");//先輸出正常制表符
        printf(" ");
        if(map[i][j]>0){
            printf("%d",map[i][j]);
        }
        else{
            printf(" ");
        }
        //printf(" ");//把光標移到下一個格子對應的起始位置
        //printf(" ");
    }
    if(j==8){
        printf("");//一行中最后一個粗黑色制表符
    }
} 
    
    //一行輸出完成
    if(i!=8){
    if((i+1)%3==0){
       printf("\n");
       printf("┣━┿━┿━╋━┿━┿━╋━┿━┿━┫\n");  
    }
    else{
    printf("\n");
    printf("┠─┼─┼─╂─┼─┼─╂─┼─┼─┨\n"); 
    }
} 
    if(i==8){
        printf("\n");
        printf("┗━┷━┷━┻━┷━┷━┻━┷━┷━┛\n"); //最后一行
    }
}    
} 

int CSudoku::resolve(int mod){
smod=mod; 
if(mod==ALL){
    solves=0; 
    dfs();  
    return solves; 
}
else if(mod==ANY){
    try 
    {
    dfs(); 
    return 0; 
} 
    catch(int){
    return 1; 
    } 
}
    return 0;
} 

int CSudoku::check(int y,int x,int *mark){
    int i,j,is,js,count=0; 
    for(i=1;i<=9;++i) 
    mark[i]=0; 
  for(i=0;i<9;++i) 
  mark[map[y][i]]=1; 
  for(i=0;i<9;++i) 
  mark[map[i][x]]=1; 
  is=y/3*3; 
  js=x/3*3; 
  for(i=0;i<3;++i){
  for(j=0;j<3;++j)
     mark[map[is+i][js+j]]=1; 
} 
  for(i=1;i<=9;++i) 
 if(mark[i]==0) 
  count++; 
  return count; 
} 

void CSudoku::dfs(){
    int i,j,im=-1,jm,min=10; 
    int mark[10]; 
// display(); 
//求自由度最小的格map[im][jm] 
for(i=0;i<9;++i){ 
    for(j=0;j<9;++j){
    if(map[i][j]) 
//如果此格已填入數則看一下格。
    continue; 
    int c=check(i,j,mark); //如果此格空,則求其自由度。
    if(c==0)//已到結尾,沒有空格了。
    return; 
    if(c<min){
        im=i;
        jm=j; 
        min=c; 
    } 
    } 
} 
if(im==-1)//若im=-1,則格子都填滿。
{
if(smod==ALL)//smod==ALL是求解過程。
{
//printf("No. %d:\n",++solves); 
    display();  
    return; 
}
else if(smod==ANY) //smod==ANY是初始化過程。
{
    throw(1); 
} 
} 
check(im,jm,mark); 
for(i=1;i<=9;++i){ 
    if(mark[i]==0) 
{ 
    map[im][jm]=i;//從小到大讓第一個可填的數填入自由度最小的格。
    dfs(); 
} 
}
    map[im][jm]=0; 
    return; 
} 

void CSudoku::analyze(){
    while(1){ 
    cout<<"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "<<endl; 
    cout<<"%%請問你想做什么?%% "<<endl; 
    cout<<"%%============================%% "<<endl;
    cout<<"%%%% "<<endl; 
    cout<<"%%1.查找最小不確定度的格子%% "<<endl; 
    cout<<"%%2.指定格子的可填數%% "<<endl; 
    cout<<"%%3.給指定格子填數%% "<<endl; 
    cout<<"%%4.顯示當前數獨%% "<<endl; 
    cout<<"%%5.查看結果%% "<<endl; 
    cout<<"%%6.返回%% "<<endl; 
    cout<<"%%%% "<<endl; 
    cout<<"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "<<endl; 
    int select; 
    cin>>select; 
    switch(select){
    case 1://求不確定度最小的空格map[im][jm] 
  {
    int i,j,im=-1,jm,min=10; 
    int mark[10]; 
    for(i=0;i<9;++i)  
    { 
    for(j=0;j<9;++j) 
    {
        if(map[i][j]) //如果此格已填入數則看一下格。
        continue; 
        int c=check(i,j,mark); //如果此格空,則求其不確定度。
        if(c==0) 
        { 
        cout<<"不能得到結果或已無空格子!自動返回! "<<endl; 
        return; 
        } 
    if(c<min) 
    {
    im=i; 
    jm=j; 
    min=c; 
    }
    } 
}
    cout<<endl<<"不確定度最小的格子為:["<<im<<","<<jm<<"]"<<"其可填的數的個數為:"<<min<<endl<<endl; 
    cout<<"press enter to continue! "<<endl; 
    getchar(); 
    getchar(); 
    break; 
} 

    case 2:{
    int x,y; 
    int mark[10]; 
    cout<<endl<<"請輸入格子位置(如[2,4],則輸入:2 4,中間用空格.): [x,y]=";
    cin>>x>>y; 
    getchar(); 
while (map[x][y]!=0){
    cout<<endl<<"警告:此格已經有數!請重新輸入."<<endl<<endl; 
    cout<<"請重新輸入格子位置(如[2,4],則輸入:2 4,中間用空格.): [x,y]="; 
    cin>>x>>y; 
    getchar(); 
} 
    int i,j,is,js,count=0; 
    for(i=1;i<=9;++i) 
    mark[i]=0; 
    for(i=0;i<9;++i) 
    mark[map[x][i]]=1; 
    for(i=0;i<9;++i) 
    mark[map[i][y]]=1; 
    is=x/3*3; 
    js=y/3*3; 
    for(i=0;i<3;++i) 
    { 
    for(j=0;j<3;++j) 
    mark[map[is+i][js+j]]=1; 
    } 
    cout<<endl<<"此格可填數為:"; 
    for(i=1;i<=9;++i) 
if(mark[i]==0) {
    count++; 
    cout<<setw(4)<<i;  
}
cout<<endl; 
cout<<"press enter to continue! "<<endl; 
getchar(); 
break; 
} 

case 3:{
int x,y; 
cout<<endl<<"請輸入您要填格子的位置(如[2,4],則輸入:2 4,中間用空格.): [x,y]="; 
cin>>x>>y; 
cout<<"請輸入要填入的數: "; 
cin>>map[x][y]; 
cout<<"您填入的格為: map["<<x<<","<<y<<"]="<<map[x][y]<<endl; 
cout<<"press enter to continue! "<<endl; 
getchar(); 
getchar(); 
break; 
} 

case 4:{ 
cout<<endl<<"當前隨機數獨: "<<endl; 
display(); 
cout<<"press enter to continue! "<<endl; 
getchar(); 
getchar(); 
break; 
} 

case 5:{ 
cout<<endl<<"顯示結果: "<<endl; 
resolve();//沒有輸入參數,則默認為smod==ALL,見程序開始函數聲明。
cout<<"press enter to continue! "<<endl<<endl;
getchar(); 
getchar(); 
break; 
} 
case 6:
    return; 
        default:{ 
            cout<<"輸入錯誤,請重新輸入."<<endl; 
            break; 
            } 
      } 
  } 
}

//main函數
void main(){ 
  int blanks; 
  while(1){
  bool exit_f=true; 
  cout<<endl; 
  cout<<"%%%%%%%%%%%%%%%%%%%%%%%%% "<<endl; 
  cout<<"%%SUDOKU游戲%% "<<endl; 
  cout<<"%%白鶴制作%% "<<endl;  
  cout<<"%%=====================%% "<<endl; 
  cout<<"%%1.新游戲%% "<<endl; 
  cout<<"%%2.退出%% "<<endl;  
  cout<<"%%%%%%%%%%%%%%%%%%%%%%%%% "<<endl; 
  int select; 
  cin>>select; 

switch (select){  
 case 1: //開始新游戲
 {
  while(exit_f) 
 { 
    cout<<"%%%%%%%%%%%%%%%%%%%%%%%%% "<<endl; 
    cout<<"%%請選擇游戲難度%% "<<endl; 
    cout<<"%%=====================%% "<<endl; 
    cout<<"%%%% "<<endl; 
    cout<<"%%1.簡單%% "<<endl; 
    cout<<"%%2.中等%% "<<endl; 
    cout<<"%%3.困難%% "<<endl; 
    cout<<"%%4.返回%% "<<endl; 
    cout<<"%%%% "<<endl; 
    cout<<"%%%%%%%%%%%%%%%%%%%%%%%%% "<<endl; 
/* 
cout<<endl<<"請選擇游戲難度: "<<endl; 
cout<<"======================= "<<endl; 
cout<<"1.簡單"<<endl; 
cout<<"2.中等"<<endl; 
cout<<"3.困難"<<endl;  
cout<<"4. 解一個已知數獨"<<endl; 
cout<<"5. 退出"<<endl;  cout<<"======================= "<<endl<<endl;*/
    int level; 
    cin>>level; 
    switch(level){  
    case 1:{ 
    blanks=33; 
    CSudoku s(blanks); 
    break; 
  } 
case 2:{ 
    blanks=36; 
    CSudoku s(blanks); 
    break; 
} 
case 3:{ 
    blanks=39; 
    CSudoku s(blanks); 
    break; 
} 
case 4:{ 
    exit_f=false; 
    break; 
} 
default: {
    cout<<"輸入錯誤,請重新輸入."<<endl<<endl; 
    break; 
} 
} 
} 
    break; 
}
case 2: return; 
    default: {
    cout<<"輸入有誤,請重新選擇!"<<endl; 
    break; 
} 
}  
}
}  

 

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM