当前位置:编程学习 > C#/ASP.NET >>

请高人帮忙看看这个回朔数独算法有啥问题,谢谢

问题说明:
这是以前用JAVA实现的数独算法,修改成C#版本。原本在JAVA上没什么问题,但是在.net上却会经常出现无解的情况。

using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;

namespace ConsoleApplication2
{
    class sukodu
    {
       int[,] map = new int[9, 9];// 保存数独地图

        ArrayList[,] usable = new ArrayList[9, 9];// 保存数独地图中每个元素的可选列表

        Random random = new Random();

       
        public void initMap(int[,] givenMap)
        {

            for (int i = 0; i < 9; i++)
            {
                for (int j = 0; j < 9; j++)
                {
                    map[i, j] = givenMap[i, j];
                    if (map[i, j] != 0)
                    {

                        usable[i, j] = new ArrayList();


                        usable[i, j].Add(map[i, j] + 100);// 参见方法说明
                    }
                }
            }
        }


        public int[,] createAndFill()
        {

            int direction = 1;
            for (int num = 0; num < 81; )
            {

                Console.WriteLine(num+"");

                // 如果回溯到第一个元素之前,说明此题无解,返回null
                if (num < 0)
                {
                    return null;
                }

                // i:每个地图元素的行编号(0序),j:每个地图元素的列编号(0序)
                int i = num / 9;
                int j = num % 9;

                if (usable[i, j] == null)
                {// -------说明地图上的这个元素还未曾被访问过

                    createList(i, j);
                    ArrayList src = usable[i, j];
                    if (src.Count == 0)
                    {// 卡死,不能进行,回溯

                        direction = 2;// 表示遍历方向为负方向
                        Console.WriteLine("第一次访问不能继续,回朔");

                        num--;

                    }
                    else
                    {// 可选列表中有元素,则随机选择一个,并将其从可选列表中删除

                        int randomIndex = Math.Abs(random.Next()) % src.Count;

                        // int[] value=(int[])src.ToArray(new int().GetType);

                        map[i, j] = (int)src[randomIndex];
                        src.RemoveAt(randomIndex);
                        direction = 1;
                        num++;

                    }

                }// ----------说明地图上的这个元素还未曾被访问过
                else
                {// 可选列表不为空,曾经访问过  如果为空则说明还没有访问到这个点
                    if (usable[i, j].Count > 0
                            && (int)((usable[i, j])[0]) > 10)
                    {
                        switch (direction)
                        {
                            case 1:

                                num++;
                                break;
                            case 2:
                                num--;
                                Console.WriteLine("原始数据,回朔");
                                break;

                        }

                    }
                    else
                    {

                        switch (direction)
                        {

                            case 1:
                                map[i, j] = 0;
                                createList(i, j);
                                ArrayList src = usable[i, j];
                                if (src.Count == 0)
                                {// 卡死,不能进行,回溯

                                    Console.WriteLine("再次访问不能继续,回朔");

                                    direction = 2;// 表示遍历方向为负方向
                                    num--;

                                }
                                else
                                {// 可选列表中有元素,则随机选择一个,并将其从可选列表中删除

                                    int randomIndex = Math.Abs(random.Next()) % src.Count;
                                    map[i, j] = (int)src[randomIndex];
                                    src.RemoveAt(randomIndex);
                                    direction = 1;
                                    num++;

                                }

                                break;

                            case 2:
                                src = usable[i, j];
                                if (src.Count == 0)
                                {
                                    Console.WriteLine("可选列表已空,回朔");
                                    direction = 2;// 表示遍历方向为负方向
                                    num--;

                                }
                                else
                                {

                                    int randomIndex = Math.Abs(random.Next()) % src.Count;
                                    map[i, j] = (int)src[randomIndex];
                                    src.RemoveAt(randomIndex);
                                    direction = 1;
                                    num++;

                                }

                                break;
                        }

                    }

                }

            }

            return map;
        }

       
        --------------------编程问答--------------------  public int added(ArrayList list, int value)
        {

            for (int i = 0; i < list.Count; i++)
            {
                if ((int)list[i] == value)
                {
                    return i;
                }
            }
            return -1;
        }

       
        public void createList(int i, int j)
        {
            usable[i, j] = new ArrayList();
            ArrayList src = usable[i, j];
            // 初始化该元素位置可选列表,将1-9都添加进可选列表
            for (int m = 1; m <= 9; m++)
            {
                src.Add(m);
            }
            // 判断与当前元素同行元素的值是否在可选列表之中
            for (int col = 0; col < 9; col++)
            {
                int index = added(src, map[i, col]);
                if (index != -1)
                {// 当前值位于可选列表中,删除之
                    src.RemoveAt(index);
                }
            }
            // 判断与当前元素同列行元素的值是否在可选列表之中
            for (int row = 0; row < 9; row++)
            {
                int index = added(src, map[row, j]);
                if (index != -1)
                {// 当前值位于可选列表中,删除之
                    src.RemoveAt(index);
                }
            }
           
            int cellI = i / 3;// 9宫格的行编号
            int cellJ = j / 3;// 9宫格的列编号

            int indexI = cellI * 3;// 9宫格左上角第一个元素的行编号
            for (int a = 0; a < 3; a++)
            {
                int indexJ = cellJ * 3;// 9宫格左边第一列的列编号
                for (int b = 0; b < 3; b++)
                {
                    int index = added(src, map[indexI, indexJ]);
                    if (index != -1)
                    {
                        src.RemoveAt(index);// 当前值位于可选列表中,删除之
                    }
                    indexJ++;
                }
                indexI++;
            }
        }
        static void Main(string[] args)
        {         //   int[,] map = new int[9, 9];

            int[,] map ={
                                {5    ,  9  ,    0   ,   3   ,   0  ,    0   ,   1  ,    0   ,   6 },     
                                {0    ,  1    ,  0  ,    0   ,   0   ,   5  ,    3  ,    8  ,    0 },    
                                {0    ,  0    ,  6  ,    9   ,   0   ,   1    ,  0  ,    0    ,  0 },     
                                {4   ,   0  ,    0  ,    0    ,  1   ,   0   ,   2    ,  7   ,   3 },    
                                {2    ,  5   ,   0   ,   0   ,   3  ,    7   ,   0   ,   0    ,  0 },  
                                {0    ,  0    ,  0   ,   0     , 9   ,   0   ,   0    ,  0    ,  1 },   
                                {9    ,  6    ,  5  ,    1   ,   0    ,  0   ,   8   ,   0    ,  0 },   
                                {0   ,   0    ,  0   ,   6    ,  0    ,  9  ,    5    ,  0 ,     2 },   
                                {1    ,  0   ,   8  ,    0    ,  0   ,   3    ,  0  ,    9  ,    0 }    
                
                        };
            sukodu sk = new sukodu();
            sk.initMap(map);
                       long begin = Environment.TickCount;

            map = sk.createAndFill();

            long end = Environment.TickCount;

            Console.WriteLine("计算时间 消耗:" + (end - begin) + "毫秒");
            Console.WriteLine("#####################################");
            //map = sk.map;

            if (map != null)
            {
                for (int i = 0; i < 9; i++)
                {

                    for (int j = 0; j < 9; j++)
                    {


                        if (j % 3 == 2)
                        {

                            Console.Write(map[i, j] + " # ");
                        }
                        else if (j == 0)
                        {
                            Console.Write("# " + map[i, j] + "   ");

                        }
                        else
                        {
                            Console.Write(map[i, j] + "   ");
                        }
                    }
                    if (i % 3 == 2)
                    {

                        Console.WriteLine("\n#####################################");
                    }
                    else
                    {
                        Console.WriteLine();
                    }
                }

            }
            else {
                Console.WriteLine("抱歉,此迷题无解");
            }

            Console.ReadLine();

        }
    }
} --------------------编程问答-------------------- mathe好像专门写过这方面的算法文章。 
http://blog.csdn.net/mathe/archive/2007/08/23/1755672.aspx
已经算是CSDN公认最好的算法了
常见的是用DLX算法来解决数独问题(忍不住又提起这个:《Dancing  Links》,http://www-cs-faculty.stanford.edu/~knuth/preprints.html 能下载到),效率不错。
PS:
我也在研究这个算法中,可以一起讨论
补充:.NET技术 ,  其他语言
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,