私はチックタックのつま先を再生することを学ぶ小さなpythonスクリプトを構築中です。私のプロセスは、ゲーム内で行われた各移動を保存し、それが勝利結果につながるかどうかに基づいてその移動を記録することです。最終的に私は多くのラウンドでこれを訓練しようとします。辞書のすべてのキー値のペアを変更するPythonメソッド
私の問題は、update_weights()
の方法にあります。私はそれが格納された移動(ボードオブジェクトからアクセスされ、リスト[行、col]として表される)を取って、その移動リストを反復することを期待します。この方法は、ボードの記憶された重み((3,3)個の配列の辞書)を参照し、適切な移動のための対応する重みを更新するべきである。
勝利が発生したとします。勝利シーケンスでは、#2の移動がボード位置[0,1]にありました。メソッドは重みの辞書にアクセスし(キーは移動番号です)、配列[0,1]の位置に1.05の係数を掛けます。
問題は、私の方法が正しい移動#キーに関連付けられているだけでなく、体重辞書のすべての配列を変更しているということです。私はこれがどう起こっているのか理解できません。
import numpy as np
import random
class ttt_board():
def __init__(self):
self.board_state = np.array([[0,0,0],[0,0,0],[0,0,0]])
self.board_weight = self.reset_board_weights()
self.moves = []
def reset_board_weights(self):
board_weight_instance = np.zeros((3,3))
board_weight_instance[board_weight_instance >= 0] = 0.5
board_weight = {0: board_weight_instance,
1: board_weight_instance,
2: board_weight_instance,
3: board_weight_instance,
4: board_weight_instance}
return board_weight
def reset_board(self):
self.board_state = np.array([[0,0,0],[0,0,0],[0,0,0]])
def reset_moves(self):
self.moves = []
def is_win(self):
board = self.board_state
if board.trace() == 3 or np.flipud(board).trace() == 3:
return True
for i in range(3):
if board.sum(axis=0)[i] == 3 or board.sum(axis=1)[i] == 3:
return True
else:
return False
def is_loss(self):
board = self.board_state
if board.trace() == 12 or np.flipud(board).trace() == 12:
return True
for i in range(3):
if board.sum(axis=0)[i] == 12 or board.sum(axis=1)[i] == 12:
return True
else:
return False
def is_tie(self):
board = self.board_state
board_full = True
for i in range(len(board)):
for k in range(len(board)):
if board[i][k] == 0:
board_full = False
if board_full and not self.is_win() and not self.is_loss():
return True
else:
return False
def update_board(self,player,space):
#takes player as 1 or 4
#takes space as list [0,0]
self.board_state[space[0],space[1]] = player
if player == 1:
self.store_move(space)
return
def get_avail_spots(self):
avail_spots = []
board = self.board_state
for i in range(len(board)):
for k in range(len(board)):
if board[i][k] == 0:
avail_spots.append([i,k])
return avail_spots
def gen_next_move(self):
avail_spots = self.get_avail_spots()
move = random.randrange(len(avail_spots))
return avail_spots[move]
def update_weights(self,win):
moves = self.moves
if win:
factor = 1.05
else:
factor= 0.95
for i in range(len(moves)):
row = moves[i][0]
col = moves[i][1]
old_weight = self.board_weight[i][row,col]
new_weight = old_weight*factor
self.board_weight[i][row,col] = new_weight
return
def store_move(self,move):
self.moves.append(move)
return
if __name__ == '__main__':
board = ttt_board()
while not board.is_win() and not board.is_loss() and not board.is_tie():
try:
board.update_board(1,board.gen_next_move())
board.update_board(4,board.gen_next_move())
except ValueError:
break
if board.is_win():
board.update_weights(1)
print('Player 1 wins: {w}'.format(w=board.is_win()))
elif board.is_loss():
board.update_weights(0)
print('Player 2 wins: {l}'.format(l=board.is_loss()))
elif board.is_tie():
print('Game ends in tie: {t}'.format(t=board.is_tie()))
print('Here is the final board')
print(board.board_state)
print(board.board_weight)
print(board.moves)
スクリプトを実行することによって見ることができるように、単一のゲームの後に重みの印刷された辞書は、各キーの同じ配列の値を持っています。 それぞれの配列は、それが関連付けられているキーに対応する移動#だけにアクセスする必要があるため、1つの位置でのみ変更されると思います。
それは、一般的に – martianwars
が本当に関連していないhttp://stackoverflow.com/help/mcveが、このような使用して 'numpy'アレイはおそらく起こっているので、多くのコードを読み取ることは難しいです単純なPythonリストよりもパフォーマンスが悪くなります。 –
@martianwarsは頭をアップしてくれてありがとう。コードを少なくして、問題を切り分けて更新します。 – regularGuy