-
[PS] 17081) RPG Extreme백준 PS 2022. 11. 1. 16:30
https://www.acmicpc.net/problem/17081
17081번: RPG Extreme
요즘 택희는 RPG 게임을 하고 있다. 던전을 헤쳐나가며 몬스터를 물리치고, 아이템을 모으고, 레벨 업을 하여 보스 몬스터를 물리치는 전형적인 RPG 게임이다. 이 게임은 N×M 2차원 그리드 위에서
www.acmicpc.net
Platinum2) 17081.RPG Extreme
- 구현, 시뮬레이션
Platinum 구현 문제라 조건이 많고 세세한 부분 컨트롤에 유의하자. 구현 자체 코딩에는 많은 시간이 걸리지 않았지만 AC를 받는 것까지가 어려웠다. 개인적으로 빼먹었던 조건과 질문 검색의 유의사항을 정리해보자
- 아이템 박스는 방문시 교체가 일어나지 않아도 없어진다.
- 움직일 수 없는 상황에 가시를 밟고 있다면 중복해서 데미지를 입는다.
- 보스의 이름은 "Boss"가 아닐 수 있다.
- RE 장신구로 살아나게 되면 몬스터 또한 체력을 회복한다.
- player가 죽으면 보드에 @은 출력되지 않는다.
- player의 hp가 0이하로 떨어져 죽더라도 player의 hp 출력은 0으로 한다.
유의해야할 조건들은 이정도가 있고 다른 조건들도 잘 컨트롤할 수 있도록 문제 요구사항을 확인하자.
세부적은 코드 내용은 다음과 같다.
# U R D L dx = [-1,0,1,0] dy = [0,1,0,-1] def getdata(): n, m = map(int,input().split()) board = list(list(input().rstrip()) for _ in range(n)) command = list(map(str,input().rstrip())) for idx, dir in enumerate(command) : if dir == 'U' : command[idx] = 0 elif dir == 'R' : command[idx] = 1 elif dir == 'D' : command[idx] = 2 else : command[idx] = 3 k, l = 0, 0 for i in range(n) : for j in range(m) : if board[i][j] == '&' or board[i][j] == 'M' : k += 1 if board[i][j] == 'B' : l += 1 if board[i][j] == '@' : ix, iy = i, j monster, box = dict(), dict() for i in range(k) : tmp=list(input().split()) monster[int(tmp[0])-1,int(tmp[1])-1] = [int(tmp[3]), int(tmp[4]), int(tmp[5]), int(tmp[6]), tmp[2]] for i in range(l) : tmp = list(input().split()) box[int(tmp[0])-1, int(tmp[1])-1] = [tmp[2], tmp[3]] return n, m, k, l, board, command, monster, box, ix, iy n, m, k, l, board, command, monster, box, ix, iy = getdata()
위의 코드는 이동 방향을 나타낼 dx, dy의 정의와 주어진 입력을 받아올 getdata 함수이다. ix, iy로 player의 첫 위치를 지정하고 monster와 box는 dictionary를 이용하여 좌표를 key로, 내용을 value로 받았다.
def move(board, x, y, dir) : nx = x+dx[dir] ny = y+dy[dir] if 0<=nx<n and 0<=ny<m and board[nx][ny] != '#' : return nx, ny else : return x, y # LV, HP, ATT, DEF, EXP player = [1, 20, 2, 2, 0] max_hp = 20 max_exp = 5 # weapon, armor, accessories*4 equipment = [0, 0, 0, 0, 0, 0]
board에서 움직이게 될 player의 move함수이다. 움직일 수 없는 경우는 그대로 그 자리에 가만히 있고, 움직일 수 있는 경우만 움직인다. player와 장비에 대한 사전 정의는 주석으로 설명이 되어 있다.
def printplayer(board, player, equipment, turn, max_hp, max_exp) : for i in range(n) : for j in range(m) : print(board[i][j], end="") print() print(f"Passed Turns : {turn}") print(f"LV : {player[0]}") print(f"HP : {player[1]}/{max_hp}") print(f"ATT : {player[2]}+{equipment[0]}") print(f"DEF : {player[3]}+{equipment[1]}") print(f"EXP : {player[4]}/{max_exp}")
printplayer는 출력을 위해 현재 player의 상태와 진행된 턴에 대한 출력함수이다.
def sol(max_hp, max_exp) : turn = 0 sx, sy = ix, iy board[ix][iy] = '.' for dir in command : sx, sy = move(board, sx, sy, dir) turn += 1 if board[sx][sy] == '^' : if 'DX' in equipment : player[1] -= 1 else : player[1] -= 5 if player[1] <= 0 : if 'RE' not in equipment : player[1] = 0 printplayer(board, player, equipment, turn, max_hp, max_exp) print("YOU HAVE BEEN KILLED BY SPIKE TRAP..") return else : sx, sy = ix, iy player[1] = max_hp equipment.remove('RE') if board[sx][sy] == '&' : tmp = monster[(sx, sy)] m_hp = tmp[2] flag = 0 if 'CO' in equipment : flag = 1 while True : if flag == 0 : tmp[2] -= max(1, player[2]+equipment[0]-tmp[1]) if flag == 1 : if 'DX' not in equipment : tmp[2] -= max(1, (player[2]+equipment[0])*2-tmp[1]) else : tmp[2] -= max(1, (player[2] + equipment[0]) * 3 - tmp[1]) flag = 0 if tmp[2] <= 0 : board[sx][sy] = '.' if 'EX' in equipment : player[4] += int(tmp[3]*(1.2)) else : player[4] += int(tmp[3]) if player[4] >= max_exp : player[4] = 0 player[0] += 1 max_hp += 5 player[1] = max_hp player[2] += 2 player[3] += 2 max_exp += 5 if 'HR' in equipment : player[1] += 3 if player[1] >= max_hp : player[1] = max_hp break player[1] -= max(1, tmp[0]-player[3]-equipment[1]) if player[1] <= 0 : if 'RE' not in equipment : player[1] = 0 printplayer(board, player, equipment, turn, max_hp, max_exp) print(f"YOU HAVE BEEN KILLED BY {tmp[4]}..") return else : sx, sy = ix, iy player[1] = max_hp equipment.remove('RE') tmp[2] = m_hp break if board[sx][sy] == 'B': tmp = box[sx, sy] if tmp[0] == 'W' : equipment[0] = int(tmp[1]) elif tmp[0] == 'A' : equipment[1] = int(tmp[1]) else : if tmp[1] not in equipment : for i in range(2, 6) : if equipment[i] == 0: equipment[i] = tmp[1] break board[sx][sy] = '.' if board[sx][sy] == 'M' : Hflag = 0 if 'HU' in equipment : player[1] = max_hp Hflag = 1 tmp = monster[sx, sy] m_hp = tmp[2] flag = 0 if 'CO' in equipment: flag = 1 while True: if flag == 0: tmp[2] -= max(1, player[2] + equipment[0] - tmp[1]) if flag == 1: if 'DX' not in equipment: tmp[2] -= max(1, (player[2] + equipment[0]) * 2 - tmp[1]) else: tmp[2] -= max(1, (player[2] + equipment[0]) * 3 - tmp[1]) flag = 0 if tmp[2] <= 0: if 'EX' in equipment: player[4] += int(tmp[3] * (1.2)) else: player[4] += int(tmp[3]) if player[4] >= max_exp: player[4] = 0 player[0] += 1 max_hp += 5 player[1] = max_hp player[2] += 2 player[3] += 2 max_exp += 5 if 'HR' in equipment: player[1] += 3 if player[1] >= max_hp: player[1] = max_hp board[sx][sy] = '@' printplayer(board, player, equipment, turn, max_hp, max_exp) print("YOU WIN!") return if Hflag == 0 : player[1] -= max(1, tmp[0] - player[3] - equipment[1]) else : Hflag = 0 if player[1] <= 0: if 'RE' not in equipment: player[1] = 0 printplayer(board, player, equipment, turn, max_hp, max_exp) print(f"YOU HAVE BEEN KILLED BY {tmp[4]}..") return else: sx, sy = ix, iy player[1] = max_hp equipment.remove('RE') tmp[2] = m_hp break # print(f"==={turn}th===") # board[ix][iy]='.' # dd = board[sx][sy] # board[sx][sy] = '@' # printboard(board,n) # print(f"===player===") # print(player) # print(f"===equipment===") # print(equipment) # board[sx][sy] = dd board[sx][sy] = '@' printplayer(board,player,equipment,turn,max_hp,max_exp) print("Press any key to continue.")
전체적인 조건과 움직임을 담고 있는 solution 함수이다. 각 command의 움직임에 따라 player를 이동시키고, 만나는 각 B, &, M마다 조건에 맞는 행동을 담고 있다. 중간 중간 equipment의 장신구에 의해 조건문이 많이 붙어 있으며 출력을 위한 board도 따로 신경써주어야 한다.
따로 쓰이는 알고리즘이나 아이디어는 없으나 세세한 조건을 잘 따져야하기 때문에 난이도가 높게 형성되어 있는 것 같다. 실제로 정답률도 낮다. 코드를 다 작성하고 예제 출력은 정확히 나오나 AC를 못 받는 경우가 많은 것 같고, 이런 상황에서 어느 부분이 틀렸는지 확인하기도 쉽지 않다. 코드를 논리적 흐름에 따라 더 깔끔하게 작성하고, 반복되는 부분을 함수화하여 사용하면 보다 쉽게 오류 부분을 찾을 수 있을 것 같다.
'백준 PS' 카테고리의 다른 글
[PS] 2178) 미로 탐색 (0) 2022.11.14 [PS] 2293) 동전 1 (0) 2022.11.14 [PS] 1806) 부분합 (0) 2022.10.24 [PS] 14939) 불끄기 (1) 2022.10.21 [PS] 1509) 펠린드롬분할 (0) 2022.10.21