【Unity小游戏】数独(三)——数独的n种解题技巧1

一、基础代码逻辑

1.更新所有格子的标记

标记的格式为文本串"123456789",代表这个格子可填的数字

遍历全部81个格子,循环1-9数字,如果所在的行、列、宫都没有该数字,那么就将数字加入文本串

比如"135"代表候选数只有1、3、5

        /// <summary>
        /// 根据已填的数字更新未填写格子的标记
        /// </summary>
        private void InitMarks()
        {
            //遍历81个格子
            for (int i = 0; i < 81; i++)
            {
                //计算行号
                int row = i / 9;
                //计算列号
                int column = i % 9;
                //计算所在的宫的编号
                int zoomIndex = row / 3 * 3 + column / 3;
                //初始化一个mark的文本,格式为"123456789",代表可填哪些数字
                string mark = "";
                //遍历数字1到9
                for (int num = 1; num <= 9; num++)
                {
                    //如果行、列、宫没有这个数字,那么这个数字加入标记中
                    if (!Rows[row].Contains(num) && !Columns[column].Contains(num) && !Zooms[zoomIndex].Contains(num))
                    {
                        //标记
                        mark = mark + num.ToString();
                    }
                }
                //更新标记
                //当标记中仅剩一位数字时,填入该数字,并更新相应行、列、宫的标记
                //若更新后又出现仅剩一个数字标记的格子,会继续递归这个逻辑
                UpdateMark(i, mark);
            }
        }

2.更新单个格子的标记

这里为更新单个格子的标记单独写一个方法,一个原因是后续需要检测每个解题技巧是否排除了格子中的某些数字标记,另一个原因是,每当格子的标记剩下一个数字时,都需要将这个数字填入格子,然后再更新它所在行列宫的其余格子的标记,需要递归。

        /// <summary>
        /// 更新标记,并返回标记是否有改变
        /// </summary>
        /// <param name="index"></param>
        /// <param name="mark"></param>
        /// <returns></returns>
        private bool UpdateMark(int index,string mark)
        {
            //标记位,是否有实际改变这个格子的标记内容
            bool isMarkChanged = false;
            //如果这个格子填入了数字,那么将标记置空
            if (Map[index] != 0 && MarkMap[index] != null)
            {
                MarkMap[index] = null;
                isMarkChanged = true;
            }
            //如果这个格子没有填入数字,那么更新标记
            //如果标记中的数字只有1位,那么格子填入该数字
            if(Map[index] == 0)
            {
                //如果该单元格没有填数据,那么更新标记
                string oriMark = MarkMap[index];
                MarkMap[index] = mark;
                //如果这个mark只有一位数的话,填入数据
                if(mark.Length == 1)
                {
                    //填入数字
                    //填入后,会更新行、列、宫的标记
                    FillCell(index, int.Parse(mark));
                }
                if (oriMark != mark) isMarkChanged = true;
            }
            //返回标记是否改变
            return isMarkChanged;
        }

3.填写格子

填入格子,并更新所在行、列、宫的标记,如果标记仅剩1位数字,那么再填入数字...

        /// <summary>
        /// 填入格子并更新标记并填入一些数据
        /// </summary>
        /// <param name="index"></param>
        /// <param name="number"></param>
        private void FillCell(int index, int number)
        {
            //如果所有都填完了,那么就不需要进入这个逻辑,直接返回
            if (generateCompleted) return;
            //如果要填的格子是已经有数的,规定不得覆盖,直接返回
            if (Map[index] != 0) return;
            //行号
            int row = index / 9;
            //列号
            int column = index % 9;
            //宫的编号
            int zoomIndex = GetZoomIndexWithRowColumn(row,column);
            //这个格子在所在宫里的编号,取值0-8
            int indexInZoom = GetIndexInZoomWithRowColumn(row, column);
            //如果要填的数据跟行列宫有冲突,报错
            if (Rows[row].Contains(number) || Columns[column].Contains(number) || Zooms[zoomIndex].Contains(number))
            {
                GameLogger.LogError($"Conflict: trying to fill {number} to row{row}column{column}, rowConfilict:{Rows[row].Contains(number)}, columnConflict:{ Columns[column].Contains(number)},zoomColift:{ Zooms[zoomIndex].Contains(number)}");
            }
            else
            {
                //填入
                Map[index] = number;
                //更新行列宫信息
                Rows[row].AddMember(column, number);
                Columns[column].AddMember(row, number);
                Zooms[zoomIndex].AddMember(indexInZoom, number);
                //更新格子的标记,置空
                UpdateMark(index, null);

                //检查是否所有格子都填完了
                //为了减少遍历次数,先检查所在的行、列、宫三个是否都填满了,如果是,再检查是否所有都填完
                if (Rows[row].GetCount() == 9 && Columns[column].GetCount() == 9 && Zooms[zoomIndex].GetCount() == 9)
                {
                    //标记位,记录是否所有格子都填完
                    bool allCellFilled = true;
                    //遍历所有格子,如果有发现未填完的格子,那么所有格子没有填完,直接跳出
                    for (int i = 0; i < 81; i++)
                    {
                        if (Map[i] == 0)
                        {
                            allCellFilled = false;
                            break;
                        }
                    }
                    //如果发现所有格子都填完了,触发回调,并更新标记位
                    if (allCellFilled)
                    {
                        OnGenerateCompleted();
                        generateCompleted = true;
                        GameLogger.Log(index + "  所有81格可填完");
                        return;
                    }
                }

                //更新行、列、宫的标记
                //遍历所在这一行的所有格子
                for (int ci = 0; ci < 9; ci++)
                {
                    //根据行、列计算出格子的下标
                    int index_r = GetCellIndexWithRowColumn(row, ci);
                    //如果格子没有填数,那么检查里面是否有这个数字的标记,如果有,剔除这个数字的标记
                    if(Map[index_r] == 0)
                    {
                        string mark_r = MarkMap[index_r];
                        if (mark_r == null) mark_r = "";
                        mark_r = mark_r.Replace(number.ToString(), "");
                        UpdateMark(index_r, mark_r);
                    }
                }
                //遍历所在这一列的所有格子
                for (int ri = 0; ri < 9; ri++)
                {
                    //根据行、列计算出格子的下标
                    int index_c = GetCellIndexWithRowColumn(ri, column);
                    //如果格子没有填数,那么检查里面是否有这个数字的标记,如果有,剔除这个数字的标记
                    if (Map[index_c] == 0)
                    {
                        string mark_c = MarkMap[index_c];
                        if (mark_c == null) mark_c = "";
                        mark_c = mark_c.Replace(number.ToString(), "");
                        UpdateMark(index_c, mark_c);
                    }
                }
                //遍历所在这一宫的所有格子
                for (int zi = 0; zi < 9; zi++)
                {
                    //根据行、列计算出格子的下标
                    int index_z = GetCellIndexWithZoomInfo(zoomIndex, zi / 3, zi % 3);
                    //如果格子没有填数,那么检查里面是否有这个数字的标记,如果有,剔除这个数字的标记
                    if (Map[index_z] == 0)
                    {
                        string mark_z = MarkMap[index_z];
                        if (mark_z == null) mark_z = "";
                        mark_z = mark_z.Replace(number.ToString(), "");
                        UpdateMark(index_z, mark_z);
                    }
                }
            }
        }

4.行号、列号、宫编号、格子下标之类的相互转换

        /// <summary>
        /// 用行、列号计算格子的下标号
        /// </summary>
        /// <param name="row"></param>
        /// <param name="column"></param>
        /// <returns></returns>
        private int GetCellIndexWithRowColumn(int row, int column)
        {
            int index = 9 * row + column;
            return index;
        }

        /// <summary>
        /// 用行、列号计算宫的编号
        /// </summary>
        /// <param name="row"></param>
        /// <param name="column"></param>
        /// <returns></returns>
        private int GetZoomIndexWithRowColumn(int row, int column)
        {
            int zoomIndex = row / 3 * 3 + column / 3;
            return zoomIndex;
        }
        
        /// <summary>
        /// 用行、列号计算宫里面的格子编号
        /// </summary>
        /// <param name="row"></param>
        /// <param name="column"></param>
        /// <returns></returns>
        private int GetIndexInZoomWithRowColumn(int row,int column)
        {
            int indexInZoom = row % 3 * 3 + column % 3;
            return indexInZoom;
        }

        /// <summary>
        /// 用宫编号和宫里面的行列计算格子的下标
        /// </summary>
        /// <param name="zoomIndex"></param>
        /// <param name="rowInZoom"></param>
        /// <param name="columnInZoom"></param>
        /// <returns></returns>
        private int GetCellIndexWithZoomInfo(int zoomIndex, int rowInZoom, int columnInZoom)
        {
            int globalIndex;
            int zoomRow = zoomIndex / 3;//这个区域排在9个区域的第几行
            int zoomColumn = zoomIndex % 3;//这个区域排在9个区域的第几列
            globalIndex = (rowInZoom + zoomRow * 3) * 9 + (columnInZoom + zoomColumn * 3);
            return globalIndex;
        }

二、解题技巧代码

这里参考的是全民数独app总结的技巧。

1.技巧1,摒除法

        /// <summary>
        /// 摒除法
        /// 如果一个标记只在某个单元的一个格子出现,那么这个格子必定只能填这个数
        /// </summary>
        /// <returns></returns>
        private bool HiddenSingle()
        {
            //标记位,是否有填写数据或者排除标记
            bool anyNumberFilled = false;
            //遍历数字1-9
            for (int num = 1; num <= 9; num++)
            {
                //检查是否有某一行中这个数字的标记只存在于一个格子
                Dictionary<int, int> rowDic = new Dictionary<int, int>();
                //遍历每一行
                for (int r = 0; r < 9; r++)
                {
                    //如果这行已经填满了或者已经填过这个数字,那么这一行不会有这个数字的标记,继续下一行
                    if (Rows[r].GetCount() == 9|| Rows[r].Contains(num)) continue;
                    //清空字典
                    rowDic.Clear();
                    //遍历这一行的每一格
                    for (int c = 0; c < 9; c++)
                    {
                        //计算格子的下标
                        int index = GetCellIndexWithRowColumn(r, c);
                        //如果这个格子没有填入数字,并且这个格子的标记里有这个数字,那么将这个格子的下标加入字典
                        if ((Map[index] == 0) && MarkMap[index].Contains(num.ToString()))
                        {
                            if (!rowDic.ContainsKey(index))
                            {
                                rowDic.Add(index,num);
                            }
                            //如果字典里有两个以上成员,那么不符合,继续下一位数字
                            if (rowDic.Count >= 2) break;
                        }
                    }
                    //如果字典的成员只有一个,说明这一行中只有一个格子有这个数字的标记
                    //那么这个格子就应该填入这个数字
                    if (rowDic.Count == 1)
                    {
                        //获取格子的下标,填入数字并设置标记位
                        foreach (var item in rowDic.Keys)
                        {
                            FillCell(item, num);
                            anyNumberFilled = true;
                        }
                    }
                }

                //检查是否有某一列中这个数字的标记只存在于一个格子
                Dictionary<int, int> columnDic = new Dictionary<int, int>();
                //遍历每一列
                for (int c = 0; c < 9; c++)
                {
                    if (Columns[c].GetCount() == 9|| Columns[c].Contains(num)) continue;
                    columnDic.Clear();
                    for (int r = 0; r < 9; r++)
                    {
                        int index = GetCellIndexWithRowColumn(r, c);
                        if ((Map[index] == 0) && MarkMap[index].Contains(num.ToString()))
                        {
                            if (!columnDic.ContainsKey(index))
                            {
                                columnDic.Add(index, num);
                            }
                            if (columnDic.Count >= 2) break;
                        }
                    }
                    if (columnDic.Count == 1)
                    {
                        foreach (var item in columnDic.Keys)
                        {
                            FillCell(item, num); 
                            anyNumberFilled = true;
                        }
                    }
                }
                //检查是否有某一宫中这个数字的标记只存在于一个格子
                Dictionary<int, int> zoomDic = new Dictionary<int, int>();
                //遍历每一宫
                for (int z = 0; z < 9; z++)
                {
                    if (Zooms[z].GetCount() == 9|| Zooms[z].Contains(num)) continue;
                    zoomDic.Clear();
                    for (int zi = 0; zi < 9; zi++)
                    {
                        int index = GetCellIndexWithZoomInfo(z, zi / 3, zi % 3);
                        if ((Map[index] == 0) && MarkMap[index].Contains(num.ToString()))
                        {
                            if (!zoomDic.ContainsKey(index))
                            {
                                zoomDic.Add(index, num);
                            }
                            if (zoomDic.Count >= 2) break;
                        }
                    }
                    if (zoomDic.Count == 1)
                    {
                        foreach (var item in zoomDic.Keys)
                        {
                            FillCell(item, num);
                            anyNumberFilled = true;
                        }
                    }
                }
            }
            return anyNumberFilled;
        }

