2014-08-27 2 views
3

Я пытаюсь создать каскадный симулятор Bejeweled с долотами. Пока что я смог обнаружить и удалить матчи, но теперь мне нужно, чтобы драгоценности упали. Мое состояние представлено списком досок, по одному для каждого типа драгоценностей. У меня есть маска всех драгоценностей, которые удалены.Bejeweled bit board с применением силы тяжести

Можно ли использовать некоторую побитную магию для этого?

Пример двух начальных бит-досок (давайте предположим, что есть только два типа драгоценностей и что это плата 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

Не могли бы вы добавить минимальный пример того, как выглядят эти доски? –

+0

@tobias_k Понятно? –

+0

Да, это лучше. Ну, вам нужно будет проверить, является ли ячейка '0' на всех досках, тогда вы можете сбросить ячейку выше. Это было бы намного проще, если бы вы использовали одну доску для всех драгоценностей, например. '1' для синего,' 2' для зеленого и т. Д. Любая конкретная причина, по которой вы используете несколько досок? Даже тогда вы можете легко получить эти доски из этой комбинированной доски. –

ответ

0

Чтобы свалить биты, вам нужно переместить маску на одну строку вверх с помощью бита. Выберите биты из строки выше, используя маску и копию, которая выбрала биты с одной строкой вниз с использованием сдвига бит и оргов. Простой алгоритм маскирует петлю вверх и делает движение по строкам вниз. Но оптимизация может заключаться в расширении маски с помощью сдвигов бит и ручном управлении, а затем перемещение всех вышеприведенных бит с помощью одной операции.

Хороший источник для битого борту operatinos шахматы вика: https://chessprogramming.wikispaces.com/General+Setwise+Operations

+0

Постарайтесь понять, почему он работал в оригинальном случае, чтобы заставить его работать и в более сложном случае. Это все еще только о перемещении бит вокруг со сдвигами. –

+0

Чтобы сменить разные биты на разные суммы с помощью одной команды, нужно использовать умножение. Но не может быть никакой операции размножения, управляющей требуемым движением. Или это может быть очень сложно рассчитать. Вот почему лучшим вариантом может быть создание отдельных масок для каждого столбца, у которого есть различное количество удаляемых элементов. С помощью этих масок вы можете запускать переменную только один раз для всех столбцов с одинаковым количеством шагов. Чтобы сгенерировать маску падения с представлением основного бита столбца (0-7 бит -> 1-й столбец), вы можете использовать целочисленное вычитание: 0x100-0x008 = 0x0f8 –

+0

Или я могу даже иметь таблицу поиска по 256 записей и использовать ее для преобразования каждого столбца бит доски. Для этого, однако, мне нужно придумать некоторое число, которое при умножении на данные смещает биты соответствующим образом? Как бы я вычислил это число? –

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, я бы понял, как это работает немного лучше. –

+0

@Scorpion_God By 'other_jewel_types', я имел в виду биты для типов драгоценностей, кроме тех, которые вы тестируете. В примере цикла я начал с левой стороны 'A'. 'r_A' - это строка с этой доски, используемая как временная переменная, которая изменяется. Это '' или '' с 'AB' (общая доска), а затем' xor'ed с правым бортом типа драгоценности, 'B', чтобы отфильтровать биты, которые не принадлежат в' A'. Вы видите, как пример такой же, как ваш? «AB_row» с удалением изменяется по мере продвижения цикла. –

+0

В вашем примере вы не 'или держите его со всей доской. Просто строка из него. –

Смежные вопросы