徒然なるままに生活しない為の備忘録

地方国公立大のM1。物理専攻。思いついたこととか、日々の日記とか。

XENO(カードゲーム)をPythonで作ってみる

PythonでXENO(カードゲーム)を作ってみた。

作ってみたとは言っても、あくまで仕組みを作っただけで、対戦などはできない。

XENO公式ルール

www.happybrainwash.com

コード

~
dict_card = {'10:英雄':10, '9:皇帝':9, '8:精霊':8, '7:賢者':7, '6:貴族':6, '5:死神':5, '4:乙女':4, '3:占い師':3, '2:兵士':2, '1:少年':1}
list_card = ['10:英雄', '9:皇帝', '8:精霊', '7:賢者', '6:貴族', '5:死神', '4:乙女', '3:占い師', '2:兵士', '1:少年']
reincarnation = [] # 転生札
p1_hands = [] # 1人目のプレイヤーの手札
p2_hands = [] # 2人目のプレイヤーの手札
cemetery = [] # 墓地

game_end = False # ゲームが決着するかのフラグ
turn = True # ターンプレイヤーの決定
maiden = False # 4:乙女 が使用されているかのフラグ
sage = False # 7:賢者 が使用されているかのフラグ

class Deck:
    def __init__(self):
        self.deck = ['10:英雄',
                    '9:皇帝',
                    '8:精霊',
                    '8:精霊',
                    '7:賢者',
                    '7:賢者',
                    '6:貴族',
                    '6:貴族',
                    '5:死神',
                    '5:死神',
                    '4:乙女',
                    '4:乙女',
                    '3:占い師',
                    '3:占い師',
                    '2:兵士',
                    '2:兵士',
                    '1:少年',
                    '1:少年']

    def Rein(self): # 転生札を引く操作
        reincarnation.append(self.deck[-1])
        self.deck.remove(self.deck[-1])

    def shuffle(self): # シャッフルを行う操作
        import random
        random.shuffle(self.deck)

    def draw(self, turn): # ドローを行う操作
        drawed = self.deck[0]
        if turn:
            p1_hands.append(drawed)
        else:
            p2_hands.append(drawed)
        self.deck.remove(drawed)
    
    def sage_draw(self, turn=turn): # 7:賢者 の効果によりドローを行う操作
        def draw(trun, d):
            if turn:
                hands = p1_hands
            else:
                hands = p2_hands
            hands.append(d)
            self.deck.remove(d)

        for i in range(3):
            try:
                pass
            except:
                pass
        d1 = self.deck[0]
        d2 = self.deck[1]
        d3 = self.deck[2]
        print('7:賢者 の 効果 が 適用 されています')
        print('以下から一枚を選んでください')
        print('1\t', d1)
        print('2\t', d2)
        print('3\t', d3)
        val = input()
        if val == '1':
            draw(turn, d1)
        if val == '2':
            draw(turn, d2)
        if val == '3':
            draw(turn, d3)

