问题描述:根据中国象棋的基本原则,在只有双方的将帅的棋盘上,找出所有双方可以落子的位置,也就是将帅不能
相互面对,而且只能使用一个字节存储变量。
这个问题本身是并不复杂,若没有“只能使用一个字节存储变量”这个条件的限制,直接两层 for循环,遍历将帅所有的
可能位置即可,但有了这个条件限制后,问题一下子就变得复杂了些。那么接下来我们要思考的就是如何用一个字节
的变量来做两层循环的遍历了。书中给出的第一个解法是将一个BYTE变量通过相应的位运算拆成两个用,前4位代表
将的位置,后4位代表帅的位置。事先已经将“将”和“帅”可以走的3*3的位置进行了编号,编号如下:
而书中的解法三则是利用结构体的特性来解决一个字节的变量来遍历二层循环的问题,在思想上和解法一是一样的,
只不过用了不同的技巧而已。解法三的主要代码如下:
struct
{
unsigned char a:4;
unsigned char b:4;
}i;
for (i.a = 1; i.a <= 9; i.a++)
{
for (i.b = 1; i.b <= 9; i.b++)
{
if (i.a % 3 != i.b % 3)
printf("A = %d, B = %d\n", i.a, i.b);
}
}
之所以最后讲解法二,是因为我觉得这是这三个解法中最难理解的一个,也是最有意思的一个,也充分体现了编程之
美!它的代码如下:
BYTE i = 81;
while (i--)
{
if (i / 9 % 3 == i % 9 % 3)
continue;
printf ("A = %d, B = %d\n", i / 9 + 1, i % 9 + 1);
}
81,很明显,是总共要遍历的次数,因为“将”和“帅”都有3*3个位置,那么一共就有9*9种不同的摆放位置了。而这里
最难理解的应该就是 if语句里的内容了。它这里的思想我的理解是:81分为9个3*3的块,块的编号为9~1。块的编号
就相当于“将”的位置,其值的表达式是 i / 9 + 1,这就相当于我们遍历的第一层循环;而每一个3*3块则看成“帅”的位
置,其值的表达式是i % 9 + 1,这就相当于遍历的第二层循环。如果理解了这个的话,那么再来理解if语句就不是很
难了。
我想,以后要是遇到用一个变量来遍历多层循环基本也可以用这个思路了,只是实现起来会比较麻烦点,当然在这三
个解法中,解法二毫不疑问是最容易理解,也是最好实现的一个。但为了提高我们的编程水平,还是应该掌握解法二
的思想以及实现!!!