2.技巧2,宫内区块对行列摒除

        /// <summary>
        /// 宫内区块对行列摒除
        /// 如果一个宫内某个数的标记限制在了某一行或者某一列中,那么这个数字在宫外的这一行或这一列的标记清除
        /// </summary>
        /// <returns></returns>
        private bool Pointing()
        {
            //标记位,是否填入了数字或者排除了标记
            bool anyNumberFilled = false;
            //遍历每一个宫
            for (int z = 0; z < 9; z++)
            {
                //如果这个宫未填写的格子少于两个,那么下一个宫
                if (Zooms[z].GetCount() > 7) continue;
                //遍历数字1-9
                for (int num = 1; num <= 9; num++)
                {
                    //如果这个宫已经填过这个数字,那么下一个数字
                    if (Zooms[z].Contains(num)) continue;
                    //字典,用来储存含有这个数字标记的格子的行号
                    Dictionary<int, int> rowIndexDic = new Dictionary<int, int>();
                    //字典,用来储存含有这个数字标记的格子的列号
                    Dictionary<int, int> columnIndexDic = new Dictionary<int, int>();


                    //遍历宫的每一个格子
                    for (int zi = 0; zi < 9; zi++)
                    {
                        //计算格子的下标
                        int index = GetCellIndexWithZoomInfo(z, zi/3, zi%3);
                        //行号
                        int row = index / 9;
                        //列号
                        int column = index % 9;
                        //如果这个格子没有填数并且含有这个数字的标记
                        if(Map[index]==0 && MarkMap[index].Contains(num.ToString()))
                        {
                            //添加到字典
                            if (!rowIndexDic.ContainsKey(row)) rowIndexDic.Add(row,0);
                            if (!columnIndexDic.ContainsKey(column)) columnIndexDic.Add(column, 0);
                        }
                    }

                    //如果这个宫里,所有这个数字的标记刚好在同一行,那么排除这一行其他宫这个数字的标记
                    if (rowIndexDic.Count == 1)
                    {
                        //获取行号
                        int row = 0;
                        foreach (var item in rowIndexDic.Keys)
                        {
                            //只有一个元素,获取行号
                            row = item;
                        }
                        //遍历这一行的每一格
                        for (int c = 0; c < 9; c++)
                        {
                            //如果这个格子在当前宫或者这一列已经填过这个数字,下一个格子
                            if (columnIndexDic.ContainsKey(c) || Columns[c].Contains(num)) continue;
                            //计算格子下标
                            int index = GetCellIndexWithRowColumn(row, c);
                            //如果格子没有填写过数字
                            if(Map[index] == 0)
                            {
                                //剔除格子中这个数字的标记,并更新标记位
                                string mark = MarkMap[index];
                                mark = mark.Replace(num.ToString(), "");
                                anyNumberFilled = UpdateMark(index, mark) || anyNumberFilled;
                            }
                        }
                    }
                    //如果这个宫里,所有这个数字的标记刚好在同一列,那么排除这一列其他宫这个数字的标记
                    if (columnIndexDic.Count == 1)
                    {
                        //获取列号
                        int column = 0;
                        foreach (var item in columnIndexDic.Keys)
                        {
                            //只有一个元素,获取列号
                            column = item;
                        }
                        //遍历这一列的每一格
                        for (int r = 0; r < 9; r++)
                        {
                            //如果这个格子在当前宫或者这一行已经填过这个数字,下一个格子
                            if (rowIndexDic.ContainsKey(r) || Rows[r].Contains(num)) continue;
                            //计算格子下标
                            int index = GetCellIndexWithRowColumn(r, column);
                            //如果格子没有填写过数字
                            if (Map[index] == 0)
                            {
                                //剔除格子中这个数字的标记,并更新标记位
                                string mark = MarkMap[index];
                                mark = mark.Replace(num.ToString(), "");
                                anyNumberFilled = UpdateMark(index, mark)|| anyNumberFilled  ;
                            }
                        }
                    }
                }

            }
            return anyNumberFilled;
        }

3.技巧3,行列区块对宫摒除

        /// <summary>
        /// 行列区块对宫摒除
        /// 如果某一行或某一列的这个数字的标记刚好被限制在同一个宫内,那么这个宫除这行或这列以外的标记清除
        /// </summary>
        /// <returns></returns>
        private bool Claiming()
        {
            //标记位,是否填入数字或者剔除标记
            bool anyNumberFilled = false;
            //遍历每一行
            for (int r = 0; r < 9; r++)
            {
                //如果这一行未填的格子少于两个,下一行
                if (Rows[r].GetCount() > 7) continue;
                //遍历数字1-9
                for (int num = 1; num <= 9; num++)
                {
                    //如果这一行已经填过这个数字,下一个数字
                    if (Rows[r].Contains(num)) continue;
                    //字典,用来比较这一行这个数字的标记是否在同一个宫内
                    Dictionary<int, int> zoomIndexDic = new Dictionary<int, int>();
                    //遍历这一行的每一格
                    for (int c = 0; c < 9; c++)
                    {
                        //计算格子下标
                        int index = GetCellIndexWithRowColumn(r, c);
                        //计算宫号
                        int z = GetZoomIndexWithRowColumn(r, c);
                        //如果这个格子没填数并且标记里面含有这个数字,那么将宫号添加到字典
                        if (Map[index] == 0 && MarkMap[index].Contains(num.ToString()))
                        {
                            if (!zoomIndexDic.ContainsKey(z)) zoomIndexDic.Add(z, 0);
                        }
                    }
                    //如果字典中只有一个成员,说明这一行所有这个数字的标记在同一个宫内
                    if (zoomIndexDic.Count == 1)
                    {
                        int zoomIndex = 0;
                        //获取宫号
                        foreach (var item in zoomIndexDic.Keys)
                        {
                            zoomIndex = item;
                        }
                        //遍历这个宫的9个格子
                        for (int zi = 0; zi < 9; zi++)
                        {
                            //这个格子的行号
                            int gR = zoomIndex / 3 * 3 + zi / 3;
                            //如果这个格子不在检查的这行
                            if (gR != r)
                            {
                                //计算格子下标
                                int gIndex = GetCellIndexWithZoomInfo(zoomIndex, zi / 3, zi % 3);
                                //如果格子没填数,那么剔除格子的这个数字的标记
                                if (Map[gIndex] == 0)
                                {
                                    string mark = MarkMap[gIndex];
                                    mark = mark.Replace(num.ToString(), "");
                                    anyNumberFilled = UpdateMark(gIndex, mark) || anyNumberFilled;
                                }
                            }

                        }
                    }
                }
            }
            //遍历每一列
            for (int c = 0; c < 9; c++)
            {
                if (Columns[c].GetCount() > 7) continue;
                for (int num = 1; num <= 9; num++)
                {
                    if (Columns[c].Contains(num)) continue;
                    Dictionary<int, int> zoomIndexDic = new Dictionary<int, int>();
                    for (int r = 0; r < 9; r++)
                    {
                        int index = GetCellIndexWithRowColumn(r, c);
                        int z = GetZoomIndexWithRowColumn(r, c);
                        if (Map[index] == 0 && MarkMap[index].Contains(num.ToString()))
                        {
                            if (!zoomIndexDic.ContainsKey(z)) zoomIndexDic.Add(z, 0);
                        }
                    }
                    if (zoomIndexDic.Count == 1)
                    {
                        int zoomIndex = 0;
                        foreach (var item in zoomIndexDic.Keys)
                        {
                            zoomIndex = item;
                        }
                        for (int zi = 0; zi < 9; zi++)
                        {
                            int gC = zoomIndex % 3 * 3 + zi % 3;
                            if (gC != c)
                            {
                                int gIndex = GetCellIndexWithZoomInfo(zoomIndex, zi / 3, zi % 3);
                                if (Map[gIndex] == 0)
                                {
                                    string mark = MarkMap[gIndex];
                                    mark = mark.Replace(num.ToString(), "");
                                    anyNumberFilled = UpdateMark(gIndex, mark) || anyNumberFilled;
                                }
                            }
                        }
                    }
                }
            }
            return anyNumberFilled;
        }

4.技巧4,数对摒除

        /// <summary>
        /// 数对摒除
        /// 如果某行、某列或者某个宫内找到这样的两格,有两个候选数只在这两格出现过,这两格只能填这两个数字
        /// </summary>
        /// <returns></returns>
        private bool HiddenPair()
        {
            //标记位,是否有填入数字或剔除标记
            bool anyNumberFilled = false;
            //遍历每一行
            for (int r = 0; r < 9; r++)
            {
                //如果这一行未填的格子少于2个,那么下一行
                if (Rows[r].GetCount() > 7) continue;
                //记录每个数字标记所在的列号
                string[] markInIndex = new string[9];
                //遍历数字1-9
                for (int num = 1; num <= 9; num++)
                {
                    //下标从0开始,初始化为""
                    markInIndex[num - 1] = "";
                    //如果这一行已经填过这个数,下一个数字
                    if (Rows[r].Contains(num)) continue;
                    string markS = "";
                    //遍历这一行的每一格
                    for (int c = 0; c < 9; c++)
                    {
                        //计算格子下标
                        int index = GetCellIndexWithRowColumn(r, c);
                        //如果这个格子没有填数,并且标记里面含有这个数字,那么记录列号
                        if ((Map[index] == 0) && (MarkMap[index].Contains(num.ToString())))
                        {
                            markS = markS + c;
                            markInIndex[num - 1] = markS;
                        }
                    }
                }
                //循环所有两个数字的组合
                for (int p = 0; p < 8; p++)
                {
                    //如果没有这个数字的标记,下一个数字
                    if (markInIndex[p] == "") continue;
                    //如果这个数字标记存在超过3格,下一个数字
                    if (markInIndex[p].Length >= 3) continue;
                    //两个数字组合的第二个数字
                    for (int q = 1; q < 9 - p; q++)
                    {
                        //如果这两个数字的标记只存在于相同的两个格子
                        if (markInIndex[p] == markInIndex[p + q])
                        {
                            //数字1
                            int num1 = p + 1;
                            //数字2
                            int num2 = p + q + 1;
                            //格子1列号
                            int c1 = int.Parse(markInIndex[p].Substring(0, 1));
                            //格子2列号
                            int c2 = int.Parse(markInIndex[p].Substring(1, 1));
                            //格子1下标
                            int index1 = GetCellIndexWithRowColumn(r, c1);
                            //格子2下标
                            int index2 = GetCellIndexWithRowColumn(r, c2);
                            //这两个格子的标记只能是这两个数字
                            string mark = num1.ToString() + num2.ToString();
                            anyNumberFilled = UpdateMark(index1, mark) || anyNumberFilled;
                            anyNumberFilled = UpdateMark(index2, mark) || anyNumberFilled;
                        }
                    }
                }

            }
            //遍历每一列
            for (int c = 0; c < 9; c++)
            {
                if (Columns[c].GetCount() > 7) continue;
                string[] markInIndex = new string[9];
                for (int num = 1; num <= 9; num++)
                {
                    markInIndex[num - 1] = "";
                    if (Columns[c].Contains(num)) continue;
                    string markS = "";
                    for (int r = 0; r < 9; r++)
                    {
                        int index = GetCellIndexWithRowColumn(r, c);
                        if ((Map[index] == 0) && (MarkMap[index].Contains(num.ToString())))
                        {
                            markS = markS + r;
                            markInIndex[num - 1] = markS;
                        }
                    }
                }
                for (int p = 0; p < 8; p++)
                {
                    if (markInIndex[p] == "") continue;
                    if (markInIndex[p].Length >= 3) continue;
                    for (int q = 1; q < 9 - p; q++)
                    {
                        if (markInIndex[p] == markInIndex[p + q])
                        {
                            int num1 = p + 1;
                            int num2 = p + q + 1;
                            int r1 = int.Parse(markInIndex[p].Substring(0, 1));
                            int r2 = int.Parse(markInIndex[p].Substring(1, 1));
                            int index1 = GetCellIndexWithRowColumn(r1, c);
                            int index2 = GetCellIndexWithRowColumn(r2, c);
                            string mark = num1.ToString() + num2.ToString();
                            anyNumberFilled = UpdateMark(index1, mark) || anyNumberFilled;
                            anyNumberFilled = UpdateMark(index2, mark) || anyNumberFilled;
                        }
                    }
                }
            }

            //遍历每一宫
            for (int z = 0; z < 9; z++)
            {
                if (Zooms[z].GetCount() > 7) continue;
                string[] markInIndex = new string[9];
                for (int num = 1; num <= 9; num++)
                {
                    markInIndex[num - 1] = "";
                    if (Zooms[z].Contains(num)) continue;
                    string markS = "";
                    for (int zi = 0; zi < 9; zi++)
                    {
                        int index = GetCellIndexWithZoomInfo(z, zi / 3, zi % 3);
                        if ((Map[index] == 0) && (MarkMap[index].Contains(num.ToString())))
                        {
                            markS = markS + zi;
                            markInIndex[num - 1] = markS;
                        }
                    }
                }
                for (int p = 0; p < 8; p++)
                {
                    if (markInIndex[p] == "") continue;
                    if (markInIndex[p].Length >= 3) continue;
                    for (int q = 1; q < 9 - p; q++)
                    {
                        if (markInIndex[p] == markInIndex[p + q])
                        {
                            int num1 = p + 1;
                            int num2 = p + q + 1;
                            int zi1 = int.Parse(markInIndex[p].Substring(0, 1));
                            int zi2 = int.Parse(markInIndex[p].Substring(1, 1));
                            int index1 = GetCellIndexWithZoomInfo(z, zi1 / 3, zi1 % 3);
                            int index2 = GetCellIndexWithZoomInfo(z, zi2 / 3, zi2 % 3);
                            string mark = num1.ToString() + num2.ToString();
                            anyNumberFilled = UpdateMark(index1, mark) || anyNumberFilled;
                            anyNumberFilled = UpdateMark(index2, mark) || anyNumberFilled;
                        }
                    }
                }

            }
            return anyNumberFilled;
        }

