鱼C论坛

 找回密码
 立即注册
查看: 3076|回复: 2

[技术交流] 这是我的数独程序,可惜不会图形界面

[复制链接]
发表于 2014-6-28 01:03:31 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 andalousie 于 2014-7-9 12:36 编辑

这个是我们程序与算法综合课程设计的一道题。叫做数独游戏。
源代码
  1. #include <iostream>
  2. #include <fstream>
  3. #include <cstdlib>
  4. #include <ctime>
  5. #include <algorithm>

  6. typedef unsigned bitfield;

  7. static const bitfield maskMax = 512;
  8. static const bitfield allSet = 511;

  9. enum difficulty { EASY, MEDIUM, DIFFICULT, EVIL, DEFAULT };

  10. // Returns the size of the set
  11. static unsigned bitCount(bitfield bits)
  12. {
  13.     unsigned result = 0;
  14.     bitfield mask = 1;

  15.     while(mask != maskMax)
  16.     {
  17.         if (bits & mask)
  18.             result++;
  19.         mask *= 2;
  20.     }

  21.     return result;
  22. }

  23. // Returns a bitfield representing {num}
  24. static inline bitfield bitFor(unsigned num)
  25. {
  26.     return 1 << (num - 1);
  27. }

  28. class BlankList
  29. {
  30. public:
  31.     BlankList()
  32.     {
  33.         for (unsigned i = 0; i < 9; ++i)
  34.             rows[i] = cols[i] = allSet;
  35.         for (unsigned i = 0; i < 3; ++i)
  36.             for (unsigned j = 0; j < 3; ++j)
  37.                 blocks[i][j] = allSet;
  38.     }

  39.     void elim(unsigned i, unsigned j, unsigned n)
  40.     {
  41.         bitfield bit = bitFor(n);
  42.         rows[i] &= ~bit;
  43.         cols[j] &= ~bit;
  44.         blocks[i/3][j/3] &= ~bit;
  45.     }

  46.     void cancel(unsigned i, unsigned j, unsigned n)
  47.     {
  48.         bitfield bit = bitFor(n);
  49.         rows[i] |= bit;
  50.         cols[j] |= bit;
  51.         blocks[i/3][j/3] |= bit;
  52.     }

  53.     bitfield possible(unsigned i, unsigned j)
  54.     {
  55.         return rows[i] & cols[j] & blocks[i/3][j/3];
  56.     }
  57. private:
  58.     bitfield rows[9], cols[9];
  59.     bitfield blocks[3][3];
  60. };

  61. class Board
  62. {
  63. public:
  64.     Board()
  65.     {
  66.         for (unsigned i = 0; i < 9; ++i)
  67.             for (unsigned j = 0; j < 9; ++j)
  68.                 matrix[i][j] = 0;
  69.     }
  70.     Board(unsigned seed)
  71.     {
  72.         for (unsigned i = 0; i < 9; ++i)
  73.             for (unsigned j = 0; j < 9; ++j)
  74.                 matrix[i][j] = 0;

  75.         std::srand(seed);
  76.         _random_fill();
  77.     }
  78.     void set(unsigned row, unsigned col, unsigned val)
  79.     {
  80.         matrix[row][col] = val;
  81.         if (matrix[row][col])
  82.             Blank.elim(row, col, val);
  83.     }
  84.     unsigned unset(unsigned row, unsigned col)
  85.     {
  86.         unsigned val = matrix[row][col];
  87.         if (val)
  88.             Blank.cancel(row, col, val);
  89.         matrix[row][col] = 0;
  90.         return val;
  91.     }
  92.     bitfield mask_check(unsigned i, unsigned j, bitfield mask)
  93.     {
  94.         return Blank.possible(i, j) & mask;
  95.     }
  96.     bitfield house_check(bitfield possible, unsigned i, unsigned j)
  97.     {
  98.         unsigned row_base = i / 3 * 3;
  99.         unsigned col_base = j / 3 * 3;
  100.         for (unsigned row = row_base; row < row_base + 3; ++row)
  101.             for (unsigned col = col_base; col < col_base + 3; ++col)
  102.             {
  103.                 if ((row == i && col == j) || matrix[row][col])
  104.                     continue;
  105.                 possible &= ~Blank.possible(row, col);
  106.             }
  107.         return possible;
  108.     }
  109.     bitfield rl_check(bitfield tricky, unsigned i, unsigned j)
  110.     {
  111.         bitfield row_hidden = allSet;
  112.         bitfield col_hidden = allSet;
  113.         for (unsigned row = 0; row < 9; ++row)
  114.             if (!matrix[row][j] && row != i)
  115.                 col_hidden &= ~Blank.possible(row, j);
  116.         for (unsigned col = 0; col < 9; ++col)
  117.             if (!matrix[i][col] && col != j)
  118.                 row_hidden &= ~Blank.possible(i, col);
  119.         return tricky & (row_hidden | col_hidden);
  120.     }
  121.     void hidden_fill()
  122.     {
  123.         bool again;
  124.         do
  125.         {
  126.             again = false;
  127.             for (unsigned i = 0; i < 9; ++i)
  128.             {
  129.                 for (unsigned j = 0; j < 9; ++j)
  130.                 {
  131.                     if (matrix[i][j]) continue;
  132.                     bitfield possible = Blank.possible(i, j);
  133.                     if (bitCount(possible) == 1)
  134.                     {
  135.                         set(i, j, numFor(possible));
  136.                         again = true;
  137.                         continue;
  138.                     }
  139.                     bitfield tricky = house_check(possible, i, j);
  140.                     if (bitCount(tricky) == 1)
  141.                     {
  142.                         set(i, j, numFor(tricky));
  143.                         again = true;
  144.                         continue;
  145.                     }
  146.                     tricky = rl_check(tricky, i, j);
  147.                     if (bitCount(tricky) == 1)
  148.                     {
  149.                         set(i, j, numFor(tricky));
  150.                         again = true;
  151.                         continue;
  152.                     }
  153.                 }
  154.             }
  155.         }
  156.         while (again);
  157.     }
  158.     unsigned remaining()
  159.     {
  160.         unsigned count = 0;
  161.         for (unsigned i = 0; i < 9; ++i)
  162.             for (unsigned j = 0; j < 9; ++j)
  163.                 if (!matrix[i][j])
  164.                     ++count;
  165.         return count;
  166.     }
  167.     bool findMin(unsigned& row, unsigned& col)
  168.     {
  169.         bool found = false;
  170.         unsigned count = 10;

  171.         for (unsigned i = 0; i < 9; ++i)
  172.             for (unsigned j = 0; j < 9; ++j)
  173.             {
  174.                 if (!matrix[i][j] &&
  175.                         bitCount(Blank.possible(i, j)) < count)
  176.                 {
  177.                     count = bitCount(Blank.possible(i, j));
  178.                     row = i;
  179.                     col = j;
  180.                     found = true;
  181.                 }
  182.             }
  183.         return found;
  184.     }
  185.     bool backtrack(unsigned depth)
  186.     {
  187.         unsigned row, col;
  188.         if (!findMin(row, col))
  189.             if (!depth)
  190.                 return true;
  191.             else
  192.                 return false;

  193.         // Iterate through the possible values this cell could have
  194.         unsigned num = 1;
  195.         bitfield mask = bitFor(num);
  196.         while (mask != maskMax)
  197.         {
  198.             if (mask_check(row, col, mask))
  199.             {
  200.                 set(row, col, num);
  201.                 if (backtrack(depth-1))
  202.                     return true;
  203.                 unset(row, col);
  204.             }

  205.             // Advance to the next number
  206.             mask *= 2;
  207.             num++;
  208.         }
  209.         return false;
  210.     }
  211.     unsigned value(unsigned i, unsigned j)
  212.     {
  213.         return matrix[i][j];
  214.     }
  215.     bool assert(unsigned i, unsigned j, unsigned val)
  216.     {
  217.         return matrix[i][j] == val;
  218.     }
  219.     void print_board(std::ostream & out)
  220.     {
  221.         for (unsigned i = 0; i < 9; ++i)
  222.         {
  223.             for (unsigned j = 0; j < 9; ++j)
  224.             {
  225.                 out << matrix[i][j] << " ";
  226.             }
  227.             out << std::endl;
  228.         }
  229.     }
  230. private:
  231.     unsigned matrix[9][9];
  232.     BlankList Blank;

  233.     static unsigned numFor(bitfield bit)
  234.     {
  235.         unsigned num = 0;
  236.         while (bit)
  237.         {
  238.             bit >>= 1;
  239.             ++num;
  240.         }
  241.         return num;
  242.     }
  243.     bool _fill(bool is_big, unsigned place,
  244.                unsigned num, bitfield usable = allSet)
  245.     {
  246.         if (is_big)
  247.         {
  248.             if (num == 10)
  249.                 return true;
  250.             if (place == 9)
  251.                 return _fill(is_big, 0, num + 1);
  252.         }
  253.         if (place == 9)
  254.             return true;
  255.         static unsigned look_up[] =
  256.         {
  257.             0,  1,  2,
  258.             9,  10, 11,
  259.             18, 19, 20
  260.         };
  261.         static unsigned base[] =
  262.         {
  263.             0,  3,  6,
  264.             27, 30, 33,
  265.             54, 57, 60
  266.         };
  267.         unsigned block;
  268.         bitfield usable_blocks = allSet;
  269.         while (usable_blocks)
  270.         {
  271.             while (true)
  272.             {
  273.                 block = std::rand() % 9;
  274.                 if (usable_blocks & bitFor(block + 1))
  275.                     break;
  276.             }
  277.             usable_blocks &= ~bitFor(block + 1);
  278.             if (bitFor(block + 1) & usable)
  279.             {
  280.                 unsigned loc = base[block] + look_up[place];
  281.                 unsigned row = loc / 9, col = loc % 9;
  282.                 if (!matrix[row][col] &&
  283.                         (bitFor(num) & Blank.possible(row, col)))
  284.                 {
  285.                     set(row, col, num);
  286.                     usable &= ~bitFor(block + 1);
  287.                     if (_fill(is_big, place + 1, num, usable))
  288.                         return true;
  289.                     unset(row, col);
  290.                     usable |= bitFor(block + 1);
  291.                 }
  292.             }
  293.         }
  294.         return false;
  295.     }

  296.     void _random_fill()
  297.     {
  298.         for (unsigned i = 1; i <= 4; ++i)
  299.             _fill(false, 0, i);
  300.         while (true)
  301.             if (_fill(true, 0, 5))
  302.                 break;
  303.     }
  304. };

  305. class Holes
  306. {
  307. public:
  308.     Holes(Board & board)
  309.         : puzzle(board)
  310.     {}
  311.     void digHoles(difficulty level)
  312.     {
  313.         static unsigned look_up[] =
  314.         {
  315.             0,  1,  2,
  316.             9,  10, 11,
  317.             18, 19, 20
  318.         };
  319.         static unsigned base[] =
  320.         {
  321.             0,  3,  6,
  322.             27, 30, 33,
  323.             54, 57, 60
  324.         };
  325.         for (unsigned i = 0; i < 9; ++i)
  326.         {
  327.             unsigned array[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
  328.             unsigned diff = _random_by_level(level);
  329.             std::random_shuffle(array, array + 9);
  330.             for (unsigned j = 0; j < diff; ++j)
  331.             {
  332.                 unsigned loc = base[i] + look_up[array[j]];
  333.                 unsigned row = loc / 9, col = loc % 9;
  334.                 _valid_dig(row, col, level);
  335.             }
  336.         }
  337.     }
  338.     Board& to_play()
  339.     {
  340.         return puzzle;
  341.     }
  342. private:
  343.     Board puzzle;

  344.     unsigned _random_by_level(difficulty level)
  345.     {
  346.         unsigned random = 5;

  347.         switch (level)
  348.         {
  349.         case EASY:
  350.             random = std::rand() % 2 + 4;
  351.             break;
  352.         case MEDIUM:
  353.             random = std::rand() % 3 + 5;
  354.             break;
  355.         case DIFFICULT:
  356.             random = std::rand() % 4 + 5;
  357.         case EVIL:
  358.             random = std::rand() % 4 + 6;
  359.             break;
  360.         default:
  361.             break;
  362.         }
  363.         return random;
  364.     }

  365.     void _valid_dig(unsigned i, unsigned j, difficulty level)
  366.     {
  367.         unsigned val = puzzle.unset(i, j);
  368.         for (unsigned num = 1; num <= 9; ++num)
  369.         {
  370.             if (num != val &&
  371.                     puzzle.mask_check(i, j, bitFor(num)))
  372.             {
  373.                 Board bd = puzzle;
  374.                 bd.set(i, j, num);
  375.                 bd.hidden_fill();
  376.                 if (bd.backtrack(bd.remaining()))
  377.                 {
  378.                     puzzle.set(i, j, val);
  379.                     return;
  380.                 }
  381.             }
  382.         }
  383.     }
  384. };

  385. class Sudoku
  386. {
  387. public:
  388.     Sudoku(const char * name, bool play = false)
  389.         : in(name)
  390.     {
  391.         unsigned num = 0;
  392.         for (unsigned i = 0; i < 9; ++i)
  393.         {
  394.             for (unsigned j = 0; j < 9; ++j)
  395.             {
  396.                 in >> num;
  397.                 _board.set(i, j, num);
  398.             }
  399.         }
  400.         _board.print_board(std::cout);
  401.         _answer = _board;
  402.         if (_solve())
  403.         {
  404.             if (!play)
  405.             {
  406.                 std::cout << "The answer is:" << std::endl;
  407.                 _answer.print_board(std::cout);
  408.             }
  409.         }
  410.         else
  411.             std::cout << "The sudoku is not solvable!" << std::endl;
  412.     }
  413.     Sudoku(difficulty level, std::ostream & out)
  414.     {
  415.         generate(level, out);
  416.     }
  417.     void generate(difficulty level, std::ostream & out)
  418.     {
  419.         _answer = Board(static_cast<unsigned>(std::time(0)));
  420.         Holes game(_answer);
  421.         game.digHoles(level);
  422.         _board = game.to_play();
  423.         _board.print_board(out);
  424.     }
  425.     void play(unsigned& row, unsigned& col, unsigned& val)
  426.     {
  427.         if (_board.mask_check(row, col, bitFor(val)))
  428.             if (_answer.assert(row, col, val))
  429.             {
  430.                 _board.set(row, col, val);
  431.                 system("cls");
  432.                 _board.print_board(std::cout);
  433.             }
  434.             else
  435.                 std::cout << "You've chosen the wrong number.\n";
  436.         else
  437.             std::cout << "Your play violated the rules.\n";
  438.     }
  439.     bool is_complete()
  440.     {
  441.         for (unsigned i = 0; i < 9; ++i)
  442.             for (unsigned j = 0; j < 9; ++j)
  443.                 if (!_answer.assert(i, j, _board.value(i, j)))
  444.                     return false;
  445.         return true;
  446.     }
  447. private:
  448.     std::ifstream in;
  449.     Board _board;
  450.     Board _answer;

  451.     bool _solve()
  452.     {
  453.         _answer.hidden_fill();
  454.         if (_answer.backtrack(_answer.remaining()))
  455.             return true;
  456.         else
  457.             return false;
  458.     }
  459. };

  460. int main()
  461. {
  462.     char mode = 0;
  463.     std::cout << "Input puzzle file (I) or Generate one (G): ";
  464.     std::cin >> mode;
  465.     if (mode == 'I')
  466.     {
  467.         char file[100];
  468.         bool flag;
  469.         std::cout << "Please specify the file: ";
  470.         std::cin >> file;
  471. AM:
  472.         std::cout << "Automatically (A) solve it or Manually (M): ";
  473.         std::cin >> mode;
  474.         if (mode == 'A')
  475.             flag = false;
  476.         else if (mode == 'M')
  477.             flag = true;
  478.         else
  479.         {
  480.             std::cout << "Invalid Input!\n";
  481.             goto AM;
  482.         }

  483.         system("cls");
  484.         Sudoku puzzle(file, flag);
  485.         if (flag)
  486.         {
  487.             unsigned row, col, val;
  488.             while (!puzzle.is_complete())
  489.             {
  490.                 std::cout << "Enter a position and a number (i, j, num): ";
  491.                 std::cin >> row >> col >> val;
  492.                 puzzle.play(row, col, val);
  493.             }
  494.             std::cout << "You have completed the puzzle." << std::endl;
  495.         }
  496.     }
  497.     else if (mode == 'G')
  498.     {
  499.         std::cout << "Which Level: Easy (E) Medium (M) Difficult(D) Evil(U) ";
  500.         std::cin >> mode;
  501.         difficulty level;
  502.         bool flag;
  503.         switch (mode)
  504.         {
  505.         case 'E':
  506.             level = EASY;
  507.             break;
  508.         case 'M':
  509.             level = MEDIUM;
  510.             break;
  511.         case 'D':
  512.             level = DIFFICULT;
  513.             break;
  514.         case 'U':
  515.             level = EVIL;
  516.             break;
  517.         default:
  518.             level = DEFAULT;
  519.             break;
  520.         }
  521. SP:
  522.         std::cout << "Save it to a file (S) or Play now (P): ";
  523.         std::cin >> mode;
  524.         if (mode == 'S')
  525.             flag = false;
  526.         else if (mode == 'P')
  527.             flag = true;
  528.         else
  529.         {
  530.             std::cout << "Invalid Input!\n";
  531.             goto SP;
  532.         }

  533.         if (flag)
  534.         {
  535.             system("cls");
  536.             Sudoku puzzle(level, std::cout);
  537.             unsigned row, col, val;
  538.             while (!puzzle.is_complete())
  539.             {
  540.                 std::cout << "Enter a position and a number (i, j, num): ";
  541.                 std::cin >> row >> col >> val;
  542.                 puzzle.play(row, col, val);
  543.             }
  544.             std::cout << "You have completed the puzzle." << std::endl;
  545.         }
  546.         else
  547.         {
  548.             std::ofstream ofs("Sudoku.out");
  549.             Sudoku puzzle(level, ofs);
  550.             std::cout << "Saved as Sudoku.out" << std::endl;
  551.         }
  552.     }
  553.     system("pause");
  554. }
复制代码
可执行文件 Sudoku.zip (8.63 KB, 下载次数: 1)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2014-6-28 01:04:21 | 显示全部楼层
(1) 需求和规格说明
在一个9×9的大正方形中,包含93×3的小正方形。如图4所示。可以看到,其每行、每列、每个小正方形,都有9个空格。
要求只用19这些数字,填满大正方形中所有的81个空格,同时满足:
1)在每列的9个空格中分别填入19,且每个数字在此列中只能出现一次;
2)在每行的9个空格中分别填入19,且每个数字在此行中只能出现一次;
3)在每个小正方形的9个空格中分别填入19,且每个数字在此正方形中只能出现一次;
游戏一开始会给定了某些空格的值。参加游戏的人根据这些已知的值以及上面的约束条件,推理出剩余的空格的值。
(2) 设计
根据上述需求,采用unsigned类型进行存储,并且通过简单的位运算来获取对应的格子上可填入的数字。有两个基本类:BlankListBoard,分别用来获取数独上空白位置可填入的数字,以及对一个数独棋盘的一系列操作。另外,还有一个作为用户接口的类Sudoku,提供初始化数独、生成数独、以及数独求解的操作;一个Holes类,用来给已经生成的完全数独进行挖洞,以生成真正的数独。
由于各个类的功用和数据相同成分不多,因此我采用的是潜入对象的做法,而没有使用继承。除了少数需要全局使用的变量和函数意外,数据基本都封装在各个类里面。在参考网上一些代码的基础上,我自己特别补充了hidden_fill方法,个人认为可以一定程度缩小解空间,所以引入了此方法对数独中naked single类型、hiddensingle类型、还有full house类型的确定解进行了筛查。之后再进行回溯进行求解。生成棋盘则是采用了回溯的方法,而不是采用Las Vegas的随机方法,旨在使完全数独生成更加随机化。
属性和方法定义
   
