Pythonでソリティアのクロンダイク開発Part3
こんにちは、にわこまです。
今回は、コマンドプロンプトに表示するための関数を紹介します。今までは「作成」だけでしたが、表示関係の関数であるため動きをみることができます。完成形をイメージすることができるのではないでしょうか。
誤字脱字など何かございましたら、ご連絡お願い致します。 TwitterのDMでも承ります。
スポンサードサーチ
ソリティアのクロンダイク開発Part3
今回は、コマンドプロンプトに表示する関数を作成します。具体的には、山札、組札、場札の列、コマンドです。
完成形を以下に示します。
また、上記の関数以外にいくつか作成します。具体的には、選択されたカードを表示する関数、座標の判定を行う関数、勝利判定を行う関数です。
山札と組札を表示する関数の作成
山札と組札を表示する関数(printDeck)を作成します。この関数は大きく分けて、山札や組札の名前を表示する部分と、実際のデータを表示する部分に分けられます。
関数printDeckのソースコードです。klondike.pyの1番下の行に追記します。
# DeckとMarkDeckの表示設定
def printDeck(deck, markDecks):
# kinds of decks
print("")
print(" +------+ +------+------+------+------+")
print(" | Deck | | S | H | C | D |")
print(" +------+ +------+------+------+------+")
print(" | ", end="")
man = " "*4
if(type(deck.frontCard) == Card):
man = deck.frontCard.getMAN()
print("{0} | ".format(man), end="")
#print("| ---- | | ---- | ---- | ---- | ---- |")
print("| ", end="")
for markDeck in markDecks.values():
man = " "*4
card = markDeck.topCard
if(type(card) == Card):
man = card.getMAN()
print("{0} | ".format(man), end="")
print("")
#print("| ---- | | ---- | ---- | ---- | ---- |")
print(" +------+ +------+------+------+------+")
print("")
コードの解説
引数は、山札(Deck)と組札の辞書(markDecks)です。辞書は、スペード、ハート、クラブ、ダイヤの順番で固定します。
5、6、7行目が、山札と組札の名前を表示する処理を行っています。
8行目~24行目が、実際のデータを表示する処理を行っています。表示をきれいにするための空白などの説明は省きます。
10、11、12行目で、山札の実際のデータを表示する処理を行っています。
山札(Deckクラス)の引いたカード(self.frontCard)があるかないかの確認を行い、ある場合はマークと数字を指定の形式で変数に代入します。ない場合は、半角の空白を4つ代入します。
15行目~20行目で、組札の実際のデータを表示する処理を行っています。
組札(MarkDeckクラス)の1番上のカード(self.topCard)があるかないかの確認を行い、ある場合はマークと数字を指定の形式で変数に代入します。ない場合は、半角の空白を4つ代入します。
動作確認
正しく表示されるか確認するため、動作確認を行います。コマンドプロンプトを開き、「python」と入力し、エンターを押してください。「>>>」が出力されれば、起動しています。
C:\Users\Name\python3\blog_python\solitaire>python
Python 3.7.0b3 (v3.7.0b3:4e7efa9c6f, Mar 29 2018, 18:42:04) [MSC v.1913 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>
次に、klondikeから必要なクラスと関数をインポートします。
>>> from klondike import Card, Deck, MarkDeck
>>> from klondike import printDeck
>>>
さらに、山札と組札のオブジェクトを作成します。markDeckDictは、必ず以下の順番で代入します。
>>> mydeck = Deck()
>>> SDeck = MarkDeck("Spade")
>>> HDeck = MarkDeck("Heart")
>>> CDeck = MarkDeck("Club")
>>> DDeck = MarkDeck("Diamond")
>>> markDeckDict = {"Spade":SDeck, "Heart":HDeck, "Club":CDeck, "Diamond":DDeck}
>>>
実際に表示させてみます。以下のように表示されます。
>>> printDeck(mydeck, markDeckDict)
+------+ +------+------+------+------+
| Deck | | S | H | C | D |
+------+ +------+------+------+------+
| | | | | | |
+------+ +------+------+------+------+
>>>
DeckクラスのturnCardや、数字が1のカードオブジェクトを作成して動作を確認してみます。
>>> mydeck.turnCard()
>>> printDeck(mydeck, markDeckDict)
+------+ +------+------+------+------+
| Deck | | S | H | C | D |
+------+ +------+------+------+------+
| S_13 | | | | | |
+------+ +------+------+------+------+
>>>
>>> s_01 = Card("Spade", 1)
>>> SDeck.setCard(s_01)
>>> printDeck(mydeck, markDeckDict)
+------+ +------+------+------+------+
| Deck | | S | H | C | D |
+------+ +------+------+------+------+
| S_13 | | S__1 | | | |
+------+ +------+------+------+------+
>>>
以上で動作確認は完了です。
スポンサードサーチ
場札の列を表示する関数の作成
場札の列を表示する関数(printHeader、printColDeck)を作成します。この関数は、大きく分けて「Col1」、「Col2」など、何列目かを示す名前と実際の場札の列のカードを表示する部分に分けられます。
関数printHeaderと関数printColDeckのソースコードです。以下コードをklondike.pyの1番下の行に追記します。
# カラム見出しの表示設定
def printHeader():
# header
colList = ["Col1", "Col2", "Col3", "Col4", "Col5", "Col6", "Col7"]
print(" +------+------+------+------+------+------+------+")
print(" | ", end="")
for col in colList:
print(col, "| ", end="")
print("")
print(" ==================================================")
# 出力(場札)
def printColDeck(decklist):
printHeader()
# data
leng = 0
for obj in decklist:
if(leng < len(obj.colDeck)):
leng = len(obj.colDeck)
#print(leng)
# 1 2 3 4 5 6 7 8 9 10
llist = [[], [], [], [], [], [], [], [], [], [],
[], [], [], [], [], [], [], [], []]
for obj in decklist:
objleng = len(obj.colDeck)
for i in range(objleng):
card = obj.colDeck[i]
if(card.fab):
s = card.mark[0] + "_" + str(card.number)
if(card.number <= 9):
s = card.mark[0] + "_" + "_" + str(card.number)
llist[i].append(s)
else:
llist[i].append("Back")
for i in range(objleng, leng):
llist[i].append(' ')
for i in range(leng):
print(" | ", end="")
for card in llist[i]:
print(card, "| ", end="")
if(i <= 9):
print(" {0} ".format(i+1))
else:
print(" {0} ".format(i+1))
print(" +------+------+------+------+------+------+------+")
print("")
コードの解説
2行目~10行目の「printHeader()」は、何行目かを示す名前を表示するための関数です。
4行目の「colList」は、7列分の名前が代入されているリストです。
7、8行目で実際に名前を表示しています。
13行目~47行目の「printColDeck()」は、実際の場札の列のカードを表示するための関数です。
引数の「decklist」は、1列目から7列目の順で代入します。
14行目の「printHeader()」は、先ほど定義した関数です。カードを表示する前に表示したいため、ここで使用します。
16行目~19行目の「leng」は、最大の行数を確認するための変数です。この変数は、余分な行を表示させないために使います。
22、23行目の「llist」は、リストの中のリストが1行を表しています。最大で19行分のリストが代入されています。
24行目~36行目はllistの中のリストに、表示する文字列を追加しています。
・カードがあり、表の状態である場合はマークと数字を指定の形式で追加します。
・カードがあり、裏の状態である場合は「Back」という文字列を追加します。
・カードがない場合は、半角空白4つを追加します。
38行目~47行目は、実際にカードとカード指定用の数字を表示しています。
動作確認
正しく表示されるか確認するため、動作確認を行います。コマンドプロンプトを開き、「python」と入力し、エンターを押してください。「>>>」が出力されれば、起動しています。
C:\Users\Name\python3\blog_python\solitaire>python
Python 3.7.0b3 (v3.7.0b3:4e7efa9c6f, Mar 29 2018, 18:42:04) [MSC v.1913 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>
次に、klondikeから必要なクラスと関数をインポートします。
>>> from klondike import Card, Deck, ColumnDeck
>>> from klondike import printHeader, printColDeck
>>>
さらに、山札と場札の列のオブジェクトを作成します。
>>> mydeck = Deck()
>>> col1 = ColumnDeck()
>>> col2 = ColumnDeck()
>>> col3 = ColumnDeck()
>>> col4 = ColumnDeck()
>>> col5 = ColumnDeck()
>>> col6 = ColumnDeck()
>>> col7 = ColumnDeck()
>>> decklist = [col1, col2, col3, col4, col5, col6, col7]
>>>
実際に表示させてみます。ColumnDeckにカードをセットしていないため、以下のように表示されます。
>>> printColDeck(decklist)
+------+------+------+------+------+------+------+
| Col1 | Col2 | Col3 | Col4 | Col5 | Col6 | Col7 |
==================================================
>>>
初期状態のようにカードをセットして、表示させます。
>>> mydeck.shuffleCards()
>>> for i in range(7):
... coldeck = decklist[i]
... for _ in range(i+1):
... coldeck.setInitCard(mydeck.getInitCard())
...
>>> for coldeck in decklist:
... coldeck.colDeck[-1].fab = True
...
>>> printColDeck(decklist)
+------+------+------+------+------+------+------+
| Col1 | Col2 | Col3 | Col4 | Col5 | Col6 | Col7 |
==================================================
| S__6 | Back | Back | Back | Back | Back | Back | 1
+------+------+------+------+------+------+------+
| | S__7 | Back | Back | Back | Back | Back | 2
+------+------+------+------+------+------+------+
| | | C__2 | Back | Back | Back | Back | 3
+------+------+------+------+------+------+------+
| | | | H_13 | Back | Back | Back | 4
+------+------+------+------+------+------+------+
| | | | | C_13 | Back | Back | 5
+------+------+------+------+------+------+------+
| | | | | | D__9 | Back | 6
+------+------+------+------+------+------+------+
| | | | | | | S__3 | 7
+------+------+------+------+------+------+------+
>>>
以上で動作確認は完了です。
コマンドを表示する関数の作成
コマンドを表示する関数(printCmd)を作成します。文字列の長さ同一にして表示します。
関数printCmdのソースコードです。以下のコードをklondike.pyの1番下の行に代入します。
# コマンド表示設定
def printCmd():
cmddict = {
"山札を見る":"Turn",
"山札のカードを指定する":"Deck",
"列のカードを指定する":"Row, Column",
"組札のカードを指定する":"Spade or Heart or Club or Diamond",
}
print(" +" + "-"*24 + "+" + "-"*35 + "+")
header = ["行動", "コマンド"]
print(" | " + header[0].center(11, " ") + " | " + header[1].center(29, " ") + " |")
print(" " + "="*62)
for k, v in cmddict.items():
print(" | " + k.ljust(11, ' ') + " | " + v.ljust(33, " ") + " |")
print(" +" + "-"*24 + "+" + "-"*35 + "+")
コードの解説
3行目~8行目の「cmdict」は、コマンドの辞書です。行動内容をkey、コマンドををvalue としています。
・カードを引く場合は、「Turn」と入力します。
・山札のカードを移動するカードとして指定する場合は、「Deck」と入力します。
・場札の列のカードを指定する場合は、「行, 列」という形で入力します。
・組札のカードを指定する場合は、「Spade」、「Heart」、「Club」、「Diamond」の中から指定のマークを入力します。
10、11行目は、行動とコマンドというカラム名を表示しています。
13行目~15行目は、cmddictの行動内容とコマンドを表示しています。
所々ある数字は、微調整の結果です。気にしないでください。
動作確認
コマンドが正しく表示されるか確認するため、動作確認を行います。コマンドプロンプトを開き、「python」と入力し、エンターを押してください。「>>>」が出力されれば、起動しています。
C:\Users\Name\python3\blog_python\solitaire>python
Python 3.7.0b3 (v3.7.0b3:4e7efa9c6f, Mar 29 2018, 18:42:04) [MSC v.1913 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>
次に、klondikeから必要な関数をインポートします。
>>> from klondike import printCmd
>>>
実際に表示させてみます。以下のように表示されます。
>>> printCmd()
+------------------------+-----------------------------------+
| 行動 | コマンド |
==============================================================
| 山札を見る | Turn |
+------------------------+-----------------------------------+
| 山札のカードを指定する | Deck |
+------------------------+-----------------------------------+
| 列のカードを指定する | Row, Column |
+------------------------+-----------------------------------+
| 組札のカードを指定する | Spade or Heart or Club or Diamond |
+------------------------+-----------------------------------+
>>>
以上で動作確認は完了です。
スポンサードサーチ
その他の関数の作成
その他の関数(printCards、confRowCol、CheckEnd)を作成します。
「printCards」は、選択したカードの一覧を表示するための関数です。
「confRowCol」は、場札の列のカードを数字で指定したときに、エラーが起こらないように確認するための関数です。
「CheckEnd」は、ゲームの勝利(成功)を判定するため関数です。
その他の関数のソースコードです。以下のコードをklondike.pyの1番下の行に追記します。
# 選択されたカード一覧
def printCards(cards):
if(type(cards) in [list, Card]):
print("Card : ", end="")
if(type(cards) == list):
for card in cards:
print(card.getMAN(), ",", end="")
print("")
elif(type(cards) == Card):
print(cards.getMAN())
pass
# cmd : row, col判定
def confRowCol(cmd):
if("," in cmd):
cmdlist = cmd.split(",")
confRow = True if cmdlist[0] in rowNumList else False
confCol = True if cmdlist[1] in colNumList else False
if(confRow and confCol):
return True
return False
# 勝利条件の確認
def CheckEnd(mdd):
# mdd = markDeckDict
for v in mdd.values():
if(len(v.markDeck) == 13): pass
else: return False
return True
コードの解説
2行目~11行目の「printCards()」は、プレイヤーが選択したカードのマークと数字を指定の形式で表示するための関数です。
引数の「cards」は、カード単体またはカードが複数枚代入されているリストを指定します。そのため3行目のif文では、list型またはCard型であるcardsを処理の対象とします。
さらに、そのifの中でlist型とCard型の処理を分けています。
引数の「cards」が、list型またはCard型でないときは何もしません。
14行目~21行目の「confRowCol()」は、場札の列のカードを正しく指定できているかを確認するための関数です。
引数の「cmd」は、先述したコマンドです。
場札の列は、「行, 列」という形で指定します。この形で指定されたかを確認します。
24行目~29行目の「CheckEnd()」は、勝利を判定するための関数です。引数の「mdd」は、組札の辞書です。 全ての組札において、1から13があるか確認しています。
まとめ
今回は、表示関係の関数とその他の関数を作成しました。
表示関係の関数については、動作確認を行ったためこの開発の完成がイメージできたのではないかと思います。
その他の関数については、理解しづらかったもしれませんが、次回使う関数であるため無理に理解しなくて大丈夫です。
次回は、実行関数(main)を作成します。完成まで開発を行います。お楽しみに!
最後までお読み頂きありがとうございます。
何か作って欲しいというリクエストがあれば、TwitterのDMで承ります。
スポンサードサーチ