问题描述:
在中国象棋规则中,将和帅规定只能在田字格中移动,且将和帅是不能碰面的,请求解出所有可能的符合规则的将帅位置。
限制条件:
只能使用一个字节的变量
问题解答:
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 3
int 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~80
while(--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;
}
参考资料: