数读游戏的不完全解法----采用位异或的方式记录每一格数字的可能性
来源:互联网 发布:周治平 知乎 编辑:程序博客网 时间: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");
}*/
}
}
}
- 数读游戏的不完全解法----采用位异或的方式记录每一格数字的可能性
- 中国象棋,马不重复的走完每一格
- appium使用sendkeys输入银行卡卡号(每4个数字自动空一格)总是输入不正确的解决办法
- appium使用sendkeys输入银行卡卡号(每4个数字自动空一格)总是输入不正确的解决办法
- 远程桌面玩游戏的可能性
- 关于抢数字游戏的解法
- 求解21位花朵数的解法
- 数独游戏的AI解法
- 数独游戏的简单回溯解法
- [算法]游戏'数读’的基本解法 JAVA版。
- SQL:将多条记录的不同数据放入同一格中
- 用逗号每3位分割数字的javascript代码
- 苹果电视操控方式的可能性
- 给每条记录的时间增加随机秒数
- Catalan数的解法
- 求4位数字的回文数
- 猴子选大王,有1-100个数字,每数6位删除一个,顺序循环,最后只有一个数字的时候是1-100中的几?
- 数独游戏的深度优先遍历解法
- 控制textbox的最大可输入数的方法(javascript)
- 利用oracle的with语句和动态sql,自动产生用交叉表格式显示的汇总语句
- 2006厦门企业100强名单
- 不得不说的几件事
- 7月7日
- 数读游戏的不完全解法----采用位异或的方式记录每一格数字的可能性
- 用汇编写个最小的WDM驱动程序进RING0
- MSSQL注入攻击的防护
- 如何确定 Winsock2 是否损坏并从损坏中恢复
- 今天陪女朋友逛街花了一块钱,好心疼啊!(转贴 大家开心一下!谁信,谁傻)
- 请不要做浮躁的人
- 让webwork返回一个xml
- ASP.NET Web服务和Flash打造MP3播放器
- mount -a