类名
   

成员类别


类型


成员名


描述


BlankList


属性


bitfield


rows[9]


对应行可填数





bitfield


cols[9]


对应列可填数





bitfield


blocks[9]


对应房子可填数





方法


void


elim(unsigned, unsigned,  unsigned)


在增添数据时,从可填数中除去该数字





void


cancel(unsigned, unsigned,  unsigned)


在删除数据时,从可填数中增添该数字





bitfield


possible(unsigned,  unsigned)


返回对应格子的可填数(在只考虑行、列、房子不冲突的情况下)


Board


属性


unsigned


matrix[9][9]


9*9格子的二维数组





BlankList


Blank


嵌入的BlankList对象,用于存储可填数





方法





Board()


构造函数,用于已存在的数独








Board(unsigned)


传入随机数种子的构造函数,用于生成新的完全数独





void


set(unsigned, unsigned, unsigned)


用于设置一个格子上的值





bool


unset(unsigned, unsigned)


用于取消设置一个格子的值,并返回取消的值





bitfield


mask_check(unsigned,  unsigned, bitfield mask)


检查mask代表的数字中可填的





bitfield


house_check(bitfield,  unsigned, unsigned)


从possible里筛选出需要填的格子意外同一个房子中,其他未填格子中都不可能的数





bitfield


