Redian新闻
>
使用位字段和掩码写一个国际象棋游戏 | Linux 中国

使用位字段和掩码写一个国际象棋游戏 | Linux 中国

科技
 
导读:使用位字段和掩码是不用数据结构组合数据的常用方法。                                 
本文字数:3232,阅读时长大约:4分钟

假设你在用 C 语言写一个国际象棋游戏。追踪棋盘上棋子的一种方法是定义一个结构,该结构定义了棋盘上每个可能的棋子及其颜色,因此每个格子都包含该结构中的一个元素。例如,你可以将结构定义成下面这样:

  1. struct chess_pc {
  2.    int piece;
  3.    int is_black;
  4. }

有了这个数据结构,你的程序就会知道每个格子里是什么棋子及棋子的颜色。你可以快速识别出棋子是兵、车、马、象、后还是王,以及棋子是黑还是白。但是,有一种更直接的方法来跟踪这些信息,同时只用更少的数据和内存。与为棋盘上的每个方格存储两个 int 值的结构不同,我们可以存储单个 int 值,并使用二进制位字段和掩码来标识每个方格中的棋子和颜色。

比特和二进制

当使用位字段表示数据时,我们最好像计算机一样思考。让我们从列出可能的棋子开始,并为每个棋子分配一个数字。让我们进入下一个步骤,用二进制表示这个数字,也就是按照计算机追踪它的方式。记住,二进制数是由比特组成的,比特要么是 0,要么是 1。

◈ 00000000: 空(0)
◈ 00000001: 兵(1)
◈ 00000010: 车(2)
◈ 00000011: 马(3)
◈ 00000100: 象(4)
◈ 00000101: 后(5)
◈ 00000110: 王(6)

要列出一个棋盘上的所有棋子,我们只需要三个比特从右到左依次代表值 1、2 和 4。例如,数字 6 是二进制的 110。6 的二进制表示中的其他所有位都是 0。

一个聪明一点的方法:我们可以使用那些额外的总是为零的比特来跟踪一个棋子是黑还是白。我们可以使用数字 8(二进制 00001000)来表示棋子是否为黑色。如果这一位是 1,则代表该棋子是黑色;如果是 0,则代表该棋子是白色。这被称为位字段,稍后我们可以使用二进制掩码将其取出。

用位字段存储数据

要编写一个使用位字段和掩码的国际象棋程序,我们可以从以下定义开始:

  1. /* 棋子 */
  2. #define EMPTY 0 // 空
  3. #define PAWN 1 // 兵
  4. #define ROOK 2 // 车
  5. #define KNIGHT 3 // 马
  6. #define BISHOP 4 // 象
  7. #define QUEEN 5 // 后
  8. #define KING 6 // 王
  9. /* 棋色 */
  10. #define BLACK 8 // 黑
  11. #define WHITE 0 // 白
  12. /* 掩码 */
  13. #define PIECE 7

当你为一个棋格赋值时,比如初始化棋盘,你可以赋一个 int 类型的值来跟踪棋子及其颜色。例如,要在棋盘的 0,0 位置存储棋子黑车,你可以使用下面的代码:

  1.   int board[8][8];
  2. ..
  3.   board[0][0] = BLACK | ROOK;

| 是二进制“或”(OR)操作符,这意味着计算机将合并两个数字的比特。对于每个比特的位置,如果任意一个数字的比特为 1,该位置比特的结果也是 1。BLACK 的值(8,即二进制下的 00001000)和 ROOK 的值(2,即二进制下的 00000010)的二进制或结果是二进制下的 00001010,即 10:

  1.     00001000 = 8
  2.  OR 00000010 = 2
  3.     ________
  4.     00001010 = 10

类似地,要在棋盘的 6,0 位置存储一个白色兵,你可以这样做:

  1.   board[6][0] = WHITE | PAWN;

这样存储的值就是 WHITE(0)和 PAWN(1)的二进制或的结果,也即是 1。

  1.     00000000 = 0
  2.  OR 00000001 = 1
  3.     ________
  4.     00000001 = 1

用掩码获取数据

在下棋过程中,程序需要知道棋格中的棋子和它的颜色。我们可以使用二进制掩码来分离这部分。

举个例子,程序可能需要知道棋局中棋盘上特定棋格的内容,例如位于 board[5][3] 的数组元素。这个是什么棋子,是黑的还是白的?为了识别棋子,使用二进制“与”(AND)操作符将元素的值与掩码 PIECE 结合起来:

  1.   int board[8][8];
  2.   int piece;
  3. ..
  4.   piece = board[5][3] & PIECE;