5.技巧5,三数组摒除

        /// <summary>
        /// 三数组摒除
        /// 如果某行、某列或者某个宫内找到这样的三格,有三个候选数只在这三格出现过,那么这三个候选数一定在这三格中,删除这三个中的其他标记
        /// </summary>
        /// <returns></returns>
        private bool HiddenTripple()
        {
            //标记位,是否填入数字或者剔除标记
            bool anyNumberFilled = false;
            //遍历每一行
            for (int r = 0; r < 9; r++)
            {
                //如果这一行未填的格子少于三个,那么下一行
                if (Rows[r].GetCount() > 6) continue;
                //储存每个数字所在的列号
                string[] markInIndex = new string[9];
                //遍历数字1-9
                for (int num = 1; num <= 9; num++)
                {
                    //下标从0开始,初始化为""
                    markInIndex[num - 1] = "";
                    //如果这一行已经填过这个数字,那么下一个数字
                    if (Rows[r].Contains(num)) continue;
                    //遍历这一行的每一格
                    for (int c = 0; c < 9; c++)
                    {
                        //计算格子下标
                        int index = GetCellIndexWithRowColumn(r, c);
                        //如果这个格子没有填数,并且标记里面含有这个数字,保存列号
                        if ((Map[index] == 0) && (MarkMap[index].Contains(num.ToString())))
                        {
                            markInIndex[num - 1] = markInIndex[num - 1] + c.ToString();
                        }
                    }
                }
                //遍历所有三个数字组合
                for (int p = 0; p < 7; p++)
                {
                    //如果这一行不存在这个数字的标记,或者有这个数字标记的格子超过4个,那么下一个数字
                    if (markInIndex[p] == "" || markInIndex[p].Length >= 4) continue;
                    for (int q = 1; q < 8 - p; q++)
                    {
                        if (markInIndex[p + q] == "" || markInIndex[p + q].Length >= 4) continue;
                        for (int k = 1; k < 9 - p - q; k++)
                        {
                            if (markInIndex[p + q + k] == "" || markInIndex[p + q + k].Length >= 4) continue;
                            //字典,判断有这三个数字标记的格子是否处在相同的三列
                            Dictionary<string, int> indexDic = new Dictionary<string, int>();
                            //将第一个数字标记存在的列号加到字典
                            for (int m = 0; m < markInIndex[p].Length; m++)
                            {
                                string s = markInIndex[p].Substring(m, 1);
                                if (!indexDic.ContainsKey(s))
                                {
                                    indexDic.Add(s, 0);
                                }
                            }
                            //将第二个数字标记存在的列号加到字典
                            for (int m = 0; m < markInIndex[p + q].Length; m++)
                            {
                                string s = markInIndex[p + q].Substring(m, 1);
                                if (!indexDic.ContainsKey(s))
                                {
                                    indexDic.Add(s, 0);
                                }
                            }
                            //将第三个数字标记存在的列号加到字典
                            for (int m = 0; m < markInIndex[p + q + k].Length; m++)
                            {
                                string s = markInIndex[p + q + k].Substring(m, 1);
                                if (!indexDic.ContainsKey(s))
                                {
                                    indexDic.Add(s, 0);
                                }
                            }
                            //如果这三个数字标记正好处于相同的三列里面
                            if (indexDic.Count <= 3)
                            {
                                //数字1
                                int num1 = p + 1;
                                //数字2
                                int num2 = p + q + 1;
                                //数字3
                                int num3 = p + q + k + 1;
                                //数组取出字典里的列号
                                int[] indexArr = new int[indexDic.Count];
                                int indexArr_i = 0;
                                foreach (var item in indexDic.Keys)
                                {
                                    indexArr[indexArr_i] = int.Parse(item);
                                    indexArr_i++;
                                }
                                //格子1下标
                                int cellIndex1 = 9 * r + indexArr[0];
                                string s = "";
                                string mark = MarkMap[cellIndex1];
                                //剔除格子1里面除了这三个数字以外的其他标记
                                if (mark.Contains(num1.ToString()))
                                {
                                    s = s + num1.ToString();
                                }
                                if (mark.Contains(num2.ToString()))
                                {
                                    s = s + num2.ToString();
                                }
                                if (mark.Contains(num3.ToString()))
                                {
                                    s = s + num3.ToString();
                                }
                                anyNumberFilled = UpdateMark(cellIndex1, s) || anyNumberFilled;
                                //格子2下标
                                int cellIndex2 = 9 * r + indexArr[1];
                                s = "";
                                mark = MarkMap[cellIndex2];
                                //剔除格子2里面除了这三个数字以外的其他标记
                                if (mark.Contains(num1.ToString()))
                                {
                                    s = s + num1.ToString();
                                }
                                if (mark.Contains(num2.ToString()))
                                {
                                    s = s + num2.ToString();
                                }
                                if (mark.Contains(num3.ToString()))
                                {
                                    s = s + num3.ToString();
                                }
                                anyNumberFilled = UpdateMark(cellIndex2, s) || anyNumberFilled;

                                
                                if (indexDic.Count == 3)
                                {
                                    //格子3下标
                                    int cellIndex3 = 9 * r + indexArr[2];
                                    s = "";
                                    mark = MarkMap[cellIndex3];
                                    //剔除格子3里面除了这三个数字以外的其他标记
                                    if (mark.Contains(num1.ToString()))
                                    {
                                        s = s + num1.ToString();
                                    }
                                    if (mark.Contains(num2.ToString()))
                                    {
                                        s = s + num2.ToString();
                                    }
                                    if (mark.Contains(num3.ToString()))
                                    {
                                        s = s + num3.ToString();
                                    }
                                    anyNumberFilled = UpdateMark(cellIndex3, s) || anyNumberFilled;


                                }
                            }

                        }
                    }
                }

            }
            //遍历每一列
            for (int c = 0; c < 9; c++)
            {
                if (Columns[c].GetCount() > 6) continue;
                string[] markOrNot = new string[9];
                for (int num = 1; num <= 9; num++)
                {
                    markOrNot[num - 1] = "";
                    if (Columns[c].Contains(num)) continue;
                    for (int r = 0; r < 9; r++)
                    {
                        int index = GetCellIndexWithRowColumn(r, c);
                        if ((Map[index] == 0) && (MarkMap[index].Contains(num.ToString())))
                        {
                            markOrNot[num - 1] = markOrNot[num - 1] + r.ToString();
                        }
                    }
                }
                for (int p = 0; p < 7; p++)
                {
                    if (markOrNot[p] == "" || markOrNot[p].Length >= 4) continue;
                    for (int q = 1; q < 8 - p; q++)
                    {
                        if (markOrNot[p + q] == "" || markOrNot[p + q].Length >= 4) continue;
                        for (int k = 1; k < 9 - p - q; k++)
                        {
                            if (markOrNot[p + q + k] == "" || markOrNot[p + q + k].Length >= 4) continue;

                            Dictionary<string, int> indexDic = new Dictionary<string, int>();
                            for (int m = 0; m < markOrNot[p].Length; m++)
                            {
                                string s = markOrNot[p].Substring(m, 1);
                                if (!indexDic.ContainsKey(s))
                                {
                                    indexDic.Add(s, 0);
                                }
                            }
                            for (int m = 0; m < markOrNot[p + q].Length; m++)
                            {
                                string s = markOrNot[p + q].Substring(m, 1);
                                if (!indexDic.ContainsKey(s))
                                {
                                    indexDic.Add(s, 0);
                                }
                            }
                            for (int m = 0; m < markOrNot[p + q + k].Length; m++)
                            {
                                string s = markOrNot[p + q + k].Substring(m, 1);
                                if (!indexDic.ContainsKey(s))
                                {
                                    indexDic.Add(s, 0);
                                }
                            }
                            if (indexDic.Count <= 3)
                            {
                                int num1 = p + 1;
                                int num2 = p + q + 1;
                                int num3 = p + q + k + 1;
                                int[] indexArr = new int[indexDic.Count];
                                int indexArr_i = 0;
                                foreach (var item in indexDic.Keys)
                                {
                                    indexArr[indexArr_i] = int.Parse(item);
                                    indexArr_i++;
                                }
                                int cellIndex1 = c + 9 * indexArr[0];
                                string s = "";
                                string mark = MarkMap[cellIndex1];
                                if (mark.Contains(num1.ToString()))
                                {
                                    s = s + num1.ToString();
                                }
                                if (mark.Contains(num2.ToString()))
                                {
                                    s = s + num2.ToString();
                                }
                                if (mark.Contains(num3.ToString()))
                                {
                                    s = s + num3.ToString();
                                }
                                anyNumberFilled = UpdateMark(cellIndex1, s) || anyNumberFilled;

                                int cellIndex2 = c + 9 * indexArr[1];
                                s = "";
                                mark = MarkMap[cellIndex2];
                                if (mark.Contains(num1.ToString()))
                                {
                                    s = s + num1.ToString();
                                }
                                if (mark.Contains(num2.ToString()))
                                {
                                    s = s + num2.ToString();
                                }
                                if (mark.Contains(num3.ToString()))
                                {
                                    s = s + num3.ToString();
                                }
                                anyNumberFilled = UpdateMark(cellIndex2, s) || anyNumberFilled;

                                if (indexDic.Count == 3)
                                {
                                    int cellIndex3 = c + 9 * indexArr[2];
                                    s = "";
                                    mark = MarkMap[cellIndex3];
                                    if (mark.Contains(num1.ToString()))
                                    {
                                        s = s + num1.ToString();
                                    }
                                    if (mark.Contains(num2.ToString()))
                                    {
                                        s = s + num2.ToString();
                                    }
                                    if (mark.Contains(num3.ToString()))
                                    {
                                        s = s + num3.ToString();
                                    }
                                    anyNumberFilled = UpdateMark(cellIndex3, s) || anyNumberFilled;
                                }
                            }

                        }
                    }
                }

            }
            //遍历每一宫
            for (int z = 0; z < 9; z++)
            {
                if (Zooms[z].GetCount() > 6) continue;
                string[] markOrNot = new string[9];
                for (int num = 1; num <= 9; num++)
                {
                    markOrNot[num - 1] = "";
                    if (Zooms[z].Contains(num)) continue;
                    for (int zi = 0; zi < 9; zi++)
                    {
                        int index = GetCellIndexWithZoomInfo(z, zi / 3, zi % 3);
                        if ((Map[index] == 0) && (MarkMap[index].Contains(num.ToString())))
                        {
                            markOrNot[num - 1] = markOrNot[num - 1] + zi.ToString();
                        }
                    }
                }
                for (int p = 0; p < 7; p++)
                {
                    if (markOrNot[p] == "" || markOrNot[p].Length >= 4) continue;
                    for (int q = 1; q < 8 - p; q++)
                    {
                        if (markOrNot[p + q] == "" || markOrNot[p + q].Length >= 4) continue;

                        for (int k = 1; k < 9 - p - q; k++)
                        {
                            if (markOrNot[p + q + k] == "" || markOrNot[p + q + k].Length >= 4) continue;

                            Dictionary<string, int> indexDic = new Dictionary<string, int>();
                            for (int m = 0; m < markOrNot[p].Length; m++)
                            {
                                string s = markOrNot[p].Substring(m, 1);
                                if (!indexDic.ContainsKey(s))
                                {
                                    indexDic.Add(s, 0);
                                }
                            }
                            for (int m = 0; m < markOrNot[p + q].Length; m++)
                            {
                                string s = markOrNot[p + q].Substring(m, 1);
                                if (!indexDic.ContainsKey(s))
                                {
                                    indexDic.Add(s, 0);
                                }
                            }
                            for (int m = 0; m < markOrNot[p + q + k].Length; m++)
                            {
                                string s = markOrNot[p + q + k].Substring(m, 1);
                                if (!indexDic.ContainsKey(s))
                                {
                                    indexDic.Add(s, 0);
                                }
                            }

                            if (indexDic.Count <= 3)
                            {
                                int num1 = p + 1;
                                int num2 = p + q + 1;
                                int num3 = p + q + k + 1;

                                int[] indexArr = new int[indexDic.Count];
                                int indexArr_i = 0;
                                foreach (var item in indexDic.Keys)
                                {
                                    indexArr[indexArr_i] = int.Parse(item);
                                    indexArr_i++;
                                }
                                int cellIndex1 = GetCellIndexWithZoomInfo(z, indexArr[0] / 3, indexArr[0] % 3);
                                string s = "";
                                string mark = MarkMap[cellIndex1];
                                if (mark.Contains(num1.ToString()))
                                {
                                    s = s + num1.ToString();
                                }
                                if (mark.Contains(num2.ToString()))
                                {
                                    s = s + num2.ToString();
                                }
                                if (mark.Contains(num3.ToString()))
                                {
                                    s = s + num3.ToString();
                                }
                                anyNumberFilled = UpdateMark(cellIndex1, s) || anyNumberFilled;


                                int cellIndex2 = GetCellIndexWithZoomInfo(z, indexArr[1] / 3, indexArr[1] % 3);
                                s = "";
                                mark = MarkMap[cellIndex2];
                                if (mark.Contains(num1.ToString()))
                                {
                                    s = s + num1.ToString();
                                }
                                if (mark.Contains(num2.ToString()))
                                {
                                    s = s + num2.ToString();
                                }
                                if (mark.Contains(num3.ToString()))
                                {
                                    s = s + num3.ToString();
                                }
                                anyNumberFilled = UpdateMark(cellIndex2, s) || anyNumberFilled;



                                if (indexDic.Count == 3)
                                {
                                    int cellIndex3 = GetCellIndexWithZoomInfo(z, indexArr[2] / 3, indexArr[2] % 3);
                                    s = "";
                                    mark = MarkMap[cellIndex3];
                                    if (mark.Contains(num1.ToString()))
                                    {
                                        s = s + num1.ToString();
                                    }
                                    if (mark.Contains(num2.ToString()))
                                    {
                                        s = s + num2.ToString();
                                    }
                                    if (mark.Contains(num3.ToString()))
                                    {
                                        s = s + num3.ToString();
                                    }
                                    anyNumberFilled = UpdateMark(cellIndex3, s) || anyNumberFilled;


                                }
                            }

                        }
                    }
                }

            }
            return anyNumberFilled;
        }

