python으로 체스 게임 작성 [3일차]

11918 단어 codenewbiepython
코로나로 인해 우리는 여전히 봉쇄 상태로, 나는 이 시간을 내 12yo로 텍스트 장기 게임을 구현하고 있다.이 시리즈에서 나는 우리가 무엇을 했는지, 그리고 프로젝트가 어떻게 발전했는지 공유할 것이다.
우리는 그 중에서 체스 스텝의 기본적인 유효성과 스텝이 유효한지 검사하는 방법을 끝냈지만, 우리는 여전히 그것들을 테스트하지 않았기 때문에, 우리는 그것들이 유효한지 모른다.또는, 더 정확히 말하자면, 코드가 테스트를 거치지 않았기 때문에, 나는 코드가 예상대로 작동하지 않을 것이라고 절대 믿는다. 우리는 어디에 문제가 생겼는지 찾기만 하면 된다.오늘 우리는 테스트를 진행할 것이다.
테스트의 첫 번째 규칙은 테스트가 서로 독립되어야 한다는 것이다. 따라서 우리는 모든 테스트 설정에서 다시 사용하기 위해 회로판 창설 논리를 하나의 단독 방법으로 이동할 것이다.
def create_board():
  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"]

  return board
12당신이 return에게 무엇을 했느냐고 물었을 때 나는 설명하기가 좀 어려웠다. 이것은 정말 교육에서 가장 어려운 부분이다. 당신이 잘 아는 것이 당신의 사고방식에 완전히 박혀 있을 때--당신은 return을 어떻게 설명합니까?내가 생각한 것은 누군가가 이 방법을 호출할 때, 마치 선생님이 우리에게 숙제를 완성하라고 하신 것과 같다는 것이다.만약 우리가 결과를 되돌려 주지 않는다면, 그들은 우리의 일에 접근할 수 없을 것이다. 그것은 우리의 가정 컴퓨터 (방법 범위) 에 남아 있고, 선생님은 그것을 보고 평점을 받을 수 없을 것이다.아마도 나는 본래 더 잘 설명할 수 있었지만, 효과는 매우 좋았다.
지금, 나는 우리가 우리의 코드를 테스트하고 싶다고 말했다.우리 어떻게 해야 돼?12yo의 대답은 대체로 코드를 읽고 우리가 어떤 것도 빠뜨리지 않도록 하는 것이다.현재, 이 화이트보드 면접은 매우 좋다. 그러나 우리는 이곳에서 고품질의 소프트웨어를 작성하고, 우리는 테스트를 작성하여, 개발 기간과 생산에 들어간 후에 우리의 안전을 보장하기를 바란다.우리는 우리의 코드를 실행하기 위해 테스트를 작성해야 하며, 그것이 우리의 목적에 도달할 수 있도록 확보해야 한다.
12yo가 테스트를 결정하는 첫 번째 일은 우리가 is_valid_rook_move 방법을 정확하게 실현했는지의 여부이다.이것이 바로 그가 생각한 것이다.
def test_rook_is_not_blocked():
  board = create_board()
  board[1][0] = EMPTY
  result = is_valid_rook_move(board, "WR", 2, 0)
  print(board)
  print(result)
출력:
   ---- ---- ---- ---- ---- ---- ---- ----
8 | BR | BN | BB | BQ | BK | BB | BN | BR |
   ---- ---- ---- ---- ---- ---- ---- ----
7 | BP | BP | BP | BP | BP | BP | BP | BP |
   ---- ---- ---- ---- ---- ---- ---- ----
6 |    |    |    |    |    |    |    |    |
   ---- ---- ---- ---- ---- ---- ---- ----
5 |    |    |    |    |    |    |    |    |
   ---- ---- ---- ---- ---- ---- ---- ----
4 |    |    |    |    |    |    |    |    |
   ---- ---- ---- ---- ---- ---- ---- ----
3 |    |    |    |    |    |    |    |    |
   ---- ---- ---- ---- ---- ---- ---- ----
