【编程之美】中国象棋将帅问题

1 题目

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

2 代码

#include <cstdio>
#include <iostream>
using namespace std;

#define LEFT            (255<<4)
#define RIGHT           (255>>4)
#define LGET(a)         ((a & LEFT)>>4)
#define RGET(a)         (a & RIGHT)
#define LSET(a, b)      (a = ((a & RIGHT) ^ (b<<4)))
#define RSET(a, b)      (a = ((a & LEFT) ^ b))
/*
 * 把一个八们的unsigned char c的前4位和后4位当作两个数来使用。0-255足够使用了。
 * 其中LEFT为0x00001111,RIGHT为0x11110000.
 * RGET(a) 通过a与RIGHT取&操作来实现取a低4位值。LGET通过a与LEFT取&并右移4位来实现取a高4位值。
 * LSET(a, b)把a的低4位设置为b。RSET(a, b)把a的高4位设置为b。
 */
void solution1(){
    unsigned char c;
    for(LSET(c, 1); LGET(c)<=9; LSET(c, LGET(c)+1))
        for(RSET(c, 1); RGET(c)<=9; RSET(c, RGET(c)+1))
            if(LGET(c)%3 != RGET(c)%3)
                cout<<"A:="<<LGET(c)<<" B:="<<RGET(c)<<endl;    
}
/*
 * i/9取8时i%9可以取到8-0。
 * i/9取7时i%9可以取到8-0。
 * ...
 */
void solution2(){
    int i = 81;
    while(i--){
        if(i/9%3 == i%9%3)
            continue;
        cout<<"A:="<<i/9+1<<" B:="<<i%9+1<<endl;
    }
}
/*
 * 用a的4位和b的4位。
 */
void solution3(){
    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);
}
int main(int argc, char *argv[])
{
    // solution1();
    // solution2();
    solution3();
    return 0;
}

Author: visaya fan <visayafan[AT]gmail.com>

Date: 2011-08-24 00:15:54

HTML generated by org-mode 6.33x in emacs 23

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值