def Card(name, deck): # カードを使用して効果を適用し、手札から捨てるまでの操作

    def Hero(deck):
        pass

    def Emperor(deck):
        global game_end

        def emperor_turn(turn):
            global game_end
            if turn:
                hands = p1_hands
                player = 1
                opp_hands = p2_hands
                opp_player = 2
            else:
                hands = p2_hands
                player = 2
                opp_hands = p1_hands
                opp_player = 1

            if '10:英雄' in p2_hands:
                    print('プレイヤー', opp_player, 'が 10:英雄 を 持っていました\nプレイヤー1 の 勝ちです')
                    game_end = True
            else:
                print('プレイヤー', opp_player, 'が', opp_hands[0], 'を 捨てました')
                print('プレイヤー', opp_player, 'は 転生札 を 引きます')
                cemetery.append(opp_hands[0])
                opp_hands.clear()
                opp_hands.append(reincarnation[0])
                print('プレイヤー', opp_player, 'は', opp_hands[0], 'を 引きました')
                reincarnation.clear()

        if maiden:
            print('4:乙女 の 効果 に よって 無効 に なりました')
        else:
            emperor_turn(turn)

    def Spilit(deck):
        if maiden:
            print('4:乙女 の 効果 に よって 無効 に なりました')
        else:
            print('手札を交換します')
            exchanged1 = p1_hands[0]
            exchanged2 = p2_hands[0]
            p1_hands.clear()
            p2_hands.clear()
            p1_hands.append(exchanged2)
            p2_hands.append(exchanged1)
            print('プレイヤー 1 の 手札は\t', p1_hands)
            print('プレイヤー 2 の 手札は\t', p2_hands)

    def Sage(deck):
         global sage
         sage = True

    def Aristocrat(deck):
        global game_end
        if maiden:
            print('4:乙女 の 効果 に よって 無効 に なりました')
        else:
            print('プレイヤー 1 が', p1_hands[0], 'を 出しました')
            print('プレイヤー 2 が', p2_hands[0], 'を 出しました')
            if dict_card[p1_hands[0]] > dict_card[p2_hands[0]]:
                print('プレイヤー 1 の 勝ち です')
            if dict_card[p1_hands[0]] < dict_card[p2_hands[0]]:
                print('プレイヤー 2 の 勝ち です')
            if dict_card[p1_hands[0]] == dict_card[p2_hands[0]]:
                print('ゲーム は 引き分け です')
            game_end = True

    def Reaper(deck):
        if maiden:
            print('4:乙女 の 効果 に よって 無効 に なりました')
        else:
            if turn:
                discard = p2_hands[0]
                cemetery.append(discard)
                p2_hands.clear()
                print('プレイヤー 2 は', discard, 'を 捨てました')
                deck.draw(not(turn))
            else:
                discard = p1_hands[0]
                cemetery.append(discard)
                p1_hands.clear()
                print('プレイヤー 1 は', discard, 'を 捨てました')
                deck.draw(not(turn))

    def Maiden(deck):
        global maiden
        maiden = True
        pass

    def Soothsayer(deck):
        if maiden:
            print('4:乙女 の 効果 に よって 無効 に なりました')
        else:
            if turn:
                print('3:占い師 の 効果 に より プレイヤー 2 の 手札 が 公開 されます')
                print('プレイヤー 2 の 手札 は', p2_hands[0])
            else:
                print('3:占い師 の 効果 に より プレイヤー 1 の 手札 が 公開 されます')
                print('プレイヤー 1 の 手札 は', p1_hands[0])

    def Soldier(deck):
        global game_end
        list_card2 = list_card[::-1]
        if maiden:
            print('4:乙女 の 効果 に よって 無効 に なりました')
        else:
            print('相手プレイヤー の 手札 を 1~10 の 番号 で 言い当ててください')
            while True:
                val = input()
                try:
                    val = int(val)
                    if 0 < val < 11:
                        if turn:
                            if int(val) == list_card2.index(p2_hands[0]) + 1:
                                print('プレイヤー1 は プレイヤー2 の 手札 を 言い当てました!')
                                print('プレイヤー1 の 勝利 です')
                                game_end = True
                            else:
                                print('プレイヤー1 は プレイヤー2 の 手札 を 言い当てられませんでした…')
                        else:
                            if int(val) == list_card2.index(p1_hands[0]) + 1:
                                print('プレイヤー2 は プレイヤー1 の 手札 を 言い当てました!')
                                print('プレイヤー2 の 勝利 です')
                                game_end = True
                            else:
                                print('プレイヤー2 は プレイヤー1 の 手札 を 言い当てられませんでした…')
                        break
                    else:
                        print('1~10の整数値を入力してください')
                except:
                    print('1~10の整数値を入力してください')

    def Boy(deck):
        if maiden:
            print('4:乙女 の 効果 に よって 無効 に なりました')
        else:
            if '1:少年' in cemetery:
                if turn:
                    if '10:英雄' in p2_hands:
                        print('プレイヤー2 が 10:英雄 を 持っていました\nプレイヤー1 の 勝ちです')
                        game_end = True
                    else:
                        print('プレイヤー2 が', p2_hands[0], 'を 捨てました')
                        print('プレイヤー2 は 転生札 を 引きます')
                        cemetery.append(p2_hands[0])
                        p2_hands.clear()
                        p2_hands.append(reincarnation[0])
                        print('プレイヤー2 は', p2_hands[0], 'を 引きました')
                        reincarnation.clear()
                else:
                    if 'Hero' in p1_hands:
                        print('プレイヤー1 が 10:英雄 を 持っていました\nプレイヤー2 の 勝ちです')
                        game_end = True
                    else:
                        print('プレイヤー1 が', p2_hands[0], 'を 捨てました')
                        print('プレイヤー1 は 転生札 を 引きます')
                        cemetery.append(p1_hands[0])
                        p1_hands.clear()
                        p1_hands.append(reincarnation[0])
                        print('プレイヤー2 は', p2_hands[0], 'を 引きました')
                        reincarnation.clear()
            else:
                print('あなたは1枚目の1:少年を使用したため、効果は発動しません')

    effect_list = [Hero, Emperor, Spilit, Sage, Aristocrat, Reaper, Maiden, Soothsayer, Soldier, Boy]

    # カードを場に出す
    if turn:
        p1_hands.remove(name)
    else:
        p2_hands.remove(name)

    # 効果を適用する
    effect_list[list_card.index(name)](deck)

    # カードを墓地に送る
    cemetery.append(name)

