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

问题描述:

在中国象棋规则中,将和帅规定只能在田字格中移动,且将和帅是不能碰面的,请求解出所有可能的符合规则的将帅位置。

限制条件:

只能使用一个字节的变量

问题解答:

                            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;
}

参考资料:

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

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

    原文作者:xyw_eliot
    原文地址: https://blog.csdn.net/xyw_blog/article/details/19474627
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