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–白に占有されている
    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の関数の多入口状況は最適化できますか?