Pythonでソリティアのクロンダイク開発Part4

パイソンでソリティアのクロンダイク開発パートよんのサムネイル

こんにちは、にわこまです。

今回は、クロンダイクの実行部分(main文)を作成します。初期状態の設定やグローバル変数の設定、ループ処理を作成します。

本記事で、クロンダイクの完成まで紹介します。

 

誤字脱字など何かございましたら、ご連絡お願い致します。TwitterのDMでも承ります。

 

 

スポンサードサーチ


ソリティアのクロンダイク開発Part4

今回は、クロンダイクの実行部分(main文:以下main文)を作成します。main文は長いため、変数や初期状態を設定する部分とループ処理の部分で説明を分けます。

 

本記事で、クロンダイクを完成させます。この記事を読み終わるころには、みなさんのパソコンでクロンダイクをプレイできるようになります。

 

みなさんに、クロンダイクを完成させてもらいたいため、分からにくい点がございましたら、メールかTwitterのDMで連絡をお願いいたします。

 

 

main文 Part1

クロンダイクの初期状態の設定とmain文で使用する変数の設定を作成します。 クロンダイクの初期設定は、Part3で表示関係の関数の動作確認を行ったときのプログラムと一緒です。

 

main文のソースコードです。以下のコードをklondike.pyの1番下の行に追記します。

# main文
def main():
    # 山札
    myDeck = Deck()
    myDeck.shuffleCards()

    # 組札
    DDeck = MarkDeck("Diamond")
    HDeck = MarkDeck("Heart")
    SDeck = MarkDeck("Spade")
    CDeck = MarkDeck("Club")
    markDeckDict = {"Spade":SDeck, "Heart":HDeck, "Club":CDeck, "Diamond":DDeck}

    # 場札の列
    fieldDecks = []
    for _ in range(7):
        fieldDecks.append(ColumnDeck())

    # 初期カード設定
    for i in range(7):
        colDeck = fieldDecks[i]
        for _ in range(i+1):
            colDeck.setInitCard(myDeck.getInitCard())

    # 1番手前のカードを表向きに
    for deck in fieldDecks:
        deck.colDeck[-1].fab = True

    # グローバル変数
    global rowNumList
    global colNumList
    rowNumList = ["1", "2", "3", "4", "5", "6", "7", "8", "9",
                  "10", "11", "12", "13", "14", "15", "16", "17", "18", "19"]
    colNumList = ["1", "2", "3", "4", "5", "6", "7"]
    markList = ["Spade", "Heart", "Club", "Diamond"]

    # 初期状態表示
    printDeck(myDeck, markDeckDict)
    printColDeck(fieldDecks)
    printCmd()

if __name__ == '__main__':
    main()

 

コードの解説

4、5行目は、山札の設定を行っています。

4行目は、山札のオブジェクトを作成しています。5行目は、山札をシャッフルしています。

 

8行目~12行目は、組札の設定を行っています。

8、9、10、11行目は、各組札のオブジェクトを作成しています。12行目は、組札の表示や勝利条件の判定に使う、辞書を作成しています。

 

15行目~17行目は、場札の列を作成しています。

 

20行目~23行目は、各場札の列にカードを追加しています。(例:1列目は1枚、2列目は2枚、、、7列目は7枚)

 

26、27行目は、場札の列の1番手前のカードを表の状態にしています。

 

30行目~35行目は、コマンドが正しく入力されているかを調べるための文字列を設定しています。「rowNumList」と「colNumList」は、関数confRowColで使用するためグローバル変数にしています。

 

38行目~40行目は、初期状態を表示するための関数を実行しています。

 

42、43行目は、main文を実行するためのものです。

 

 

スポンサードサーチ


スポンサードサーチ


動作確認

変数と初期状態を設定したため確認を行います。コマンドプロンプトを開き、klondike.pyが保存されているフォルダまで移動します。移動したら以下のコマンドを実行します。

python klondike.py

 

実行したら以下のように表示されます。

クロンダイクの初期状態を表示した画像

 

以上で動作確認は完了です。

 

 

main文 Part2

コマンドの判定やカードの取得、追加を行うループ処理を作成します。

コマンドの条件分岐は、6つあります。