2 |    | WP | WP | WP | WP | WP | WP | WP |
   ---- ---- ---- ---- ---- ---- ---- ----
1 | WR | WN | WB | WQ | WK | WB | WN | WR |
   ---- ---- ---- ---- ---- ---- ---- ----
    a    b    c    d    e    f    g    h  
False
잠깐만, 뭐라고?이것은 마땅히 효과적인 행동이어야 한다!이 차의 길은 완전히 개방되었다.우리는 코드에 print 명령을 추가했는데, 첫 번째 순환 후에 우리가 막 종료한 것을 발견했다.
def is_valid_rook_move(board, 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:
    ...
읊다, 읊조리다그래...아마 if found_rank == -1!!!우리는 목표 파일 (열) 에서 한 부분을 찾으려고 하지만, 전제는 목표 열 (줄) 에서 찾지 못했다는 것이다.고쳤어, 성공했어!
출력:
   ---- ---- ---- ---- ---- ---- ---- ----
8 | BR | BN | BB | BQ | BK | BB | BN | BR |
   ---- ---- ---- ---- ---- ---- ---- ----
7 | BP | BP | BP | BP | BP | BP | BP | BP |
   ---- ---- ---- ---- ---- ---- ---- ----
6 |    |    |    |    |    |    |    |    |
   ---- ---- ---- ---- ---- ---- ---- ----
5 |    |    |    |    |    |    |    |    |
   ---- ---- ---- ---- ---- ---- ---- ----
4 |    |    |    |    |    |    |    |    |
   ---- ---- ---- ---- ---- ---- ---- ----
3 |    |    |    |    |    |    |    |    |
   ---- ---- ---- ---- ---- ---- ---- ----
2 |    | WP | WP | WP | WP | WP | WP | WP |
   ---- ---- ---- ---- ---- ---- ---- ----
1 | WR | WN | WB | WQ | WK | WB | WN | WR |
   ---- ---- ---- ---- ---- ---- ---- ----
    a    b    c    d    e    f    g    h  
True
쿨!여기 assert 명령을 소개했습니다.나는 그에게 만약 우리가 많은 테스트를 썼다면, 우리는 모든 테스트의 예상 결과를 기억하기 어려울 것이다. 우리가 원하는 것은 간단하고 사용하기 쉬운 것이며, 우리에게 신뢰할 수 있는 빠른 결과를 줄 수 있을 것이라고 말했다.단언문: 이 말이 사실입니까?만약 없다면, 우리가 편리하게 사용할 수 있도록 빨간색 오류가 발생할 것이다.오류가 없으면 테스트가 성공적으로 실행되었는지 확인하기 위해 인쇄해야 합니다. (이 부분을 썼습니다.)
def test_rook_is_not_blocked():
  board = create_board()
  board[1][0] = EMPTY
  result = is_valid_rook_move(board, "WR", 2, 0)
  assert result 
  print("test_rook_is_not_blocked passed")
출력:
test_rook_is_not_blocked passed
우리는 막힌 차를 대상으로 하는 테스트와 수평 이동을 위한 테스트 용례를 추가했다. (완전한 코드가 앞에 있으니 지금은 걱정할 필요가 없다.)
그리고 저희도 기본적인 is_valid_move 방법을 테스트해 보도록 하겠습니다. 맞혀보세요!우리도 거기서 벌레 한 마리를 발견했어...if 0 > target_file > 7 부작용: 얼굴 손바닥:.
다음으로 변경:
def is_valid_move(board, piece, target_rank, target_file):
  # out of bounds
  if  target_rank < 0 or target_rank > 7:
    return False
  if  target_file < 0 or 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)

  return True
우리는 마침내 다음과 같은 테스트 세트를 얻었다. (내가 휴대전화에서 소셜 미디어를 볼 때 그가 이 모든 것을 썼다. 와)
def test_is_rank_valid():
  board = create_board()
  result = is_valid_move(board, "xx", 22, 4)
  assert not result
  result = is_valid_move(board, "xx", -2020, 4)
  assert not result
  result = is_valid_move(board, "xx", 0, 4)
  assert result
  print("test_is_rank_valid passed")