rl_check(bitfield,  unsigned unsigned)


从tricky里筛选出对应行或对应列中,其他未填格子中都不可能的数





void


hidden_fill()


填入可以确定的值





unsigned


remaining()


未填的格子数量





bool


findMin(unsigned&, unsigned&)


查找可填数数量最少的格子





bool


backtrack(unsigned)


回溯求解





unsigned


value(unsigned, unsigned)


(i, j)格子中的值





bool


assert(unsigned, unsigned,  unsigned)


确认(i, j)中的值是否为val





void


print_board(std::ostream  &)


输出整个数独





unsigned


numFor()








bool


_fill(bool, unsigned,  unsigned, bitfield)


完全数独的填充,针对填入数大小决定是否回溯到上一个数





void


_random_fill()


递归完全数独填充,调用_fill函数


Holes


属性


Board


puzzle


嵌入的Board对象





方法


void


digHoles(difficulty)


“挖洞”操作





Board


to_play


返回挖洞结束的数独





unsigned


_random_by_level(difficulty)


根据难度随机生成每个房子里挖洞的数目





void


_valid_dig(unsigned,  unsigned, difficulty)


只挖有效的洞(要求挖完剩下的是有唯一解的数独)


Sudoku


属性


std::ifstream


in


输入文件流





Board


