【游戏之乐】中国象棋 让你学会位运算
来源:互联网 发布:淘宝优惠券转手机端 编辑:程序博客网 时间:2024/05/21 09:27
任务难度:3
任务说明:
在中国象棋里,当只剩下将帅(A和B代指将和帅)两个棋子时 将帅不能处于同一列 要求输出将帅的所有合法位置(将帅所在的九宫格从上到下从左至右编号为1~9)
例如:
合法位置:
A=1,B=2
不合法位置:
A=1,B=1
要求:只能使用一个变量
乍一看问题并不难,但是最后的要求是只能使用一个变量,这也是好玩之处~~
先让我们思考一下A和B的状态共有多少种,九宫格的9个位置,即各有9种状态,9需要用4bit来存储,储存AB两种状态则至少需要8bit,即一个BYTE
那么主体思想就是我们通过某种循环方式,分别枚举AB状态的所有值(1~9)当两个状态的%3即为两个状态的列数相同时,则不能输出,否则输出
接下来介绍三种方法,让你学会位运算:
方法一:
假设我们开一个BYTE型的变量b,用左边的4bit存储B的状态,用右边的4bit存储A的状态,我们需要实现4种操作,即取出该变量的左边四位或右边四位,将该变量的左边四位或右边四位设置为n值(n取1~9)
取出右边的值只需要将变量b与00001111(RMASK)相与即可,取出左边四位的值只需要先将b与11110000(LMASK)相与,再右移四位即可
而将右边的值改为n 就需要将左边的值先保留下来 即将变量b与11110000相与,然后再和n异或即可
而将左边的值改为n 就需要将右边的值先保留下来,即将变量b与00001111相与,然后再和右移四位后的n异或即可
我们用四个宏定义的函数实现上述功能,循环枚举的时候只需要先将b的左右置为1,然后每次多置1即可,代码如下:
#include <cstdio>#include <windows.h>/*解法一*/#define HALF_BIT_LENGTH 4//因为要频繁使用左右移4位的操作,这里把4宏定义出来#define FULLMASK 255//即11111111 用于得出LMASK和RMASK#define LMASK (FULLMASK<<HALF_BIT_LENGTH)//将11111111左移4位 即得到11110000#define RMASK (FULLMASK>>HALF_BIT_LENGTH)//即00001111#define RGET(b) (b & RMASK)//得到右4位#define LGET(b) ((b& LMASK)>>HALF_BIT_LENGTH)//得到左4位#define RSET(b,n) (b= (b & LMASK)^n)//将右四位置为n#define LSET(b,n) (b= (b & RMASK)^(n<<HALF_BIT_LENGTH))//将左四位置为n#define GRIDW 3//由于求列数时需要对3取余,这里也宏定义出来int main(){unsigned char b;for (RSET(b,1);RGET(b)<=GRIDW*GRIDW;RSET(b,(RGET(b)+1))){//枚举右四位从1到9的情况,即枚举A的9种状态for (LSET(b,1);LGET(b)<=GRIDW*GRIDW;LSET(b,(LGET(b)+1))){//枚举左四位1到9的情况,即枚举B的9种状态if (RGET(b)%GRIDW!=LGET(b)%GRIDW)//列数不同则表示AB位置合法{printf("A=%d, B=%d\n",RGET(b),LGET(b));}}}return 0;}
是不是感觉很奇妙呢?这就是位运算的妙用,接下来介绍两种更为简便的方法
方法二:我们将AB的所有状态排列组合,其实只有81种组合方式,我们直接定义一个BYTE变量i表示AB位置的排列方式,i=1表示A为1 B为1
用i/9+1表示A i%9+1表示B i的取值范围为1~81 想一想这样是不是涵盖了A与B分别取1~9的81种情况
代码如下:
#include <cstdio>#include <windows.h>BYTE i=0;int main(){for (;i<=81;i++){if ( i/9%3 != i%9%3){printf("A=%d, B=%d\n",i/9+1,i%9+1);}}return 0;
接下来介绍最后一种方法 最简单也最容易理解 直接创建一个大小为BYTE的struct变量 将BYTE的前4位和后4位分开直接设为两个成员变量
代码如下:
#include <cstdio>#include <windows.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;
- 【游戏之乐】中国象棋 让你学会位运算
- 第一章 游戏之乐 中国象棋将帅问题
- 编程之美--游戏之乐--1.2中国象棋将帅问题
- 简简单单学会C#位运算
- 【游戏之乐】让CPU占用率曲线听你指挥
- Firefox os 游戏开发之中国象棋
- 游戏中的位运算
- 中国象棋将帅问题; 伟大的位运算; 终于开窍了。。。
- 位运算中你不知道的高深之处!
- 学会让自己之值钱
- 编程之美 中国象棋将帅问题 位操作
- 第1章 游戏之乐 让cpu 占用率曲线听你的指挥
- 十分钟让你学会放松
- 学会精力管理 让你事半功倍
- 让你的电脑学会自己起床
- 让你学会Linux计划任务
- 一个例子让你学会使用jxl
- 学会沟通让你在职场如鱼得水
- 符号编码-ASCII、Unicode、Unicode big endian、UTF-8之间的关系(转)
- OC的点语法
- Linux系统下如何查看及修改文件读写权限
- hibernate之5.many2one单向
- Android adb不是内部或外部命令 问题解决
- 【游戏之乐】中国象棋 让你学会位运算
- Java_Web Project_jdbc数据库连接底层;
- HDU-2087 剪花布条(kmp)
- 寻找一个字符串中连续出现次数最多的子串
- 【手把手教你做智能车】第二节-IAR新建工程及基本设置
- 推荐!国外程序员整理的C++资源大全
- 从Trie树(字典树)谈到后缀树
- 推荐!国外程序员整理的 C++ 资源大全
- 【软件工程】产品调研分析报告