应用重力的宝石迷阵钻头板

时间:2014-08-27 10:25:14

标签: python algorithm python-3.x bit-manipulation

我正在尝试制作带有位板的Bejeweled级联模拟器。到目前为止,我已经能够检测并删除匹配,但现在我需要让珠宝掉下来。我的状态由位板列表代表,每种类型的宝石都有一个。我有一个被删除的所有珠宝的面具。

是否可以使用一些按位魔术来做到这一点?

两个初始位板的示例(我们假设只有两种类型的珠宝,它是4x4板而不是8x8)。第一位是左下角,第四位是左上角,最后一位是右上角。

0 0 1 1    1 1 0 0
1 0 0 0    0 1 1 1
1 1 1 1    0 0 0 0
0 0 1 0    1 1 0 1

删除匹配后:

0 0 1 1    1 1 0 0
1 0 0 0    0 0 0 0
0 0 0 0    0 0 0 0
0 0 1 0    1 1 0 1

使用的面具是:

0 0 0 0
0 1 1 1
1 1 1 1
0 0 0 0

在重力之后它应该看起来像:

0 0 0 0    0 0 0 0
0 0 0 0    1 0 0 0
1 0 1 1    0 1 0 0
0 0 1 0    1 1 0 1

这是用整数实现的,步骤如下:

[43814, 21721]       # Initial state
[35076, 4249], 26210 # State after matches have been removed, mask used to remove matches
[8962, 4149]         # State after gravity has been applied

2 个答案:

答案 0 :(得分:0)

要使用bithift将你的面具移动一行所需的位数。使用掩码从上面的行中选择位,并使用位移和oring将所选位复制一行。简单的算法会将掩码循环到顶部并逐行向下移动。但优化可能是通过位移和自我进行扩展来扩展掩码,然后通过单次操作将所有上面的位移动。

位板操作的良好来源是国际象棋维基:https://chessprogramming.wikispaces.com/General+Setwise+Operations

答案 1 :(得分:0)

让我们打电话给左边的宝石,A;右边,B;以及董事会的物理代表,AB
在删除之后,我们有:

               0 0 1 1      1 1 0 0     1111
AB =  A | B =  1 0 0 0  or  0 0 0 0  =  1000
               0 0 0 0      0 0 0 0     0000
               0 0 1 0      1 1 0 1     1111

算法:

For each row (r, a temporary variable) above the lowest row with removals:
  For each jewel type:
    starting with the lowest row where removals occurred (AB_row)
    While r is not zero
      make a temporary copy of AB_row (AB_row_copy)
      new row for jewel_type := (row | AB_row) ^ same_row_for_other_jewel_types
      r := r & AB_row_copy
      ascend to next row of AB

示例:

使用删除更新最低行上方的第一行:

# AB_row is the lowest row with removals from the bitboard that combines all
# jewel types; r_A is a copy from the A bitboard of the first row above AB_row 
r_A = 1 0 0 0, AB_row = 0 0 0 0 

  # make a copy of AB_row
  AB_row_copy = 0 0 0 0

  # calculate the new row for jewel type A
  # new row for jewel_type := (row | AB_row) ^ same_row_for_other_jewel_types
  new row for A = (1 0 0 0 | 0 0 0 0) ^ 0 0 0 0 = 1 0 0 0

  # update the fallen bits from r_A
  # r := r & AB_row_copy
  r_A = 1 0 0 0 & 0 0 0 0 = 0 0 0 0

# r_B at this row is zero, nothing to do.
r_B = 0 0 0 0

使用删除更新最低行上方的第二行:

# row for A has the same process same as above
r_A = 0 0 1 1, AB_row = 1 0 0 0 // AB_row is the lowest row with removals
  AB_row_copy = 1 0 0 0
  new row for A = (0 0 1 1 | 1 0 0 0) ^ 0 0 0 0 = 1 0 1 1
  r_A = 0 0 1 1 & 1 0 0 0 = 0 0 0 0


# AB_row is the lowest row with removals from the bitboard that combines all
# jewel types; r_B is a copy from the B bitboard of the second row above AB_row
r_B = 1 1 0 0, AB_row = 1 0 1 1

  # make a copy of AB_row
  AB_row_copy = 1 0 1 1

  # calculate the new row for jewel type B
  # new row for jewel_type := (row | AB_row) ^ same_row_for_other_jewel_types
  new row for B = (1 1 0 0 | 1 0 1 1) ^ 1 0 1 1 = 0 1 0 0

  # update the fallen bits from r_B
  # r := r & AB_row_copy
  r_B = 1 1 0 0 & 1 0 1 1 = 1 0 0 0

# since there are still set bits remaining in r_B after removing the fallen 
# bit, we continue with r_B, proceeding to the next row up.

# AB_row now is the next row up from the lowest row with removals, again from
# the bitboard combining all jewel types; r_B is the same variable, now with 
# one set bit less (one "fallen" bit)
r_B = 1 0 0 0, AB_row = 0 0 0 0

  # make a copy of AB_row
  AB_row_copy = 0 0 0 0

  # calculate the new row for jewel type B
  # new row for jewel_type := (row | AB_row) ^ same_row_for_other_jewel_types
  new row for B = (1 0 0 0 | 0 0 0 0) ^ 0 0 0 0 = 1 0 0 0

  # update the fallen bits from r_B
  r_B = 1 0 0 0 & 0 0 0 0 = 0 0 0 0

  #r_B is now zero so the while loop is terminated