コード例 #1
0
        /// <summary>
        /// 填充单元格
        /// </summary>
        /// <param name="table">表</param>
        /// <param name="index">索引</param>
        /// <returns>返回结果</returns>
        public 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].answer != 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);
        }
コード例 #2
0
        /// <summary>
        /// 处理相关单元格
        /// 包括行,列和宫
        /// </summary>
        /// <param name="cellMethod">调用方法</param>
        /// <param name="table">表</param>
        /// <param name="index">索引</param>
        /// <returns>返回结果</returns>
        private bool DealRelativeCell(RelativeCellMethod cellMethod, Cell[,] table, int index)
        {
            bool flag = true;
            Cell cell = table[index / 9, index % 9];

            for (int i = 0; i < 9; i++)
            {
                //同列单元格
                if (i != index / 9)
                {
                    //不能等于本单元格
                    flag &= cellMethod(table, i, index % 9, index);
                }

                //同行单元格
                if (i != index % 9)
                {
                    //不能等于本单元格
                    flag &= cellMethod(table, index / 9, i, index);
                }
            }

            //宫内的其它四个单元格
            for (int i = nineCells[index / 9]; i < nineCells[index / 9] + 3; i++)
            {
                for (int j = nineCells[index % 9]; j < nineCells[index % 9] + 3; j++)
                {
                    if (i != index / 9 && j != index % 9)
                    {
                        flag &= cellMethod(table, i, j, index);
                    }
                }
            }
            if (cellMethod == RecoverCellCandidate)
            {
                cell.answer = 0;
            }
            return(flag);
        }