_board


正在使用的数独





Board


_answer


当前数独的答案





方法





Sudoku(const char *, bool)


输入文件的构造函数








Sudoku(difficulty, std::ostream &)


自动产生数独的构造函数





void


generate(difficulty, std::ostream &)


产生一个给定难度的数独





void


play(unsigned&,unsigned&, unsigned&)


玩家输入对应位置数值





bool


is_complete()


确认是否正确完成





bool


_solve()


求解过程


想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-7-9 12:32:05 | 显示全部楼层
本帖最后由 andalousie 于 2014-7-11 16:12 编辑

新的测试代码,部分。

  1. class Board
  2. {
  3. public:
  4.     Board()
  5.         : remains(81)
  6.     {
  7.         for (unsigned i = 0; i < 9; ++i)
  8.             for (unsigned j = 0; j < 9; ++j)
  9.             {
  10.                 matrix[i][j] = 0;
  11.                 memory[i][j] = allSet;
  12.             }
  13.     }
  14.     Board(unsigned seed)
  15.         : remains(81)
  16.     {
  17.         for (unsigned i = 0; i < 9; ++i)
  18.             for (unsigned j = 0; j < 9; ++j)
  19.             {
  20.                 matrix[i][j] = 0;
  21.                 memory[i][j] = allSet;
  22.             }

  23.         std::srand(seed);
  24.         _random_fill();
  25.     }
  26.     void set(unsigned row, unsigned col, unsigned val, bool advanced = false)
  27.     {
  28.         matrix[row][col] = val;
  29.         if (matrix[row][col])
  30.         {
  31.             Blank.elim(row, col, val);
  32.             --remains;
  33.         }
  34.         if (advanced)
  35.             _update(row, col);
  36.     }
  37.     unsigned unset(unsigned row, unsigned col)
  38.     {
  39.         unsigned val = matrix[row][col];
  40.         if (val)
  41.         {
  42.             Blank.cancel(row, col, val);
  43.             ++remains;
  44.         }
  45.         matrix[row][col] = 0;
  46.         return val;
  47.     }
  48.     bitfield mask_check(unsigned i, unsigned j, bitfield mask)
  49.     {
  50.         return Blank.possible(i, j) & mask & memory[i][j];
  51.     }
  52.     bitfield house_check(unsigned i, unsigned j, bool advanced = false)
  53.     {
  54.         bitfield house_hidden = allSet;
  55.         unsigned row_base = i / 3 * 3;
  56.         unsigned col_base = j / 3 * 3;
  57.         for (unsigned row = row_base; row < row_base + 3; ++row)
  58.             for (unsigned col = col_base; col < col_base + 3; ++col)
  59.             {
  60.                 if ((row == i && col == j) || matrix[row][col])
  61.                     continue;
  62.                 house_hidden &= advanced ? ~memory[row][col] : ~Blank.possible(row, col);
  63.             }
  64.         return house_hidden;
  65.     }
  66.     bitfield row_check(unsigned i, unsigned j, bool advanced = false)
  67.     {
  68.         bitfield row_hidden = allSet;
  69.         for (unsigned col = 0; col < 9; ++col)
  70.             if (!matrix[i][col] && col != j)
  71.                 row_hidden &= advanced ? ~memory[i][col] : ~Blank.possible(i, col);
  72.         return row_hidden;
  73.     }
  74.     bitfield col_check(unsigned i, unsigned j, bool advanced = false)
  75.     {
  76.         bitfield col_hidden = allSet;
  77.         for (unsigned row = 0; row < 9; ++row)
  78.             if (!matrix[row][j] && row != i)
  79.                 col_hidden &= advanced ? ~memory[row][j] : ~Blank.possible(row, j);
  80.         return col_hidden;
  81.     }
  82.     bitfield decide(bitfield & possible, bitfield & house,
  83.                     bitfield & row,      bitfield & col)
  84.     {
  85.         if (bitCount(possible) == 1)
  86.             return possible;

  87.         bitfield check1 = possible & house;
  88.         if (bitCount(check1) == 1)
  89.             return check1;

  90.         bitfield check2 = possible & row;
  91.         if (bitCount(check2) == 1)
  92.             return check2;

  93.         bitfield check3 = possible & col;
  94.         if (bitCount(check3) == 1)
  95.             return check3;

  96.         bitfield check = check1 & check2;
  97.         if (bitCount(check) == 1)
  98.             return check;

  99.         check = check1 & check3;
  100.         if (bitCount(check) == 1)
  101.             return check;

  102.         check = check2 & check3;
  103.         if (bitCount(check) == 1)
  104.             return check;

  105.         check &= check1;
  106.         if (bitCount(check) == 1)
  107.             return check;

  108.         return 0;
  109.     }
  110.     void hidden_fill()
  111.     {
  112.         bool again;
  113.         do
  114.         {
  115.             again = false;
  116.             for (unsigned i = 0; i < 9; ++i)
  117.             {
  118.                 for (unsigned j = 0; j < 9; ++j)
  119.                 {
  120.                     if (matrix[i][j]) continue;
  121.                     bitfield possible = Blank.possible(i, j);
  122.                     bitfield house = house_check(i, j);
  123.                     bitfield row = row_check(i, j);
  124.                     bitfield col = col_check(i, j);
  125.                     bitfield to_check = decide(possible, house, row, col);
  126.                     if (to_check)
  127.                     {
  128.                         set(i, j, numFor(to_check));
  129.                         again = true;
  130.                     }
  131.                 }
  132.             }
  133.         }
  134.         while (again);
  135.     }
  136.     bitfield candidate_check(unsigned i, unsigned j)
  137.     {
  138.         bitfield row_locked(0), col_locked(0), row_i(0), col_j(0);
  139.         unsigned row_base = i / 3 * 3;
  140.         unsigned col_base = j / 3 * 3;
  141.         unsigned total_count = 0;
  142.         for (unsigned row = row_base; row < row_base + 3; ++row)
  143.         {
  144.             if (row == i)
  145.             {
  146.                 for (unsigned col = col_base; col < col_base + 3; ++col)
  147.                 {
  148.                     if (matrix[row][col])
  149.                         continue;
  150.                     row_i |= memory[row][col];
  151.                 }
  152.             }
  153.             else
  154.             {
  155.                 for (unsigned col = col_base; col < col_base + 3; ++col)
  156.                 {
  157.                     if (matrix[row][col])
  158.                         continue;
  159.                     row_locked |= memory[row][col];
  160.                     ++total_count;
  161.                 }
  162.             }
  163.         }
  164.         if (total_count && total_count == bitCount(row_locked))
  165.             memory[i][j] &= ~row_locked;
  166.         bitfield pointing = row_i & ~row_locked;
  167.         if (pointing)
  168.             for (unsigned col = 0; col < 9; ++col)
  169.             {
  170.                 if (matrix[i][col] || (col >= col_base && col < col_base + 3))
  171.                     continue;
  172.                 memory[i][col] &= ~pointing;
  173.             }

  174.         total_count = 0;
  175.         for (unsigned col = col_base; col < col_base + 3; ++col)
  176.         {
  177.             if (col == j)
  178.             {
  179.                 for (unsigned row = row_base; row < row_base + 3; ++row)
  180.                 {
  181.                     if (matrix[row][col])
  182.                         continue;
  183.                     col_j |= memory[row][col];
  184.                 }
  185.             }
  186.             else
  187.             {
  188.                 for (unsigned row = row_base; row < row_base + 3; ++row)
  189.                 {
  190.                     if (matrix[row][col])
  191.                         continue;
  192.                     col_locked |= memory[row][col];
  193.                     ++total_count;
  194.                 }
  195.             }
  196.         }
  197.         if (total_count && total_count == bitCount(col_locked))
  198.             memory[i][j] &= ~col_locked;
  199.         pointing = col_j & ~col_locked;
  200.         if (pointing)
  201.             for (unsigned row = 0; row < 9; ++row)
  202.             {
  203.                 if (matrix[row][j] || (row >= row_base && row < row_base + 3))
  204.                     continue;
  205.                 memory[row][j] &= ~pointing;
  206.             }

  207.                 for (unsigned col = 0; col < 9; ++col)
  208.                 {
  209.                         if (matrix[i][col] || (col >= col_base && col < col_base + 3))
  210.                                 continue;
  211.                         row_i &= ~memory[i][col];
  212.                 }
  213.                 if (row_i)
  214.                 {
  215.                         for (unsigned r = row_base; r < row_base + 3; ++r)
  216.                                 for (unsigned c = col_base; c < col_base + 3; ++c)
  217.                                 {
  218.                                         if (r == i || matrix[r][c])
  219.                                                 continue;
  220.                                         memory[r][c] &= ~row_i;
  221.                                 }
  222.                 }

  223.                 for (unsigned row = 0; row < 9; ++row)
  224.                 {
  225.                         if (matrix[row][j] || (row >= row_base && row < row_base + 3))
  226.                                 continue;
  227.                         col_j &= ~memory[row][j];
  228.                 }
  229.                 if (col_j)
  230.                 {
  231.                         for (unsigned r = row_base; r < row_base + 3; ++r)
  232.                                 for (unsigned c = col_base; c < col_base + 3; ++c)
  233.                                 {
  234.                                         if (c == j || matrix[r][c])
  235.                                                 continue;
  236.                                         memory[r][c] &= ~col_j;
  237.                                 }
  238.                 }
  239.         return memory[i][j];
  240.     }
  241.     void advanced_fill()
  242.     {
  243.         bool again;
  244.         unsigned sum;
  245.         for (unsigned i = 0; i < 9; ++i)
  246.             for (unsigned j = 0; j < 9; ++j)
  247.                 if (!matrix[i][j])
  248.                     memory[i][j] &= Blank.possible(i, j);

  249.         do
  250.         {
  251.             again = false;
  252.             sum   = 0;
  253.             for (unsigned i = 0; i < 9; ++i)
  254.                 for (unsigned j = 0; j < 9; ++j)
  255.                     sum += memory[i][j];

  256.             for (unsigned i = 0; i < 9; ++i)
  257.             {
  258.                 for (unsigned j = 0; j < 9; ++j)
  259.                 {
  260.                     if (matrix[i][j]) continue;
  261.                     bitfield possible = candidate_check(i, j);
  262.                     //print_possible();
  263.                     bitfield house = house_check(i, j, true);
  264.                     bitfield row = row_check(i, j, true);
  265.                     bitfield col = col_check(i, j, true);
  266.                     bitfield to_check = decide(possible, house, row, col);
  267.                     if (to_check)
  268.                         set(i, j, numFor(to_check), true);
  269.                 }
  270.             }

  271.             for (unsigned i = 0; i < 9; ++i)
  272.                 for (unsigned j = 0; j < 9; ++j)
  273.                     sum -= memory[i][j];
  274.             if (sum) again = true;
  275.         }
  276.         while (again);
  277.     }
  278.     unsigned remaining()
  279.     {
  280.         return remains;
  281.     }
  282.     bool findMin(unsigned& row, unsigned& col)
  283.     {
  284.         bool found = false;
  285.         unsigned count = 10;

  286.         for (unsigned i = 0; i < 9; ++i)
  287.             for (unsigned j = 0; j < 9; ++j)
  288.             {
  289.                 if (!matrix[i][j] && (bitCount(Blank.possible(i, j)
  290.                                         & memory[i][j])) < count)
  291.                 {
  292.                     count = bitCount(Blank.possible(i, j) & memory[i][j]);
  293.                     row = i;
  294.                     col = j;
  295.                     found = true;
  296.                 }
  297.             }
  298.         return found;
  299.     }
  300.     bool backtrack(unsigned depth)
  301.     {
  302.         unsigned row, col;
  303.         if (!findMin(row, col))
  304.             if (!depth)
  305.                 return true;
  306.             else
  307.                 return false;

  308.         // Iterate through the possible values this cell could have
  309.         unsigned num = 1;
  310.         bitfield mask = bitFor(num);
  311.         while (mask != maskMax)
  312.         {
  313.             if (mask_check(row, col, mask))
  314.             {
  315.                 set(row, col, num);
  316.                 if (backtrack(depth-1))
  317.                     return true;
  318.                 unset(row, col);
  319.             }

  320.             // Advance to the next number
  321.             mask *= 2;
  322.             num++;
  323.         }
  324.         return false;
  325.     }
  326.     unsigned value(unsigned i, unsigned j)
  327.     {
  328.         return matrix[i][j];
  329.     }
  330.     bool assert(unsigned i, unsigned j, unsigned val)
  331.     {
  332.         return matrix[i][j] == val;
  333.     }
  334.     void print_possible()
  335.     {
  336.         for (unsigned i = 0; i < 9; ++i)
  337.         {
  338.             for (unsigned j = 0; j < 9; ++j)
  339.             {
  340.                 output << memory[i][j] << " ";
  341.             }
  342.             output << std::endl;
  343.         }
  344.         output << std::endl;
  345.     }
  346.     void print_board(std::ostream & out)
  347.     {
  348.         for (unsigned i = 0; i < 9; ++i)
  349.         {
  350.             for (unsigned j = 0; j < 9; ++j)
  351.             {
  352.                 out << matrix[i][j] << " ";
  353.             }
  354.             out << std::endl;
  355.         }
  356.         out << std::endl;
  357.     }
  358. private:
  359.     unsigned matrix[9][9];
  360.     bitfield memory[9][9];
  361.     unsigned remains;
  362.     BlankList Blank;

  363.     static unsigned numFor(bitfield bit)
  364.     {
  365.         unsigned num = 0;
  366.         while (bit)
  367.         {
  368.             bit >>= 1;
  369.             ++num;
  370.         }
  371.         return num;
  372.     }
  373.     void _update(unsigned row, unsigned col)
  374.     {
  375.         unsigned row_base = row / 3 * 3;
  376.         unsigned col_base = col / 3 * 3;
  377.         unsigned r, c;

  378.         for (unsigned i = 0; i < 9; ++i)
  379.         {
  380.             if (!matrix[row][i])
  381.                 memory[row][i] &= Blank.possible(row, i);
  382.             if (!matrix[i][col])
  383.                 memory[i][col] &= Blank.possible(i, col);
  384.             r = row_base + i / 3;
  385.             c = col_base + i % 3;
  386.             if (r != row && c != col && !matrix[r][c])
  387.                 memory[r][c] &= Blank.possible(r, c);
  388.         }
  389.     }
  390.     bool _fill(bool is_big, unsigned block, unsigned num)
  391.     {
  392.         if (is_big)
  393.         {
  394.             if (num == 10)
  395.                 return true;
  396.             if (block == 9)
  397.                 return _fill(is_big, 0, num + 1);
  398.         }
  399.         if (block == 9)
  400.             return true;
  401.         static unsigned look_up[] =
  402.         {
  403.             0,  1,  2,
  404.             9,  10, 11,
  405.             18, 19, 20
  406.         };
  407.         static unsigned base[] =
  408.         {
  409.             0,  3,  6,
  410.             27, 30, 33,
  411.             54, 57, 60
  412.         };
  413.         unsigned place;
  414.         bitfield available = allSet;
  415.         while (available)
  416.         {
  417.             while (true)
  418.             {
  419.                 place = std::rand() % 9;
  420.                 if (available & bitFor(place + 1))
  421.                     break;
  422.             }
  423.             available &= ~bitFor(place + 1);

  424.             unsigned loc = base[block] + look_up[place];
  425.             unsigned row = loc / 9, col = loc % 9;
  426.             if (!matrix[row][col] &&
  427.                     (bitFor(num) & Blank.possible(row, col)))
  428.             {
  429.                 set(row, col, num);
  430.                 if (_fill(is_big, block + 1, num))
  431.                     return true;
  432.                 unset(row, col);
  433.             }
  434.         }
  435.         return false;
  436.     }

  437.     void _random_fill()
  438.     {
  439.         for (unsigned i = 1; i <= 5; ++i)
  440.             _fill(false, 0, i);
  441.         if (!_fill(true, 0, 6))
  442.                         std::cout << "Error" << std::endl;
  443.     }
  444. };

  445. class Holes
  446. {
  447. public:
  448.     Holes(Board & board)
  449.         : puzzle(board)
  450.     {}
  451.     void digHoles(difficulty level)
  452.     {
  453.         static unsigned look_up[] =
  454.         {
  455.             0,  1,  2,
  456.             9,  10, 11,
  457.             18, 19, 20
  458.         };
  459.         static unsigned base[] =
  460.         {
  461.             0,  3,  6,
  462.             27, 30, 33,
  463.             54, 57, 60
  464.         };
  465.         for (unsigned i = 0; i < 9; ++i)
  466.         {
  467.             unsigned array[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
  468.             unsigned diff = _random_by_level(level);
  469.             std::random_shuffle(array, array + 9);
  470.             for (unsigned j = 0; j < diff; ++j)
  471.             {
  472.                 unsigned loc = base[i] + look_up[array[j]];
  473.                 unsigned row = loc / 9, col = loc % 9;
  474.                 _valid_dig(row, col, level);
  475.             }
  476.         }
  477.     }
  478.     Board& to_play()
  479.     {
  480.         return puzzle;
  481.     }
  482. private:
  483.     Board puzzle;

  484.     unsigned _random_by_level(difficulty level)
  485.     {
  486.         unsigned random = 5;

  487.         switch (level)
  488.         {
  489.         case EASY:
  490.             random = std::rand() % 7 + 3;
  491.             break;
  492.         case MEDIUM:
  493.             random = std::rand() % 5 + 3;
  494.             break;
  495.         case DIFFICULT:
  496.             random = std::rand() % 5 + 4;
  497.             break;
  498.         case EVIL:
  499.             random = std::rand() % 5 + 5;
  500.             break;
  501.         default:
  502.             break;
  503.         }
  504.         return random;
  505.     }

  506.     void _valid_dig(unsigned i, unsigned j, difficulty level)
  507.     {
  508.         unsigned val = puzzle.unset(i, j);
  509.                 if (level == EASY)
  510.                 {
  511.                         Board bd = puzzle;
  512.                         bd.hidden_fill();
  513.                         if (bd.remaining())
  514.                         {
  515.                                 puzzle.set(i, j, val);
  516.                                 return;
  517.                         }
  518.                 }
  519.         for (unsigned num = 1; num <= 9; ++num)
  520.         {
  521.             if (num != val &&
  522.                     puzzle.mask_check(i, j, bitFor(num)))
  523.             {
  524.                 Board bd = puzzle;
  525.                 bd.set(i, j, num);
  526.                 bd.hidden_fill();
  527.                                 bd.advanced_fill();
  528.                 if (bd.backtrack(bd.remaining()))
  529.                 {
  530.                     puzzle.set(i, j, val);
  531.                     return;
  532.                 }
  533.             }
  534.         }
  535.     }
  536. };

  537. class Sudoku
  538. {
  539. public:
  540.     Sudoku(const char * name, bool play = false)
  541.     {
  542.         std::ifstream in(name);
  543.         unsigned num = 0;
  544.         for (unsigned i = 0; i < 9; ++i)
  545.         {
  546.             for (unsigned j = 0; j < 9; ++j)
  547.             {
  548.                 in >> num;
  549.                 _board.set(i, j, num);
  550.             }
  551.         }
  552.         _board.print_board(std::cout);
  553.         _answer = _board;
  554.         /*        if (_solve())
  555.                 {
  556.                     if (!play)
  557.                     {
  558.                         std::cout << "The answer is:" << std::endl;
  559.                         _answer.print_board(std::cout);
  560.                     }
  561.                 }
  562.                 else
  563.                     std::cout << "The sudoku is not solvable!" << std::endl;*/
  564.         solve();
  565.     }
  566.     Sudoku(difficulty level, std::ostream & out)
  567.     {
  568.         generate(level, out);
  569.     }
  570.     void generate(difficulty level, std::ostream & out)
  571.     {
  572.         _answer = Board(static_cast<unsigned>(std::time(0)));
  573.                 while (true)
  574.                 {
  575.                         Holes game(_answer);
  576.                         game.digHoles(level);
  577.                         Board bd = game.to_play();
  578.                         bd.hidden_fill();
  579.                         if (level > EASY && !bd.remaining())
  580.                                 continue;
  581.                         bd.advanced_fill();
  582.                         if (level > MEDIUM && !bd.remaining())
  583.                                 continue;
  584.                         if (level > DIFFICULT && bd.remaining() < 30)
  585.                                 continue;
  586.                         _board = game.to_play();
  587.                         break;
  588.                 }
  589.         _board.print_board(out);
  590.     }
  591.     void play(unsigned& row, unsigned& col, unsigned& val)
  592.     {
  593.         if (_board.mask_check(row, col, bitFor(val)))
  594.             if (_answer.assert(row, col, val))
  595.             {
  596.                 _board.set(row, col, val);
  597.                 system("cls");
  598.                 _board.print_board(std::cout);
  599.             }
  600.             else
  601.                 std::cout << "You've chosen the wrong number.\n";
  602.         else
  603.             std::cout << "Your play violated the rules.\n";
  604.     }
  605.     bool is_complete()
  606.     {
  607.         for (unsigned i = 0; i < 9; ++i)
  608.             for (unsigned j = 0; j < 9; ++j)
  609.                 if (!_answer.assert(i, j, _board.value(i, j)))
  610.                     return false;
  611.         return true;
  612.     }
  613. private:
  614.     Board _board;
  615.     Board _answer;

  616.     bool _solve()
  617.     {
  618.         _answer.hidden_fill();
  619.         if (_answer.backtrack(_answer.remaining()))
  620.             return true;
  621.         else
  622.             return false;
  623.     }

  624.     void solve()
  625.     {
  626.         //std::ofstream out("Sudoku.out");
  627.         _answer.hidden_fill();
  628.         _answer.advanced_fill();
  629.                 _answer.backtrack(_answer.remaining());
  630.         _answer.print_board(std::cout);
  631.     }
  632. };
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-20 21:40

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表