1.山札を見る。(Turn)
2.山札のカードを指定する。(Deck)
3.列のカードを指定する。(行,列)
4.組札のカードを指定する。(Spade,Heart,Club,Diamond)
5.ゲームを終了する(End)
6.1、2、3、4、5以外

この6つの条件分岐のソースコードを示した後、ひとつ1つの条件分岐について説明します。

 

main文のソースコードです。以下のコードをklondike.pyに追記します。

# main文
def main():
    # 山札
    myDeck = Deck()
    ・
  ・
  省略
  ・
  ・
    printCmd()

   # ==== ここから 追加 ====
  # ループ処理
    play_count = 0
    while(True):
        cmd = input("コマンド : ")
        if( (cmd == "Turn") or (cmd == "turn") ):
            pass
        elif( cmd in ["Deck", "deck"] ):
            pass
        elif( confRowCol(cmd) ):
            pass
        elif( cmd in markList ):
            pass
        elif(cmd == "End" or cmd == "end"):
            pass
        else:
           pass

        printDeck(myDeck, markDeckDict)
        printColDeck(fieldDecks)
        play_count += 1
        if(CheckEnd(markDeckDict)):
            print("お疲れさまでした!")
            print("play_count : ", play_count)
            break
        printCmd()
    # ==== ここまで 追加 ====

if __name__ == '__main__':
    main()

 

コードの解説

16行目の「cmd = input(“コマンド : “)」は、入力されたコマンドを変数cmdに代入します。

17、19、21、23、25、27行目は、先述した6つの条件分岐です。あとでソースコードと一緒に説明します。文字列を入力する条件分岐においては、小文字でもTrueの判定にしています。

 

30、31行目は、山札と組札、場札の列を表示しています。

 

33行目~36行目は、勝利条件の判定を行っています。また、ループ処理から抜け出すため「break」を実行しています。

 

37行目は、コマンドを表示しています。

 

 

条件分岐:1.山札を見る。(Turn)

条件分岐「山札を見る。(True)」のソースコードです。klondike.pyに追記します。

# main文
def main():
  ・
  ・
  省略
  ・
  ・
   play_count = 0
    while(True):
        cmd = input("コマンド : ")
        if( (cmd == "Turn") or (cmd == "turn") ):
            print("Turn up a card.")
            myDeck.turnCard()
  ・
  ・
  以下省略

13行目の「myDeck.turnCard()」によって、山札のself.topCardを更新しています。

 

 

条件分岐:2.山札のカードを指定する。(Deck)

条件分岐「山札のカードを指定する。(Deck)」のソースコードです。klondike.pyに追記します。

# main文
def main():
    ・
  ・
  省略
  ・
  ・
    # ループ処理
    play_count = 0
    while(True):
        cmd = input("コマンド : ")
        if( (cmd == "Turn") or (cmd == "turn") ):
            省略
        elif( cmd in ["Deck", "deck"] ):
       # ==== ここから 追加 ====
            card = myDeck.getTempFrontCard()
            printCards(card)
            if(type(card) == Card):
                print("Please select destination. ex) Column, Spade, etc...")
                dest = input("Destination : ")
                if(dest in colNumList):
                    if(fieldDecks[int(dest)-1].confSetCard(card)):
                        card = myDeck.getFrontCard()
                        fieldDecks[int(dest)-1].setCard(card)
                    else:
                        print("")
                        continue
                elif(dest in markList):
                    if(markDeckDict[dest].confSetCard(card)):
                        card = myDeck.getFrontCard()
                        markDeckDict[dest].setCard(card)
                    else:
                        print("")
                        continue
                else:
                    print("その移動先は選択できません。")
                    print("Destination : ", dest)
                    continue
            else:
                print("The deck has no opend card. Do Turn.")
                print("")
                continue
       # ==== ここまで 追加 ====
  ・
  ・
  以下省略

16行目の「card = myDeck.getTempFrontCard()」は、一時的にカードを取得して変数cardに代入しています。

17行目の「printCards(card)」は、選択したカードを表示しています。

18、39行目は、一時的に取得したカードがの型によって条件分岐しています。

19、20行目は、選択したカードの移動先を入力してもらうためのものです。

21、28、35行目は、「場札の列」、「組札」、「前の2つ以外」で条件分岐しています。

「場札の列」を移動先に選択した場合(21行目)と「組札」を移動先に選択した場合(28行目)は、カードを追加できるかを判定し、カードを追加します。

 

 

