KEK 개발로그
파이썬 실습2 - 베스킨라빈스 31 게임(BaskinRobbins 31) 본문
이번에 만들어 볼 게임은 '베스킨~라빈스~31'게임이다.
이 게임의 규칙은 아래와 같다.
[간단설명]
1부터 31까지의 숫자를 플레이어와 컴퓨터가 번갈아 가면서 순서대로 말합니다.
숫자를 말할 때는 1개부터 3개까지의 연속된 숫자를 말할 수 있습니다.
즉, 처음 시작하는 사람이 무조건 1 혹은 1, 2 혹은 1, 2, 3을 말하면서 시작하고,
그 뒷 사람은 앞 사람이 말한 숫자에 이어서 또 1개\~3개의 연속된 숫자를 차례대로 말하는 방식입니다.
(앞 사람이 3까지 불렀다면, 뒷 사람은 4 혹은 4, 5 혹은 4, 5, 6을 말해야 합니다.)
그렇게 해서 31을 부르는 사람이 지는 게임입니다.
[상세설명]
1. 컴퓨터가 먼저 숫자를 말할지, 플레이어가 먼저 숫자를 말할지는 랜덤으로 정한다.
2. 컴퓨터 혹은 플레이어는 1 혹은 1, 2 혹은 1, 2, 3을 말하면서 게임을 시작한다.
(단, 컴퓨터가 숫자를 1개 부를지, 2개 부를지, 3개 부를지는 random 패키지를 이용해서 랜덤으로 정한다
플레이어는 input 함수를 통해서 연속해서 부르고 싶은 숫자 개수를 입력한다.)
3. 컴퓨터 혹은 플레이어는 앞 사람이 부른 숫자에 이어서, 1개~3개까지의 연속된 숫자를 말한다.
4.2\~3번을 31을 말하는 사람이 나올 때까지 반복한다. (즉, 2\~3번을 for문 혹은 while문으로 작성할 것.
단, 컴퓨터와 플레이어 모두 31을 초과해서 숫자를 부를 수는 없다.)
5. 31을 말하는 사람이 컴퓨터라면 '플레이어 승'을,
31을 말하는 사람이 플레이어라면 '컴퓨터 승'을 출력한다.
(가능하다면, 컴퓨터가 숫자를 뽑는 코드와 플레이어가 숫자를 뽑는 코드는 함수화를 해보세요!)
상세 설명을 통해 이번 실습에서 중점적으로 연습할 부분은 '함수'라고 생각이들어서 함수에 focus를 좀 더 맞춰서 코드를 작성해봤다.
[베스킨라빈스 31 게임 1]
from random import *
print('베스킨라빈스 31 게임')
print('1부터 31까지의 숫자를 번갈아 불러 31을 부르는 사람이 지는 게임 입니다.')
print('부를 숫자의 개수를 적어주세요!')
number = 0
def player():
global number # 전역변수 불러오기(다른 함수에서 공통적으로 쓸 수 있는 변수!)
put_num = range(1,4)
p = int(input('1~3 사이의 수를 입력해주세요: '))
while p not in put_num: # 순서 중요! (while문보다 for문을 앞에 적었더니 4를 치면 바로 다시 입력해주세요 나오지 않고 플레이어:~~ 나오고 나서 while문이 실행됨)
p = int(input('1~3 사이의 수를 다시 입력해주세요: '))
for _ in range(p): # i는 리스트에 있는 값들을 불러오는 것. 여기서는 필요없기 때문에 값이 필요하지 않을 때 사용하는 "_" 사용
number += 1
print('플레이어:', number)
def computer():
global number
c = randrange(1,4)
for _ in range(c):
number += 1
print('컴퓨터:', number)
turn = randrange(0,2) # 순서를 랜덤하게 배정(0=컴퓨터 선공 or 1=플레이어 선공)
while True:
if turn == 0:
computer()
turn += 1
turn %= 2
elif turn == 1: # else 이면 turn=1.
player()
turn += 1
turn %= 2
if number >= 31: # 게임 전반적인 규칙. turn과는 결이 다른 규칙이므로 새로 if써주기.
break # 31이 넘는 순간 반복문 탈출
if turn == 0:
print('컴퓨터 승!')
else:
print('플레이어 승!')
코드를 작성하면서 어려웠던 부분은 2가지 정도 있었다.
1. 컴퓨터와 플레이어 중 누가 선공으로 숫자를 말할지에 대한 순서 랜덤 배정.
# turn == 0일때 >> 컴퓨터가 선공 / turn == 1 일때 >> 플레이어가 선공. 이렇게 부여하여
turn = randrange(0,2) 를 통해 랜덤으로 0이 뽑히면 컴퓨터가 먼저 게임을 시작하고,
1이 뽑히면 플레이어가 먼저 게임을 시작하게 했다.
2. 게임 규칙 상 말하는 숫자가 31이 되면 게임을 종료해야 하기 때문에 컴퓨터의 행동과 플레이어의 행동을 각각의 함수로 만들었지만 그 안에서 말해지는 숫자는 계속 연결되고, 갱신되어야 했다. 즉, 다른 함수에서 공통적으로 쓸 수 있는 변수를 지정해야 하는데, 함수의 '인자'에 대한 이해를 잘 못하고 있었던 터라서 인자를 지정하지 않고 global을 사용해서 전역변수로 문제를 풀었다.
* 하지만 global을 사용하는건 좋은 풀이가 아닙니다. 전역변수가 많아지다 보면 함수 내부에서 선언한 변수들이랑 함수밖에서 선언한 변수들이 꼬이기도 하고, 의존 관계를 가지게 되므로 서로 얽히고설켜서 좋지 않은 구조를 만들어 낸어 개발자들 사이에서는 전역변수 사용이 어느정도 금기시 되어 있다고 합니다. 비추천!!
* 함수 밖에 있는 value를 갱신하거나 받고 싶으면 함수에 인자를 할당해서 return으로 하는게 좋다. global 사용은 Nope!! 인자와 리턴을 잘 활용하자.
( 함수 인자에 넣어줘야 return값 제대로 받을 수 있음! 습관 잘 들이자. ex. count_num=변수선언 / user_play(count_num) 인자에 넣어줌 / return count_num 리턴으로 값을 갱신함)
[베스킨라빈스 31 게임 2]
from random import randrange
the_last_number = 0
# 3. 컴퓨터 혹은 플레이어는 앞 사람이 부른 숫자에 이어서, 1개~3개까지의 연속된 숫자를 말한다.
def computer_pick(the_last_number):
c = randrange(1, 4)
# 31 초과는 부를 수 없고, 31 초과를 부르려고 한다면 그냥 컴퓨터가 31까지 부르려 한다고 생각
if the_last_number + c > 31:
c = 31 - the_last_number
for i in range(1, 1+c):
print('컴퓨터: ', the_last_number + i)
return the_last_number + c
def player_pick(the_last_number):
p = int(input())
# 31 초과는 부를 수 없음
# 해당 예외처리는 플레이어가 숫자를 입력한다는 전제하에 작성된 것이고, 정확한 예외처리는 try, except 를 사용하는 것이 맞습니다!
while (p not in [1, 2, 3]) or (the_last_number + p > 31):
print('다시 입력하세요!')
p = int(input())
for i in range(1, 1+p):
print('플레이어: ', the_last_number + i)
return the_last_number + p
# 1. 컴퓨터가 먼저 숫자를 말할지, 플레이어가 먼저 숫자를 말할지는 랜덤으로 정한다.
whos_first = randrange(0, 2)
# 2. 컴퓨터 혹은 플레이어는 1 혹은 1, 2 혹은 1, 2, 3을 말하면서 게임을 시작한다. (단, 컴퓨터가 숫자를 1개 부를지, 2개 부를지, 3개 부를지는 random 패키지를 이용해서 랜덤으로 정한다. 플레이어는 input 함수를 통해서 부르고 싶은 숫자까지 이어서 말한다.)
# 컴퓨터가 먼저 할 경우
if whos_first == 1:
the_last_number = computer_pick(the_last_number)
# 4. 2~3번을 31을 말하는 사람이 나올 때까지 반복한다. (즉, 2~3번을 while문으로 작성할 것. 단, 컴퓨터와 플레이어 모두 31을 초과해서 숫자를 부를 수는 없다.)
# 5. 31을 말하는 사람이 컴퓨터라면 '플레이어 승'을, 31을 말하는 사람이 플레이어라면 '컴퓨터 승'을 출력한다.
while True:
the_last_number = player_pick(the_last_number)
if the_last_number == 31:
print('컴퓨터 승!')
break
the_last_number = computer_pick(the_last_number)
if the_last_number == 31:
print('플레이어 승!')
break
- 사실 이 게임에서 가장 중요한건 '마지막으로 부른 수를 저장해놓는다!'라는 것이다.(변수 선언, 함수 인자, return)
위 코드에서는 the_last_number라는 변수를 설정해줘서 이걸 함수 인자로 넣어주고, for문으로 또 불리는 숫자만큼 수가 커지고 return으로 마지막 수를 갱신해주면서 앞사람이 말한 숫자에 이어서 수가 커지도록 설정해줬다.
(여기서 return의 기능을 잘 이해해야 함. 함수가 리턴을 하면 실행 후에 그 결과 값을 새로운 변수에 저장할 수 있게 하는 것이 리턴의 역할! 즉, return을 통해서 the_last_number의 값을 갱신해주고, 이걸 토대로 코드가 계속 돌아감.)
-리스트와 범위를 활용한 예외처리. (while (p not in [1,2,3]) or (the_last_number + p > 31): )
-선공을 누가할지 랜덤으로 뽑는 것을 randrange를 활용해서 구현한 것은 같은데, 컴퓨터가 1일 때 먼저하는걸 게임이 실제로 진행되는 순서를 나타내는 while문 밖에서 설정해줘서 while문이 굉장히 깔끔해서 보기 좋았던 것 같다.
'Python' 카테고리의 다른 글
파이썬 실습1 - 업다운게임 인공지능(Updown AI) (0) | 2021.12.24 |
---|---|
파이썬 실습1 - 업다운게임(UpDown) (0) | 2021.12.23 |