Algorithm/これがコードテスト/実装/ゲーム開発


📖質問する


  ヘミンはゲームキャラクターが地図を移動するシステムを開発している.キャラクタの位置は1 x 1サイズの正方形からなるNxMサイズの矩形で、各格子は陸地または海洋です.キャラクターは東西南北から一つの場所を眺めている.
  地図上の各格子は(A,B)で表すことができ、Aは北から来た格子の個数、Bは西から来た格子の個数である.キャラクターは上下左右に移動でき、海の空間に入ることはできません.
  キャラクターの動きを設定するためのマニュアルは以下の通り.
  • 現在位置で、現在方向を基準として左方向(反時計回り方向90度回転)から順に行き先を決めます.
  • のキャラクターの真左にまだ行ったことのない格子がある場合は、左に回転して左に1格進みます.左方向に未通過の格子がない場合は左方向のみ回転し、第1段階に戻る.
  • 4 4方向が既に行ったものや海の格子であれば、眺める方向を保ち、1段後ろに1段後ろに進み、1段目に戻ります.しかし、このとき後ろの方向が海の格子になっていて、後ろに進めないと移動が止まってしまいます.
  • ヘミンはこのような過程を繰り返し、キャラクターの移動に異常があるかどうかをテストしようとした.マニュアルに従ってロールを移動した後、ロールがアクセスするセル数を出力するプログラムを作成します.

    入力条件

  • の最初の行に、スペースで区切られた一覧の縦サイズNと横サイズMを入力します.(3 <= N,M <= 50)
  • の2行目では、ゲームキャラクタが存在するセルの座標(A,B)と注視方向dがそれぞれスペースで区切られている.方向dの値は4種類あります.
  • 0:北
  • 1:東方
  • 2:ユニークな
  • 3:西側
  • の3行目から地図が陸地なのか海なのかの情報が提供されます.N行では,地図の状態は北から南へ順次与えられ,各行のデータは西から東へ順次与えられる.地図の外角はいつも海です.
  • 0:陸地
  • 1:海
  • 最初のゲームキャラクターが置かれた格子状態は常に陸地である.
  • しゅつりょくじょうけん

  • 最初のゲームキャラクターが置かれた格子状態は常に陸地である.
  • 📝解法


  • の方向に従って、前進、後退の変位がリストされる.
    (上図の黄色いブロック)
  • 符号ストリームは、上の画像の淡い緑色雲に位置する.
  • パスワード

    import sys
    
    # 바라보는 방향에 따른 전진, 후진의 변위를 리스트로 저장해두기
    proceed = [(-1, 0), (0, 1), (1, 0), (0, -1)]
    back = [(1, 0), (0, -1), (-1, 0), (0, 1)]
    
    n, m = map(int, sys.stdin.readline().split())
    a, b, d = map(int, sys.stdin.readline().split())
    
    # 방문 여부를 담는 이차원 리스트 0으로 초기화
    # 0: 아직 방문하지 않음, 1: 방문했음
    visit = [[0] * m for _ in range(n)]
    visit[a][b] = 1
    
    # 게임의 맵 정보를 입력받아서 2차원 리스트로 저장
    game_map = list()
    for i in range(n):
      tmp = list(map(int, sys.stdin.readline().split())) 
      game_map.append(tmp)
    
    rotation = 0 # 회전 수를 담는 변수
    answer = 1 # 방문한 칸의 수를 담는 변수
    while True:
      # 캐릭터를 왼쪽 방향으로 회전시킨다.
      rotation += 1
      d -= 1
      if d == -1:
        d = 3
    
      if rotation <= 4:
        # 전진할 경우 다음 위치
        next_a = a + proceed[d][0]
        next_b = b + proceed[d][1]
        
        # 전진한 위치가 이미 가본 곳이거나 바다인 경우에는 캐릭터를 움직이지 않고 1단계로 돌아감
        if game_map[next_a][next_b] == 1 or visit[next_a][next_b] == 1:
          continue
        # 안 가본 곳이면 캐릭터를 한 칸 전진시킨다. 즉 현재 위치를 갱신한다.
        else:
          a = next_a
          b = next_b
          visit[a][b] = 1
          answer += 1
          rotation = 0
      # 네 방향 모두 이미 가본 칸이거나 바다로 되어있는 칸인 경우
      else:
        # 후진할 경우 다음 위치
        next_a = a + back[d][0]
        next_b = b + back[d][1]
        # 후진한 위치가 바다가 아닌경우 캐릭터를 한 칸 후진시킨다. 즉 현재 위치를 갱신한다.
        if game_map[next_a][next_b] == 0:
          a = next_a
          b = next_b
          rotation = 0
        # 후진한 위치가 바다인 경우 움직임을 멈춘다.
        else:
          break
    
    print(answer)

    に感銘を与える


    『これがコードテスト』という本で、難易度2の問題を初めて解いたのですが、ちょっと怖かったのですが、ゆっくりと問題についてアルゴリズムを構想していたので、思ったより早かったです.
    また、前に実施問題で、変衛たちをリストに並べて使う方法を忘れていたのでifゲートをたくさん書きましたが、今回の問題では、そうしなかった私に拍手...👏👏
    本のサンプルコードと大まかな流れは似ていますが、キャラクターを左に回転させる方法が単独で体現されているのが印象的です.私はwhileドアに左に回転するコードを書いただけです.
    while True:
      rotation += 1
      d -= 1
      if d == -1:
        d = 3
    本のサンプルコードでは、
    def turn_left():
        global d
        d -= 1
        if d == -1:
            d = 3
    
    ...
    
    while True:
        turn_left()
    このように,コメントがなくても,現在のコードの動作を一目で見ることができる.
    可読性のあるコードを作成するには、このように単独で使用するのが望ましい.