def test_is_file_valid():
  board = create_board()
  result = is_valid_move(board, "xx", 0, 22)
  assert not result
  result = is_valid_move(board, "xx", 0, -2020)
  assert not result
  result = is_valid_move(board, "xx", 0, 4)
  assert result
  print("test_is_file_valid passed")

def test_is_target_square_taken():
  board = create_board()
  result = is_valid_move(board, "Wx", 0, 1)
  assert not result
  print("test_is_target_square_taken passed")

def test_rook_is_blocked():
  board = create_board()
  result = is_valid_rook_move(board, "BR", 5, 0)
  assert not result
  board[7][5] = EMPTY
  result = is_valid_rook_move(board, "BR", 7, 5)
  assert not result
  print("test_rook_is_blocked passed")

def test_rook_is_not_blocked():
  board = create_board()
  board[1][0] = EMPTY
  result = is_valid_rook_move(board, "WR", 2, 0)
  assert result
  board[0][1] = EMPTY
  result = is_valid_rook_move(board, "WR", 0, 1)
  assert result 
  print("test_rook_is_not_blocked passed")

def run_tests():
  test_is_rank_valid()
  test_is_file_valid()
  test_is_target_square_taken()
  test_rook_is_blocked()
  test_rook_is_not_blocked()
run_tests()
출력:
test_is_rank_valid passed
test_is_file_valid passed
test_is_target_square_taken passed
test_rook_is_blocked passed
test_rook_is_not_blocked passed
그래!!!
내가 처리해야 할 마지막 일은 is_valid_rook_move의 믿을 수 없는 플러그인if and 순환이다.
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
나는 12yo에게 우리가 여기서 추출할 수 있는 공통된 논리가 있는지 물었다. 솔직히 그는 없었다. 그러나 괜찮아. 이것은 좀 이해하기 어렵다.목표 블록을 찾기 전이나 후에 찾든 논리는 똑같다. 코드가 어디에서 시작되고 언제 끝날지 알려주기만 하면 된다.우리는 이렇게 색인을 추출한다. (나는 이 부분을 썼다.)
if found_rank == target_rank:
    start_file = min(target_file+1, found_file+1)
    end_file = max(target_file, found_file)
    for i in range(start_file, end_file):
        if board[target_rank][i] != EMPTY:
          return False
  else: # found_file == target_file
    start_rank = min(target_rank+1, found_rank+1)
    end_rank = max(target_rank, found_rank)
    for i in range(start_rank, end_rank):
        if board[i][target_file] != EMPTY:
          return False
테스트를 다시 실행합니다.
test_is_rank_valid passed
test_is_file_valid passed
test_is_target_square_taken passed
test_rook_is_blocked passed
test_rook_is_not_blocked passed
두 배야!!!
오늘의 최종 코드(위의 화려한 테스트 세트까지):
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("")

def create_board():
  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"]

  return board

def is_valid_move(board, piece, target_rank, target_file):
  # out of bounds
  if  target_rank < 0 or target_rank > 7:
    return False
  if  target_file < 0 or 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)

  return True

def is_valid_rook_move(board, 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:
    start_file = min(target_file+1, found_file+1)
    end_file = max(target_file, found_file)
    for i in range(start_file, end_file):
        if board[target_rank][i] != EMPTY:
          return False
  else: # found_file == target_file
    start_rank = min(target_rank+1, found_rank+1)
    end_rank = max(target_rank, found_rank)
    for i in range(start_rank, end_rank):
        if board[i][target_file] != EMPTY:
          return False
  return True
오늘은 여기까지.내일 저희에 가입하세요. 저희가 칠판에서 루트를 실제로 이동할 때...

좋은 웹페이지 즐겨찾기