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

来源:互联网 发布:淘宝大悦运动怎么样 编辑:程序博客网 时间:2024/04/30 19:27
问题描述:
在中国象棋规则中,将和帅规定只能在田字格中移动,且将和帅是不能碰面的,请求解出所有可能的符合规则的将帅位置。
限制条件:

只能使用一个字节的变量

问题解答:

                            1 2 3

将的移动范围: 4 5 6

                            7 8 9

                            1 2 3

帅的移动范围: 4 5 6

                            7 8 9

如果没有限制条件(使用一个字节的变量),则本题容易解决:

S1:a=将当前位置号

S2:b=帅当前位置号

S3:if a%3 != b%3 符合 else 不符合

注:a%3和b%3分别得到a、b所在的列

#include<iostream>
using namespace std;

//不对存储空间进行限制
int main(){
for (char a=9; a>0; a--)
for(char b=9; b>0; b--)
if(a%3 != b%3)
printf("a = %d, b = %d\n",a, b);
return 0;
}

方法一:

题目限制只能使用一个字节,即8位,我们可以将8位进行拆分,前4位存放a的位置1-9,后4位存放b的位置1-9.(4位能表示的范围为0-15,所以肯定能存放9以内的数字),所以要解决如何从8位字节中提取前4位和后4位。

#define HALF_BITS_LENGTH 4

// 这个值是记忆存储单元长度的一半,在这道题里是4bit

#define FULLMASK 255

// 这个数字表示一个全部bit的mask,在二进制表示中,它是11111111。

#define LMASK (FULLMASK << HALF_BITS_LENGTH)

// 这个宏表示左bits的mask,在二进制表示中,它是11110000。

#define RMASK (FULLMASK >> HALF_BITS_LENGTH)

// 这个数字表示右bits的mask,在二进制表示中,它表示00001111。

#define RSET(b, n) (b = ((LMASK & b) ^ n))

// 这个宏,将b的右边设置成n

#define LSET(b, n) (b = ((RMASK & b) ^ (n<< HALF_BITS_LENGTH)))

// 这个宏,将b的左边设置成n

#define RGET(b) (RMASK & b)

// 这个宏得到b的右边的值

#define LGET(b) ((LMASK & b) >>HALF_BITS_LENGTH)

// 这个宏得到b的左边的值

#define GRIDW 3

// 这个数字表示将帅移动范围的行宽度。

#include <stdio.h>#define HALF_BITS_LENGTH 4#define FULLMASK 255#define LMASK (FULLMASK << HALF_BITS_LENGTH)#define RMASK (FULLMASK >> HALF_BITS_LENGTH)#define RSET(b, n) (b = ((LMASK & b) |(n)))#define LSET(b, n) (b = ((RMASK & b) | (n << HALF_BITS_LENGTH)))#define RGET(b) (RMASK & b)#define LGET(b) ((LMASK & b) >> HALF_BITS_LENGTH)#define GRIDW 3int main(){      unsigned char b;         for(LSET(b, 1); LGET(b) <= GRIDW * GRIDW; LSET(b, (LGET(b) + 1)))          for(RSET(b, 1); RGET(b) <= GRIDW * GRIDW; RSET(b, (RGET(b) + 1)))               if(LGET(b) % GRIDW != RGET(b) % GRIDW)                    printf("A = %d, B = %d\n", LGET(b), RGET(b));     return 0;}
方法二:

将帅总共有81种位置组合,为了便于计算,将位置组合num的范围计为[0, 80] 共81种。

a=num/9 b=num%9

if a%3 != b%3 符合 else 不符合

#include<stdio.h>int main(){unsigned char b=81; //b的范围:0~80while(--b){if(b/9%3 != b%9%3) printf("A = %d, B = %d\n", b/9+1, b%9+1);}return 0;}
方法三:

利用位域

将一个字节划分成两个位域,分别存储将帅的位置a和b。

#include<stdio.h>struct{unsigned char a:4;unsigned char b:4;}i;int main(){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);return 0;}

参考资料:

http://my.oschina.net/cashlang/blog/57813

http://yangwei.blogbus.com/logs/1550489.html

1 0