分享

数独算法及源代码

 战神之家 2014-04-23

1.       产生符合数独规则的初始矩阵

第一行是随机生成的1~9的排列,第29行就要通过搜索来产生了。对于第29行的每一个空格,要从19逐个尝试放入,看同一列、同一行、同一个3×3的小方阵中是否出现过相同的数字,若没有就尝试放入,然后递归地搜索下一个位置的数字,若19都不行就返回上一个位置尝试下一个数字。直到找到一组解就返回。

先上C++代码:

Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->#include<iostream>

#include<algorithm>

#include <ctime>

using namespace std;


int Initial_State [ 10 ] [ 10 ] ; 


bool get_Initial_State( int i , int j  )  //搜索第( i , j )位置处可以存储的数字,找到解则返回true,否则返回false

{

    if( i > 9 || j > 9 ) 

        return true;


    for( int k = 1 ; k <= 9 ; ++k ) 

    {

        bool can = true;                // can 变量用于记录数字k能否放在 ( i , j ) 处 

        for( int m = 1 ; m < i ; ++m ) 

            if( Initial_State[m][j] == k )  // 检查同一列是否出现过数字k

            {

                can = false ;

                break ;

            }

        if ( can ) 

            for( int n = 1 ; n < j ; ++n ) 

                if( Initial_State[i][n] == k )  // 检查同一行是否出现过数字k

                {

                    can = false ;

                    break; 

                }

        if( can ) 

        {

            int up1 = ( i/3 ) * 3 + 3 ; // (i,j)方格所在的3×3小方格i坐标的上限

            int up2 = ( j/3 ) *3 + 3;   // (i,j)方格所在的3×3小方格在j坐标的上限


            if( i % 3 == 0 )    //这是针对特殊情况的处理

                up1 = i ; 

            if( j % 3 == 0 ) 

                up2 = j ;


            for( int p = up1-2 ; p <= up1 ; ++p  )  /* 检查在3×3的小方格中是否出现了同一个数字 */

            {

                if( can == false )   /* 跳出外层循环 */

                    break ;

                for( int q = up2-2 ; q <= up2 ; ++q ) 

                    if( Initial_State[p][q] == k ) 

                    {

                        can = false ;

                        break ;

                    }

            }

        }

        if( can ) 

        {

            Initial_State[i][j] = k ; 

            if( j<9 ) 

            {

                if( get_Initial_State( i  , j +1 ) )   /* 到同一行的下一位置开始搜索 */

                    return true ;  

            }

            else

            {

                if( i < 9 )  

                {

                    if( get_Initial_State( i + 1 , 1 ) )    /* 到下一行的第一个空格开始搜索 */

                        return true ;

                }

                else

                    return true ;  /* i >= 9  && j >= 9  , 搜索结束 */


            }

            Initial_State[i][j] = 0 ;   /* 关键这一步:找不到解就要回复原状,否则会对下面的搜索造成影响 */

        }

    }

    return false ;  /*  1到9都尝试过都不行,则返回递归的上一步 */

}


void start() 

{

    srand ( unsigned ( time (NULL) ) );  /* 产生random_shuffle的随机数种子 */

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

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

            Initial_State[i][j] = 0 ;


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

        Initial_State[1][i] = i ; 


    random_shuffle( &( Initial_State[1][1]) , &( Initial_State[1][10])  ) ;  /* 第一行随机排列产生 */


    get_Initial_State( 2 , 1 ) ;  /* 从第二行开始搜索 */

}


int main()

{

    start( ) ;

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

    {

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

            cout<< Initial_State [i][j] <<" " ;

        cout<<endl; 

    }

    getchar() ; 

    return 0 ;

}

按 Ctrl+C 复制代码
按 Ctrl+C 复制代码

 

   上面的算法在找到第一个解后就返回了,这样当第一行数字确定后,则只能得到一个矩阵了。也就是说上面的程序只能产生 9! 个数独初试矩阵。

 

2.       获胜条件

还有一点要注意的是检查用户的解正确与否的标准不是比较用户输入得到的矩阵与我们开始产生的初试矩阵是否相同,而是判断用户的矩阵是否满足数独的游戏规则。

这是因为一个初始矩阵被挖掉一些空格后,可能会有不止一种正确解,这里我就不详细说,这样的例子很容易举出。

 

3. 程序源代码下载 

C++写完上面的代码,发现MFC半年没用,不会做界面了。。。于是用javascript写了出来。程序全部在一个html文件中。

 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多