2014-08-27 19 views
3

我正在嘗試製作位珠寶級聯寶石模擬器。到目前爲止,我已經能夠檢測和刪除火柴,但現在我需要讓珠寶掉下來。我的狀態由一系列位板表示,每種類型的寶石一個。我有一個被刪除的所有珠寶的面具。珠光寶寶位板應用重力

是否有可能使用一些按位魔法來做到這一點?

兩個初始位板的例子(讓我們假設只有兩種類型的寶石,它是一個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 
+0

您能否添加這些位板的外觀的最小示例? – 2014-08-27 11:28:52

+0

@tobias_k它可以理解嗎? – 2014-08-27 11:46:49

+0

是的,那樣更好。那麼,你必須檢查所有電路板上的單元是否爲'0',然後你可以將單元放在上面。如果你爲所有的珠寶使用一塊電路板,這將會容易得多,例如,藍色的「1」,綠色的「2」等等。你使用多位電路板的任何特殊原因?即使那樣,你也可以很容易地從那個組合電路板中獲得這些比特板。 – 2014-08-27 11:53:49

回答

0

爲了落下位,你需要移動你的掩碼一排移位。使用掩碼從上面的行中選擇位,並使用位移和定位將選定的位複製一行。簡單的算法會循環屏蔽到頂部並逐行移動。但是優化可以通過位移和自我擴展來擴展掩碼,然後通過單個操作移動所有位以上的位。

對位板operatinos良好的來源是國際象棋的wiki:https://chessprogramming.wikispaces.com/General+Setwise+Operations

+0

試圖弄清楚爲什麼它在原始情況下工作,以使其在更復雜的情況下也能工作。它仍然只是關於移動位移。 – 2014-08-27 16:29:36

+0

要用單指令移位不同的位數,必須使用乘法。但是可能不存在管理所需移動的任何單一乘法操作。或者它可能很難計算。爲什麼更好的選擇可能是爲每個要移除元素數量不同的列生成單獨的掩碼。對於具有相同步數下降的所有列,使用這些蒙版,您只能對移動部件運行一次。要生成列主位顯示(0-7位 - >第一列)的下降掩碼,可以使用整數減法:0x100-0x008 = 0x0f8 – 2014-08-28 05:26:55

+0

或者我甚至可以有一個256條目查找表並使用它來變換每列位板。要做到這一點,我需要拿出一些數字,當乘以數據,適當地移動位?我如何計算這個數字? – 2014-08-28 05:42:23

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 
+0

這很不清楚。你能說明你的循環,並定義每個變量是什麼(例如什麼是'other_jewel_types'?)。如果你能用Python來展示我,我想我會理解它的工作原理。 – 2014-08-28 03:47:46

+0

@Scorpion_God通過'other_jewel_types',我的意思是除了您正在測試的寶石類型以外的寶石類型。在示例循環中,我從左側的「A」開始。 'r_A'是該板的一行,用作臨時變量,並被修改。它是用'AB'(總板)'或''用'右'寶石型板''B''來過濾掉不屬於'A'的位。你能看到這個例子和你的一樣嗎?隨着循環的進行,帶有刪除的「AB_row」被修改。 – 2014-08-28 03:57:59

+0

在你的例子中,儘管你不是整個電路板的「或」。從它只是一排。 – 2014-08-28 05:12:50