본문 바로가기
  • 문헌정보학도가 개발도 한다구요??
Projects/Python

Python - 인기 게임 Yacht (야추)를 대충 만들어 보았습니다.

by 개발하는사서 2021. 1. 14.

몇 달전에 집에서 치킨을 뜯으면서 인터넷 방송을 보고 있었는데, 배도라지 패밀리 스트리머들 사이에서 유행하는 주사위게임이 있었다. 원래 Yacht(얔트 정도로 발음) 라는 보드게임인데, 닌텐도 스위치에서 동명의 게임으로 나온 것이 히트를 친 것. 여기서 스트리머들이 야추라고 이 게임을 칭하면서 일반인들도 그런 발음으로 알고 있다고 한다.

주사위 눈 하나에 울고 불고 하는 아조씨들을 보니, 문득 나도 주사위에 내 운명을 맡기고 싶다는 생각이 들었다. 그러나 스위치의 가격은 학생인 본인에게 너무 높은 벽이었고, 게임마저 따로 사야 한다는 생각이 들자 

직접 만들어 보자! 라고 생각했다. 

긴 정성을 들인것은 아니기에, 어느 정도의 스파게티 코드인 점은 감안해 주시길 바란다...

drive.google.com/file/d/1kV0s5PCOJadDmEYkClJAcJWTa1I0dgjr/view?usp=sharing

관심이 있으신 분들은 위 파일을 받으셔서 yacht.exe 파일을 실행하시면 된다. 안에 족보도 적어놨으니 참고하시라. 

 

코드는 크게 3부분으로 나뉘었다.

1. 메인함수

2. 주사위를 던지는 부분

3. 점수를 매기는 부분

 

먼저 주사위를 던지는 부분은 주사위를 굴리는 부분과 주사위의 결과를 보여주는 부분으로 나뉘어져 있다. 

주사위는 roll_dice클래스의 rolling_dice_first로 처음의 주사위를 던지고, 이후 주사위를 2번 바꾸는 과정은 change_dice에서 이루어진다. 이후 결정된 주사위 눈은 result_of_dice에서 처리. pandas를 이용해 깔끔한 디자인 결과를 얻었다.

import random
import pandas as pd

class roll_dice:
    def __init__(self):
        self.dice = []
        self.number = 0
    def rolling_dice_first(self):
        dice = self.dice
        number = self.number
        for i in range(5):
            dice_value = random.choice([1, 2, 3, 4, 5, 6])
            dice.append(dice_value)
        #dice = sorted(dice)
        return dice

    def change_dice(self, query1, dice_result):
        while True:
            if query1 == 'y':
                choice_list = []
                while True:
                    query1_1 = input('몇번 주사위를 바꾸시겠습니까?(숫자 입력후 엔터. 종료는 n 입력, 선택 정정은 a 입력) : ').lower()
                    if query1_1 in ['1','2','3','4','5']:
                        choice_list.append(query1_1)
                        print('선택한 주사위 번호 : ' + str(choice_list))
                        continue
                    elif query1_1 == 'a':
                        print('선택을 초기화합니다')
                        choice_list = []
                        continue
                    elif query1_1 == 'n':
                        print('주사위 선택을 종료합니다')
                        break
                    else:
                        print('정확한 번호를 입력해 주세요')
                        continue
                for x in choice_list:
                    dice_result[int(x)-1] = random.choice([1, 2, 3, 4, 5, 6])
                return dice_result
                break
    
            elif query1 == 'n':
                return dice_result
                break
            else:
                print('유효한 값이 아닙니다. 다시 입력해주세요')
                pass


class result_of_dice:
    def __init__(self,dice_result):
        self.dice_list = dice_result
    def show_result(self):
        dice_result = self.dice_list
        series = ['1번 주사위','2번 주사위','3번 주사위','4번 주사위','5번 주사위']
        result = pd.Series(data=dice_result, index=series)
        return result

 

그 다음은 점수를 매기는 부분. 노가다의 정수가 담겨 있어 길다. 원래 첫번째 ScoreBoard클래스에 점수를 담으려고 했으나, 생각지도 못한 오류가 많이 나와 메인 파일에 집어넣어 버렸다. 덕분에 멘탈과 시간을 절약했다.

