Pythonは白黒を実現
Pythonは白黒を実現タイトル要求 コンピュータのポリシー ゲーム終了の条件 解題構想 キーロジック キー関数 Init_board: printBoard: computer_move: human_move: check_board: check_legal_move: gameover: saveinfo: main 後記 プログラムの可能な最適化方向 テーマの要件
コンピューターの戦略
可能なドロップ位置ごとに、その位置の「スコア」(反転可能な相手駒の数)を計算し、スコアが高いほどその位置でドロップするのが有利になります.各可能な位置のスコアを計算し、最大値位置ドロップを選択します.2つ以上のチェッカーが同じスコアを持っている可能性があります.この場合、行文字の最小のチェッカーを選択します.2つのチェッカーのスコアが同じで、同じ行にある場合は、列のアルファベットが小さいチェッカーを選択します.
ゲーム終了の条件
1)碁盤全体がいっぱいになった.2)一方の駒はもう相手に食べられてしまった.3)2人のプレイヤーは落子できる碁盤格を持っていない.4)一方の落子が不正な位置にある.上位3種の場合は駒数で勝負を計算し、駒の多い方が勝つ.4つ目のケースは相手が勝つと判定します.
問題を解く構想.
キーロジック
1)コンピューター将棋でも人間将棋でも,まず字が落ちるかどうかを判断する必要がある2)人間将棋の前に落子が合法かどうかを判断する3)落子が合法かどうかを判断する際には,pythonのリストには下付き-1の場合があるので,下付きの下界に注意する一方,白黒棋は,突き当たりの駒が同色であるかどうかを考慮するため,現在の探索駒と同方向の次の駒(潜在的な同色可能性)が境界を越えているかどうかに注意する.例:4*4盤の「白黒白白」は、次の駒の境界を考慮しないと、黒から1周して戻ってきて黒を見つけて3つの白棋を反転させるエラーが発生する4)実際に反転し、落子が合法かどうかを検出し、落子のスコアを計算するのに同じループロジックが用いられる.だから1つだけ書いて基本的にコピーして貼ればいい5)何度もsortで重みの違う比較をする6)ゲーム終了の場合は状況別に検討する
キー関数
Init_board:
碁盤サイズn(nは偶数、かつ4≦n≦26)を読み込み、要求に応じて碁盤を初期化する.プログラムは、各チェッカーのステータスを次の文字で表します.-占有されていないX–黒に占有されているO–白に占有されている
printBoard:
ボードを出力します.例:4×4碁盤の初期状態は以下の通りである:a b c d a..b . O X . c . X O . d . . . .
computer_move:
コンピューター将棋.落子位置は「行列文字」のフォーマットで表され、例えば「ba」は駒落行b列aを表す.
human_move:
ユーザーが碁を打つ
check_board:
ゲームが終了したかどうかを検出
check_legal_move:
色がcolorの駒が碁盤格(row,col)に落ちるのが合法かどうかを検出する
gameover:
ゲーム終了、スコア集計、結果出力
saveinfo:
毎回ヒューマン・マシン・ゲームの情報を1行としてファイルreversiに書き込む.csvでは、これらの情報には、ゲーム開始時間、単一ゲームで使用される時間、碁盤サイズ、黒棋プレイヤー、白棋プレイヤー、ゲームスコア、情報間にカンマ文字で区切られるものが含まれる.
main
後記
プログラム可能な最適化方向
プログラムで発生する可能性のあるエラー!一方がもともと碁を打つことができなくて、もう一方が碁を打った後に突然碁を打つことができます!そこで「碁があるかどうか」の条件コードをリセットする必要があります.ここでは大きな作業が終わるまで待ってから修正します.1)パソコンの黒さや白さを分けて議論するのは面倒です(コード量*2に相当します).関数で解決できますか?2)実は落子の位置を判断して、点数と合法的に使うかどうかも同じ関数で、関数を使ってコードの多重化を行うことができて、そんなに多く書く必要はありません.3)あとは基本的にpycharmで逐次debugをするので、いくつかの判断とlist文はそんなにきれいではないかもしれません4)プログラムの安定性は検証されます(本当にコンピュータとそんなに多くの碁を打つのがおっくうです5)gameoverの関数の多入口状況は最適化できますか?
コンピューターの戦略
可能なドロップ位置ごとに、その位置の「スコア」(反転可能な相手駒の数)を計算し、スコアが高いほどその位置でドロップするのが有利になります.各可能な位置のスコアを計算し、最大値位置ドロップを選択します.2つ以上のチェッカーが同じスコアを持っている可能性があります.この場合、行文字の最小のチェッカーを選択します.2つのチェッカーのスコアが同じで、同じ行にある場合は、列のアルファベットが小さいチェッカーを選択します.
ゲーム終了の条件
1)碁盤全体がいっぱいになった.2)一方の駒はもう相手に食べられてしまった.3)2人のプレイヤーは落子できる碁盤格を持っていない.4)一方の落子が不正な位置にある.上位3種の場合は駒数で勝負を計算し、駒の多い方が勝つ.4つ目のケースは相手が勝つと判定します.
問題を解く構想.
キーロジック
1)コンピューター将棋でも人間将棋でも,まず字が落ちるかどうかを判断する必要がある2)人間将棋の前に落子が合法かどうかを判断する3)落子が合法かどうかを判断する際には,pythonのリストには下付き-1の場合があるので,下付きの下界に注意する一方,白黒棋は,突き当たりの駒が同色であるかどうかを考慮するため,現在の探索駒と同方向の次の駒(潜在的な同色可能性)が境界を越えているかどうかに注意する.例:4*4盤の「白黒白白」は、次の駒の境界を考慮しないと、黒から1周して戻ってきて黒を見つけて3つの白棋を反転させるエラーが発生する4)実際に反転し、落子が合法かどうかを検出し、落子のスコアを計算するのに同じループロジックが用いられる.だから1つだけ書いて基本的にコピーして貼ればいい5)何度もsortで重みの違う比較をする6)ゲーム終了の場合は状況別に検討する
キー関数
Init_board:
碁盤サイズn(nは偶数、かつ4≦n≦26)を読み込み、要求に応じて碁盤を初期化する.プログラムは、各チェッカーのステータスを次の文字で表します.-占有されていないX–黒に占有されているO–白に占有されている
def Init_board():
global board
board = [[0] * l for row in range(l)] #
board[int(l / 2 - 1)][int(l / 2 - 1)] = -1
board[int(l / 2 - 1)][int(l / 2)] = 1
board[int(l / 2)][int(l / 2 - 1)] = 1
board[int(l / 2)][int(l / 2)] = -1 #
return board
# 0 ,1 ,-1
printBoard:
ボードを出力します.例:4×4碁盤の初期状態は以下の通りである:a b c d a..b . O X . c . X O . d . . . .
def printBoard():
l = len(board)
print(' ', end = ' ')
for i in range(l):
print(chr(ord('a') + i), end = ' ')
print()
for i in range(l):
print(chr(ord('a') + i), end = ' ')
for j in range(l):
if (board[i][j] == 0):
print('.', end = ' ')
elif (board[i][j] == 1):
print('X', end = ' ')
else:
print('O', end = ' ')
print()
computer_move:
コンピューター将棋.落子位置は「行列文字」のフォーマットで表され、例えば「ba」は駒落行b列aを表す.
def computer_move(row, col, color): #
global board
if (check != 0): #check ( ), 0
board[row][col] = color #
direction = ((-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1))
for i in range(8):
z = 1 # 8
while (0<= row + (z+1) * direction[i][0] < l) and (0<= col + (z+1) * direction[i][1] < l) and (
board[row + z * direction[i][0]][col + z * direction[i][1]] == -color):# , ( ), 。
z += 1 # python -1 , 0, ( -1)
if board[row + z * direction[i][0]][col + z * direction[i][1]] == color: #
for j in range(z):
board[row + j * direction[i][0]][col + j * direction[i][1]] = color #
break
human_move:
ユーザーが碁を打つ
def human_move(row, col, color): # ,
global board
if (check != 0):
board[row][col] = color
direction = ((-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1))
for i in range(8):
z = 1
while (0<=row + (z+1) * direction[i][0] < l) and (0 <= col + (z+1) * direction[i][1] < l) and (
board[row + z * direction[i][0]][col + z * direction[i][1]] == -color):
z += 1
if board[row + z * direction[i][0]][col + z * direction[i][1]] == color:
for j in range(z):
board[row + j * direction[i][0]][col + j * direction[i][1]] = color
break
check_board:
ゲームが終了したかどうかを検出
def check_board(): #
a1 = 1 #
a21 = 1 #
a22 = 1 #
a4 = 0 #
for i in range(l):
for j in range(l): #
if (board[i][j] == 0): #
a1 = 0
elif (board[i][j] == 1): #
a21 = 0
else: #
a22 = 0
if not (check): # check 0 ,
a4 = 1
if (a1 or (a21 and a22) or (not (xp or op)) or a4):
if (a1 or (a21 and a22) or (not (xp or op))): # xp op
if (not (xp or op)): # 0,
print("Both player have no vaild move!")
gameover('score') #
else: # a4 , ,
gameover('illegal')
check_legal_move:
色がcolorの駒が碁盤格(row,col)に落ちるのが合法かどうかを検出する
def check_legal_move(row, col, color): #
direction = ((-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1))
score = 0
for i in range(8): # , ,
zscore = 1
while (0 <= (row + (zscore+1) * direction[i][0]) < l) and (0 <= (col + (zscore+1) * direction[i][1]) < l) and (
(board[row + zscore * direction[i][0]][col + zscore * direction[i][1]]) == -color):
if (board[row + (zscore + 1) * direction[i][0]][col + (zscore + 1) * direction[i][1]] == color):
score += zscore
break
zscore += 1
return score
gameover:
ゲーム終了、スコア集計、結果出力
def gameover(s): #
global s1
global condition
global black
global white
condition = 0 # 0,
if s == 'score': # ,
print('Game Over!')
black = 0
white = 0
for i in range(l):
for j in range(l):
if board[i][j] == 1:
black += 1
if board[i][j] == -1:
white += 1
if (black > white):
print('X : O =', black, ':', white)
print('X player wins!')
elif (black < white):
print('O player wins!')
print('X : O =', black, ':', white)
else:
print('Draw!')
s1 = str(black) + 'to' + str(white) # s1
return s1
if s == 'illegal':
print('Invaild move!')
s1 = 'Invaild move!'
if s == 'gg':
print('Human gave up!')
s1 = 'Human gave up!'
print('Game Over!')
if (color == 1): # gg ,color
print('O player wins.')
else:
print('X player wins.')
return s1
saveinfo:
毎回ヒューマン・マシン・ゲームの情報を1行としてファイルreversiに書き込む.csvでは、これらの情報には、ゲーム開始時間、単一ゲームで使用される時間、碁盤サイズ、黒棋プレイヤー、白棋プレイヤー、ゲームスコア、情報間にカンマ文字で区切られるものが含まれる.
def saveinfo(): #
time3 = time.time() #
long = time3-time2 #
f = open('Reversi.csv', 'a+')
s = str(time1) + ',' + str(long) + ',' + str(l) + '*' + str(l) + ',' + Xplayer + ',' + Oplayer + ',' + s1
f.write(s) #
f.write('
')
f.close()
main
import datetime
import time
time1 = datetime.datetime.now().strftime('%Y-%m-%d %T') #
time2 = time.time() #
l = int(input('Enter the board dimension:')) # l
board = Init_board() #
x1 = input('Computer plays (X/O):') # x1
if (x1 == 'X'): #
hcolor = -1
Xplayer = 'computer'
Oplayer = 'human' #
condition = 1 # 1,
printBoard() # 、
while condition: # 1( gameover),
legal = []
for i in range(l):
for j in range(l):
if (board[i][j] == 0):
if (check_legal_move(i, j, 1) != 0):
legal.append([i, j, check_legal_move(i, j, 1)]) # legal
legal.sort(key=lambda x: x[1], reverse=False)
legal.sort(key=lambda x: x[0], reverse=False)
legal.sort(key=lambda x: x[2], reverse=True) # , ,
if (legal != []): #
row = legal[0][0]
col = legal[0][1]
color = 1
check = check_legal_move(row, col, color)
xp = 1 # X
op = 1 # O
computer_move(row, col, 1) # check ,
print('Computer places X at', chr(ord('a') + row), chr(ord('a') + col), '.')
else:
xp = 0 #
print('X player has no vaild move.') #
printBoard() #
check_board() #
if (condition != 0): #
legal = []
for i in range(l):
for j in range(l):
if board[i][j] == 0:
if (check_legal_move(i, j, -1) != 0) and (board[i][j] == 0):
legal.append([i, j, check_legal_move(i, j, -1)]) #
if (legal != []):
inter = input('Enter move for O (Rowcol):')
if inter == 'gg': #
gameover('gg')
break
row = ord(inter[0]) - 97 # ASCII
col = ord(inter[1]) - 97
color = -1
if (row>=l) or (col>=l) or (row<0) or (col <0): # ,
gameover('illegal')
break
check = check_legal_move(row, col, color) #
xp = 1
op = 1
human_move(ord(inter[0]) - 97, ord(inter[1]) - 97, -1) #
check_board() #
if check:
printBoard() # ,
else:
op = 0 #
print("O player has no vaild move.")
saveinfo() #
else: # ,
hcolor = 1
Oplayer = 'computer'
Xplayer = 'human'
condition = 1
printBoard()
while condition:
legal = []
for i in range(l):
for j in range(l):
if (board[i][j] == 0):
if (check_legal_move(i, j, 1) != 0):
legal.append([i, j, check_legal_move(i, j, 1)])
if (legal != []):
inter = input('Enter move for X (Rowcol):')
if inter == 'gg':
gameover('gg')
break
row = ord(inter[0]) - 97
col = ord(inter[1]) - 97
color = 1
if (row>=l) or (col>=l) or (row<0) or (col <0):
gameover('illegal')
break
check = check_legal_move(row, col, color)
xp = 1
op = 1
human_move(ord(inter[0]) - 97, ord(inter[1]) - 97, 1)
check_board()
if check:
printBoard()
else:
op = 0
print("O player has no vaild move.")
if condition:
legal = []
for i in range(l):
for j in range(l):
if (board[i][j] == 0):
if (check_legal_move(i, j, -1) != 0):
legal.append([i, j, check_legal_move(i, j, -1)])
legal.sort(key=lambda x: x[1], reverse=False)
legal.sort(key=lambda x: x[0], reverse=False)
legal.sort(key=lambda x: x[2], reverse=True)
if (legal != []):
xp = 1
op = 1
row = legal[0][0]
col = legal[0][1]
color = -1
check = check_legal_move(row, col, color)
computer_move(row, col, -1)
else:
xp = 0
print("X player has no vaild move.")
check_board()
printBoard()
print('Computer places O at', chr(ord('a') + row), chr(ord('a') + col), '.')
saveinfo()
後記
プログラム可能な最適化方向
プログラムで発生する可能性のあるエラー!一方がもともと碁を打つことができなくて、もう一方が碁を打った後に突然碁を打つことができます!そこで「碁があるかどうか」の条件コードをリセットする必要があります.ここでは大きな作業が終わるまで待ってから修正します.1)パソコンの黒さや白さを分けて議論するのは面倒です(コード量*2に相当します).関数で解決できますか?2)実は落子の位置を判断して、点数と合法的に使うかどうかも同じ関数で、関数を使ってコードの多重化を行うことができて、そんなに多く書く必要はありません.3)あとは基本的にpycharmで逐次debugをするので、いくつかの判断とlist文はそんなにきれいではないかもしれません4)プログラムの安定性は検証されます(本当にコンピュータとそんなに多くの碁を打つのがおっくうです5)gameoverの関数の多入口状況は最適化できますか?