이번 주 중 3일간 진행된 텍스트게임의 코드리뷰를 진행해 보겠습니다. 이번 프로젝트의 중점은 클래스를 얼마나 잘 활용할 수 있는지 라고 생각합니다. 결과적으로만 보면 요구한 사항은 충족되게 결과물을 완성했지만, 클래스 활용에 있어서는 잘하지 못했다고 생각합니다. 이번 프로젝트의 파일은 총 2개로 클래스가 담겨있는 main.py
와 함수와 실행부분이 들어있는 action.py
로 구성 되어 있습니다. 조금 더 분할 했어야 확실히 구분되고 코드 수정하기도 좋았을 것 같은데 요구조건을 구현하는데만도 시간이 모자라서 분할하지 못했습니다.
이번 프로젝트는 말그대로 텍스트 게임을 고도화 시키는 주제이며, 이전 개인과제로 주어졌던 텍스트 게임을 고도화 시켜 완성하는게 목표입니다.
저희 조는 단순 rpg게임을 만들기 보다 현재 부트캠프에 참가하는 우리들이 성장하는 이야기 였으면 좋겠다는 의견을 채택해 개발자 성장 rpg 게임이 되었습니다. 직업은 프론트, 백엔드, 풀스택 총 3개이며 공격에 영향을 주는 스탯은 html, javascript, python으로 정했습니다. 사실 각 직업에 저 언어들이 주 언어라고 하긴 힘들지만 간단한 게임으로 구성하다 보니 다양한 언어를 추가하기가 힘들어서 저 3개로 선정되었습니다.
물론 html이 프로그래밍 언어가 아니라는 것은 저도 인지하고 있습니다!
먼저 Player
클래스 입니다. 모든 직업에 기초가 되는 클래스입니다.
class Player():
def __init__(self, id):
self.id = id
self.hp = random.randint(100, 200)
self.max_hp = self.hp
self.mp = random.randint(100, 150)
self.max_mp = self.mp
self.level = 1
self.exp = 0
self.max_exp = 50
self.html = random.randint(20, 30) # 스탯 1. 기본공격
self.javascript = random.randint(20, 30) # 스탯 2.마법공격 - front
self.python = random.randint(20, 30) # 스탯 3. 마법공격 - back
print(f"\n{self.id}이(가) 생성 되었습니다.")
print(f"""
LV: {self.level}
HP: {self.hp}/{self.max_hp}
MP: {self.mp}/{self.max_mp}
EXP: {self.exp}/{self.max_exp}
Html: {self.html}/Javascript: {self.javascript}/Python: {self.python}
""")
__init__
함수입니다. Player
클래스가 실행되면 자동으로 작동하며 self
와 id
를 인자로 받습니다. 밑에 많은 변수들이 지정되어 있는데도 인자를 id
만 받는 것은 레벨과 경험치는 고정으로 들어가고 나머지 스탯은 모두 랜덤한 값으로 들어가게 만들었기 때문입니다. 이후 나올 얘기이지만 저희 조는 풀스택 직업을 히든 직업으로 만들어 랜덤한 값이 일정 수치 이상일 경우 전직 가능하게 만들었습니다.
# 레벨업 함수
def gain_exp(self, mon_exp):
self.exp += mon_exp
if self.exp >= self.max_exp:
while self.exp >= self.max_exp:
next_exp = self.exp - self.max_exp
self.level_up(next_exp)
def level_up(self, current_exp):
self.level += 1
self.max_hp += 10
self.max_mp += 5
self.html += 5
self.javascript += 5
self.python += 5
self.hp = self.max_hp
self.mp = self.max_mp
self.exp = current_exp
self.max_exp += 20
print(f"{self.id}이(가) 레벨업 했습니다. LV : {self.level}")
Player
클래스 안에 있는 경험치 획득함수와 레벨업 함수입니다. 몬스터는 몬스터 마다 경험치가 다르고 처치 되었을때 몬스터의 경험치가 플레이어에게 넘어갑니다. gain_exp
함수는 그렇게 추가된 플레이어의 경험치가 본인이 가지고 있는 경험치 통을 넘어가게 되면 자신의 현재 경험치에서 레벨업에 필요한 경험치를 빼고 레벨업 함수를 사용합니다. while
문을 넣게된게 이 부분 때문인데 정상 플레이라면 한 번에 두 번 레벨업할 일이 없습니다만.. 혹시나 간과한 부분이 있어 레벨업을 두 번 해야한다면 반복문을 돌리는게 맞다 판단하여 넣게 되었습니다. 그리고 next_exp
변수는 레벨업하고 남은 경험치를 0으로 만들면 플레이어가 섭섭해할 것 같아서 다시 반환 해주기 위해 선언 했습니다.
그리고 level_up
함수입니다. 이 함수는 current_exp
를 인자로 받고 있는데 이는 위에 언급한 gain_exp
함수의 next_exp
변수가 들어가게 됩니다. 레벨업을 하면 레벨을 1 올려주고 나머지 기타 스탯들의 상승과 최대 체력,마나 상승, hp,mp 풀회복, 경험치통 한계 상승 넘어간 경험치 반환을 담고 있습니다.
class Frontend(Player):
def __init__(self, id, hp, mp, html, javascript, python):
self.id = id
self.hp = hp
self.max_hp = self.hp
self.mp = mp
self.max_mp = self.mp
self.level = 1
self.exp = 0
self.max_exp = 50
self.html = html
self.javascript = javascript
self.python = python
# 프론트엔드 일반 공격
def attack(self, target):
damage = random.randint(int(self.html * 0.8), int(self.html * 1.3))
target.hp = max(target.hp - damage, 0)
print(f"{self.id}의 웹표준 공격! {target.id}에게 {damage}의 데미지를 입혔습니다.")
if target.hp == 0:
print(f"{target.id}이(가) 쓰러졌습니다.")
target.drop_item(self) # 몬스터가 죽으면 드랍
# 프론트엔드 마법 공격
def magic_attack(self, target):
self.mp = max(self.mp - 50, 0)
if self.mp == 0:
print("마나가 부족합니다.")
return
damage = random.randint(int(self.javascript * 0.8), int(self.javascript * 1.2))
target.hp = max(target.hp - damage, 0)
print(f"{self.id}의 리액트 공격! {target.id}에게 {damage}의 마법데미지를 입혔습니다.")
if target.hp == 0:
print(f"{target.id}이(가) 쓰러졌습니다.")
target.drop_item(self) # 몬스터가 죽으면 드랍
Player
클래스를 상속받은 Frontend
클래스 입니다. 본래 일반 공격의 계수는 모든 직업이 같기에 Player
클래스에 넣고 싶었으나 회의 때 나온 직업 별 스킬대사를 다르게 하자는 안건이 반영되어 각 직업 별로 일반공격을 넣어주게 되었습니다. 출력되는 html만 다른 정도라면 Player
클래스에 넣어도 출력만 다르게 구현하는게 가능할 것 같았는데 급박한 상황 속에 진행하느라 제대로 찾아보지 못했습니다. 뼈아프네요..
이 게임의 경우 맘에드는 능력치가 나올 때까지 사용자가 능력치를 다시 굴릴 수 있고 이후 바로 직업을 선택하는 방식입니다. 그래서 Player
클래스에 다 있는 변수들이지만 굴려진 능력치를 그대로 다음 직업에 이식할 수 있도록 경험치 관련을 제외하고 인자를 모두 받게 했습니다.
attack
함수인데 일반공격을 담당하는 함수로 target
을 인자로 받습니다. damage
라는 변수에 html능력의 수치만큼 랜덤한 데미지가 들어가도록 설계하였습니다. 그렇게 만든 대미지를 target
의 hp에서 뺀 값과 0 중에 더 큰 숫자를 뽑아 target
의 hp가 되도록 만들었는데 이는 target
의 hp가 0보다 밑으로 떨어지는 것을 막기 위해서입니다. 코드를 작성하다보니 음수로 떨어져도 문제는 없었지만 저 방법을 만들고 이해하는게 재밌었습니다.
def magic_attack(self, target):
self.mp = max(self.mp - 50, 0)
if self.mp == 0:
print("마나가 부족합니다.")
damage = random.randint(int(self.javascript * 0.8), int(self.javascript * 1.2))
target.hp = max(target.hp - damage, 0)
print(f"{self.id}의 리액트 공격! {target.id}에게 {damage}의 마법데미지를 입혔습니다.")
if target.hp == 0:
print(f"{target.id}이(가) 쓰러졌습니다.")
target.drop_item(self) # 몬스터가 죽으면 드랍
magic_attack
함수로 마법공격을 담당하는 함수입니다. 전반적으로 일반공격과 유사한 코드를 가지고 다른 점은 마나가 부족할 경우 마나가 부족하다는 메시지를 출력하게 했습니다.
나머지 직업들도 모두 같은 형태이고 출력되는 문구와 대미지 산정방식이 차이만 있으니 넘어가겠습니다.
몬스터는 마법공격을 가지고 있지 않지만 회복과 대기라는 기능이 있습니다.
class Monster():
def __init__(self, id, hp, power, exp):
self.id = id
self.hp = hp
self.max_hp = self.hp
self.power = power
self.exp = exp
def attack(self, target):
damage = random.randint(int(self.power * 0.8), int(self.power * 1.2))
target.hp = max(target.hp - damage, 0)
print(f"{self.id}의 공격! {target.id}에게 {damage}의 데미지를 입혔습니다.")
if target.hp == 0:
print(f"{target.id}이(가) 쓰러졌습니다.")
return 0
return target.hp
def cure(self, max_hp):
self.hp += 10
print(f'{self.id}가 자신의 체력을 10만큼 회복했습니다. 현재 체력 : {self.hp}')
if self.hp > max_hp:
self.hp = max_hp
return self.hp
def wait(self):
print(f'{self.id}가 대기했습니다.')
Monster
클래스에 속하는 몬스터들은 생성될 때 id
, hp
, power
, exp
를 입력받습니다. 여기서 경험치는 몬스터가 죽었을 때 플레이어에게 전해줄 경험치 입니다. attack
함수는 위와 동일하고 스스로를 치유하는 cure
함수는 10만큼의 체력을 회복시키고 최대체력 이상으로 현재체력이 올라가는 것을 방지했습니다. 한 가지 아쉬웠던 점은 최대체력에 비례한 회복량을 갖춘 스킬로 만들지 않았다는 것입니다. 상위 몬스터들에게는 대기와 동급의 스킬이 아닌가 생각이 됩니다. 그리고 대기만 하는 wait
함수가 있습니다.
def drop_item(self, player): # 몬스터가 죽으면 드랍 아이템 , 확률
#포션
redportion = Equipment('빨간물약', 100, 0)
blueportion = Equipment('파란물약', 0, 100)
# 장비
hongongpa = Equipment('혼공파',0,0,3,3,3)
mouse = Equipment('마우스', 0,0,5,5,5)
keyboard = Equipment('키보드',0,0,5,1,10)
macbook = Equipment('맥북', 0,0,5,10,1)
chatgpt = Equipment('(전설)챗GPT',0,0,15,15,15)
items = [redportion, blueportion, hongongpa, mouse, keyboard, macbook, chatgpt] # 드랍 아이템 종류
probabilities = [0.3, 0.3, 0.2, 0.09, 0.05, 0.05, 0.01] # 드랍 확률
for i in range(len(items)):
if random.random() < probabilities[i]:
item = items[i]
if item in [redportion, blueportion]:
print(f"{player.id}이(가) {item.name}을(를) 획득하였습니다.")
player.use_item(item)
print(f"{player.id}이(가) HP를 {item.hp}만큼 / MP를 {item.mp}만큼 회복시켰습니다.")
else:
print(f"{player.id}이(가) {item.name}을(를) 획득하여. 장착했습니다")
player.use_item(item)
print(f"html: {item.html} / javascript: {item.javascript} / python: {item.python} 만큼 증가했습니다.")
몬스터에게 아이템을 드롭시키는 drop_item
함수입니다. items
에 선언한 아이템들을 리스트의 형태로 넣어주고 probabilities
에 각각의 확률을 리스트 형태로 만들었습니다. 이후 for
문을 이용해 랜덤한 값이 해당 확률보다 작을 경우 아이템을 획득하도록 만들었습니다.
class Dungeon():
def __init__(self, name):
self.name = name
self.monsters = []
def enter(self):
print(f"{self.name}에 입장하셨습니다.")
def append_monsters(self, *monster):
mon_list = [monster]
for m in mon_list:
self.monsters.append(m)
def get_monsters(self):
return self.monsters
def remove_monster(self, monster):
self.monsters.remove(monster)
시간을 너무도 많이 소비해 버린 애증의 Dungeon
클래스입니다. 본래 목적은 던전 안에 몬스터를 등록시키고 던전 클래스에 있는 몬스터리스트를 가져와 전투하는 방식으로 방향을 잡았고 자신도 있었습니다. 허나 문자열은 정보를 담고있지 않다 라거나, 튜플은 변동될 수 없다 라거나, 이상한 id값 같은게 나오기도 하는 등 문제를 해결하기위해 혼자 몰두했던 시간이 너무도 많았고 결국 실패해서 팀원들한테 죄송한 마음을 가지고 있습니다. 다방면으로 노력했지만 결과가 나오지 못해 몬스터를 던전에 등록시키긴 했으나 몬스터 리스트는 행동 함수 파트 안에 개별적으로 들어가게 선회했습니다. 많은 시간을 쏟았지만 시간 대비 가장 초라한 클래스인 Dungeon
클래스였습니다.
class Equipment(): # 장비 부모 객체
def __init__(self, name, hp, mp, html = 0, javascript = 0, python = 0):
self.name = name
self.hp = hp
self.mp = mp
self.html = html
self.javascript = javascript
self.python = python
별 다른 함수없이 오로지 장비라는 것을 생성시키기 위해 만든 Equipment
함수입니다. 각각 능력을 가지고 있고 해당 아이템을 소비하면서 가진 능력치를 플레이어에게 넘겨줍니다.
def player_action(list):
mon_list = list
while True: # while문을 사용해 break를 걸 때 까지 계속 실행
try: player_skill_input = int(input("\n공격할 방식의 번호를 입력해주세요: "))
if player_skill_input == 0 or player_skill_input > 2: # 1,2 외에 다른 숫자가 들어오면 다시 입력
print("공격방식을 다시 입력해주세요")
continue # while문을 처음부터 다시 시작함
if player_skill_input == 2:
if p1.mp < 5:
print("스킬을 사용하는데 필요한 MP가 모자랍니다.")
continue
except ValueError: # ValueError가 나왔을때 execpt문 실행
print("공격방식을 숫자로 입력해주세요")
continue
break # while문을 빠져나옴
print("\n===공격 대상 선택===")
for i, m in enumerate(mon_list): # enumerate함수를 사용해 i는 순서를 m은 m1,m2와 같은 몬스터 변수를 입력
print(f"{i+1}. {m.id} (HP: {m.hp} / {m.max_hp})")
while True: # while문을 사용해 break를 걸 때 까지 계속 실행
try:
player_target_input = int(input("\n공격할 대상의 번호를 입력해주세요: "))
if player_target_input <= 0 or player_target_input > len(mon_list): # 0 또는 리스트의 갯수보다 더 많은 숫자 입력 시 다시 입력
print("잘못된 대상을 선택하셨습니다. 다시 선택해주세요.")
continue
except ValueError: # ValueError가 나왔을때 execpt문 실행
print("대상 번호를 숫자로 입력해주세요.")
continue
break
target = mon_list[player_target_input -1]
if player_skill_input == 1: # 공격방식의 번호 입력이 1(노말어택)이라면
p1.attack(target) # main 파일 Player 클래스의 attack함수 실행
elif player_skill_input == 2: # 공격방식의 번호 입력이 2(매직어택)이라면
p1.magic_attack(target)
플레이어의 턴에 진행되는 player_action
함수입니다. mon_list
라는 변수에 인자로 받은 list를 전달해주며 while
문을 시작합니다. try-except
문을 이용해 예외처리를 해주고 그 안에 공격 방식, 공격 대상의 내용이 들어가 있습니다. 공격방식에는 1과 2외에는 입력 값을 받지 않기에 그외에는 전부 예외 처리하고, continue
를 이용해 다시 반복문을 시작하게 하고 마법공격의 경우 필요한 mp 이하로 mp를 가지고 있다면 공격할 수 없게 만들었습니다.
공격 대상의 경우 몬스터가 죽으면 선택지에서 제거되게 만들고 싶었습니다. 그래서 enumerate
함수를 사용해 몬스터가 죽어 리스트에서 삭제되었다면 print
에서 나오는 몬스터도 변경되도록 만들었습니다.
def monster_action(monsters):
# 살아있는 몬스터들만 행동
for monster in monsters:
action_num = random.randint(1, 3)
if action_num == 1:
monster.cure(monster.max_hp)
elif action_num == 2:
monster.wait()
elif action_num == 3:
monster.attack(p1)
# 몬스터 리스트 제거 함수
def monster_death(monsters_list, player):
for m in monsters_list:
if m.hp <= 0:
monsters_list.remove(m)
player.gain_exp(m.get_exp())
다음은 몬스터의 함수 부분입니다. monster_action
함수는 1 ~ 3의 랜덤 숫자 중 하나가 결정되면 해당 숫자에 맞는 몬스터의 스킬이 발동되도록 만들었습니다.
monster_death
함수는 몬스터가 죽었을 경우 몬스터 리스트에서 해당 몬스터를 제거하는 함수입니다.
def dungeon_03(dungeon, monster1, monster2, monster3):
dungeon.enter()
dungeon.append_monsters(monster1, monster2, monster3)
monsters_list = [monster1, monster2, monster3]
turn = 1
while True: # break가 걸릴 때 까지 반복 실행
new_cmd()
print(f"\n====={turn}번째 턴====") # f_string을 이용
time.sleep(0.3) # 텍스트가 한번에 입력되는 것을 방지함, 좀 더 게임처럼 즐길 수 있음
p1.show_status() # p1 = 플레이어, 플레이어의 상태를 보여주는 status함수를 사용
for m in monsters_list: # 몬스터 리스트에 있는 몬스터들을 m이라는 변수에 순차 저장
m.status()
time.sleep(0.3)
print("\n===플레이어 턴===")
player_action(monsters_list) # 플레이어 행동함수 실행
monster_death(monsters_list, p1) # 몬스터 리스트 제거 함수 실행
if monsters_list == []: # 몬스터가 모두 죽어서 리스트가 비어버렸다면
print("\n====clear!====\n당신이 승리했습니다.")
if dungeon == tenth_dungeon:
print("축하합니다. 당신은 모든 역경을 이겨내고 진짜 개발자가 되셨습니다.")
print("\n===몬스터 턴===")
time.sleep(0.3)
monster_action(monsters_list) # 몬스터 행동함수 실행
if p1.hp <= 0: # 플레이어의 체력이 0보다 같거나 작다면
print("\n당신이 사망하였습니다.\n 마을로 돌아갑니다.")
break
다음은 dungeon_03
함수입니다. 뒤의 03은 몬스터가 3마리 나온다는 의미입니다. 본래 Dungeon
클래스가 원하는대로 기능을 했더라면 이렇게 함수가 나오지 않았을 것 같습니다. 해당 함수의 파라미터를 *args
, **kwargs
, 리스트변수 등 다양한 노력을 했으나 결국 제출 시점까지 해결하지 못해 비효율적인 코드를 작성한 것 같습니다. 똑같은 함수를 인자만 바꿔서 복제해놓는다는게 뭔가 창피합니다...
해당 함수는 던전 입장을 알리는 던전 클래스의 enter
함수와 던전에 몬스터를 추가하는 함수인 append_monsters
를 사용하며 시작합니다. 이후에는 반복문을 이용해 위에 열거했던 행동함수들이 순서대로 나오게 만들었습니다.
show_status
함수는 전투 전 자신의 상태를 알려주는 함수이고 status
함수는 몬스터의 상태를 알려주는 함수입니다. status
의 경우 for
문 안에 배치해두었는데 이는 리스트에 들어가있는 몬스터를 한마리씩 상태를 보여주게 하기 위함입니다.
중간 if
문의 경우 클리어를 했을 때 입력된 dungeon
인자가 마지막 던전인 10번째 던전이라면 엔딩이 나오게 만들었고, 마지막 if
문의 경우 플레이어가 죽었을 경우에 기능합니다.
def new_cmd():
com_os = platform.system() # 사용자 시스템의 os가 무엇인지 탐색
input("\nENTER 키를 눌러 다음으로 진행하세요") # 새로고침이 되기 전 나온 정보들을 사용자가 읽고 넘어갈 수 있도록 엔터 입력 후 창 새로고침 진행
if com_os == 'windows': # 환경이 윈도우라면 cls 입력
os.system('Cls')
else: # 환경이 리눅스나 맥이라면 clear 입력
os.system('Clear')
텍스트 게임이다 보니 계속해서 텍스트가 터미널에 쌓이게 되는데 그게 너무 보기 안좋아서 구글링으로 작성한 함수입니다.
p1 = main.Player(input("이름을 입력해주세요."))
while True:
choice = input("진행하려면 Y / 다시하려면 N 을 입력해주세요: ")
if choice in ["N", "n"]:
p1 = main.Player(input("이름을 입력해주세요: ")) # N을 입력할 경우 p1 재선언
continue
elif choice in ["Y", "y"]:
break
elif choice not in ["Y", "N", "y", "n"]: # 입력값이 Y/N이 아니라면 continue로 다시 반복
print("Y 또는 N을 입력해주세요")
continue
print("====직업 선택====\n1.프론트엔드\n2.벡엔드")
if p1.html > 25 and p1.javascript > 25 and p1.python > 25:
print("3.풀스택(히든)")
while True:
job_select = int(input("원하시는 직업을 선택해주세요"))
if job_select == 1:
p1 = main.Frontend(p1.id, p1.hp, p1.mp, p1.html, p1.javascript, p1.python)
print("(예비)프론트엔드 직업을 가지게 되었습니다.")
break
elif job_select == 2:
p1 = main.Backend(p1.id, p1.hp, p1.mp, p1.html, p1.javascript, p1.python)
print("(예비)백엔드 직업을 가지게 되었습니다.")
break
elif job_select == 3:
if p1.html > 25 and p1.javascript > 25 and p1.python > 25:
p1 = main.Fullstack(p1.id, p1.hp, p1.mp, p1.html, p1.javascript, p1.python)
print("(히든)풀스택 직업을 가지게 되었습니다.")
break
else:
print('올바른 직업번호를 입력해주세요')
continue
먼저 p1
이라는 변수에 Player
클래스 객체를 선언해줍니다. 플레이어의 이름을 사용자가 직접 입력할 수 있도록 input
을 이용했습니다. 이후 while
문을 만들어 사용자에게 진행여부를 묻고 대답이 Y, N, y, n
중에 나오지 않는다면 오류처리로 다시 반복문 처음으로 보내고 N, n
을 입력하면 다시 p1
객체를 생성하게하고 반복문의 처음으로 돌려 선택지를 가질 수 있게 만들었습니다.
이후 플레이어는 직업을 선택하게 되는데 만약 p1
의 스탯 중 공격에 관여하는 3개의 스탯이 25이상이 나왔다면 풀스택
이라는 히든 직업을 가질 수 있게 만들었습니다. 이후 반복문을 통해 선택한 번호에 맞는 클래스 객체를 생성하도록 만들었고, 히든 직업의 경우 앞서 나온 조건을 충족하지 않으면 생성할 수 없도록 제한을 뒀습니다.
while True:
if p1.level <= 3:
print('---------------------')
print('---- 내배캠 마을 ----')
print('---------------------\n')
print("1. 던전 진입\n2. 마을 구경하기")
while True:
action_select = int(input("행동을 선택해 주세요: "))
if action_select not in [1, 2]:
print("다시 입력해주세요")
continue
elif action_select == 1:
print("1. 초급강의 던전\n2. 점프 투 파이썬 던전\n3. 심화강의 던전\n4. 뒤로가기")
# 4. 뒤로가기
dungeon_select = int(input("던전을 선택해 주세요: "))
if dungeon_select not in [1, 2, 3, 4]:
print("다시 선택해주세요")
continue #뒤로가기가 elif로 가야된다.
elif dungeon_select == 1:
dungeon_03(first_dungeon, mons1, mons2, mons3)
break
elif dungeon_select == 2:
dungeon_03(second_dungeon, mons2, mons3, mons4)
break
elif dungeon_select == 3:
dungeon_03(third_dungeon, mons3, mons4, mons5)
break
else:
break # 마을 메뉴로 돌아감
elif action_select == 2:
continue
최종장인 실행 부분입니다. 레벨별로 입장할 수 있는 마을과 던전이 다릅니다. 간소화하는 방법이 분명 존재할 것 같은데 생각해내질 못해 저 실행 부분이 3개가 들어가 있습니다.
맨 마지막에 있는 2번을 골랐을 시 마을 구경하기라는 선택지가 골라지는데 현재 블로그에는 올리지 않았으나 아스키아트가 들어가 있습니다.
던전을 클리어해도 계속 순환 할 수있도록 만들었습니다. while
문 안에 while
문을 만들어 던전을 클리어해 break
가 일어나더라도 바깥쪽 while
문으로 돌아가 무한히 회전합니다. 라스트 던전을 클리어 후 게임을 꺼지게 할까 생각했으나 그러고 싶지 않을 수 있는 사람을 위해 엔딩 크레딧만 나오고 계속 반복문이 돌아가게 만들었습니다. 참고로 엔딩 크레딧도 아스키아트라 이곳엔 올리지 않았습니다.
이번 프로젝트는 제가 팀장을 맡아 진행되었습니다. 처음하는 팀장직이기도 했으나 저번 팀에서의 무력함을 느끼는 인원이 없도록 하겠다 다짐했습니다. 허나 프로젝트가 시작되고나니 팀 내에선 가장 숙련도가 높은 인원이였음에도 불구하고 뭘해야할지 뭘 지시해야할지 알지 못했습니다. 팀 회의때 치밀하게 계획하고 기능별로 역할 분담을 나눴어야했는데 팀에서 무력함을 느꼈던 내가 다른사람에게 이 아픔을 되풀이 했다는게 너무 화가 났습니다... 능력 부족으로 기능별로 나누는 일도 제대로 수행하지 못했고, 역할 분담도 제대로 하지 못한 무능한 팀장이 된 것 같아 마음이 아팠습니다.
나름 팀장으로서 그리고 팀 내에서 그나마 가장 숙련자로서 팀원들이 이해하지 못하는 내용을 열심히 설명하고 알려드렸지만 그마저도 잘 하지 못한 것 같습니다. 결국에는 공부인 것 같습니다. 죽도록 공부해서 저도 낙오되지 않고 팀원도 낙오되지 않게 만들겠습니다. 같은 실수는 반복하지 않겠습니다.