def main():
    global turn
    global game_end
    global maiden
    global sage
    maiden_count = 0 # 4:乙女の効果がターンをまたぐのでその処理用

    def turn_progress(turn):
        global sage
        sage_count = 0 # 7:賢者の効果がターンをまたぐのでその処理用
        if turn:
            hands = p1_hands
            player = 1
        else:
            hands = p2_hands
            player = 2

        print('プレイヤー',  player, 'の ターン です')
        if sage:
            if sage_count == 1:
                deck.sage_draw(turn)
                sage_count = 0
                sage = False
            elif sage_count == 0:
                sage_count += 1
                deck.draw(turn)
        else:
            deck.draw(turn)
        print('プレイヤー', player, 'の 手札 は')
        print(1, '\t', hands[0])
        print(2, '\t', hands[1])
        print('番号を選択して、どちらを使用するかを選択してください')
        print('墓地 を 確認 するには cemetary を 入力 してください')
        while True:
            val = input()
            if val == '0':
                print(cemetery)
            elif val == '1':
                if hands[0] == '10:英雄':
                    print('10:英雄 は 場 に 出すことが できません')
                else:
                    Card(hands[0], deck)
                    break
            elif val == '2':
                if hands[1] == '10:英雄':
                    print('10:英雄 は 場 に 出すことが できません')
                else:
                    Card(hands[1], deck)
                    break
            elif val == 'DEBUG':
                print('='*20)
                print('DEBUG MODE')
                print(deck.deck)
                print(p1_hands)
                print(p2_hands)
                print(cemetery)
                print('='*20)
            else:
                print('正しい値を入力してください')

    print("GAME START")
    deck = Deck()
    deck.shuffle()
    deck.Rein()
    print("転生札が設定されました")
    # print("DEBUG 転生札は", reincarnation[0])
    print("山札からカードを引きます")
    deck.draw(True)
    deck.draw(False)
    print("プレイヤー1 の 手札 は",p1_hands)
    print("プレイヤー2 の 手札 は",p2_hands)

    count = 0

    while True: # ターン進行
        print('-'*20)
        count += 1
        print('TURN', count)
        print('山札の残り枚数:', len(deck.deck))

        if not(deck.deck): # デッキ切れの場合の処理
            game_end = True
            print("デッキ枚数 が 残り 0枚 に なりました")
            print('プレイヤー の 手札 に よる 勝負 を 行います')
            print('プレイヤー 1 が', p1_hands[0], 'を 出しました')
            print('プレイヤー 2 が', p2_hands[0], 'を 出しました')
            if dict_card[p1_hands[0]] > dict_card[p2_hands[0]]:
                print('プレイヤー 1 の 勝ち です')
            if dict_card[p1_hands[0]] < dict_card[p2_hands[0]]:
                print('プレイヤー 2 の 勝ち です')
            if dict_card[p1_hands[0]] == dict_card[p2_hands[0]]:
                print('ゲーム は 引き分け です')
            game_end = True

        turn_progress(turn)

        if maiden: # 4:乙女の効果の処理
            if maiden_count == 1:
                print('4:乙女 の 効果 が 切れました')
                maiden = False
                maiden_count = 0
            else:
                maiden_count += 1


        if game_end: # ゲーム終了判定
            break

        turn = not(turn) # ターンの交代

if __name__ == "__main__":
    main()
~

問題点

ゲーム内容での問題点

  • そもそも対戦ゲームの体をなしていない
  • 2人対戦にしか対応していない
  • 乙女や賢者が連続で使用されたときの処理ができない
  • 騎士のナーフに対応していない

az-master.jp

コーディングでの問題点

  • ターンでの場合分けを多用しているのがまったくもってスマートじゃない
  • そもそもクラスの勉強をしたくてコードを書いたのだが、カードの効果は関数で書いてしまった上に、グローバル変数を多用しているのがあまり気に入らない
  • その他、行数を節約できる箇所が(多分絶対)多々ある

なにかアドバイスを頂けると幸いです