0

私は、パラメトリック ボード サイズhwの 2 人用ボード ゲーム ( connect 4など) に取り組んでいます。hwサイズのビットボードを使用して勝利条件を確認したい。

ボードのサイズが固定されているチェスのようなゲームでは、通常、ビットボードはある種の 64 ビット整数で表されます。hwが一定ではなく、おそらく非常に大きい場合(30*30 としましょう)、ビットボードは良い考えですか? もしそうなら、パフォーマンスを維持する大きなビットボードを処理するための C/C++ のデータ型はありますか?

私は現在Pythonに取り組んでいるので、この言語での解決策も高く評価されています! :)

前もって感謝します

4

1 に答える 1

2

このコードは、ゲームのコンセプトをいじるために少し前に書きました。関与する知的な行動はありません。ゲームをデモンストレーションするためのランダムな動き。勝利条件の迅速なチェックのみを探しているので、これは重要ではないと思います。for ループを回避し、組み込みの python/numpy 関数のみを (いくつかのトリックを使用して) 使用するように最善を尽くしたため、この実装は高速です。

import numpy as np

row_size = 6
col_size = 7
symbols = {1:'A', -1:'B', 0:' '}

def was_winning_move(S, P, current_row_idx,current_col_idx):
    #****** Column Win ******
    current_col = S[:,current_col_idx]
    P_idx= np.where(current_col== P)[0]
    #if the difference between indexes are one, that means they are consecutive.
    #we need at least 4 consecutive index. So 3 Ture value
    is_idx_consecutive = sum(np.diff(P_idx)==1)>=3
    if is_idx_consecutive:
        return True

    #****** Column Win ****** 
    current_row = S[current_row_idx,:]
    P_idx= np.where(current_row== P)[0]
    is_idx_consecutive = sum(np.diff(P_idx)==1)>=3
    if is_idx_consecutive:
        return True

    #****** Diag Win ****** 
    offeset_from_diag = current_col_idx - current_row_idx
    current_diag = S.diagonal(offeset_from_diag)
    P_idx= np.where(current_diag== P)[0]
    is_idx_consecutive = sum(np.diff(P_idx)==1)>=3
    if is_idx_consecutive:
        return True
    #****** off-Diag Win ****** 
    #here 1) reverse rows, 2)find new index, 3)find offest and proceed as diag
    reversed_rows = S[::-1,:] #1
    new_row_idx = row_size - 1 - current_row_idx #2
    offeset_from_diag = current_col_idx - new_row_idx #3
    current_off_diag = reversed_rows.diagonal(offeset_from_diag)
    P_idx= np.where(current_off_diag== P)[0]
    is_idx_consecutive = sum(np.diff(P_idx)==1)>=3
    if is_idx_consecutive:
        return True
    return False

def move_at_random(S,P):
    selected_col_idx = np.random.permutation(range(col_size))[0]
    #print selected_col_idx
    #we should fill in matrix from bottom to top. So find the last filled row in col and fill the upper row
    last_filled_row = np.where(S[:,selected_col_idx] != 0)[0]
    #it is possible that there is no filled array. like the begining of the game
    #in this case we start with last row e.g row : -1
    if last_filled_row.size != 0:
        current_row_idx = last_filled_row[0] - 1
    else:
        current_row_idx = -1
    #print 'col[{0}], row[{1}]'.format(selected_col,current_row)
    S[current_row_idx, selected_col_idx] = P
    return (S,current_row_idx,selected_col_idx)

def move_still_possible(S):
    return not (S[S==0].size == 0)

def print_game_state(S):
    B = np.copy(S).astype(object)
    for n in [-1, 0, 1]:
        B[B==n] = symbols[n]
    print B

def play_game():
    #initiate game state
    game_state = np.zeros((6,7),dtype=int)
    player = 1
    mvcntr = 1
    no_winner_yet = True
    while no_winner_yet and  move_still_possible(game_state):
        #get player symbol
        name = symbols[player]

        game_state, current_row, current_col = move_at_random(game_state, player)
        #print '******',player,(current_row, current_col)
        #print current game state
        print_game_state(game_state)
        #check if the move was a winning move
        if was_winning_move(game_state,player,current_row, current_col):
            print 'player %s wins after %d moves' % (name, mvcntr)
            no_winner_yet = False

        # switch player and increase move counter
        player *= -1
        mvcntr +=  1
    if no_winner_yet:
        print 'game ended in a draw'
        player = 0
    return game_state,player,mvcntr

if __name__ == '__main__':
    S, P, mvcntr =  play_game()

ご質問があればお知らせください

更新:説明:

各移動で、現在のセルを通過する列、行、対角線、および二次対角線を見て、現在のシンボルで連続するセルを見つけます。ボード全体をスキャンすることは避けてください。

ここに画像の説明を入力

各方向のセルの抽出:

桁:

current_col = S[:,current_col_idx]

行:

current_row = S[current_row_idx,:]

対角線: 主対角線から目的の対角線のオフセットを見つけます。

diag_offset = current_col_idx - current_row_idx
current_diag = S.diagonal(offset)

非対角:

行列の行を逆にします。

S_reversed_rows = S[::-1,:]

新しいマトリックスの行インデックスを見つけます

new_row_idx = row_size - 1 - current_row_idx
current_offdiag = S.diagonal(offset)

ここに画像の説明を入力

于 2015-05-19T08:41:34.913 に答える