calc_score는 말 그대로, 점수를 계산하는 클래스다. 사용자의 주사위가 해당 족보와 일치할떄, 점수를 계산해서 반환한다. 별거없으나, 사용자가 전략적 선택을 위해 점수가 나오지 않음에도 불구하고 해당 족보를 선택하여 일부러 0의 점수를 받는일이 있기 때문에, 족보가 성립하는 조건을 뒤늦게 추가하느라 진을 뺐다.

Check_Score는 사용자의 주사위가 해당 족보의 조건에 맞을때 알려주기 위한 부분이다.

Choice_Score는 사용자가 원하는 칸에 계산된 값을 넣어준다.

next_phase는 일정조건을 달성하면 보너스 점수를 주는데, 그것을 계산하기 위한 부분과 점수의 총합을 보여주는 부분이 있다. 

import pandas as pd

class ScoreBoard:
    def __init__(self):
        self.player_list = []
        self.board = []
    def score(self,player_list):
        df = pd.DataFrame(columns=player_list, index=['Aces','Twos','Threes','Fours','Fives','Sixes','Bonus','Choice','Four-Of-A-Kind','Full House','Small Straight','Large Straight','Yacht','TOTAL SCORE'])
        df = df.fillna(0)
        return df

class calc_score:
    def __init__(self):
        self.score = 0
    def Aces(self,change_dice_result):
        score = self.score
        val1 = change_dice_result.count(1)
        score = val1*1
        return score

    def Twos(self,change_dice_result):
        score = self.score
        val1 = change_dice_result.count(2)
        score = val1*2
        return score

    def Threes(self,change_dice_result):
        score = self.score
        val1 = change_dice_result.count(3)
        score = val1*3
        return score

    def Fours(self,change_dice_result):
        score = self.score
        val1 = change_dice_result.count(4)
        score = val1*4
        return score

    def Fives(self,change_dice_result):
        score = self.score
        val1 = change_dice_result.count(5)
        score = val1*5
        return score

    def Sixes(self,change_dice_result):
        score = self.score
        val1 = change_dice_result.count(6)
        score = val1*6
        return score

    def Choice(self,change_dice_result):
        score = self.score
        for i in change_dice_result:
            score = score + i
        return score

    def Four_Of_A_Kind(self,change_dice_result): #여기 문제, 변수 i가 1 이후의 값을 반환하지 않음 ---- 해결
        score = self.score
        for item in [1,2,3,4,5,6]:
            if change_dice_result.count(item) >= 4:
                for x in change_dice_result:
                    score = score + x
                return score
            else:
                pass
            if item == 6 and change_dice_result.count(item) < 4:
                return 0
            else:
                pass

    def Full_House(self, change_dice_result):
        score = self.score
        val1 = change_dice_result.count(1)
        val2 = change_dice_result.count(2)
        val3 = change_dice_result.count(3)
        val4 = change_dice_result.count(4)
        val5 = change_dice_result.count(5)
        val6 = change_dice_result.count(6)
        if (val1 == 3 or val2 == 3 or val3 == 3 or val4 == 3 or val5 == 3 or val6 == 3) and (val1 == 2 or val2 == 2 or val3 == 2 or val4 == 2 or val5 == 2 or val6 == 2):
            return 25
        else:
            return 0

    def Small_Straight(self,change_dice_result):
        score = self.score
        change_dice_result = list(set(change_dice_result))
        change_dice_result = sorted(change_dice_result)
        for i in range(1, 4):
            if (i in change_dice_result) and (i + 1 in change_dice_result) and (i + 2 in change_dice_result) and (i + 3 in change_dice_result):
                score = 30
                return score
            elif (i == 3) and (score != 30):
                score = 0
                return score


    def Large_Straight(self, change_dice_result):
        score = self.score
        change_dice_result = list(set(change_dice_result))
        change_dice_result = sorted(change_dice_result)
        for i in range(1,3):
            if (i in change_dice_result) and (i + 1 in change_dice_result) and (i + 2 in change_dice_result) and (i + 3 in change_dice_result) and (i + 4 in change_dice_result):
                score = 40
                return score
            elif (i == 2) and (score != 30):
                score = 0
                return score


    def Yacht(self, change_dice_result):
        score = self.score
        change_dice_result = list(set(change_dice_result))
        if len(change_dice_result) == 1:
            return 50
        else:
            return 0

