数读游戏的不完全解法----采用位异或的方式记录每一格数字的可能性

来源:互联网 发布:周治平 知乎 编辑:程序博客网 时间:2024/05/14 11:33

最近喜欢上了数读游戏,所以想写一个数读游戏的算法,但后来在调试过程中发现,一些very hard级的游戏,解到后来需要试填数字,这就是我这个算法不完全的原因,不支持试填数字。试填数字可能就涉及到了回溯(因为不能保证所填的数字一定正确),我实在不想浪费太多的时间在这个算法上,所以暂时只能让他不完全下去,好在这个算法可以找到所有确定数字位置。

思路:采用位的方式,111111111(511,十进制),如果该空格内的数字不可能是123678,则对应的位应该为100011000。依次类推,把所有空格的可能性全都记录下来。然后按列,按行,按9个小方格判断,该空格得可能数字。不做过多解释了,喜欢数读游戏的人肯定知道怎么回事。

具体算法如下:(没有过多的解释说明,太懒了^_^)

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.IO;
namespace sudoku
{
    public class soduku
    {
        public class NumArray
        {
            public int inum = 0;
            public int ifnum = 511;
            public bool bstate = false;
        }

        public int Bit(int ibit)
        {
            return 1<<--ibit;
        }
        public int Num(int inum)
        {
            for (int j = 0; j < 9; j++)
            {
                if ((inum ^ (1 << j)) == 0)
                {
                    return j;
                }
            }
            return 0;
        }
        private int iSum = 81;
        private NumArray[,] isoduku;
        public soduku(int [,] inumber)
        {
            isoduku = new NumArray[9, 9];
            for (int i = 0; i < 9; i++)
            {
                for (int j = 0; j < 9; j++)
                {
                    isoduku[i, j] = new NumArray();
                    if (inumber[i, j] != 0)
                    {
                        isoduku[i, j].inum = inumber[i, j];
                        isoduku[i, j].bstate = true;
                        iSum--;
                        isoduku[i, j].ifnum = -1;
                    }
                   
                }
            }
            ScanInit();
        }
        public void ScanInit()
        {
            for (int i = 0; i < 9; i++)
            {
                for (int j = 0; j < 9; j++)
                {
                    if (isoduku[i, j].bstate)
                    {
                        ScanRowCol(i, j);
                        ScanArray(i, j);
                    }
                }
            }
        }

