什么是在数据库中存储整个国际象棋游戏最节省空间的方法?考虑到平均游戏长度为50-70步(1步表示两位玩家各走一次),希望所需空间少于800位。
棋子的初始位置可以用6位来存储,而每步移动可能需要2-4位。有没有办法将其存储得更少一些呢?
棋子的初始位置可以用6位来存储,而每步移动可能需要2-4位。有没有办法将其存储得更少一些呢?
1. e3 e5
2. Qg4 d6
number_of_moves(7 bits)
start_position (6bits) - target_position (6bits)
start_position (6bits) - target_position (6bits)
...
例如:
70
E2 - E4
D7 - D5
...
70 moves * 12 bits + 7 bits = 847 bits = 106 Bytes
number_of_moves(7 bits)
white_piece_ix (4bits) - target_position (6bits)
black_piece_ix (4bits) - target_position (6bits)
...
70 moves * 10 bits + 7 bits = 707 bits = 89 bytes
这已经低于您的800个比特
如果这还不够,您可以使用变量棋子索引表。因此,每当某个棋子从棋盘上“删除”,您都需要将索引的值进行移动,以便未使用的棋子将被下一个索引使用,并且间隙将位于最后的值上(例如,如果第13号棋子被移除,则14号和15号棋子将成为13号和14号)。这样一来,一方只剩下少于8个棋子时,您可以使用每个索引3个比特,少于4个棋子时使用2个比特,依此类推,最终您将以每步7到10个比特的速度结束。
现在您还可以应用压缩(LZW或Huffman),我建议使用LZW,因为Huffman还需要传递概率分布表,而这可能会是:
16 * ceil(log2(2*70)) bits = ~ 128 bits
相对于800位的限制,这是数据中的相当大部分,而LZW在运行时构建其词典,它的大小可以任意选择(所以即使有小内存也不应该是一个大问题)
有32个棋子和64个方格。因此,需要11位来存储一个棋子及其位置:5位用于表示棋子,6位用于表示位置。
起始位置是固定的,所以不需要存储它。之后,你只需要存储移动的棋子的位置:每个棋子需要11位。也就是说,你存储的游戏只记录了每个棋子的移动。你知道棋子的起始位置,所以你只需要存储棋子的最终位置。
大多数移动只需使用11位(一个棋子移动)。有趣的是,通过更新被吃掉的棋子的位置可以编码捕获。游戏逻辑可以判断两个棋子是否占据同一空间,并从棋盘上移除被吃掉的棋子。这是件好事,因为没有第65个空间(即“不在棋盘上”)可以放置被吃掉的棋子:你没有相应的位数。吃过路兵也可以用类似的方式进行编码:让游戏逻辑理解它。我最初认为王车易位需要编码两个棋子的移动,但实际上并不需要。国王总是移动两个空间,而在其他任何情况下都是非法移动。你的逻辑可以轻松识别这个“非法”移动并执行正确的操作。
兵升变成一个问题。走法不是问题,但你需要一种方式来指代新创建的棋子。棋子只有5个比特位,而这些已经被使用完了。考虑将你的国王的马兵从G7移动到G8。通常情况下,你会存储[14,62](即棋子编号14移动到位置62)。你需要一种方式来表示,嘿,棋子编号14现在是一个皇后而不是一个兵。这是可以做到的,但需要额外的比特位。