zoukankan      html  css  js  c++  java
  • 数独的优化回朔算法(四)

    FillCell

    这个方法是填充数独表的递归方法,看长长滴代码:

    代码
    /// <summary>
    /// 填充单元格
    /// </summary>
    /// <param name="table"></param>
    /// <param name="index">索引</param>
    /// <returns>返回结果</returns>
    private bool FillCell(Cell[,] table, int index)
    {
        RelativeCellMethod removeCandidateMethod 
    = new RelativeCellMethod(RemoveCellCandidate);
        RelativeCellMethod recoverCandidateMethod 
    = new RelativeCellMethod(RecoverCellCandidate);

        
    if (index >= 81)
        {
    //如果索引超出范围,则表示数独已成功生成,直接返回
            return true;
        }
        
    if (table[index / 9, index % 9].Value != 0)
        {
    //如果索引的单元格已赋值,则直接跳到下一个索引赋值
            return FillCell(table, index + 1);
        }
        
    bool flag = true;
        List
    <int> nextCandidates = new List<int>();
        
    //预先保存好改单元格的候选数序列,如果所有候选数都不成功,则把候选数全部还原之后再返回
        nextCandidates.AddRange(table[index / 9, index % 9].Candidate);

        
    while (table[index / 9, index % 9].Candidate.Count > 0 && flag)
        {
    //如果单元格候选数个数大于0,且标记为真,则循环试探候选数
            SetValue(table[index / 9, index % 9]);//为单元格赋值
            flag &= DealRelativeCell(removeCandidateMethod, table, index);//移除相关单元格的对应这个值的候选数
            if (!flag)
            {
    //如果移除候选数失败,则恢复候选数,并继续下个循环
                DealRelativeCell(recoverCandidateMethod, table, index);
            }
            
    else
            {
    //如果移除候选数成功,则继续试探填充下一个单元格
                flag &= FillCell(table, index + 1);
                
    if (!flag)
                {
    //如果填充下一个单元格失败,则恢复候选数,并继续下个循环
                    DealRelativeCell(recoverCandidateMethod, table, index);
                }
                
    else
                {
    //如果填充下一个单元格成功,则直接返回(运行到这里肯定表示整个数独已成功生成!)
                    return true;
                }
            }
            flag 
    = !flag;//把标志取反,继续下个循环
        }
        
    if (table[index / 9, index % 9].Candidate.Count == 0)
        {
    //如果所有候选数都是过了且全部失败,恢复此单元格的候选数,并返回false
            table[index / 9, index % 9].Candidate.AddRange(nextCandidates);
            
    return false;
        }
        
    return flag;
    }

    前两行定义了两个代理方法,在while方法中,一个一个的试单元格的候选数填入到单元格中,如果填入失败,则恢复候选数,继续尝试下一个候选数,如果所有候选数都不能正确生成数独,那么跳出while循环,函数返回false,返回到上一个单元格,将上一个单元格的值重置为0,试另外的候选数,以此类推。直到索引index大于等于81,则表示所有单元格都已成功赋值,那么全部返回true。

    接下来只需要写一个显示数独的方法:

     

    Show

    如下:

    代码
    /// <summary>
    /// 显示数独
    /// </summary>
    /// <param name="table"></param>
    private void Show(Cell[,] table)
    {
        
    for (int i = 0; i < 9; i++)
        {
            
    for (int j = 0; j < 9; j++)
            {
                Console.Write(
    "{0,2}", table[i, j].Value);

            }
            Console.WriteLine();
        }
        Console.WriteLine(
    "----------------------------------------------");

    }

    还有一个初始化数独表,然后开始填充数独的方法:

    StartFillTable

    代码
    /// <summary>
    /// 开始生成数独
    /// </summary>
    public void StartFillTable()
    {
        Cell[,] table 
    = new Cell[99];
        
    while (true)
        {
            
    for (int i = 0; i < 9; i++)
                
    for (int j = 0; j < 9; j++//初始化数独表
                    table[i, j] = new Cell();

            
    bool flag = FillCell(table, 0);//填充数独表
            if (flag)//如果生成数独成功,则显示这个数独
                Show(table);
            Console.ReadKey();
        }
    }

    我是用控制台应用程序编写的,如果是用Silverlight或者其他的呈现会更好看!,下面是Main方法和结果显示:

     

    class Program
    {
        
    static void Main(string[] args)
        {
            CellMethod method 
    = new CellMethod();
            method.StartFillTable();
        }
    }

    只要按回车键就可以生成一个不一样的新数独!

    对于有兴趣的读者,如果是要继续开发成数独游戏,可以随机的遮罩一定数量的格子,难度越高遮罩的格子越多,这样能保证的是数独游戏一定有解,但是解不一定唯一。如果要保证解唯一,那么就需要再用一个类似这个的解数独的方法,让计算机先做我们遮罩后的数独,看是不是有且仅有一个解,如果不是,那么重新选择遮罩区域,直到计算机发现解唯一为止,然后输出到前端,给玩家来玩!

    下一篇是整个程序的源代码。

  • 相关阅读:
    someThink
    快捷键
    typedef 的本质
    读取配置文件
    stl file
    摘自CSDNhttp://blog.csdn.net/gnuhpc/archive/2009/11/13/4808405.aspx
    thread demo
    B/S和C/S区别 java程序员
    上传文件 java程序员
    (八)VS的操作和使用技巧 java程序员
  • 原文地址:https://www.cnblogs.com/cdts_change/p/1656260.html
Copyright © 2011-2022 走看看