       //扫描行列,将不可能的数字去掉
        public void ScanRowCol(int i,int j)
        {
            for (int k = 0; k < 9; k++)
            {
                if (!isoduku[i, k].bstate)
                {
                    if((isoduku[i,k].ifnum & Bit(isoduku[i, j].inum)) != 0)
                        isoduku[i, k].ifnum ^= Bit(isoduku[i, j].inum);
                }
                if (!isoduku[k, j].bstate)
                {
                    if ((isoduku[k, j].ifnum & Bit(isoduku[i, j].inum)) != 0)
                        isoduku[k, j].ifnum ^= Bit(isoduku[i, j].inum);
                }
            }
        }

//扫描小方格,将不可能的数字去掉
        public void ScanArray(int i, int j)
        {
            for (int m = (i / 3) * 3; m <= (i / 3) * 3 + 2;m++ )
            {
                for (int n = (j / 3) * 3; n <= (j / 3) * 3 + 2; n++)
                {
                    if (!isoduku[m, n].bstate)
                    {
                        if ((isoduku[m, n].ifnum & Bit(isoduku[i, j].inum)) != 0)
                            isoduku[m, n].ifnum ^= Bit(isoduku[i, j].inum);
                    }

                }
            }
        }

//最终的扫描函数
        public bool SearchArray()
        {
            int iloop = 0;
            while (true)
            {
               
                for (int i = 0; i < 9; i++)
                {
                    for (int j = 0; j < 9; j++)
                    {
                        if (!isoduku[i, j].bstate)
                        {
                            if (SearchRowCol(i, j) != 0)
                                continue;
                            if (SearchArray(i, j) != 0)
                                continue;
                        }
                    }
                }
                iloop++;
                if (iSum == 0)
                    return true;
                else
                    if (iloop > 10)
                        return false;
            }
            return false;
        }

//搜索行列,确定符合条件的数字,同时去掉该行,该列的其他空格的可能是这个数字的可能性
        public int SearchRowCol(int i,int j)
        {
           
            int icount = 0;
            int iset = 0;
            for (int k = 0; k < 9; k++)
            {
                for (int m = 0; m < 9; m++)
                {
                    if (!isoduku[i, m].bstate)
                    {
                        if ((isoduku[i, m].ifnum & (1 << k)) == (1 << k))
                        {
                            icount++;
                            iset = m;
                        }
                        if ((isoduku[i, m].ifnum == (1 << k)) && !isoduku[i, m].bstate)
                        {
                           
                            isoduku[i, m].inum = ++k;
                            isoduku[i, m].bstate = true;
                            ScanRowCol(i, m);
                            ScanArray(i,m);
                            iSum--;
                            return k;
                        }

                    }
                }
                if ((icount == 1) && !isoduku[i, iset].bstate)
                {
                    isoduku[i, iset].inum = ++k;
                    isoduku[i, iset].bstate = true;
                    ScanRowCol(i, iset);
                    ScanArray(i,iset);
                    iSum--;
                    return k;

                }
                icount = 0;
            }
            for (int k = 0; k < 9; k++)
            {
                for (int m = 0; m < 9; m++)
                {
                    if (!isoduku[m, j].bstate)
                    {
                        if ((isoduku[m, j].ifnum & (1 << k)) == (1 << k))
                        {
                            icount++;
                            iset = m;
                        }
                        if ((isoduku[m, j].ifnum == (1 << k)) && !isoduku[m, j].bstate)
                        {

                            isoduku[m, j].inum = ++k;
                            isoduku[m, j].bstate = true;
                            ScanRowCol(m, j);
                            ScanArray(m, j);
                            iSum--;
                            return k;
                        }

                    }
                }
                if ((icount == 1) && !isoduku[iset, j].bstate)
                {
                    isoduku[iset, j].inum = ++k;
                    isoduku[iset, j].bstate = true;
                    ScanRowCol(iset , j);
                    ScanArray(iset, j);
                    iSum--;
                    return k;

                }
                icount = 0;
            }
            return 0;
        }

//搜索小方块(3X3),同上
        public int SearchArray(int i,int j)
        {
            int icount = 0;
            int isetx = 0;
            int isety = 0;
            for (int k = 0; k < 9; k++)
            {
                for (int m = (i / 3) * 3; m <= (i / 3) * 3 + 2; m++)
                {
                    for (int n = (j / 3) * 3; n <= (j / 3) * 3 + 2; n++)
                    {
                        if (!isoduku[m, n].bstate)
                        {
                            if ((isoduku[m, n].ifnum & (1 << k)) == (1 << k))
                            {
                                icount++;
                                isetx = m;
                                isety = n;
                            }
                            if ((isoduku[m, n].ifnum == (1 << k)) && !isoduku[m,n].bstate)
                            {
                                isoduku[m, n].inum = ++k;
                                isoduku[m, n].bstate = true;
                                ScanRowCol(m, n);
                                ScanArray(m, n);
                                iSum--;
                                return k;
                            }

                        }
                    }
                }
                if ((icount == 1) && !isoduku[isetx, isety].bstate)
                {
                    isoduku[isetx, isety].inum = ++k;
                    isoduku[isetx, isety].bstate = true;
                    ScanRowCol(isetx, isety);
                    ScanArray(isetx, isety);
                    iSum--;
                    return k;
                }
                icount = 0;
            }
            return 0;
        }
        public void Show()
        {
            for (int i = 0; i < 9; i++)
            {
                for (int j = 0; j < 9; j++)
                {
                    if(isoduku[i,j].ifnum == -1)
                        System.Console.Write("{0,4}","["+isoduku[i,j].inum.ToString()+"]");
                    else
                        System.Console.Write("{0,4}", isoduku[i, j].inum.ToString() + " ");
                }
                System.Console.Write("/r/n");
            }
        }
        public void Show(string strpath)
        {
            //FileStream fs = new FileStream(strpath, FileAccess.Write);
            StreamWriter sw = File.AppendText(strpath);
            //sw =
           
            sw.WriteLine("------------------------------------");
            for (int i = 0; i < 9; i++)
            {
                for (int j = 0; j < 9; j++)
                {
                    if (isoduku[i, j].ifnum == -1)
                        sw.Write("{0,4}", "[" + isoduku[i, j].inum.ToString() + "]");
                    else
                        sw.Write("{0,4}", isoduku[i, j].inum.ToString() + " ");
                }
                sw.Write("/r/n");
            }
            sw.Close();
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            int[,] iarray = new int[9, 9]{
            {2,3,0,6,0,0,0,9,0},
            {0,0,0,0,0,0,0,4,0},
            {0,5,0,9,0,1,0,0,0},
            {7,0,0,0,2,0,0,0,3},
            {1,0,0,3,0,5,0,0,9},
            {3,0,0,0,6,0,0,0,5},
            {0,0,0,2,0,4,0,1,0},
            {0,2,0,0,0,0,0,0,0},
            {0,1,0,0,0,6,0,7,8}};

            int[,] iarray1 = new int[9, 9]{
            {5,0,0,0,0,0,0,0,1},
            {0,0,0,0,1,0,0,3,0},
            {0,3,4,0,0,0,2,6,0},

            {0,7,3,0,0,6,4,5,0},
            {0,0,0,2,0,4,0,0,0},
            {0,4,6,9,0,0,8,1,0},

            {0,6,1,0,0,0,3,9,0},
            {0,8,0,0,4,0,0,0,0},
            {3,0,0,0,0,0,0,0,8}};

            int[,] iarray2 = new int[9, 9]{
            {0,1,0,9,0,4,0,8,0},
            {0,0,0,0,3,0,0,0,0},
            {0,0,3,2,0,5,6,0,0},

            {7,0,2,0,0,0,5,0,8},
            {5,3,0,0,0,0,0,6,9},
            {8,0,9,0,0,0,1,0,7},

            {0,0,7,5,0,8,4,0,0},
            {0,0,0,0,9,0,0,0,0},
            {0,2,0,7,0,3,0,9,0}};
            int[,] iarray3 = new int[9, 9]{
            {0,0,0,1,5,8,0,9,0},
            {1,0,0,2,0,3,0,0,4},
            {0,0,0,0,0,0,0,0,3},

            {0,6,0,0,3,0,0,2,8},
            {0,0,5,0,0,0,4,0,0},
            {3,4,0,0,9,0,0,5,0},

            {7,0,0,0,0,0,0,0,0},
            {5,0,0,3,0,7,0,0,1},
            {0,3,0,4,2,9,0,0,0}};
            int[,] iarray4 = new int[9, 9]{
            {4,8,0,0,0,0,0,0,3},
            {0,0,0,0,7,0,0,4,6},
            {0,0,6,4,0,3,0,0,0},

            {0,0,0,0,0,7,1,3,0},
            {6,0,0,5,0,9,0,0,8},
            {0,1,8,3,0,0,0,0,0},

            {0,0,0,9,0,1,3,0,0},
            {7,9,0,0,5,0,0,0,0},
            {2,0,0,0,0,0,0,8,9}};
            int[,] iarray5 = new int[9, 9]{
            {4,9,0,0,0,6,0,0,0},
            {0,0,0,0,0,0,0,2,9},
            {7,0,0,0,0,8,0,0,3},

            {0,4,5,0,1,9,0,0,8},
            {0,0,0,8,0,7,0,0,0},
            {8,0,0,3,4,0,6,9,0},

            {1,0,0,6,0,0,0,0,2},
            {2,3,0,0,0,0,0,0,0},
            {0,0,0,7,0,0,0,8,4}};
            int[,] iarray6 = new int[9, 9]{
            {0,0,0,0,0,1,0,9,0},
            {2,0,7,0,0,0,4,0,0},
            {0,4,0,0,2,0,0,1,0},

            {0,0,0,2,0,3,0,0,7},
            {0,0,2,0,6,0,5,0,0},
            {8,0,0,1,0,7,0,0,0},

            {0,7,0,0,3,0,0,4,0},
            {0,0,5,0,0,0,8,0,3},
            {0,6,0,5,0,0,0,0,0}};
            sudoku.soduku isoduku = new soduku(iarray5);
            isoduku.SearchArray();
            isoduku.Show();
/*            XmlDocument xdoc = new XmlDocument();
            xdoc.Load(@"./sudoku.xml");
            int[,] sudokuarray = new int[9, 9];
            XmlNodeList xnodelist = xdoc.SelectNodes(@"/sudoku/item");
            foreach (XmlNode xnode in xnodelist)
            {
                XmlNodeList xlist = xnode.ChildNodes;
                int i = 0;
                foreach (XmlElement xele in xlist)
                {
                    string str = xele.InnerText;
                    for (int j = 0; j < 9; j++)
                    {
                        sudokuarray[i, j] = int.Parse(str[j].ToString());
                    }
  
                        i++;
                }
                sudoku.soduku isoduku = new soduku(sudokuarray);
                isoduku.SearchArray();
                isoduku.Show(@"./result.txt");
            }*/
           
           

        }
    }
}

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 淘宝登录原始密码忘记了怎么办 微信原始密码忘记了怎么办 优酷会员重复交费怎么办 微信解绑手机号密码忘了怎么办 闪银呼呼逾期5天怎么办 忘记淘宝账号和密码怎么办 蘑菇街账号忘了怎么办 台式电脑密码忘记了怎么办 单位社保登陆密码忘记了怎么办 12306的登录密码忘了怎么办 网银支付密码忘了怎么办 邮政网银密码忘了怎么办 12306新注册待核验怎么办 建行网银盾密码忘了怎么办 建行网银登陆密码忘了怎么办 建行网银密码忘了怎么办 建行手机网银密码忘了怎么办 移动宽带账号密码忘了怎么办 移动宽带忘记账号密码怎么办 宽带账号密码忘了怎么办 不知道宽带账号密码怎么办 宽带的账号密码忘记了怎么办 wifi登录名忘记了怎么办 苹果手机微信图纸打不开怎么办 手机qq邮箱文件打不开怎么办 12360忘记用户名和密码怎么办 刚开店铺没生意怎么办 淘宝账户不符合注销条件怎么办 网易邮箱登录密码忘记了怎么办 q号密码忘记了怎么办 志愿者注册忘记密码和用户名怎么办 w10电脑语言栏不见了怎么办 w10美式键盘没了怎么办 xp电脑开机密码忘记了怎么办 电脑开机密码到期忘记改怎么办 电脑账户数据库密码忘了怎么办 微信不能拍摄了怎么办 华硕笔记本用户名密码忘了怎么办 学信网登录密码用户名搞忘怎么办 电脑密码输入错误会被锁怎么办 电脑被锁机软件设了密码怎么办