条件分岐:3.列のカードを指定する。(行,列)

条件分岐「列のカードを指定する。(行,列)」のソースコードです。「import re」をpythonファイルの1番上の行に追記します。klondike.pyに追記します。

# main文
def main():
  ・
  ・
  省略
  ・
  ・

    # ループ処理
    play_count = 0
    while(True):
        cmd = input("コマンド : ")
        if( (cmd == "Turn") or (cmd == "turn") ):
            省略
        elif( cmd in ["Deck", "deck"] ):
            省略
        elif( confRowCol(cmd) ):
            # ==== ここから 追加 ====
            cmdlist = cmd.split(",")
            row = int(re.sub("\\D", "", cmdlist[0]))
            col = int(re.sub("\\D", "", cmdlist[1]))
            if(str(row) in rowNumList and str(col) in colNumList):
                cards = fieldDecks[col-1].getTempCards(row-1)
                if(cards != None):
                    printCards(cards)
                    print("Please select destination. ex) Column, Spade, etc...")
                    dest = input("Destination : ")
                    if(dest in colNumList):
                        if(fieldDecks[int(dest)-1].confSetCards(cards)):
                            cards = fieldDecks[col-1].getCards(row-1)
                            fieldDecks[int(dest)-1].setCards(cards)
                    elif(dest in markList):
                        print(dest , " : ", markList)
                        if(markDeckDict[dest].confSetCard(cards[0])):
                            cards = fieldDecks[col-1].getCards(row-1)
                            markDeckDict[dest].setCard(cards[0])
                    else:
                        print("その移動先は選択できません。")
                        print("")
                        continue
                else:
                    print("{0}, {1}にカードがありません。".format(row, col))
                    print("")
                    continue
            else:
                print("カードの選択の仕方が間違っています。正例:2, 3")
            # ==== ここまで 追加 ====
  ・
  ・
  以下省略

19、20、21行目は、「行,列」という形で入力されたコマンドを行と列に分けてint型に変換しています。

22行目は、入力された行と列が範囲内の数字か判定しています。

23行目は、一時的に取得したカードを変数cardsに代入しています。

24、41行目は、入力された行と列にカードがあるかないかを判定しています。

25行目の「printCards(cards)」は、選択したカードを表示しています。

27行目は、移動先を指定してもらうためのものです。

28、32、37行目は、「場札の列」、「組札」、「前の2つ以外」で条件分岐しています。

「場札の列」を移動先に選択した場合(28行目)と「組札」を移動先に選択した場合(32行目)は、カードを追加できるかを判定し、カードを追加します。

 

 

条件分岐:4.組札のカードを指定する。(Spade,Heart,Club,Diamond)

条件分岐「組札のカードを指定する。」のソースコードです。klondike.pyに追記します。

# main文
def main():
  ・
  ・
  省略
  ・
  ・

    # ループ処理
    play_count = 0
    while(True):
        cmd = input("コマンド : ")
        if( (cmd == "Turn") or (cmd == "turn") ):
            省略
        elif( cmd in ["Deck", "deck"] ):
            省略
        elif( confRowCol(cmd) ):
            省略
    elif( cmd in markList ):
            # ==== ここから 追加 ====
            card = markDeckDict[cmd].getTempCard()
            if(card != None):
                printCards(card)
                print("Please select destination.", end="")
                print("ex) Column(1~7)")
                dest = input("Destination : ")
                if(dest in colNumList):
                    if(fieldDecks[int(dest)-1].confSetCard(card)):
                        card = markDeckDict[cmd].getCard()
                        fieldDecks[int(dest)-1].setCards(card)
                    else:
                        print("")
                        continue
                else:
                    print("その移動先は選択できません。")
                    print("Destination : ", dest)
                    continue
            else:
                print("{0}にカードがありません。".format(cmd))
                print("")
                continue
            # ==== ここまで 追加 ====
  ・
  ・
  以下省略

21行目の「card = markDeckDict[cmd].getTempCard()」は、一時的に取得したカードを変数cardに代入しています。

22、38行目は、変数cardにカードがあるかないかを判定しています。

23行目の「printCards(card)」は、選択したカードを表示しています。

26行目は、移動先を指定してもらうためのものです。