class Check_Score:
    def __init__(self):
        self.score_list = []
        self.comment = ''
    def check(self, change_dice_result):
        cs = calc_score()
        print('\n'+'='*20)
        if cs.Four_Of_A_Kind(change_dice_result) != 0:
            print('Four_Of_A_Kind 가능!')
        else:
            pass

        if cs.Full_House(change_dice_result) != 0:
            print('Full_House 가능!')
        else:
            pass

        if cs.Small_Straight(change_dice_result) != 0:
            print('Small_Straight 가능!!!')
        else:
            pass

        if cs.Large_Straight(change_dice_result) != 0:
            print('Large_Straight 가능!!!!')
        else:
            pass

        if cs.Yacht(change_dice_result) != 0:
            print('★★★★ !야추 가능! ★★★★★')
        else:
            pass
        print('=' * 20 + '\n')

class Choice_Score:
    def __init__(self):
        self.select = ''
        self.score = 0
    def Choice_Score(self,change_dice_result,df,player_name,select_num):
        if select_num == '1':
            score = self.score
            score = calc_score().Aces(change_dice_result)
            df.loc['Aces',player_name] = score
            return df
        if select_num == '2':
            score = self.score
            score = calc_score().Twos(change_dice_result)
            df.loc['Twos',player_name] = score
            return df
        if select_num == '3':
            score = self.score
            score = calc_score().Threes(change_dice_result)
            df.loc['Threes',player_name] = score
            return df
        if select_num == '4':
            score = self.score
            score = calc_score().Fours(change_dice_result)
            df.loc['Fours',player_name] = score
            return df
        if select_num == '5':
            score = self.score
            score = calc_score().Fives(change_dice_result)
            df.loc['Fives',player_name] = score
            return df
        if select_num == '6':
            score = self.score
            score = calc_score().Sixes(change_dice_result)
            df.loc['Sixes',player_name] = score
            return df
        if select_num == '7':
            score = self.score
            score = calc_score().Choice(change_dice_result)
            df.loc['Choice',player_name] = score
            return df
        if select_num == '8':
            score = self.score
            score = calc_score().Four_Of_A_Kind(change_dice_result)
            df.loc['Four-Of-A-Kind',player_name] = score
            return df
        if select_num == '9':
            score = self.score
            score = calc_score().Full_House(change_dice_result)
            df.loc['Full House',player_name] = score
            return df
        if select_num == '10':
            score = self.score
            score = calc_score().Small_Straight(change_dice_result)
            df.loc['Small Straight',player_name] = score
            return df
        if select_num == '11':
            score = self.score
            score = calc_score().Large_Straight(change_dice_result)
            df.loc['Large Straight',player_name] = score
            return df
        if select_num == '12':
            score = self.score
            score = calc_score().Yacht(change_dice_result)
            df.loc['Yacht',player_name] = score
            return df
        else:
            print('유효한 값이 아닙니다')
            pass

class next_phase:
    def __init__(self):
        self.num = 0
    def Bonus(self, df,player_name):
        num = self.num
        num = df[player_name].iloc[:6].sum()
        if num >= 63:
            df.loc['Bonus', player_name] = 35
            return df
        else:
            pass
    def Total_Score(self,df,player_name):
        num = self.num
        num = df[player_name].iloc[:].sum()
        df.loc['TOTAL SCORE', player_name] = num
        return df

마지막으로, 이 모든 것을 종합하는 메인파일! (사실 main()은 쓰지 않았다.)

여기가 설명하기 젤 복잡하다. 대충 만들었기 때문에.... 

