《编程之美》 1.2 中国象棋将帅问题

问题描述:

下过中国象棋的朋友都知道。双方的“将”和“帅”相隔遥远,并且不能照面。在象棋残局中,许多高手座利用这一规则走出精妙的杀招。假设棋盘上只有“将”和“帅”二子 (为了下面叙述方便,我们约定用A 表示“将”,B表示“帅”)。
A、B二子被限制在己方3x3 的格子里运动。每一步,A、B分别可以横向或纵向移
动一格。但不能沿对角线移动。另外,A不能面对B,也就是说,A 和B不能处于同一
纵向直线上。请写出一个程序,输出A、B所有合法位置。要求在代码中只能使用一个字节存储变量。

如图:

《编程之美》 1.2 中国象棋将帅问题

想法:

 此题的关键在于最后一个要求:代码中只能使用一个字节存储变量。

并不难想到此题的解决方案:

for(a:A的每个位置)
    for(b:B的每个位置)
        if(a和b不在同一直线)
            输出

但实际上写的时候,由于只能用一个变量,会发现内层循环很难写

这个时候就会想到一个方法:将变量拆开,用前后两部分分别表示A和B

用到两个小公式:

  a%0x10 -> 后半个字节

  a>>4 -> 前半个字节

结合上述想法,

代码如下:

 1 #include<stdio.h>
 2 int main() {
 3     unsigned char ch;
 4     for(ch=0x01; ch<=0x09; ch=ch%0x10+1) {
 5         for(ch=ch%0x10+0x10; ch>>4<=9; ch+=16)
 6             if(((ch%0x10)-(ch>>4))%3)
 7                 printf("A: %d  ; B:%d\n",ch%0x10,ch>>4);
 8     }
 9     return 0;
10 }