27、34行目は、「場札の列」と「場札の列以外」で条件分岐しています。

「場札の列」を移動先に指定した場合は、カードを追加できるかを判定し、カードを追加します。

 

 

条件分岐:5.ゲームを終了する(End)

条件分岐「ゲームを終了する(End)」のソースコードです。klondike.pyに追記します。この条件分岐は、クリア不可能であるとプレイヤーが判断した場合に使われます。

# main文
def main():
  ・
  ・
  省略
  ・
  ・

    # ループ処理
    play_count = 0
    while(True):
        cmd = input("コマンド : ")
        if( (cmd == "Turn") or (cmd == "turn") ):
            省略
        elif( cmd in ["Deck", "deck"] ):
            省略
        elif( confRowCol(cmd) ):
            省略
    elif( cmd in markList ):
            省略
    elif(cmd == "End" or cmd == "end"):
            print("終了します。")
            break
  ・
  ・
  以下省略

23行目の「break」は、ループから抜け出すためのものです。

 

 

条件分岐:6.1、2、3、4、5以外

条件分岐「1~5以外」のソースコードです。klondike.pyに追記します。

# main文
def main():
  ・
  ・
  省略
  ・
  ・

    # ループ処理
    play_count = 0
    while(True):
        cmd = input("コマンド : ")
        if( (cmd == "Turn") or (cmd == "turn") ):
            省略
        elif( cmd in ["Deck", "deck"] ):
            省略
        elif( confRowCol(cmd) ):
            省略
    elif( cmd in markList ):
            省略
    elif(cmd == "End" or cmd == "end"):
            省略
    else:
            print("That command is wrong.")
            print("")
            continue
  ・
  ・
  以下省略

26行目の「continue」は、ループ処理の始めに戻るためのものです。つまり、コマンドの選択に戻ります。

条件分岐「1~5以外」は、コマンドの入力ミスとして判定しています。

 

 

スポンサードサーチ


スポンサードサーチ


動作確認

6つの条件分岐が正しく分岐されるか確認するため、動作確認を行います。細かい条件分岐については、動作確認を行いません。

コマンドプロンプトを開き、klondike.pyが保存されているフォルダまで移動します。以下のコマンドを実行します。

python klondike.py

 

以下のように表示されます。

クロンダイクを実行したあとに、1番最初に表示される盤面をキャプチャした画像

 

1つ目の条件分岐「山札を見る。(Turn)」の動作確認を行います。「Turn」を入力し、エンターを押します。「Deck」の部分にカードが表示されています。

コマンド「Turn」を実行して、山札が更新された画像

 

2つ目の条件分岐「山札のカードを指定する。(Deck)」の動作確認を行います。Deck」を入力し、エンターを押します。

山札のカードを移動させられなければ、「Turn」を何回か実行します。

何回かコマンド「Turn」を実行して、山札のカードを場札の列に移動させた画像

 

3つ目の条件分岐「列のカードを指定する。(行,列)」の動作確認を行います。適当な「行,列」を指定し、カードを移動させます。

場札の列をカードを組札に移動させた画像

 

4つ目の条件分岐「組札のカードを指定する。」の動作確認を行います。適当なマーク(Spade,Heart,Club,Diamond)を指定して、カードを移動させます。

場合によっては、確認が難しと思うため、ゲームを実際にプレイするときに確認してください。

 

5つ目の条件分岐を行う前に、6つ目の条件分岐の動作確認を行います。わざとコマンドを間違えて「That commnd is wrong.」という文字列が表示されることを確認します。

 

最後に条件分岐「ゲームを終了する。(End)」の動作確認を行います。「End」を入力し、エンターを押します。「終了します」という文字列と共にプログラムの実行が終了することを確認します。

 

以上で動作確認は完了です。

 

 

まとめ

今回は、「Pythonでソリティアのクロンダイク開発」の最終パートでした。 クロンダイクの完成までを本記事で紹介しました。

 

条件分を理解することや動作確認がめんどうくさかったと思いますが、クロンダイクを完成させることができました。

 

分かりにくい点やエラーが発生して前に進めない方はTwitterのDMまたはお問い合わせのページからメールをお願いいたします。

下記から、klondike.pyをダウンロードできます

 

 

最後までお読みいただきありがとうございます。


スポンサードサーチ