Python [ 2日]でチェスゲームを書く


我々はまだCOVID - 19のためにロックダウンにあります、そして、私は私の12 yoでテキストチェスゲームを実装するために時間を使っています.このシリーズでは、私たちがしたこととプロジェクトがどのように進化したかを共有します.
私たちは2次元ボードを印刷する方法で出発しました.
私たちは、次のステップについて少し話をしました-ユーザーからの入力を得て、それを解析してください、さもなければ、動きの論理を実行し始めてください.12 yo移動を実装するために選んだ.彼が言ったことによると、このメソッドの動作方法を定義しました
  • ユーザーは移動するために、そして、それが行くべきであるところ(目標正方形)
  • の名前を提供します
  • は、移動が有効であるかどうか決定し、一致する部分
  • を見つける
  • 移動が有効な場合、我々は、ターゲットの正方形に一致する部分を移動します.
  • この点で、12 yoは、チェス行がランクとコラムと呼ばれていることを指摘しました、そして、コラムはファイルです.まあ、sorrrrry:アイロール:.これが定義されたインターフェースです.
    def is_valid_move(piece, target_rank, target_file):
      pass
    
    最初にチェックするのは、ターゲットの正方形がボードの境界にある場合です.
    def is_valid_move(piece, target_rank, target_file):
      # out of bounds
      if  0 > target_rank > 7:
        return False
      if  0 > target_file > 7:
        return False
    
    OK、クール.次は何ですか.
    ターゲットの四角形には、同じ色の部分がないことを確認する必要があります.
      ...
      # piece with same color is in the target cell
      if board[target_rank][target_file][0] == piece[0]:
        return False
    
    今何?12 yoは我々がRookのために有効であるかどうかチェックし始めることを提案しました.
      ...
      if piece in ("WR", "BR"):
        pass
    
    どうやってこれをやるの?
    最初に、我々は同じランクの上で、または、目標広場と同じファイルの上にルークがあるかどうかチェックする必要があります.
    ...
    found = False
    for i in range(8):
        if (board[target_rank][i] == piece):
          found = True
          break
    
    for i in range(8):
        if (board[i][target_file] == piece):
          found = True
          break
    
      return found
    

    Remember that we're doing a naive solution and we'll deal with optimizations later, there are definitely better ways to write this code!


    待って、しかし、作品が既にターゲットの広場にある場合?
    実は.ターゲットの正方形に同じ色の部分があるかどうかをチェックした状態で既にカバーされています.さあ、動きましょう.
    次のことを確認する必要がある別の部分は、ターゲットの広場に我々の方法をブロックしている場合です.しかし、我々の前の実装は、私たちにこれを理解するのに十分な情報を与えませんでした.それで、我々が我々が作品を見つけたところのインデックスを含むように我々の実装を変えましょう.我々は実際には、後で我々は移動を実行するが、スポイラーを取得する必要があります!
    ...
    found_rank = -1
    found_file = -1
    for i in range(8):
      if board[target_rank][i] == piece:
        found_rank = target_rank
        found_file = i
        break
    
    # TODO: deal with the case where there are two matching pieces
    if found_rank > -1:
      for i in range(8):
        if board[i][target_file] == piece:
          found_rank = i
          found_file = target_file
          break
    
    if found_rank < 0 or found_file < 0:
      return False
    
    それでは、見つけた作品とターゲットセルの間に何かがあるか確認しましょう.
    ...
    if found_rank == target_rank:
      if found_file > target_file:
        for i in range(target_file+1, found_file):
          if board[target_rank][i] != "  ":
            return False
      else: # found_file < target_file
        for i in range(found_file+1, target_file):
          if board[target_rank][i] != "  ":
            return False
    else: # found_file == target_file
      if found_rank > target_rank:
        for i in range(target_rank+1, found_rank):
          if board[i][target_file] != "  ":
            return False
      else: # found_rank < target_rank
        for i in range(found_rank+1, target_rank):
          if board[i][target_file] != "  ":
            return False
    return True
    
    私はその文字列比較を好まないので、それをより明確にするために定数に変えました.
    EMPTY = "  "
    
    すべてのロジックを別々のメソッドに詰め込みましょう.私たちも、白が底にあるけれども、インデックスが0 - 7であると理解しました、したがって、我々はおそらく我々が板を定義して、それをボトムアップに印刷する方法を逆にしたいです.
    今日の最後のコードはこちら
    EMPTY = "  "
    
    def print_board(board):
      row_number = 8
      print("  ", end="")
      print(" ----"*8)
      for row in reversed(board):
          print(row_number, end=" ")
          row_number -= 1
          for cell in row:
              print("| {} ".format(cell), end="")
          print("|")
          print("  ", end="")
          print(" ----"*8)
      print("  ", end="")
      for letter in ['a','b','c','d','e','f','g','h']:
          print("  {}  ".format(letter), end="")
      print("")
    
    
    board = [[EMPTY]*8]*8
    
    board[0] = ["WR","WN","WB","WQ","WK","WB","WN","WR"]
    board[1] = ["WP","WP","WP","WP","WP","WP","WP","WP"]
    board[6] = ["BP","BP","BP","BP","BP","BP","BP","BP"]
    board[7] = ["BR","BN","BB","BQ","BK","BB","BN","BR"]
    
    def is_valid_move(piece, target_rank, target_file):
      # out of bounds
      if  0 > target_rank > 7:
        return False
      if  0 > target_file > 7:
        return False
      # piece with same color is in the target cell
      if board[target_rank][target_file][0] == piece[0]:
        return False
    
      if piece in ("WR", "BR"):
        return is_valid_rook_move(piece, target_rank, target_file)
    
    def is_valid_rook_move(piece, target_rank, target_file):
      found_rank = -1
      found_file = -1
      for i in range(8):
        if board[target_rank][i] == piece:
          found_rank = target_rank
          found_file = i
          break
    
      if found_rank > -1:
        for i in range(8):
          if board[i][target_file] == piece:
            found_rank = i
            found_file = target_file
            break
    
      if found_rank < 0 or found_file < 0:
        return False
    
      if found_rank == target_rank:
        if found_file > target_file:
          for i in range(target_file+1, found_file):
            if board[target_rank][i] != EMPTY:
              return False
        else: # found_file < target_file
          for i in range(found_file+1, target_file):
            if board[target_rank][i] != EMPTY:
              return False
      else: # found_file == target_file
        if found_rank > target_rank:
          for i in range(target_rank+1, found_rank):
            if board[i][target_file] != EMPTY:
              return False
        else: # found_rank < target_rank
          for i in range(found_rank+1, target_rank):
            if board[i][target_file] != EMPTY:
              return False
      return True
    
    私はこの権利を得たかどうかわからないが、12 yoは疲れていたので、ここで止まりました.テストのために明日我々に加わってください!