6.技巧6,显性数对+数对占位

        /// <summary>
        /// 显性数对+数对占位
        /// 如果在一个单元里面找到两个拥有相同两个候选数的格子,那么这个单元的其他格子剔除这两个候选数
        /// </summary>
        /// <returns></returns>
        private bool NakedPair()
        {
            //标记位,是否填入数字或剔除标记
            bool anyNumberFilled = false;
            //遍历每一行
            for (int r = 0; r < 9; r++)
            {
                //如果这行未填的格子少于2格,那么下一行
                if (Rows[r].GetCount() > 7) continue;
                //遍历这一行的所有两格组合,寻找两格有且仅有相同两个候选数的
                for (int p = 0; p < 8; p++)
                {
                    //格子1下标
                    int cellIndex1 = GetCellIndexWithRowColumn(r, p);
                    //要求这一格未填写且仅有两个候选数
                    if (Map[cellIndex1] == 0 && MarkMap[cellIndex1].Length == 2)
                    {
                        //遍历这一行所有的两格组合
                        for (int q = 1; q < 9 - p; q++)
                        {
                            //格子2下标
                            int cellIndex2 = GetCellIndexWithRowColumn(r, p + q);
                            //要求这一格未填写且仅有两个候选数
                            if (Map[cellIndex2] == 0 && MarkMap[cellIndex2].Length == 2)
                            {
                                //如果格子1和格子2的标记是一样的
                                if (MarkMap[cellIndex1] == MarkMap[cellIndex2])
                                {
                                    string mark = MarkMap[cellIndex1];
                                    //标记中的第一个数字
                                    int num1 = int.Parse(mark.Substring(0, 1));
                                    //标记中的第二个数字
                                    int num2 = int.Parse(mark.Substring(1, 1));
                                    //遍历这一行的所有格子,除了这两格以外,清除其他格子这两个数字的标记
                                    for (int c = 0; c < 9; c++)
                                    {
                                        //判断不是上述两格
                                        if (c != p && c != (p + q))
                                        {
                                            //格子下标
                                            int cellIndex = GetCellIndexWithRowColumn(r, c);
                                            //清除格子中关于这两个数字的标记
                                            string markOfIndex = MarkMap[cellIndex];
                                            if (Map[cellIndex] == 0)
                                            {
                                                markOfIndex = markOfIndex.Replace(num1.ToString(), "");
                                                markOfIndex = markOfIndex.Replace(num2.ToString(), "");
                                            }
                                            anyNumberFilled = UpdateMark(cellIndex, markOfIndex) || anyNumberFilled;

                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            //遍历每一列
            for (int c = 0; c < 9; c++)
            {
                if (Columns[c].GetCount() > 7) continue;
                for (int p = 0; p < 8; p++)
                {
                    int cellIndex1 = GetCellIndexWithRowColumn(p, c);
                    if (Map[cellIndex1] == 0 && MarkMap[cellIndex1].Length == 2)
                    {
                        for (int q = 1; q < 9 - p; q++)
                        {
                            int cellIndex2 = GetCellIndexWithRowColumn(p + q, c);
                            if (Map[cellIndex2] == 0 && MarkMap[cellIndex2].Length == 2)
                            {
                                if (MarkMap[cellIndex1] == MarkMap[cellIndex2])
                                {
                                    string mark = MarkMap[cellIndex1];
                                    int num1 = int.Parse(mark.Substring(0, 1));
                                    int num2 = int.Parse(mark.Substring(1, 1));
                                    for (int r = 0; r < 9; r++)
                                    {
                                        if (r != p && r != (p + q))
                                        {
                                            int cellIndex = GetCellIndexWithRowColumn(r, c);
                                            string markOfIndex = MarkMap[cellIndex];
                                            if (Map[cellIndex] == 0)
                                            {
                                                markOfIndex = markOfIndex.Replace(num1.ToString(), "");
                                                markOfIndex = markOfIndex.Replace(num2.ToString(), "");
                                            }
                                            anyNumberFilled = UpdateMark(cellIndex, markOfIndex) || anyNumberFilled;

                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            //遍历每一宫
            for (int z = 0; z < 9; z++)
            {
                if (Zooms[z].GetCount() > 7) continue;
                for (int p = 0; p < 8; p++)
                {
                    int cellIndex1 = GetCellIndexWithZoomInfo(z, p / 3, p % 3);
                    if (Map[cellIndex1] == 0 && MarkMap[cellIndex1].Length == 2)
                    {
                        for (int q = 1; q < 9 - p; q++)
                        {
                            int cellIndex2 = GetCellIndexWithZoomInfo(z, (p + q) / 3, (p + q) % 3);
                            if (Map[cellIndex2] == 0 && MarkMap[cellIndex2].Length == 2)
                            {
                                if (MarkMap[cellIndex1] == MarkMap[cellIndex2])
                                {
                                    string mark = MarkMap[cellIndex1];
                                    int num1 = int.Parse(mark.Substring(0, 1));
                                    int num2 = int.Parse(mark.Substring(1, 1));
                                    for (int i = 0; i < 9; i++)
                                    {
                                        if (i != p && i != (p + q))
                                        {
                                            int cellIndex = GetCellIndexWithZoomInfo(z, i / 3, i % 3);
                                            string markOfIndex = MarkMap[cellIndex];
                                            if (Map[cellIndex] == 0)
                                            {
                                                markOfIndex = markOfIndex.Replace(num1.ToString(), "");
                                                markOfIndex = markOfIndex.Replace(num2.ToString(), "");
                                            }
                                            anyNumberFilled = UpdateMark(cellIndex, markOfIndex) || anyNumberFilled;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return anyNumberFilled;
        }

7.技巧7,显性三数组+三元数组占位

        /// <summary>
        /// 显性三数组+三元数组占位
        /// </summary>
        /// <returns></returns>
        private bool NakedTriple()
        {
            //标记位,是否填入数字或者清除标记
            bool anyNumberFilled = false;
            //遍历每一行
            for (int r = 0; r < 9; r++)
            {
                //如果这一行未填的格子最多只有3个,那么无需用这个方法排除其余格子
                if (Rows[r].GetCount() > 5) continue;
                //遍历所有的三格组合
                for (int c = 0; c < 7; c++)
                {
                    //格子1下标
                    int index1 = GetCellIndexWithRowColumn(r, c);
                    //如果这个格子已经填了数,那么下一格
                    if (Map[index1] == 0)
                    {
                        //遍历所有的三格组合
                        for (int j = 1; j < 8 - c; j++)
                        {
                            //格子2下标
                            int index2 = GetCellIndexWithRowColumn(r, c + j);
                            //如果这个格子已经填了数,那么下一格
                            if (Map[index2] == 0)
                            {
                                //遍历所有的三格组合
                                for (int k = 1; k < 9 - j - c; k++)
                                {
                                    //格子3下标
                                    int index3 = GetCellIndexWithRowColumn(r, c + j + k);
                                    //如果这个格子已经填了数,那么下一格
                                    if (Map[index3] == 0)
                                    {
                                        //字典用来判断三个格子里面是否刚好是三个相同的数字标记
                                        Dictionary<int, int> numDic = new Dictionary<int, int>();
                                        //将三个格子里面的标记加到字典中
                                        string mark = MarkMap[index1];
                                        for (int n = 0; n < mark.Length; n++)
                                        {
                                            int num = int.Parse(mark.Substring(n, 1));
                                            if (!numDic.ContainsKey(num)) numDic.Add(num, 0);
                                        }
                                        mark = MarkMap[index2];
                                        for (int n = 0; n < mark.Length; n++)
                                        {
                                            int num = int.Parse(mark.Substring(n, 1));
                                            if (!numDic.ContainsKey(num)) numDic.Add(num, 0);
                                        }
                                        mark = MarkMap[index3];
                                        for (int n = 0; n < mark.Length; n++)
                                        {
                                            int num = int.Parse(mark.Substring(n, 1));
                                            if (!numDic.ContainsKey(num)) numDic.Add(num, 0);
                                        }
                                        //如果字典的成员为,说明这三个格子里只包含这三个数字的标记,那么这三个格子必定只能填这三个数字
                                        //清除这一行除这三个格子以外其他格子的这三个数字标记
                                        if (numDic.Count == 3)
                                        {
                                            //遍历这一行的所有格子
                                            for (int l = 0; l < 9; l++)
                                            {
                                                //如果是上面的三格之一,那么下一格
                                                if (l != c && l != (c + j) && l != (c + j + k))
                                                {
                                                    //计算格子下标
                                                    int cellIndex = GetCellIndexWithRowColumn(r, l);
                                                    //如果格子没有填数,那么清除格子里面这三个数字的标记
                                                    if (Map[cellIndex] == 0)
                                                    {
                                                        string markofIndex = MarkMap[cellIndex];
                                                        foreach (var item in numDic.Keys)
                                                        {
                                                            markofIndex = markofIndex.Replace(item.ToString(), "");
                                                        }
                                                        anyNumberFilled = UpdateMark(cellIndex, markofIndex) || anyNumberFilled;
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            //遍历每一列
            for (int c = 0; c < 9; c++)
            {
                if (Columns[c].GetCount() > 5) continue;
                for (int r = 0; r < 7; r++)
                {
                    int index1 = GetCellIndexWithRowColumn(r, c);
                    if (Map[index1] == 0)
                    {
                        for (int j = 1; j < 8 - r; j++)
                        {
                            int index2 = GetCellIndexWithRowColumn(r + j, c);
                            if (Map[index2] == 0)
                            {
                                for (int k = 1; k < 9 - j - r; k++)
                                {
                                    int index3 = GetCellIndexWithRowColumn(r + j + k, c);
                                    if (Map[index3] == 0)
                                    {
                                        Dictionary<int, int> numDic = new Dictionary<int, int>();
                                        string mark = MarkMap[index1];
                                        for (int n = 0; n < mark.Length; n++)
                                        {
                                            int num = int.Parse(mark.Substring(n, 1));
                                            if (!numDic.ContainsKey(num)) numDic.Add(num, 0);
                                        }
                                        mark = MarkMap[index2];
                                        for (int n = 0; n < mark.Length; n++)
                                        {
                                            int num = int.Parse(mark.Substring(n, 1));
                                            if (!numDic.ContainsKey(num)) numDic.Add(num, 0);
                                        }
                                        mark = MarkMap[index3];
                                        for (int n = 0; n < mark.Length; n++)
                                        {
                                            int num = int.Parse(mark.Substring(n, 1));
                                            if (!numDic.ContainsKey(num)) numDic.Add(num, 0);
                                        }

                                        if (numDic.Count == 3)
                                        {
                                            for (int l = 0; l < 9; l++)
                                            {
                                                if (l != r && l != (r + j) && l != (r + j + k))
                                                {
                                                    int cellIndex = GetCellIndexWithRowColumn(l, c);
                                                    if (Map[cellIndex] == 0)
                                                    {
                                                        string markofIndex = MarkMap[cellIndex];
                                                        foreach (var item in numDic.Keys)
                                                        {
                                                            markofIndex = markofIndex.Replace(item.ToString(), "");
                                                        }
                                                        anyNumberFilled = UpdateMark(cellIndex, markofIndex) || anyNumberFilled;

                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            //遍历每一宫
            for (int z = 0; z < 9; z++)
            {
                if (Zooms[z].GetCount() > 5) continue;
                for (int zi = 0; zi < 7; zi++)
                {
                    int index1 = GetCellIndexWithZoomInfo(z, zi / 3, zi % 3);
                    if (Map[index1] == 0)
                    {
                        for (int j = 1; j < 8 - zi; j++)
                        {
                            int index2 = GetCellIndexWithZoomInfo(z, (zi + j) / 3, (zi + j) % 3);
                            if (Map[index2] == 0)
                            {
                                for (int k = 1; k < 9 - j - zi; k++)
                                {
                                    int index3 = GetCellIndexWithZoomInfo(z, (zi + j + k) / 3, (zi + j + k) % 3);
                                    if (Map[index3] == 0)
                                    {
                                        Dictionary<int, int> numDic = new Dictionary<int, int>();
                                        string mark = MarkMap[index1];
                                        for (int n = 0; n < mark.Length; n++)
                                        {
                                            int num = int.Parse(mark.Substring(n, 1));
                                            if (!numDic.ContainsKey(num)) numDic.Add(num, 0);
                                        }
                                        mark = MarkMap[index2];
                                        for (int n = 0; n < mark.Length; n++)
                                        {
                                            int num = int.Parse(mark.Substring(n, 1));
                                            if (!numDic.ContainsKey(num)) numDic.Add(num, 0);
                                        }
                                        mark = MarkMap[index3];
                                        for (int n = 0; n < mark.Length; n++)
                                        {
                                            int num = int.Parse(mark.Substring(n, 1));
                                            if (!numDic.ContainsKey(num)) numDic.Add(num, 0);
                                        }

                                        if (numDic.Count == 3)
                                        {
                                            for (int l = 0; l < 9; l++)
                                            {
                                                if (l != zi && l != (zi + j) && l != (zi + j + k))
                                                {
                                                    int cellIndex = GetCellIndexWithZoomInfo(z, l / 3, l % 3);
                                                    if (Map[cellIndex] == 0)
                                                    {
                                                        string markofIndex = MarkMap[cellIndex];
                                                        foreach (var item in numDic.Keys)
                                                        {
                                                            markofIndex = markofIndex.Replace(item.ToString(), "");
                                                        }
                                                        anyNumberFilled = UpdateMark(cellIndex, markofIndex) || anyNumberFilled;

                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return anyNumberFilled;
        }

8.技巧8,四数组摒除

        /// <summary>
        /// 四数组摒除
        /// 有这么四个候选数,只出现在某个单元的四个格子中,那么这四个格子中的其他候选数排除
        /// </summary>
        /// <returns></returns>
        private bool HiddenQuadruple()
        {
            //标记位,是否填入数字或者剔除标记
            bool anyNumberFilled = false;
            //遍历每一行
            for (int r = 0; r < 9; r++)
            {
                //如果未填的格子少于五个,那么没必要用这个方法剔除标记,下一行
                if (Rows[r].GetCount() > 4) continue;
                //遍历所有四个数字组合
                for (int num = 1; num <= 6; num++)
                {
                    //如果这一行已经填过这个数字,下一行
                    if (Rows[r].Contains(num)) continue;
                    //遍历所有四个数字组合
                    for (int j = 1; j <= 7 - num; j++)
                    {
                        //如果这一行已经填过这个数字,下一行
                        if (Rows[r].Contains(num + j)) continue;
                        //遍历所有四个数字组合
                        for (int k = 1; k <= 8 - num - j; k++)
                        {
                            //如果这一行已经填过这个数字,下一行
                            if (Rows[r].Contains(num + j + k)) continue;
                            //遍历所有四个数字组合
                            for (int l = 1; l <= 9 - num - j - k; l++)
                            {
                                //如果这一行已经填过这个数字,下一行
                                if (Rows[r].Contains(num + j + k + l)) continue;
                                //字典,用来判断这四个数字是不是只出现在四格中
                                Dictionary<int, int> indexDic = new Dictionary<int, int>();
                                //遍历这一行的所有格子
                                for (int c = 0; c < 9; c++)
                                {
                                    //格子下标
                                    int index = GetCellIndexWithRowColumn(r, c);
                                    if (Map[index] != 0) continue;
                                    //如果这个格子含有至少一个这四个数字的标记,那么将列号加入字典
                                    if (MarkMap[index].Contains(num.ToString()) ||
                                        MarkMap[index].Contains((num + j).ToString()) ||
                                        MarkMap[index].Contains((num + j + k).ToString()) ||
                                        MarkMap[index].Contains((num + j + k + l).ToString()))
                                    {
                                        indexDic.Add(c, 0);
                                    }
                                }
                                //如果有这四个数字标记的格子少于等于4个,那么排除这四个格子里面其余数字的标记
                                if (indexDic.Count <= 4)
                                {
                                    //排除这四个格子里面其余数字的标记
                                    foreach (var item in indexDic.Keys)
                                    {
                                        int index = GetCellIndexWithRowColumn(r, item);
                                        string mark = MarkMap[index];
                                        string revMark = "";
                                        if (mark.Contains(num.ToString()))
                                        {
                                            revMark = revMark + num;
                                        }
                                        if (mark.Contains((num + j).ToString()))
                                        {
                                            revMark = revMark + (num + j);
                                        }
                                        if (mark.Contains((num + j + k).ToString()))
                                        {
                                            revMark = revMark + (num + j + k);
                                        }
                                        if (mark.Contains((num + j + k + l).ToString()))
                                        {
                                            revMark = revMark + (num + j + k + l);
                                        }
                                        anyNumberFilled = UpdateMark(index, revMark) || anyNumberFilled;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            //遍历每一列
            for (int c = 0; c < 9; c++)
            {
                if (Columns[c].GetCount() > 4) continue;
                for (int num = 1; num <= 6; num++)
                {
                    if (Columns[c].Contains(num)) continue;
                    for (int j = 1; j <= 7 - num; j++)
                    {
                        if (Columns[c].Contains(num + j)) continue;
                        for (int k = 1; k <= 8 - num - j; k++)
                        {
                            if (Columns[c].Contains(num + j + k)) continue;
                            for (int l = 1; l <= 9 - num - j - k; l++)
                            {
                                if (Columns[c].Contains(num + j + k + l)) continue;
                                Dictionary<int, int> indexDic = new Dictionary<int, int>();
                                for (int r = 0; r < 9; r++)
                                {
                                    int index = GetCellIndexWithRowColumn(r, c);
                                    if (Map[index] != 0) continue;
                                    if (MarkMap[index].Contains(num.ToString()) ||
                                        MarkMap[index].Contains((num + j).ToString()) ||
                                        MarkMap[index].Contains((num + j + k).ToString()) ||
                                        MarkMap[index].Contains((num + j + k + l).ToString()))
                                    {
                                        indexDic.Add(r, 0);
                                    }
                                }
                                if (indexDic.Count <= 4)
                                {
                                    foreach (var item in indexDic.Keys)
                                    {
                                        int index = GetCellIndexWithRowColumn(item, c);
                                        string mark = MarkMap[index];
                                        string revMark = "";
                                        if (mark.Contains(num.ToString()))
                                        {
                                            revMark = revMark + num;
                                        }
                                        if (mark.Contains((num + j).ToString()))
                                        {
                                            revMark = revMark + (num + j);
                                        }
                                        if (mark.Contains((num + j + k).ToString()))
                                        {
                                            revMark = revMark + (num + j + k);
                                        }
                                        if (mark.Contains((num + j + k + l).ToString()))
                                        {
                                            revMark = revMark + (num + j + k + l);
                                        }
                                        anyNumberFilled = UpdateMark(index, revMark) || anyNumberFilled;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            //遍历每一宫
            for (int z = 0; z < 9; z++)
            {
                if (Zooms[z].GetCount() > 4) continue;
                for (int num = 1; num <= 6; num++)
                {
                    if (Zooms[z].Contains(num)) continue;
                    for (int j = 1; j <= 7 - num; j++)
                    {
                        if (Zooms[z].Contains(num + j)) continue;
                        for (int k = 1; k <= 8 - num - j; k++)
                        {
                            if (Zooms[z].Contains(num + j + k)) continue;
                            for (int l = 1; l <= 9 - num - j - k; l++)
                            {
                                if (Zooms[z].Contains(num + j + k + l)) continue;
                                Dictionary<int, int> indexDic = new Dictionary<int, int>();
                                for (int zi = 0; zi < 9; zi++)
                                {
                                    int index = GetCellIndexWithZoomInfo(z, zi / 3, zi % 3);
                                    if (Map[index] != 0) continue;
                                    if (MarkMap[index].Contains(num.ToString()) ||
                                        MarkMap[index].Contains((num + j).ToString()) ||
                                        MarkMap[index].Contains((num + j + k).ToString()) ||
                                        MarkMap[index].Contains((num + j + k + l).ToString()))
                                    {
                                        indexDic.Add(zi, 0);
                                    }
                                }
                                if (indexDic.Count <= 4)
                                {
                                    foreach (var item in indexDic.Keys)
                                    {
                                        int index = GetCellIndexWithZoomInfo(z, item / 3, item % 3);
                                        string mark = MarkMap[index];
                                        string revMark = "";
                                        if (mark.Contains(num.ToString()))
                                        {
                                            revMark = revMark + num;
                                        }
                                        if (mark.Contains((num + j).ToString()))
                                        {
                                            revMark = revMark + (num + j);
                                        }
                                        if (mark.Contains((num + j + k).ToString()))
                                        {
                                            revMark = revMark + (num + j + k);
                                        }
                                        if (mark.Contains((num + j + k + l).ToString()))
                                        {
                                            revMark = revMark + (num + j + k + l);
                                        }
                                        anyNumberFilled = UpdateMark(index, revMark) || anyNumberFilled;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return anyNumberFilled;
        }

9.技巧9,显性四数组

        /// <summary>
        /// 显性四数组
        /// </summary>
        /// <returns></returns>
        private bool NakedQuadruple()
        {
            //标记位,是否填入数字或剔除标记
            bool anyNumberFilled = false;
            //遍历每一行
            for (int r = 0; r < 9; r++)
            {
                //如果未填的格子少于五个,那么没必要用这个方法剔除标记,下一行
                if (Rows[r].GetCount() > 4) continue;
                //遍历所有的四格组合
                for (int c = 0; c < 6; c++)
                {
                    //格子1下标
                    int index1 = GetCellIndexWithRowColumn(r, c);
                    //如果这个格子已经填了数,那么下一格
                    if (Map[index1] != 0) continue;
                    //遍历所有的四格组合
                    for (int j = 1; j < 7 - c; j++)
                    {
                        //格子2下标
                        int index2 = GetCellIndexWithRowColumn(r, c + j);
                        //如果这个格子已经填了数,那么下一格
                        if (Map[index2] != 0) continue;
                        //遍历所有的四格组合
                        for (int k = 1; k < 8 - c - j; k++)
                        {
                            //格子3下标
                            int index3 = GetCellIndexWithRowColumn(r, c + j + k);
                            //如果这个格子已经填了数,下一格
                            if (Map[index3] != 0) continue;
                            //遍历所有的四格组合
                            for (int l = 1; l < 9 - c - j - k; l++)
                            {
                                //格子4下标
                                int index4 = GetCellIndexWithRowColumn(r, c + j + k + l);
                                //如果这个格子已经填了数,下一格
                                if (Map[index4] != 0) continue;
                                //字典用来判断这四个格子里面的标记是否少于等于四个
                                Dictionary<int, int> numDic = new Dictionary<int, int>();
                                //将这四个格子的标记添加到字典
                                string mark = MarkMap[index1];
                                for (int m = 0; m < mark.Length; m++)
                                {
                                    int num = int.Parse(mark.Substring(m, 1));
                                    if (!numDic.ContainsKey(num)) numDic.Add(num, 0);
                                }
                                mark = MarkMap[index2];
                                for (int m = 0; m < mark.Length; m++)
                                {
                                    int num = int.Parse(mark.Substring(m, 1));
                                    if (!numDic.ContainsKey(num)) numDic.Add(num, 0);
                                }
                                mark = MarkMap[index3];
                                for (int m = 0; m < mark.Length; m++)
                                {
                                    int num = int.Parse(mark.Substring(m, 1));
                                    if (!numDic.ContainsKey(num)) numDic.Add(num, 0);
                                }
                                mark = MarkMap[index4];
                                for (int m = 0; m < mark.Length; m++)
                                {
                                    int num = int.Parse(mark.Substring(m, 1));
                                    if (!numDic.ContainsKey(num)) numDic.Add(num, 0);
                                }
                                //如果字典成员少于等于四个,排除这一行其余格子的这四个数字标记
                                if (numDic.Count <= 4)
                                {
                                    //遍历这一行的所有格子
                                    for (int ci = 0; ci < 9; ci++)
                                    {
                                        //如果是上面四格之一,那么下一格
                                        if (ci != c && ci != (c + j) && ci != (c + j + k) && ci != (c + j + k + l))
                                        {
                                            //格子下标
                                            int index = GetCellIndexWithRowColumn(r, ci);
                                            //如果格子已经填数,下一格
                                            if (Map[index] != 0) continue;
                                            //剔除格子里面四个数字的标记
                                            string markofIndex = MarkMap[index];
                                            foreach (var item in numDic.Keys)
                                            {
                                                markofIndex = markofIndex.Replace(item.ToString(), "");
                                            }
                                            anyNumberFilled = UpdateMark(index, markofIndex) || anyNumberFilled;
                                        }
                                    }
                                }
                            }

                        }
                    }
                }
            }
            //遍历每一列
            for (int c = 0; c < 9; c++)
            {
                if (Columns[c].GetCount() > 4) continue;
                for (int r = 0; r < 6; r++)
                {
                    int index1 = GetCellIndexWithRowColumn(r, c);
                    if (Map[index1] != 0) continue;
                    for (int j = 1; j < 7 - r; j++)
                    {
                        int index2 = GetCellIndexWithRowColumn(r + j, c);
                        if (Map[index2] != 0) continue;
                        for (int k = 1; k < 8 - r - j; k++)
                        {
                            int index3 = GetCellIndexWithRowColumn(r + j + k, c);
                            if (Map[index3] != 0) continue;
                            for (int l = 1; l < 9 - r - j - k; l++)
                            {
                                int index4 = GetCellIndexWithRowColumn(r + j + k + l, c);
                                if (Map[index4] != 0) continue;
                                Dictionary<int, int> numDic = new Dictionary<int, int>();
                                string mark = MarkMap[index1];
                                for (int m = 0; m < mark.Length; m++)
                                {
                                    int num = int.Parse(mark.Substring(m, 1));
                                    if (!numDic.ContainsKey(num)) numDic.Add(num, 0);
                                }
                                mark = MarkMap[index2];
                                for (int m = 0; m < mark.Length; m++)
                                {
                                    int num = int.Parse(mark.Substring(m, 1));
                                    if (!numDic.ContainsKey(num)) numDic.Add(num, 0);
                                }
                                mark = MarkMap[index3];
                                for (int m = 0; m < mark.Length; m++)
                                {
                                    int num = int.Parse(mark.Substring(m, 1));
                                    if (!numDic.ContainsKey(num)) numDic.Add(num, 0);
                                }
                                mark = MarkMap[index4];
                                for (int m = 0; m < mark.Length; m++)
                                {
                                    int num = int.Parse(mark.Substring(m, 1));
                                    if (!numDic.ContainsKey(num)) numDic.Add(num, 0);
                                }

                                if (numDic.Count <= 4)
                                {
                                    for (int ri = 0; ri < 9; ri++)
                                    {
                                        if (ri != r && ri != (r + j) && ri != (r + j + k) && ri != (r + j + k + l))
                                        {
                                            int index = GetCellIndexWithRowColumn(ri, c);
                                            if (Map[index] != 0) continue;
                                            string markofIndex = MarkMap[index];

                                            foreach (var item in numDic.Keys)
                                            {
                                                markofIndex = markofIndex.Replace(item.ToString(), "");
                                            }
                                            anyNumberFilled = UpdateMark(index, markofIndex) || anyNumberFilled;
                                        }
                                    }
                                }
                            }

                        }
                    }
                }
            }
            //遍历每一宫
            for (int z = 0; z < 9; z++)
            {
                if (Zooms[z].GetCount() > 4) continue;
                for (int zi = 0; zi < 6; zi++)
                {
                    int index1 = GetCellIndexWithZoomInfo(z, zi / 3, zi % 3);
                    if (Map[index1] != 0) continue;
                    for (int j = 1; j < 7 - zi; j++)
                    {
                        int index2 = GetCellIndexWithZoomInfo(z, (zi+j) / 3, (zi + j) % 3);
                        if (Map[index2] != 0) continue;
                        for (int k = 1; k < 8 - zi - j; k++)
                        {
                            int index3 = GetCellIndexWithZoomInfo(z, (zi + j + k) / 3, (zi + j + k) % 3);
                            if (Map[index3] != 0) continue;
                            for (int l = 1; l < 9 - zi - j - k; l++)
                            {
                                int index4 = GetCellIndexWithZoomInfo(z, (zi + j + k + l) / 3, (zi + j + k + l) % 3) ;
                                if (Map[index4] != 0) continue;
                                Dictionary<int, int> numDic = new Dictionary<int, int>();
                                string mark = MarkMap[index1];
                                for (int m = 0; m < mark.Length; m++)
                                {
                                    int num = int.Parse(mark.Substring(m, 1));
                                    if (!numDic.ContainsKey(num)) numDic.Add(num, 0);
                                }
                                mark = MarkMap[index2];
                                for (int m = 0; m < mark.Length; m++)
                                {
                                    int num = int.Parse(mark.Substring(m, 1));
                                    if (!numDic.ContainsKey(num)) numDic.Add(num, 0);
                                }
                                mark = MarkMap[index3];
                                for (int m = 0; m < mark.Length; m++)
                                {
                                    int num = int.Parse(mark.Substring(m, 1));
                                    if (!numDic.ContainsKey(num)) numDic.Add(num, 0);
                                }
                                mark = MarkMap[index4];
                                for (int m = 0; m < mark.Length; m++)
                                {
                                    int num = int.Parse(mark.Substring(m, 1));
                                    if (!numDic.ContainsKey(num)) numDic.Add(num, 0);
                                }

                                if (numDic.Count <= 4)
                                {
                                    for (int zii = 0; zii < 9; zii++)
                                    {
                                        if (zii != zi && zii != (zi + j) && zii != (zi + j + k) && zii != (zi + j + k + l))
                                        {
                                            int index = GetCellIndexWithZoomInfo(z, zii / 3, zii % 3);
                                            if (Map[index] != 0) continue;
                                            string markofIndex = MarkMap[index];

                                            foreach (var item in numDic.Keys)
                                            {
                                                markofIndex = markofIndex.Replace(item.ToString(), "");
                                            }
                                            anyNumberFilled = UpdateMark(index, markofIndex) || anyNumberFilled;
                                        }
                                    }
                                }
                            }

                        }
                    }
                }
            }
            return anyNumberFilled;
        }

10.技巧10,X-Wing

        /// <summary>
        /// X-Wing
        /// 如果有两行的两个候选数刚好除在两列上,那么那两列其他行的这个数排除
        /// </summary>
        /// <returns></returns>
        private bool XWing()
        {
            //标记位,是否填入数字或剔除标记
            bool anyNumberFilled = false;
            //遍历数字1-9
            for (int num = 1; num <= 9; num++)
            {
                //遍历所有两行组合
                for (int r = 0; r < 8; r++)
                {
                    //如果这一行未填的格子少于2格,下一行
                    if (Rows[r].GetCount() > 7) continue;
                    //如果这一行已经包含这个数字,下一行
                    if (Rows[r].Contains(num)) continue;
                    //遍历所有两行组合
                    for (int j = 1; j < 9 - r; j++)
                    {
                        //如果这一行未填的格子少于2格,下一行
                        if (Rows[r + j].GetCount() > 7) continue;
                        //如果这一行已经包含这个数字,下一行
                        if (Rows[r + j].Contains(num)) continue;

                        string indexInRow1 = "";
                        string indexInRow2 = "";

                        //遍历这两行的每一格,如果存在这个数字标记,就将列号保存到文本串
                        for (int c = 0; c < 9; c++)
                        {
                            //第一行的格子
                            int index1 = GetCellIndexWithRowColumn(r, c);
                            if (Map[index1] == 0 && MarkMap[index1].Contains(num.ToString())) indexInRow1 = indexInRow1 + c;
                            //第二行的格子
                            int index2 = GetCellIndexWithRowColumn(r + j, c);
                            if (Map[index2] == 0 && MarkMap[index2].Contains(num.ToString())) indexInRow2 = indexInRow2 + c;
                        }
                        //如果这两行的这个数字标记刚好在相同的两列上,排除这两列其他行的标记
                        if ((indexInRow1 == indexInRow2) && (indexInRow1.Length == 2))
                        {
                            //列1
                            int col1 = int.Parse(indexInRow1.Substring(0, 1));
                            //列2
                            int col2 = int.Parse(indexInRow1.Substring(1, 1));
                            //遍历除了这两行的其他行
                            for (int ri = 0; ri < 9; ri++)
                            {
                                if (ri != r && ri != (r + j))
                                {
                                    //格子1,剔除这个数字标记
                                    int index1InCol1 = GetCellIndexWithRowColumn(ri,col1);
                                    if (Map[index1InCol1] == 0)
                                    {
                                        string mark = MarkMap[index1InCol1];
                                        mark = mark.Replace(num.ToString(), "");
                                        anyNumberFilled = UpdateMark(index1InCol1, mark) || anyNumberFilled;
                                    }
                                    //格子2,剔除这个数字标记
                                    int index2InCol2 = GetCellIndexWithRowColumn(ri, col2);
                                    if (Map[index2InCol2] == 0)
                                    {
                                        string mark = MarkMap[index2InCol2];
                                        mark = mark.Replace(num.ToString(), "");
                                        anyNumberFilled = UpdateMark(index2InCol2, mark) || anyNumberFilled;

                                    }
                                }
                            }
                        }

                    }
                }
            }
            //遍历每一列每一个数字
            for (int num = 1; num <= 9; num++)
            {
                for (int c = 0; c < 1; c++)
                {
                    if (Columns[c].GetCount() > 7) continue;
                    if (Columns[c].Contains(num)) continue;
                    for (int j = 1; j < 9 - c; j++)
                    {
                        if (Columns[c + j].GetCount() > 7) continue;
                        if (Columns[c + j].Contains(num)) continue;

                        string indexInColumn1 = "";
                        string indexInColumn2 = "";

                        for (int r = 0; r < 9; r++)
                        {
                            int index1 = GetCellIndexWithRowColumn(r, c);
                            if (Map[index1] == 0 && MarkMap[index1].Contains(num.ToString())) indexInColumn1 = indexInColumn1 + r;
                            int index2 = GetCellIndexWithRowColumn(r, c + j);
                            if (Map[index2] == 0 && MarkMap[index2].Contains(num.ToString())) indexInColumn2 = indexInColumn2 + r;
                        }
                        if ((indexInColumn1 == indexInColumn2) && (indexInColumn1.Length == 2))
                        {
                            int row1 = int.Parse(indexInColumn1.Substring(0, 1));
                            int row2 = int.Parse(indexInColumn1.Substring(1, 1));
                            for (int ci = 0; ci < 9; ci++)
                            {
                                if (ci != c && ci != (c + j))
                                {
                                    int index1InRow1 = GetCellIndexWithRowColumn(row1, ci);
                                    if (Map[index1InRow1] == 0)
                                    {
                                        string mark = MarkMap[index1InRow1];
                                        mark = mark.Replace(num.ToString(), "");
                                        anyNumberFilled = UpdateMark(index1InRow1, mark) || anyNumberFilled;
                                    }

                                    int index2InRow2 = GetCellIndexWithRowColumn(row2, ci);
                                    if (Map[index2InRow2] == 0)
                                    {
                                        string mark = MarkMap[index2InRow2];
                                        mark = mark.Replace(num.ToString(), "");
                                        anyNumberFilled = UpdateMark(index2InRow2, mark) || anyNumberFilled;
                                    }
                                }
                            }
                        }

                    }
                }
            }
            return anyNumberFilled;
        }

11.技巧11,剑鱼

        /// <summary>
        /// 剑鱼
        /// 有三行的某个数字刚好落在三列中,那么这三列其他行的这个数字排除
        /// </summary>
        /// <returns></returns>
        private bool Swordfish()
        {
            //标记位,是否填入数据或者剔除标记
            bool anyNumberFilled = false;
            //遍历数字1-9
            for (int num = 1; num <= 9; num++)
            {
                //遍历所有三行组合
                for (int r = 0; r < 7; r++)
                {
                    //如果这一行未填的格子少于2格,下一行
                    if (Rows[r].GetCount() > 7) continue;
                    //如果这一行填过这个数字,下一行
                    if (Rows[r].Contains(num)) continue;
                    //遍历所有三行组合
                    for (int j = 1; j < 8 - r; j++)
                    {
                        //如果这一行未填的格子少于2格,下一行
                        if (Rows[r + j].GetCount() > 7) continue;
                        //如果这一行填过这个数字,下一行
                        if (Rows[r + j].Contains(num)) continue;
                        //遍历所有三行组合
                        for (int k = 1; k < 9 - r - j; k++)
                        {
                            //如果这一行未填的格子少于2格,下一行
                            if (Rows[r + j + k].GetCount() > 7) continue;
                            //如果这一行填过这个数字,下一行
                            if (Rows[r + j + k].Contains(num)) continue;

                            string indexInRow1 = "";
                            string indexInRow2 = "";
                            string indexInRow3 = "";

                            //遍历这三行的所有列
                            for (int c = 0; c < 9; c++)
                            {
                                //第一行的格子1
                                int index1 = GetCellIndexWithRowColumn(r, c);
                                //如果含有这个数字的标记,将列号记录在字符串中
                                if (Map[index1] == 0 && MarkMap[index1].Contains(num.ToString())) indexInRow1 = indexInRow1 + c;
                                //第二行的格子2
                                int index2 = GetCellIndexWithRowColumn(r + j, c);
                                //如果含有这个数字的标记,将列号记录在字符串中
                                if (Map[index2] == 0 && MarkMap[index2].Contains(num.ToString())) indexInRow2 = indexInRow2 + c;
                                //第三行的格子3
                                int index3 = GetCellIndexWithRowColumn(r + j + k, c);
                                //如果含有这个数字的标记,将列号记录在字符串中
                                if (Map[index3] == 0 && MarkMap[index3].Contains(num.ToString())) indexInRow3 = indexInRow3 + c;

                            }
                            //字典,用来判断这三行的这个数字标记是否落在相同的三列中
                            Dictionary<int, int> indexDic = new Dictionary<int, int>();
                            //将这三行包含这个数字标记的列号加到字典中
                            string indexStr = indexInRow1;
                            for (int m = 0; m < indexStr.Length; m++)
                            {
                                int index = int.Parse(indexStr.Substring(m, 1));
                                if (!indexDic.ContainsKey(index)) indexDic.Add(index, 0);
                            }
                            indexStr = indexInRow2;
                            for (int m = 0; m < indexStr.Length; m++)
                            {
                                int index = int.Parse(indexStr.Substring(m, 1));
                                if (!indexDic.ContainsKey(index)) indexDic.Add(index, 0);
                            }
                            indexStr = indexInRow3;
                            for (int m = 0; m < indexStr.Length; m++)
                            {
                                int index = int.Parse(indexStr.Substring(m, 1));
                                if (!indexDic.ContainsKey(index)) indexDic.Add(index, 0);
                            }
                            //如果落在相同的三列中,那么剔除这三列其他行的这个数字的标记
                            if (indexDic.Count == 3)
                            {
                                //获取三个列号
                                int[] Cols = new int[3];
                                int col_i = 0;
                                foreach (var item in indexDic.Keys)
                                {
                                    Cols[col_i] = item;
                                    col_i++;
                                }
                                //遍历这三列的所有行
                                for (int ri = 0; ri < 9; ri++)
                                {
                                    if (ri != r && ri != (r + j) && ri != (r + j + k))
                                    {
                                        //格子下标
                                        int index1InCol1 = GetCellIndexWithRowColumn(ri,Cols[0]);
                                        //剔除这三列中其余行所有这个数字的标记
                                        if (Map[index1InCol1] == 0)
                                        {
                                            string mark = MarkMap[index1InCol1];
                                            mark = mark.Replace(num.ToString(), "");
                                            anyNumberFilled = UpdateMark(index1InCol1, mark) || anyNumberFilled;
                                        }

                                        int index2InCol2 = GetCellIndexWithRowColumn(ri, Cols[1]);
                                        if (Map[index2InCol2] == 0)
                                        {
                                            string mark = MarkMap[index2InCol2];
                                            mark = mark.Replace(num.ToString(), "");
                                            anyNumberFilled = UpdateMark(index2InCol2, mark) || anyNumberFilled;

                                        }

                                        int index3InCol3 = GetCellIndexWithRowColumn(ri, Cols[2]);
                                        if (Map[index3InCol3] == 0)
                                        {
                                            string mark = MarkMap[index3InCol3];
                                            mark = mark.Replace(num.ToString(), "");
                                            anyNumberFilled = UpdateMark(index3InCol3, mark) || anyNumberFilled;

                                        }
                                    }
                                }
                            }
                        }

                    }
                }
            }
            //遍历每一列每一个数字
            for (int num = 1; num <= 9; num++)
            {
                for (int c = 0; c < 7; c++)
                {
                    if (Columns[c].GetCount() > 7) continue;
                    if (Columns[c].Contains(num)) continue;
                    for (int j = 1; j < 8 - c; j++)
                    {
                        if (Columns[c + j].GetCount() > 7) continue;
                        if (Columns[c + j].Contains(num)) continue;
                        for (int k = 1; k < 9 - c - j; k++)
                        {
                            if (Columns[c + j + k].GetCount() > 7) continue;
                            if (Columns[c + j + k].Contains(num)) continue;

                            string indexInCol1 = "";
                            string indexInCol2 = "";
                            string indexInCol3 = "";

                            for (int r = 0; r < 9; r++)
                            {
                                int index1 = GetCellIndexWithRowColumn(r, c);
                                if (Map[index1] == 0 && MarkMap[index1].Contains(num.ToString())) indexInCol1 = indexInCol1 + r;
                                int index2 = GetCellIndexWithRowColumn(r, c + j);
                                if (Map[index2] == 0 && MarkMap[index2].Contains(num.ToString())) indexInCol2 = indexInCol2 + r;
                                int index3 = GetCellIndexWithRowColumn(r, c + j + k);
                                if (Map[index3] == 0 && MarkMap[index3].Contains(num.ToString())) indexInCol3 = indexInCol3 + r;

                            }
                            Dictionary<int, int> indexDic = new Dictionary<int, int>();
                            string indexStr = indexInCol1;
                            for (int m = 0; m < indexStr.Length; m++)
                            {
                                int index = int.Parse(indexStr.Substring(m, 1));
                                if (!indexDic.ContainsKey(index)) indexDic.Add(index, 0);
                            }
                            indexStr = indexInCol2;
                            for (int m = 0; m < indexStr.Length; m++)
                            {
                                int index = int.Parse(indexStr.Substring(m, 1));
                                if (!indexDic.ContainsKey(index)) indexDic.Add(index, 0);
                            }
                            indexStr = indexInCol3;
                            for (int m = 0; m < indexStr.Length; m++)
                            {
                                int index = int.Parse(indexStr.Substring(m, 1));
                                if (!indexDic.ContainsKey(index)) indexDic.Add(index, 0);
                            }

                            if (indexDic.Count == 3)
                            {
                                int[] rows = new int[3];
                                int row_i = 0;
                                foreach (var item in indexDic.Keys)
                                {
                                    rows[row_i] = item;
                                    row_i++;
                                }
                                for (int ci = 0; ci < 9; ci++)
                                {
                                    if (ci != c && ci != (c + j) && ci != (c + j + k))
                                    {
                                        int index1InCol1 = GetCellIndexWithRowColumn(rows[0],ci);
                                        if (Map[index1InCol1] == 0)
                                        {
                                            string mark = MarkMap[index1InCol1];
                                            mark = mark.Replace(num.ToString(), "");
                                            anyNumberFilled = UpdateMark(index1InCol1, mark) || anyNumberFilled;
                                        }

                                        int index2InCol2 = GetCellIndexWithRowColumn(rows[1], ci);
                                        if (Map[index2InCol2] == 0)
                                        {
                                            string mark = MarkMap[index2InCol2];
                                            mark = mark.Replace(num.ToString(), "");
                                            anyNumberFilled = UpdateMark(index2InCol2, mark) || anyNumberFilled;
                                        }

                                        int index3InCol3 = GetCellIndexWithRowColumn(rows[2], ci);
                                        if (Map[index3InCol3] == 0)
                                        {
                                            string mark = MarkMap[index3InCol3];
                                            mark = mark.Replace(num.ToString(), "");
                                            anyNumberFilled = UpdateMark(index3InCol3, mark) || anyNumberFilled;

                                        }
                                    }
                                }
                            }
                        }

                    }
                }
            }
            return anyNumberFilled;
        }

12.技巧12,水母

        /// <summary>
        /// 水母
        /// 有四行的某个数字刚好落在四列中,那么这四列其他行的这个数字排除
        /// </summary>
        /// <returns></returns>
        private bool Jellyfish()
        {
            //标记位,是否填入数字或剔除标记
            bool anyNumberFilled = false;
            //遍历数字1-9
            for (int num = 1; num <= 9; num++)
            {
                //遍历所有的四行组合
                for (int r = 0; r < 6; r++)
                {
                    //如果这一行未填的格子少于2个,下一行
                    if (Rows[r].GetCount() > 7) continue;
                    //如果这一行已经填过这个数字,下一行
                    if (Rows[r].Contains(num)) continue;
                    //遍历所有的四行组合
                    for (int j = 1; j < 7 - r; j++)
                    {
                        //如果这一行未填的格子少于2个,下一行
                        if (Rows[r + j].GetCount() > 7) continue;
                        //如果这一行已经填过这个数字,下一行
                        if (Rows[r + j].Contains(num)) continue;
                        //遍历所有的四行组合
                        for (int k = 1; k < 8 - r - j; k++)
                        {
                            //如果这一行未填的格子少于2个,下一行
                            if (Rows[r + j + k].GetCount() > 7) continue;
                            //如果这一行已经填过这个数字,下一行
                            if (Rows[r + j + k].Contains(num)) continue;
                            //遍历所有的四行组合
                            for (int l = 1; l < 9 - r - j - k; l++)
                            {
                                //如果这一行未填的格子少于2个,下一行
                                if (Rows[r + j + k + l].GetCount() > 7) continue;
                                //如果这一行已经填过这个数字,下一行
                                if (Rows[r + j + k + l].Contains(num)) continue;

                                string indexInRow1 = "";
                                string indexInRow2 = "";
                                string indexInRow3 = "";
                                string indexInRow4 = "";

                                //遍历这四行的每一列,如果含有这个数字标记,那么将列号记录到字符串
                                for (int c = 0; c < 9; c++)
                                {
                                    int index1 = GetCellIndexWithRowColumn(r, c);
                                    if (Map[index1] == 0 && MarkMap[index1].Contains(num.ToString())) indexInRow1 = indexInRow1 + c;
                                    int index2 = GetCellIndexWithRowColumn(r+j, c);
                                    if (Map[index2] == 0 && MarkMap[index2].Contains(num.ToString())) indexInRow2 = indexInRow2 + c;
                                    int index3 = GetCellIndexWithRowColumn(r+j+k, c);
                                    if (Map[index3] == 0 && MarkMap[index3].Contains(num.ToString())) indexInRow3 = indexInRow3 + c;
                                    int index4 = GetCellIndexWithRowColumn(r+j+k+l, c);
                                    if (Map[index4] == 0 && MarkMap[index4].Contains(num.ToString())) indexInRow4 = indexInRow4 + c;


                                }
                                //字典,用来判断这四行的这个数字标记是否落在四列中
                                Dictionary<int, int> indexDic = new Dictionary<int, int>();
                                //将这四行含有这个数字标记的列号添加到字典
                                string indexStr = indexInRow1;
                                for (int m = 0; m < indexStr.Length; m++)
                                {
                                    int index = int.Parse(indexStr.Substring(m, 1));
                                    if (!indexDic.ContainsKey(index)) indexDic.Add(index, 0);
                                }
                                indexStr = indexInRow2;
                                for (int m = 0; m < indexStr.Length; m++)
                                {
                                    int index = int.Parse(indexStr.Substring(m, 1));
                                    if (!indexDic.ContainsKey(index)) indexDic.Add(index, 0);
                                }
                                indexStr = indexInRow3;
                                for (int m = 0; m < indexStr.Length; m++)
                                {
                                    int index = int.Parse(indexStr.Substring(m, 1));
                                    if (!indexDic.ContainsKey(index)) indexDic.Add(index, 0);
                                }
                                indexStr = indexInRow4;
                                for (int m = 0; m < indexStr.Length; m++)
                                {
                                    int index = int.Parse(indexStr.Substring(m, 1));
                                    if (!indexDic.ContainsKey(index)) indexDic.Add(index, 0);
                                }

                                //如果落在四列上
                                if (indexDic.Count == 4)
                                {
                                    //获取四个列号
                                    int[] Cols = new int[4];
                                    int col_i = 0;
                                    foreach (var item in indexDic.Keys)
                                    {
                                        Cols[col_i] = item;
                                        col_i++;
                                    }
                                    //遍历每一行
                                    for (int ri = 0; ri < 9; ri++)
                                    {
                                        //除了这四行以外,其余这四列的格子剔除这个数字标记
                                        if (ri != r && ri != (r + j) && ri != (r + j + k) && ri != (r + j + k + l))
                                        {
                                            //格子1下标
                                            int index1InCol1 = GetCellIndexWithRowColumn(ri, Cols[0]);
                                            //剔除这个数字的标记
                                            if (Map[index1InCol1] == 0)
                                            {
                                                string mark = MarkMap[index1InCol1];
                                                mark = mark.Replace(num.ToString(), "");
                                                anyNumberFilled = UpdateMark(index1InCol1, mark) || anyNumberFilled;
                                            }
                                            //格子2下标
                                            int index2InCol2 = GetCellIndexWithRowColumn(ri, Cols[1]);
                                            //剔除这个数字的标记
                                            if (Map[index2InCol2] == 0)
                                            {
                                                string mark = MarkMap[index2InCol2];
                                                mark = mark.Replace(num.ToString(), "");
                                                anyNumberFilled = UpdateMark(index2InCol2, mark) || anyNumberFilled;
                                            }
                                            //格子3下标
                                            int index3InCol3 = GetCellIndexWithRowColumn(ri, Cols[2]);
                                            //剔除这个数字的标记
                                            if (Map[index3InCol3] == 0)
                                            {
                                                string mark = MarkMap[index3InCol3];
                                                mark = mark.Replace(num.ToString(), "");
                                                anyNumberFilled = UpdateMark(index3InCol3, mark) || anyNumberFilled;
                                            }
                                            //格子4下标
                                            int index4InCol4 = GetCellIndexWithRowColumn(ri, Cols[3]);
                                            //剔除这个数字的标记
                                            if (Map[index4InCol4] == 0)
                                            {
                                                string mark = MarkMap[index4InCol4];
                                                mark = mark.Replace(num.ToString(), "");
                                                anyNumberFilled = UpdateMark(index4InCol4, mark) || anyNumberFilled;
                                            }
                                        }
                                    }
                                }

                            }
                        }

                    }
                }
            }
            //遍历每一列每一个数字
            for (int num = 1; num <= 9; num++)
            {
                for (int c = 0; c < 6; c++)
                {
                    if (Columns[c].GetCount() > 7) continue;
                    if (Columns[c].Contains(num)) continue;
                    for (int j = 1; j < 7 - c; j++)
                    {
                        if (Columns[c + j].GetCount() > 7) continue;
                        if (Columns[c + j].Contains(num)) continue;
                        for (int k = 1; k < 8 - c - j; k++)
                        {
                            if (Columns[c + j + k].GetCount() > 7) continue;
                            if (Columns[c + j + k].Contains(num)) continue;
                            for (int l = 1; l < 9 - c - j - k; l++)
                            {
                                if (Columns[c + j + k + l].GetCount() > 7) continue;
                                if (Columns[c + j + k + l].Contains(num)) continue;

                                string indexInCol1 = "";
                                string indexInCol2 = "";
                                string indexInCol3 = "";
                                string indexInCol4 = "";

                                for (int r = 0; r < 9; r++)
                                {
                                    int index1 = GetCellIndexWithRowColumn(r, c);
                                    if (Map[index1] == 0 && MarkMap[index1].Contains(num.ToString())) indexInCol1 = indexInCol1 + r;
                                    int index2 = GetCellIndexWithRowColumn(r, c + j);
                                    if (Map[index2] == 0 && MarkMap[index2].Contains(num.ToString())) indexInCol2 = indexInCol2 + r;
                                    int index3 = GetCellIndexWithRowColumn(r, c + j + k);
                                    if (Map[index3] == 0 && MarkMap[index3].Contains(num.ToString())) indexInCol3 = indexInCol3 + r;
                                    int index4 = GetCellIndexWithRowColumn(r, c + j + k + l);
                                    if (Map[index4] == 0 && MarkMap[index4].Contains(num.ToString())) indexInCol4 = indexInCol4 + r;
                                }
                                Dictionary<int, int> indexDic = new Dictionary<int, int>();
                                string indexStr = indexInCol1;
                                for (int m = 0; m < indexStr.Length; m++)
                                {
                                    int index = int.Parse(indexStr.Substring(m, 1));
                                    if (!indexDic.ContainsKey(index)) indexDic.Add(index, 0);
                                }
                                indexStr = indexInCol2;
                                for (int m = 0; m < indexStr.Length; m++)
                                {
                                    int index = int.Parse(indexStr.Substring(m, 1));
                                    if (!indexDic.ContainsKey(index)) indexDic.Add(index, 0);
                                }
                                indexStr = indexInCol3;
                                for (int m = 0; m < indexStr.Length; m++)
                                {
                                    int index = int.Parse(indexStr.Substring(m, 1));
                                    if (!indexDic.ContainsKey(index)) indexDic.Add(index, 0);
                                }
                                indexStr = indexInCol4;
                                for (int m = 0; m < indexStr.Length; m++)
                                {
                                    int index = int.Parse(indexStr.Substring(m, 1));
                                    if (!indexDic.ContainsKey(index)) indexDic.Add(index, 0);
                                }
                                if (indexDic.Count == 4)
                                {
                                    int[] rows = new int[4];
                                    int row_i = 0;
                                    foreach (var item in indexDic.Keys)
                                    {
                                        rows[row_i] = item;
                                        row_i++;
                                    }
                                    for (int ci = 0; ci < 9; ci++)
                                    {
                                        if (ci != c && ci != (c + j) && ci != (c + j + k) && ci != (c + j + k + l))
                                        {
                                            int index1InCol1 = GetCellIndexWithRowColumn(rows[0], ci);
                                            if (Map[index1InCol1] == 0)
                                            {
                                                string mark = MarkMap[index1InCol1];
                                                mark = mark.Replace(num.ToString(), "");
                                                anyNumberFilled = UpdateMark(index1InCol1, mark) || anyNumberFilled;
                                            }

                                            int index2InCol2 = GetCellIndexWithRowColumn(rows[1], ci);
                                            if (Map[index2InCol2] == 0)
                                            {
                                                string mark = MarkMap[index2InCol2];
                                                mark = mark.Replace(num.ToString(), "");
                                                anyNumberFilled = UpdateMark(index2InCol2, mark) || anyNumberFilled;
                                            }

                                            int index3InCol3 = GetCellIndexWithRowColumn(rows[2], ci);
                                            if (Map[index3InCol3] == 0)
                                            {
                                                string mark = MarkMap[index3InCol3];
                                                mark = mark.Replace(num.ToString(), "");
                                                anyNumberFilled = UpdateMark(index3InCol3, mark) || anyNumberFilled;

                                            }

                                            int index4InCol4 = GetCellIndexWithRowColumn(rows[3], ci);
                                            if (Map[index4InCol4] == 0)
                                            {
                                                string mark = MarkMap[index4InCol4];
                                                mark = mark.Replace(num.ToString(), "");
                                                anyNumberFilled = UpdateMark(index4InCol4, mark) || anyNumberFilled;

                                            }
                                        }
                                    }
                                }

                            }
                        }

                    }
                }
            }
            return anyNumberFilled;
        }
    }

猜你喜欢

转载自blog.csdn.net/weixin_61427881/article/details/134432136