[BOJ/Python] 1063.킹

괄괄이·2023년 10월 20일

백준

목록 보기
4/6

https://www.acmicpc.net/problem/1063

문제

8*8크기의 체스판에 왕이 하나 있다. 킹의 현재 위치가 주어진다. 체스판에서 말의 위치는 다음과 같이 주어진다. 알파벳 하나와 숫자 하나로 이루어져 있는데, 알파벳은 열을 상징하고, 숫자는 행을 상징한다. 열은 가장 왼쪽 열이 A이고, 가장 오른쪽 열이 H까지 이고, 행은 가장 아래가 1이고 가장 위가 8이다. 예를 들어, 왼쪽 아래 코너는 A1이고, 그 오른쪽 칸은 B1이다.

킹은 다음과 같이 움직일 수 있다.

R : 한 칸 오른쪽으로
L : 한 칸 왼쪽으로
B : 한 칸 아래로
T : 한 칸 위로
RT : 오른쪽 위 대각선으로
LT : 왼쪽 위 대각선으로
RB : 오른쪽 아래 대각선으로
LB : 왼쪽 아래 대각선으로
체스판에는 돌이 하나 있는데, 돌과 같은 곳으로 이동할 때는, 돌을 킹이 움직인 방향과 같은 방향으로 한 칸 이동시킨다. 아래 그림을 참고하자.

입력으로 킹이 어떻게 움직여야 하는지 주어진다. 입력으로 주어진 대로 움직여서 킹이나 돌이 체스판 밖으로 나갈 경우에는 그 이동은 건너 뛰고 다음 이동을 한다.

킹과 돌의 마지막 위치를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 킹의 위치, 돌의 위치, 움직이는 횟수 N이 주어진다. 둘째 줄부터 N개의 줄에는 킹이 어떻게 움직여야 하는지 주어진다. N은 50보다 작거나 같은 자연수이고, 움직이는 정보는 위에 쓰여 있는 8가지 중 하나이다.

출력

첫째 줄에 킹의 마지막 위치, 둘째 줄에 돌의 마지막 위치를 출력한다.

예제 입력 1

A1 A2 5
B
L
LB
RB
LT

예제 출력 1

A1
A2

예제 입력 2

A1 H8 1
T

예제 출력 2

A2
H8

풀이

행렬의 위치가 알파벳+숫자로 표시된다. 이에 맞춰서 주어진 위치를 좌표상 인덱스 위치로 변환한 뒤, 킹과 돌을 조건에 따라 움직이면서 최종 위치를 구한다.

♟ 체스판 위치 문제에 맞게 구하기

열: 알파벳, 가장 왼쪽부터 A
   0 : A, 1 : B, 2 : C, 3 : D, 4 : E, 5 : F, 6 : G, 7 : H
행: 숫자, 가장 아래부터 1
   7 : 1, 6 : 2, 5 : 3, 4 : 3, 3 : 4, 2 : 5, 1 : 6, 0 : 7
-> 딕셔너리에 열, 행에 해당하는 알파벳과 숫자 정보를 튜플로 묶어 넣어서 사전 준비
# 8 * 8 체스판

# 킹이 존재, 움직이는 방향: 상하좌우 4방향 대각선 => 총 8방향 델타탐색
# 돌도 존재, 킹이 돌이 있는 곳으로 이동하면 돌을 킹이 움직인 방향으로 한 칸 이동
# 킹이나 돌이 체스판 밖으로 나가면 그 이동은 건너 뛰고 다음 이동
# 킹과 돌의 마지막 위치 구하기
import sys
input = sys.stdin.readline
# 1. 주어진 위치 정보 -> 좌표상 위치로 변환
row = { '1': 7, '2': 6, '3': 5, '4': 4, '5': 3, '6': 2, '7': 1, '8': 0}
row_reverse = { 7: '1', 6: '2', 5: '3', 4: '4', 3: '5', 2: '6', 1: '7', 0: '8'}
col = { 'A': 0, 'B': 1, 'C': 2, 'D': 3, 'E': 4, 'F': 5, 'G': 6, 'H': 7}
col_reverse = { 0: 'A', 1: 'B', 2: 'C', 3: 'D', 4: 'E', 5: 'F', 6: 'G', 7: 'H'}
arr = [[0] * 8 for _ in range(8)]
# 킹, 돌, 움직임 횟수
king, stone, n = input().split()

# 킹, 돌의 좌표 위치 구하기
king = (row[king[1]], col[king[0]])
stone = (row[stone[1]], col[stone[0]])

# 배열에 킹, 돌 놓아주기
arr[king[0]][king[1]] = 'K'
arr[stone[0]][stone[1]] = 'S'

king_start = (king[0], king[1])
stone_start = (stone[0], stone[1])
for _ in range(int(n)):
    move = input().rstrip()
    # 처음 킹의 위치 x, y 를 move에 따라 움직인다
    x, y = king_start
    sx, sy = stone_start

    # 주어진 명령에 따른 움직임
    if move == 'R':
        y += 1
    elif move == 'L':
        y -= 1
    elif move == 'B':
        x += 1
    elif move == 'T':
        x -= 1
    elif move == 'RT':
        x -= 1
        y += 1
    elif move == 'LT':
        x -= 1
        y -= 1
    elif move == 'RB':
        x += 1
        y += 1
    elif move == 'LB':
        x += 1
        y -= 1
    # 이동한 위치가 제한 범위 밖이면 제외, 위치 변화 되돌려줌
    if x < 0 or x >= 8 or y < 0 or y >= 8:
        x, y = king_start
        continue
    # 이동한 위치에 돌이 있으면 돌도 똑같이 이동시키고 돌의 위치가 제한 범위 안인지도 확인 (아니라면 제외)
    # 근데 적다보니까 이럼 돌도 똑같이 if 8개 돌려야 한다. 그냥 움직임 정리해둬도 좋을듯...
    if arr[x][y] == 'S':
        # 이것은 돌의 위치
        if move == 'R':
            sy += 1
        elif move == 'L':
            sy -= 1
        elif move == 'B':
            sx += 1
        elif move == 'T':
            sx -= 1
        elif move == 'RT':
            sx -= 1
            sy += 1
        elif move == 'LT':
            sx -= 1
            sy -= 1
        elif move == 'RB':
            sx += 1
            sy += 1
        elif move == 'LB':
            sx += 1
            sy -= 1

        # 돌의 이동 위치가 제한 범위 밖이면 제외, 위치 변화 되돌려줌
        if 0 > sx or sx >= 8 or 0 > sy or sy >= 8:
            sx, sy = stone_start
            arr[sx][sy] = 'S'
            continue
    # 제외 조건들 다 거르면 이제 위치 정말 그대로 이동시킴
    # 돌은 한 칸 밀려서 sx,sy로 이동하고
    # x, y에 있던 값은 0이 된다. 
    # 킹은 좌표 위치만 신경 쓰면 되니까 배열에서 갱신시킬 필요가 없다. 
    arr[sx][sy] = 'S'
    arr[x][y] = 0
    king_start = (x, y)
    stone_start = (sx, sy)

x, y = king_start
sx, sy = stone_start
# 다시 알파벳+숫자 형태로 위치 변환 후 출력 
print(col_reverse[y]+row_reverse[x])
print(col_reverse[sy]+row_reverse[sx])

0개의 댓글