二进制“与”(AND)操作符(&)将两个二进制值结合,这样对于任意位,如果两个数字中的那个位都是 1,那么结果也是 1。例如,如果 board[5][3] 的值是 11(二进制下的 00001011),那么 11 和 掩码 PIECE(7,二进制下的 00000111)二进制与的结果为二进制下的 00000011,也即 3。这代表马,马的值是 3。

  1.     00001011 = 11
  2. AND 00000111 = 7
  3.     ________
  4.     00000011 = 3

解析棋子的颜色是一个简单的事情,只需要将棋子的值与 BLACK 位字段进行二进制与操作。比如,你可以写一个名为 is_black 的函数来确定棋子是黑还是白:

  1. int
  2. is_black(int piece)
  3. {
  4.   return (piece & BLACK);
  5. }

之所以可以这样,是因为 BLACK 的值为 8(二进制下的 00001000)。在 C 语言中,任何非零值都被视为 True,零总是 False。所以如果 5,3 处的棋子是黑色的,则 is_black(board[5][3]) 返回 True 值(8);如果是白色的,则返回 False 值(0)。

位字段

使用位字段和掩码是不使用结构组合数据的常用方法。它们值得被程序员收藏到“工具包”中。虽然数据结构对于需要跟踪相关数据的有序编程是一种有价值的工具,但是使用单独的元素来跟踪单个的开或闭值(例如棋子的颜色)的效率较低。在这些情况下,可以考虑使用位字段和掩码来更高效地组合数据。


via: https://opensource.com/article/21/8/binary-bit-fields-masks

作者:Jim Hall 选题:lujun9972 译者:FYJNEVERFOLLOWS 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出


LCTT 译者 :FYJNEVERFOLLOWS
🌟🌟
翻译: 3.0 篇
|
贡献: 92 天
2022-05-07
2022-08-07
https://linux.cn/lctt/FYJNEVERFOLLOWS
欢迎遵照 CC-BY-SA 协议规定转载,
如需转载,请在文章下留言 “转载:公众号名称”,
我们将为您添加白名单,授权“转载文章时可以修改”。

微信扫码关注该文公众号作者

戳这里提交新闻线索和高质量文章给我们。
相关阅读
关于 Linux 和 Git 的创造者 Linus Torvalds 的 20 件趣事 | Linux 中国历史最佳惨败给智能肛珠?作弊疑云笼罩国际象棋别的简报|国际象棋机器人比赛中压断人类男孩手指在 Linux 上使用 Rhythbox 听音乐 | Linux 中国国际象棋大师被质疑"用跳蛋作弊",他急了:脱光跟你再比一场!在 Linux 上玩电子游戏的三种方式 | Linux 中国商汤AI象棋机器人到底谁在买?北大象棋大师已签收3 个可在 Linux 上玩旧 NES 游戏的 NES 模拟器 | Linux 中国检查 Linux 磁盘使用情况 | Linux 中国在 Linux 中使用 Etcher 创建可启动 USB – 下载和使用指南 | Linux 中国如何使用 Linux sed 命令自动进行文件编辑 | Linux 中国国际象棋如何作弊?不是传说中的遥控肛塞在 Linux 中使用组合键输入隐藏的字形 | Linux 中国健身房、酸豆角肉末、后院风情T-Space网校2022秋季学期:国际象棋神秘的 GeckoLinux 创建者推出了一个新的 Debian 合成发行版 | Linux 中国使用 Podman Desktop 在 Fedora Linux 上管理容器 | Linux 中国“作弊”:只需要知道这一个 Linux 命令就够了 | Linux 中国弘仁(清) 山水册在 Linux 上使用 Bash 创建一个临时文件 | Linux 中国“肛珠作弊谣言”成国际象棋史上最大丑闻19岁美国选手爆冷击败国际象棋世界冠军,最新调查称其此前可能作弊100多次转载一篇小说: 春药 (别想歪)我是如何使用 Linux fmt 命令来格式化文本 | Linux 中国美丽事业Linux inxi 命令的 3 种使用方法 | Linux 中国诺基亚勒令一个开源 Linux 手机项目 “NOTKIA” 改名字 | Linux 中国国际象棋"肛珠作弊案"结局!没找到肛珠,却揪出更多作弊者?!如何在 Linux 中使用 Pandoc 转换文件格式 | Linux 中国我如何使用现场 USB 设备恢复我的 Linux 系统 | Linux 中国唐山打人事件,警察哪去了?如何在 Linux 中使用媒体传输协议访问安卓设备的内部存储和 SD 卡 | Linux 中国Linux 优先的 AI 图像提升器 Upscayl 发布了第一个版本 | Linux 中国有了扩展,GNOME Web 正逐渐成为 Linux 桌面上一个有吸引力的选择 | Linux 中国
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。