클래스 개념을 실습하기 위해 간단한 보드게임을 만들어 보기로 했다.
결과물은 위에 보이는 표지 이미지이다.
class Player:
def __init__(self):
self.idx = 0
def show_you(self):
print("\n")
print("Let's get started!")
print("This is you: " + self.icon)
print("This is where you are now: " + str(self.idx))
def show_enemy(self):
print("\n")
print("FYI, this is your enemy: " + self.icon)
print("This is where the enemy is now: " + str(self.idx))
def set_the_order(self, n):
self.order = n
def roll_the_dice(self):
dice_number = random.randrange(1, 7)
print("The dice number of " + self.name + ": " + str(dice_number))
return dice_number
def move(self, n):
self.idx += n
class WhitePlayer(Player):
def __init__(self, name):
self.idx = 0
self.icon = '○'
self.name = name # you or enemy
class BlackPlayer(Player):
def __init__(self, name):
self.idx = 0
self.icon = '●'
self.name = name # you or enemy
파이썬의 클래스는 자바와 달리 모두 public 접근이 가능하고, property에 직접 접근을 막는 방법이 없다.
그렇다고 해도 변수를 private으로 명시하는 방법은 있다.
변수 앞에 _를 붙여서 private 변수임을 동료 개발자에게 표시할 수 있고, 언더바를 두 개 붙이면 name mangling이 적용되어 _클래스명__속성명 형태로만 접근할 수 있게 된다.
private 변수에 대해서는, 아래와 같이 어노테이션(@)을 사용해 getter/setter를 따로 만들어준다.
@property
def order(self):
return self.__order
@order.setter
def order(self, n):
self.__order = n
함수명이 get_order, set_order 같이 서로 다를 경우 name 'order' is not defined 에러가 발생했다. (참고: https://stackoverflow.com/questions/598077/why-does-foo-setter-in-python-not-work-for-me)
파이썬의 클래스 함수를 사용할 때, 필요한 param이 없더라도 def에서 self라는 param은 표시해주어야 한다. 만약 다음과 같이 작성하면
def show_you():
...
함수를 사용할 때 show_you()로 작성해도 다음과 같은 에러가 발생한다.
TypeError: show_you() takes 0 positional arguments but 1 was given
0개의 argument가 있어야 하는데 1개의 argument가 주어졌다는 뜻이다.
함수 선언 시 @staticmethod 어노테이션이 있으면 self를 사용하지 않으며, 위와 같이 param을 표시하지 않아도 된다. 다만 클래스/인스턴스 property에 접근하거나 클래스/인스턴스 메서드를 호출하는 것도 불가하다.
@staticmethod
def show_you():
...
intro_game()
you = pick_your_color()
enemy = set_the_enemy(you)
show_the_map(you, enemy)
set_the_order(you, enemy)
play(you, enemy)
show_the_winner(you, enemy)
goodbye()
def intro_game():
print("Welcome to the Simple Board Game!\n")
print("The Rule is simple:\n")
print("1. Pick the color, then your enemy will get the other color.")
print("The computer will make the order for each of you to roll the dice.\n")
print("2. You start from zero, and move just as the dice number.")
print("When you reach 20 first, you win.\n")
def pick_your_color():
your_color = input("If you are ready, pick the color. [B: black / W: white]")
while your_color != 'chosen':
if your_color == 'B':
your_color = 'chosen'
you = BlackPlayer('you')
elif your_color == 'W':
your_color = 'chosen'
you = WhitePlayer('you')
else:
print(your_color)
your_color = input("Sorry, the choice has to be B or W. Try again.")
you.show_you()
return you
def set_the_enemy(you):
if isinstance(you, BlackPlayer):
enemy = WhitePlayer('enemy')
else:
enemy = BlackPlayer('enemy')
enemy.show_enemy()
return enemy
def draw_map():
board_map = []
for i in range(21):
board_map.append(str(i))
return board_map
def show_the_map(you, enemy):
# 기존 icon을 지워주는 작업
board_map = draw_map()
# idx 가 20보다 큰 경우 20으로 만들어줌
if you.idx > 20:
you.idx = 20
if enemy.idx > 20:
enemy.idx = 20
# you와 enemy가 같은 위치인 경우
two_icons = you.icon + enemy.icon
if enemy.idx == you.idx:
board_map[you.idx] = two_icons
# you와 enemy가 다른 위치인 경우
else:
board_map[you.idx] = you.icon
board_map[enemy.idx] = enemy.icon
print('you: ' + str(you.idx))
print('enemy: ' + str(enemy.idx))
print("Let's see the map.")
print(board_map)
def set_the_order(you, enemy):
queue = [you, enemy]
random.shuffle(queue)
for i, v in enumerate(queue):
if queue[i] == you:
you.order = i
if queue[i] == enemy:
enemy.order = i
print("\n")
print("The computer set the order for you and the enemy.")
if you.order == 0:
print("Lucky you! You go first!")
else:
print("Your enemy goes first, and you are the second one.")
def play(you, enemy):
while you.idx < 20 and enemy.idx < 20:
roll_the_dice(you, enemy)
if you.idx == 20 or enemy.idx == 20:
break
elif input("Will you roll the dice again? [Y/N]") == "N":
break
def roll_the_dice(you, enemy):
if you.order == 0:
go(you)
show_the_map(you, enemy)
if you.idx < 20:
go(enemy)
show_the_map(you, enemy)
else:
go(enemy)
show_the_map(you, enemy)
if enemy.idx < 20:
go(you)
show_the_map(you, enemy)
def go(player):
print("\n")
dice_number = player.roll_the_dice()
player.move(dice_number)
def show_the_winner(you, enemy):
if max(you.idx, enemy.idx) == you.idx:
print("Bravo! You won!")
else:
print("The winner is your enemy.")
def goodbye():
print("Well played! See you again :)")
파이썬의 클래스가 무엇인지 공부하기 좋은 글이네요. 멋집니다.