대충 설명하면, 점수판은 pandas를 통해 미리 만들어 놓고, 주사위를 던져서 바꿀지 말지 결정한다음, 최대 2번 바꿀수 있다. 결정된 주사위는 사용자가 정한 족보의 칸에 점수를 집어 넣고, 다음 턴으로 넘어가는 구조이다. 참 쉽죠?

from dice import *
from score import *
import pandas as pd
def wallmaker(num):
    if num == 1:
        wall = '\n' + '□' * 30 + '\n'
        print(wall)
    if num == 2:
        wall = '\n' + '=' * 30 + '\n'
        print(wall)
    if num == 3:
        wall = '\n' + '■' * 30 + '\n'
        print(wall)
    if num == 4:
        wall = '\n' + '=' * 15 + '\n'
        print(wall)
    if num == 5:
        wall = '\n' + '※' * 30 + '\n'
        print(wall)
while True:
    player_name = input('이름을 입력하세요 : ')
    enemy_name = ''
    player_list = []
    player_list.append(player_name)
    if enemy_name != '':
        player_list.append(enemy_name)
    else:
        pass
    df = pd.DataFrame(columns=player_list, index=['Aces','Twos','Threes','Fours','Fives','Sixes','Bonus','Choice','Four-Of-A-Kind','Full House','Small Straight','Large Straight','Yacht','TOTAL SCORE'])
    df = df.fillna(0)

    select_deck_list = ['1','2','3','4','5','6','7','8','9','10','11','12']

    for turn_num in range(1,13):
        for player_turn in player_list:
            print('☆'*20+ '\n' + str(turn_num) + ' / 12턴 \n')
            print(str(player_turn) + '의 차례입니다! \n' + '☆'*20)
            #여기부터 게임 시작 부분 ====================================================================
            dice_result = roll_dice().rolling_dice_first()
            wallmaker(4)
            print(result_of_dice(dice_result).show_result())
            wallmaker(4)
            Check_Score().check(dice_result)
            change_dice_result = dice_result

            for i in range(2): #주사위 3번 던지는 부분
                query1 = input("바꾸실래요? (Y/N) : ").lower()
                if query1 == 'y':
                    change_dice_result = roll_dice().change_dice(query1, dice_result)
                    wallmaker(4)
                    print(result_of_dice(change_dice_result).show_result())
                    wallmaker(4)
                    Check_Score().check(change_dice_result)
                else:
                    break

            print('1 = Aces \t 2 = Twos \t 3 = Threes \t 4 = Fours \n'
                  '5 = Fives \t 6 = Sixes \t 7 = Choice \t 8 = Four_Of_A_Kind \n'
                  '9 = Full_House \t 10 = Small_Straight \t 11 = Large_Straight \t 12 = Yacht')
            while True:
                select_num = input("값을 몇번 칸에 넣으실건가요? (1 ~ 12) : ")
                print('\n')
                if select_num in select_deck_list:
                    Choice_Score().Choice_Score(change_dice_result,df,player_name,select_num) #주사위 결과를 점수판에 대입하는 부분
                    select_deck_list.remove(select_num)
                    break
                else:
                    print('이 점수 칸에는 값이 들어가 있습니다. 다른 곳에 값을 넣어주세요.\n')
                    pass
            next_phase().Bonus(df,player_name) #보너스 확인
            next_phase().Total_Score(df,player_name) #총점 확인

            print(df.apply(pd.to_numeric))
            final_total_score = df.loc['TOTAL SCORE', player_name]
            df.loc['TOTAL SCORE', player_name] = 0
            print('\n\n'+'*'*40)
            print('다음 턴!')
            print('*' * 40 + '\n\n')

    print('\n 게임 끝! \n')
    print(str(player_name)+' 님의 야추 점수는 '+ str(final_total_score) + '점 입니다. 수고하셨습니다!')

    new = input('다시할까요? (Y/N): ').lower()
    if new == 'y':
        pass
    else:
        break

 

내 친구가 말했다. 나는 코드를 암호화 하지 않아도 될거라고. 해커도 보다가 키보드 반쪽으로 부숴 버릴거라고...

댓글