베스킨라빈스 31 게임 만들기 - 파이썬(Python)
베스킨라빈스 31 게임 만들기
1. 개요
“베스킨~ 라빈스~ 31!“. 좀 놀아보았다 하신 분들은 모를 수가 없는 게임. 각 게임 플레이어가 차례로 1~3 중의 수를 외쳐서 계속 수를 더하고, 마지막 31을 외치는 플레이어가 지는 게임이다. 컴퓨터와 사용자가 1:1 대결을 한다.
2. 로직
1️⃣ Random.randrange() 를 사용하여 누가 먼저 시작할지 정한다.
2️⃣ 컴퓨터가 말하는 함수를 만든다. 컴퓨터는 random 함수를 이용하여 1과 3 사이를 말하게 한다. 현재 숫자가 어떻게 변화 되고 있는 지는 한 변수를 정하여 누적하여 값을 더하며 확인한다.
3️⃣ 사용자가 말하는 함수를 만든다. 사용자의 숫자는 input()을 이용하여 받는다. 입력 예외처리 해준다. (1~3외에 값을 받지 못하게 한다)
4️⃣ 사용자 친화적으로 게임 진행상황을 출력해주는 함수를 만든다.
5️⃣ 누군가 31을 말하게 되면 상대방이 승리 했음을 알린다.
3. 코드
import random
# 컴퓨터가 말한다
def com_say(cur_num):
while True:
com_input = random.randrange(1, 4) # 1 ~ 3 사이 입력
if is_under_equal_thirtyone(com_input, cur_num): # 입력 값이 31이하 인 경우만
break
return cur_num, com_input
# 사용자가 말한다
def user_say(cur_num):
user_input = False
while not user_input: # 사용자 입력이 제대로 값을 가지지 않았다면
try:
user_input = int(input())
if not isinstance(user_input, int) or (user_input < 1 or user_input > 3): # 정수형, 1~3사이
raise ValueError
if not is_under_equal_thirtyone(user_input, cur_num): # 31이하가 아니라면
print("최대 31 까지만 입력 할 수 있습니다")
user_input = False
continue
except ValueError:
print("유효한 수를 입력 해 주세요(1~3)")
user_input = False
return cur_num, user_input
# 게임 진행 화면 출력한다
def print_current_situation(who, say_num, cur_num):
players = ["컴퓨터", "사용자"]
msg = f"{players[who]}:"
game_over = False
for _ in range(say_num):
cur_num += 1
msg += f" {cur_num}"
if cur_num == 31:
msg += f"\n{players[not who]} 승"
game_over = True
print(msg)
return cur_num, game_over
# 컴퓨터 & 사용자 입력 값이 31 이하 인지 확인한다
def is_under_equal_thirtyone(input_num, cur_num):
return True if input_num + cur_num <= 31 else False
# 0 is COM
# 1 is USER
who_turn = random.randrange(2) # 누가 먼저 시작할 지 정한다
print("게임을 시작하지 ...")
cur_num = 0
while True:
cur_num, num_said = com_say(cur_num) if not who_turn else user_say(cur_num) # 컴퓨터 또는 사용자 입력 값 받기
cur_num, keep_game = print_current_situation(who_turn, num_said, cur_num)
if keep_game: # 게임 진행 화면 출력 (game over return)
break
who_turn = not who_turn # 턴을 변경
베스킨라빈스 31 인공지능 만들기
1. 개요
이번에는 같은 게임이지만, 컴퓨터가 똑똑해야 한다. 단순히 임의의 값을 말하는 것이 아니라 필승이 되는 수들
을 말해야 한다. 우선 어떻게 해야 이 게임을 이길 수 있는가 봐야 한다. 우선은 먼저 26을 말하는 자가 반드시 승리할 수 있다. (다음 상대 말에 엉뚱하게 답만 하지 않는 다면..) 그렇다면! 어떻게 무조건 26을 말할 수 있을까? 이 이전에 4 작은 22을 말하면 된다. 이런식으로 계속 내려가다보면 필승이 되는 수
를 알 수 있다. 그 수는 26, 22, 18, 14, 10, 6, 2
이며, 처음부터 필승이 되는 수
만 말하게 되면 반드시 이길 수 있다.
즉, 처음시작 할 때 2 값을 먼저 말하게 되고 게임을 진행 하면서 위에 열거 된 수만 말하게 된다면 반드시 이길 수 있게 된다. 컴퓨터는 사용자가 말하는 값을 보면서 다음 필승이 되는 수
들만 말하면 된다. 단, 사용자가 먼저 2를 얘기하게 되고 필승의 수
만 계속 말하게 되면 컴퓨터는 지게 된다.(유일한 컴퓨터 패배 조건)
2. 로직
1️⃣ 위 코드를 그대로 가져오자. 그리고 컴퓨터가 말하는 함수안에서 코드(머리) 몇 줄 추가 해주면 끝난다.
2️⃣ 컴퓨터는 현재까지 진행 된 수(cur_num)를 보고 자신이 말할 수 있는 수(cur+1, cur+2, cur+3) 중 필승의 수를 말한다. 필승 수에서 2를 더하거나 뺀 후 4로 나눴을 때 나머지가 0 이다.
3. 코드
import random
# 컴퓨터가 말한다
def com_say(cur_num):
can_say_num = range(cur_num+1, cur_num+4) # 컴퓨터가 말할 수 있는 숫자를 리스트에 담는다
com_input = 0
for num in can_say_num:
if (num+2) % 4 == 0: # 필승 조건에 부합하는 수가 있는 지 확인
com_input = num - cur_num # 컴퓨터 입력 숫자를 도출
if com_input == 0: # 필승 조건 값을 입력 할 수 없다면 ...
while True:
com_input = random.randrange(1, 4) # 1 ~ 3 사이 입력
if is_under_equal_thirtyone(com_input, cur_num): # 입력 값이 31이하 인 경우만
break
return cur_num, com_input
# 아래는 생략 (위와 동일)
총평
베스킨라빈스31
이 게임에 이런 비밀이 있는 지 몰랐다. 게임을 할 때 아무 생각 없이 숫자를 불렀었는데 말이다. 이 게임도 그렇고 요즘 알고리즘 문제를 풀면서도 이런 생각을 했다. 어떤 규칙을 찾고 그 규칙을 코드로 표현 하는 게 생각만큼 쉽지가 않다. 뭔가 반복성과 규칙이 보이는데도 코드로 옮기는 게 어렵다. 현재 나를 보니 부족함이 많아 슬프지만, 계속 문제들을 풀고 해결하다보면 사고의 유연함과 구현력이 생기리라 믿고 오늘도 열심히 문제들을 풀어 나가겠다.
[추가]
처음 구현할 때 현재 진행 중인 숫자를 전역변수로 사용했는데, 튜터님이 그건 좋은 방법이 아니라 해서 매개변수로 넣고 리턴해주는 방식으로 누적되는 값을 계속 기억하게 했다. 전역변수 사용을 지양하자!