数独的生成

  1. #include <IOSTREAM>  
  2. #include <CTIME>  
  3. using namespace std;  
  4.   
  5. int sudo[9][9], hole[9][9];  
  6.   
  7. bool set(int x, int y, int val)  
  8. {  
  9.     if (sudo[y][x] != 0)        //非空  
  10.         return false;  
  11.     int x0, y0;  
  12.     for (x0=0; x0<9; x0++)  
  13.     {  
  14.         if (sudo[y][x0] == val) //行冲突  
  15.             return false;  
  16.     }  
  17.     for (y0=0; y0<9; y0++)  
  18.     {  
  19.         if (sudo[y0][x] == val) //列冲突  
  20.             return false;  
  21.     }  
  22.     for (y0=y/3*3; y0<y/3*3+3; y0++)  
  23.     {  
  24.         for (x0=x/3*3; x0<x/3*3+3; x0++)  
  25.         {  
  26.             if (sudo[y0][x0] == val) //格冲突  
  27.                 return false;  
  28.         }  
  29.     }  
  30.     sudo[y][x] = val;  
  31.     return true;  
  32. }  
  33.   
  34. void reset(int x, int y)  
  35. {  
  36.     sudo[y][x] = 0;  
  37. }  
  38.   
  39. void initXOrd(int* xOrd)    //0~9随机序列  
  40. {  
  41.     int i, k, tmp;  
  42.     for (i=0; i<9; i++)  
  43.     {  
  44.         xOrd[i] = i;  
  45.     }  
  46.     for (i=0; i<9; i++)  
  47.     {  
  48.         k = rand() % 9;  
  49.         tmp = xOrd[k];  
  50.         xOrd[k] = xOrd[i];  
  51.         xOrd[i] = tmp;  
  52.     }  
  53. }  
  54.   
  55. bool fillFrom(int y, int val)  
  56. {  
  57.     int xOrd[9];  
  58.     initXOrd(xOrd);     //生成当前行的扫描序列  
  59.     for (int i=0; i<9; i++)  
  60.     {  
  61.         int x = xOrd[i];  
  62.         if (set(x, y, val))  
  63.         {  
  64.             if (y == 8)                 //到了最后一行  
  65.             {  
  66.                 if (val == 9 || fillFrom(0, val+1)) //当前填9则结束, 否则从第一行填下一个数  
  67.                     return true;  
  68.             }   
  69.             else  
  70.             {  
  71.                 if (fillFrom(y+1, val)) //下一行继续填当前数  
  72.                     return true;  
  73.             }  
  74.             reset(x, y);    //回溯  
  75.         }  
  76.     }  
  77.     return false;  
  78. }  
  79.   
  80. void digHole(int holeCnt)  
  81. {  
  82.     int idx[81];  
  83.     int i, k;  
  84.     for (i=0; i<81; i++)  
  85.     {  
  86.         hole[i / 9][i % 9] = 0;  
  87.         idx[i] = i;  
  88.     }  
  89.     for (i=0; i<holeCnt; i++)    //随机挖洞位置  
  90.     {  
  91.         k = rand() % 81;  
  92.         int tmp = idx[k];  
  93.         idx[k] = idx[i];  
  94.         idx[i] = tmp;  
  95.     }  
  96.     for (i=0; i<holeCnt; i++)  
  97.     {  
  98.         hole[idx[i] / 9][idx[i] % 9] = 1;  
  99.     }  
  100. }  
  101.   
  102. void printSudo()  
  103. {  
  104.     for (int y=0; y<9; y++)  
  105.     {  
  106.         (y % 3 == 0) ? (cout << "------------------------\n ") : (cout << " ");  
  107.         for (int x=0; x<9; x++)  
  108.         {  
  109.             (hole[y][x] == 0) ? (cout << sudo[y][x] << " ") : (cout << "  ");  
  110.             (x % 3 == 2) ? (cout << "| ") : (cout << "");  
  111.         }  
  112.         cout << endl;  
  113.     }  
  114.     cout << "------------------------\n";  
  115. }  
  116.   
  117. int main(int argc, char* argv[])  
  118. {     
  119.     srand((unsigned)time(NULL));  
  120.     while (!fillFrom(0, 1)) ;  
  121.     digHole(35);  
  122.     printSudo();  
  123.     return 0;  
  124. }  

转载于:https://www.cnblogs.com/cyl940518/p/8409294.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值