只使用一个short变量,打印出象棋所有将帅的合法位置
2014-10-01 00:00
211 查看
摘要: 象棋
在实际的软件环境中,可能包含m*n个变量。在这么大的变量下,节省一点空间都是好的。这里,主要从象棋的将帅问题入手。通过对这个问题的实现,希望能够从中领会到节省空间的一些办法。将帅问题的解应该是最简单的处理方法了,我们就是要从简单的入手从而掌握整个问题解决的手段。
首先,象棋的将帅问题是我在《《编程之美》》中看到的,里面的解法实在太繁琐。我记得光是#define就有一大堆,反正我是不喜欢看这些东西。下面,希望我这个代码能够简单明了。
将帅问题就是将和帅不能处在同一个竖线上,在正式讨论之前,提供一下正常的判断将帅位置是否合法的方法:
typedef struct stLoc
{
int x;
int y;
} Location;
bool checkValidKingLocation(Location loc1, Location loc2 )
{
if(loc1.y == loc2.y)
{
return false;
}
return true;
}
可以看出,我们需要两个位置变量。每个变量的大小为两个int,如果不使用int,使用CHAR.在考虑4字节对齐的情况下,size并没有改变。所以我们要16字节大小。
如果我们使用一个short型,或者可以直接使用char型。显然我们能够节省很多空间,虽然对于这个例子来说没有什么意义。那么要想这样实现,我们必须让将和帅两个位置在变量之中完全相互独立。将和帅可以分别使用变量中的4个bit来标识自己,说起来很简单。下面就看看实际如何利用代码实现了:
#define IsLowValid(i) ( (i&0xf) < 9 )
#define IsHighValid(i) (((i&0xf0)>>4) < 9)
#define GetLow(i) (i&0xf)
#define GetHigh(i) ((i&0xf0)>>4)
#define ClearLow(i) (i = i & 0xf0)
void printValidLoc()
{
short i =0;
while(IsHighValid(i))
{
while(IsLowValid(i))
{
if(GetHigh(i)%3 != GetLow(i)%3)
{
printf("Red(%d %d) Black(%d %d)\r\n",GetHigh(i)/3,GetHigh(i)%3,GetLow(i)/3,GetLow(i)%3);
}
i++;
}
ClearLow(i);//必须清除低位字符,否则后面的算法错误
i += 16;
}
return;
}
int _tmain(int argc, _TCHAR* argv[])
{
printValidLoc();
return 0;
}
运行后打印信息如下:
Red(0 0) Black(0 1)
Red(0 0) Black(0 2)
Red(0 0) Black(1 1)
Red(0 0) Black(1 2)
Red(0 0) Black(2 1)
Red(0 0) Black(2 2)
Red(0 1) Black(0 0)
Red(0 1) Black(0 2)
Red(0 1) Black(1 0)
Red(0 1) Black(1 2)
Red(0 1) Black(2 0)
Red(0 1) Black(2 2)
Red(0 2) Black(0 0)
Red(0 2) Black(0 1)
Red(0 2) Black(1 0)
Red(0 2) Black(1 1)
Red(0 2) Black(2 0)
Red(0 2) Black(2 1)
Red(1 0) Black(0 1)
Red(1 0) Black(0 2)
Red(1 0) Black(1 1)
Red(1 0) Black(1 2)
Red(1 0) Black(2 1)
Red(1 0) Black(2 2)
Red(1 1) Black(0 0)
Red(1 1) Black(0 2)
Red(1 1) Black(1 0)
Red(1 1) Black(1 2)
Red(1 1) Black(2 0)
Red(1 1) Black(2 2)
Red(1 2) Black(0 0)
Red(1 2) Black(0 1)
Red(1 2) Black(1 0)
Red(1 2) Black(1 1)
Red(1 2) Black(2 0)
Red(1 2) Black(2 1)
Red(2 0) Black(0 1)
Red(2 0) Black(0 2)
Red(2 0) Black(1 1)
Red(2 0) Black(1 2)
Red(2 0) Black(2 1)
Red(2 0) Black(2 2)
Red(2 1) Black(0 0)
Red(2 1) Black(0 2)
Red(2 1) Black(1 0)
Red(2 1) Black(1 2)
Red(2 1) Black(2 0)
Red(2 1) Black(2 2)
Red(2 2) Black(0 0)
Red(2 2) Black(0 1)
Red(2 2) Black(1 0)
Red(2 2) Black(1 1)
Red(2 2) Black(2 0)
Red(2 2) Black(2 1)
请按任意键继续. . .
在实际的软件环境中,可能包含m*n个变量。在这么大的变量下,节省一点空间都是好的。这里,主要从象棋的将帅问题入手。通过对这个问题的实现,希望能够从中领会到节省空间的一些办法。将帅问题的解应该是最简单的处理方法了,我们就是要从简单的入手从而掌握整个问题解决的手段。
首先,象棋的将帅问题是我在《《编程之美》》中看到的,里面的解法实在太繁琐。我记得光是#define就有一大堆,反正我是不喜欢看这些东西。下面,希望我这个代码能够简单明了。
将帅问题就是将和帅不能处在同一个竖线上,在正式讨论之前,提供一下正常的判断将帅位置是否合法的方法:
typedef struct stLoc
{
int x;
int y;
} Location;
bool checkValidKingLocation(Location loc1, Location loc2 )
{
if(loc1.y == loc2.y)
{
return false;
}
return true;
}
可以看出,我们需要两个位置变量。每个变量的大小为两个int,如果不使用int,使用CHAR.在考虑4字节对齐的情况下,size并没有改变。所以我们要16字节大小。
如果我们使用一个short型,或者可以直接使用char型。显然我们能够节省很多空间,虽然对于这个例子来说没有什么意义。那么要想这样实现,我们必须让将和帅两个位置在变量之中完全相互独立。将和帅可以分别使用变量中的4个bit来标识自己,说起来很简单。下面就看看实际如何利用代码实现了:
#define IsLowValid(i) ( (i&0xf) < 9 )
#define IsHighValid(i) (((i&0xf0)>>4) < 9)
#define GetLow(i) (i&0xf)
#define GetHigh(i) ((i&0xf0)>>4)
#define ClearLow(i) (i = i & 0xf0)
void printValidLoc()
{
short i =0;
while(IsHighValid(i))
{
while(IsLowValid(i))
{
if(GetHigh(i)%3 != GetLow(i)%3)
{
printf("Red(%d %d) Black(%d %d)\r\n",GetHigh(i)/3,GetHigh(i)%3,GetLow(i)/3,GetLow(i)%3);
}
i++;
}
ClearLow(i);//必须清除低位字符,否则后面的算法错误
i += 16;
}
return;
}
int _tmain(int argc, _TCHAR* argv[])
{
printValidLoc();
return 0;
}
运行后打印信息如下:
Red(0 0) Black(0 1)
Red(0 0) Black(0 2)
Red(0 0) Black(1 1)
Red(0 0) Black(1 2)
Red(0 0) Black(2 1)
Red(0 0) Black(2 2)
Red(0 1) Black(0 0)
Red(0 1) Black(0 2)
Red(0 1) Black(1 0)
Red(0 1) Black(1 2)
Red(0 1) Black(2 0)
Red(0 1) Black(2 2)
Red(0 2) Black(0 0)
Red(0 2) Black(0 1)
Red(0 2) Black(1 0)
Red(0 2) Black(1 1)
Red(0 2) Black(2 0)
Red(0 2) Black(2 1)
Red(1 0) Black(0 1)
Red(1 0) Black(0 2)
Red(1 0) Black(1 1)
Red(1 0) Black(1 2)
Red(1 0) Black(2 1)
Red(1 0) Black(2 2)
Red(1 1) Black(0 0)
Red(1 1) Black(0 2)
Red(1 1) Black(1 0)
Red(1 1) Black(1 2)
Red(1 1) Black(2 0)
Red(1 1) Black(2 2)
Red(1 2) Black(0 0)
Red(1 2) Black(0 1)
Red(1 2) Black(1 0)
Red(1 2) Black(1 1)
Red(1 2) Black(2 0)
Red(1 2) Black(2 1)
Red(2 0) Black(0 1)
Red(2 0) Black(0 2)
Red(2 0) Black(1 1)
Red(2 0) Black(1 2)
Red(2 0) Black(2 1)
Red(2 0) Black(2 2)
Red(2 1) Black(0 0)
Red(2 1) Black(0 2)
Red(2 1) Black(1 0)
Red(2 1) Black(1 2)
Red(2 1) Black(2 0)
Red(2 1) Black(2 2)
Red(2 2) Black(0 0)
Red(2 2) Black(0 1)
Red(2 2) Black(1 0)
Red(2 2) Black(1 1)
Red(2 2) Black(2 0)
Red(2 2) Black(2 1)
请按任意键继续. . .
相关文章推荐
- 有趣编程 打印象棋中两个老帅不碰面的所有位置组合
- 编写一个程序以确定分别由signed及unsigned限定的char、short、int及long类型变量的取值范围。采用打印标准头文件中的相应值以及直接计算两种方式实现
- 使用反射打印一个类的所有信息
- 有一个X*Y的网格,只能向右、向下移动,从(0, 0)走到(X-1, Y-1),中间某些位置有障碍物,打印所有可能的路径
- 使用递归打印出一个文件夹下所有子孙文件的树形结构
- (本程序功能:字符串A中找出包含字符串B中所有字符的位置并输出) 在使用全局变量m的时候,输出错误的结果,而用下面局部变量M就没问题。
- 使用递归法打印出一个目录里的所有文件
- 只用一个字节 计算象棋将帅之间可能的位置
- logback框架使用误区 如何将所有包的ERROR级别日志集中打印到一个日志文件中
- (1.5.1.2)编程之美:中国象棋将帅问题——一个变量实现多重循环
- 练习2-1 编写一个程序一确定分别由signed及unsigned限定的char,short,int及long类型变量的取值范围。采用打印标准头文件中的相应值以及直接计算两种方式实现。通过直接计算来确定浮点类型的取值范围是一项难度很大的任务。
- Java反射学习-使用反射修改一个类中的所有String类型的成员变量的值
- 不要把所有鸡蛋都放在一个篮子里——使用RoboCopy实现网络备份
- 不要把所有鸡蛋都放在一个篮子里——使用RoboCopy实现网络备份
- 不要把所有鸡蛋都放在一个篮子里——使用RoboCopy实现网络备份
- 打印一个N位二进制数的所有表示
- 不要把所有鸡蛋都放在一个篮子里——使用RoboCopy实现网络备份
- 列出一个工作簿中所有已使用的自定义函数
- C# Visual Studio 2005中定义一个变量让所有的Form都能访问到
- 如何使用perl遍历一个目录下的所有文件