初心者の僕には難しいですが、ラスベガスで負け続けたカードゲームの「Black Jack」を作ってみます。 作る過程でPythonを覚えるのが本来の目的です。
まずは動作結果を文字だけで表示するスクリプトで作って行きます。 その後でカードの動きをスクリーン上で見えるようなGUIで作ります(それがが難しい)。
スクリプトの原案は「プログラムのツボとコツ」からお借りしてます(秀和システム)。
ブラックジャックを作る-1
ゲームの規則は既知とします。 ゲームの組み立て(流れ)は次の通り。
1.掛け金を決める
2.プレーヤーとディーラーにカードを二枚ずつ配る(ディーラーの二枚目は隠しておく)
3.プレーヤーターン(順番)
・Stand:カードは引かずに勝負に臨む
・Hit:デッキからカードを一枚貰う
4.ディーラーターン
・カードの総計が17以上になるまでカードを引く
・17以上になったらそこで勝負が決まる
5.勝敗の決定
・21以上以上なったらバストで負け
・ポイントが多い方が勝ち、同数なら引き分け
・プレーヤーの掛け金がなくなったらゲーム終了(プレーヤーが負けとは限らない)
プログラムのcode | 説明、コメント | ||
1 | import random | 乱数発生用ライブラリー | |
2 | |||
3 | def make_deck(): | カードを52枚作る関数 | |
4 | suits = [‘S’, ‘H’, ‘D’, ‘C’] | suitsは♠、♥、♦、♠、♧の4種類 | |
5 | ranks = range(1, 14) | ranksはA~10、J、Q、Kの13個 | |
6 | deck = [(x, y) for x in ranks for y in suits] | 別項参照 | |
7 | random.shuffle(deck) | 作ったカードをシャッフルする(混ぜ合わせる) | |
8 | return deck | このdeckを後々他の関数で使用するのでreturnしておく<—ここが躓く所 | |
9 | |||
10 | def main(): | 主な処理機能をmain()と云う関数に纏える | |
11 | turn = 1 | turnとはゲームの回数 | |
12 | player_money = 100 | プレーヤの持ち金を100とする | |
13 | deck = make_deck() | 3行目のmake_decck()を駆動する。出来たdeckを持ち帰る | |
14 | print(deck) | そのdeck() 52枚を表示する | |
15 | while (player_money > 0): | 持ち金がなくなったら、ゲームは完了する | |
16 | print(‘turn : ‘, turn) | 何回目のゲームかを表示する | |
17 | print(‘players money is : ‘, player_money) | プレーヤの所持金を表示する | |
18 | turn += 1 | ここまでが一回のゲームなので、次はゲーム2と表示する | |
19 | input(‘next turn?’) | ゲーム2へ行きますか?と確認している | |
20 | print(‘Game Over ! ‘) | プレーヤの所持金が切れたら、ゲームオーバーと表示する | |
21 | |||
22 | if __name__ == ‘__main__’: | main()と云う関数が直接実行された場合のみ実行できる。 | |
23 | main() | ||
ここまでやると、プログラムに従って、次のような表示がでる。
[(2, ‘D’), (11, ‘H’), (8, ‘C’), (5, ‘H’), (1, ‘S’), ・・・・・・、(13, ‘C’), (4, ‘S’), (9, ‘D’)] #52枚のカードが出来ている
turn : 1
players money is : 100
next turn?
turn : 2
players money is : 100
next turn?
————————————————————————
ブラックジャックを作る-2
プログラムのcode | 説明、コメント | ||
1 | import random | 乱数発生用ライブラリー | |
2 | |||
3 | def make_deck(): | カードを52枚作る関数 | |
4 | suits = [‘S’, ‘H’, ‘D’, ‘C’] | suitsは♠、♥、♦、♠、♧の4種類 | |
5 | ranks = range(1, 14) | ranksはA~10、J、Q、Kの13個 | |
6 | deck = [(x, y) for x in ranks for y in suits] | 別項参照 | |
7 | random.shuffle(deck) | 作ったカードをシャッフルする(混ぜ合わせる) | |
8 | return deck | このdeckを後々他の関数で使用するのでreturnしておく <— ここが最初に躓くところ | |
9 | |||
10 | def main(): | 主な処理機能をmain()と云う関数に纏える | |
11 | turn = 1 | turnとはゲームの回数 | |
12 | player_money = 100 | プレーヤの持ち金を100とする | |
13 | deck = make_deck() | 3行目のmake_decck()を駆動する。出来たdeckを持ち帰る | |
14 | print(deck) | そのdeck() 52枚を表示する | |
15 | while (player_money > 0): | 持ち金がなくなったら、ゲームは完了する | |
16 | print(‘turn : ‘, turn) | 何回目のゲームかを表示する | |
17 | print(‘players money is : ‘, player_money) | プレーヤの所持金を表示する | |
18 | turn += 1 | ここまでが一回のゲームなので、次はゲーム2と表示する | |
19 | input(‘next turn?’) | ゲーム2へ行きますか?と確認している | |
20 | print(‘Game Over ! ‘) | プレーヤの所持金が切れたら、ゲームオーバーと表示する | |
21 |
————————————————————————–
ブラックジャックを作る-3
下の空欄にはplayerとdealerへのカードを2枚ずつ配布する。 冗長になるが、理解し易いように一枚ずつの配布を4回書いてみる。
その後に一度に配布出来るようにcodeを書きなおします。
*印の行が追加されたところ
プログラムのcode | 説明、コメント Tak-2-2-list6 | ||
1 | import random | #乱数発生用ライブラリー | |
2 | |||
3 | def make_deck(): | #カードを52枚作る関数 | |
4 | suits = [‘S’, ‘H’, ‘D’, ‘C’] | #suitsは♠、♥、♦、♠、♧の4種類 | |
5 | ranks = range(1, 14) | #ranksはA~10、J、Q、Kの13個 | |
6 | deck = [(x, y) for x in ranks for y in suits] | #別項参照 | |
7 | random.shuffle(deck) | #作ったカードをシャッフルする(混ぜ合わせる) | |
8 | return deck | #このdeckを後々他の関数で使用するのでreturnしておく<—ここ躓く | |
9 | |||
10 | def main(): | #主な処理機能をmain()と云う関数に纏える | |
11 | turn = 1 | #turnとはゲームの回数 | |
12 | player_money = 100 | #プレーヤの持ち金を100とする | |
13 | deck = make_deck() | #3行目のmake_deck()を駆動する。出来たdeckを持ち帰る | |
14 | print(deck) | #そのdeck() 52枚を表示する | |
15 | while (player_money > 0): | #持ち金がなくなったら、ゲームは完了する | |
16 | print(‘turn : ‘, turn) | #何回目のゲームかを表示する | |
17 | print(‘players money is : ‘, player_money) | #プレーヤの所持金を表示する | |
18 | |||
* | 19 | player_hand = [] | # プレイヤーの持ち札を格納するリスト |
* | 20 | dealer_hand = [] | # ディーラーの持ち札を格納するリスト |
* | 21 | deck = make_deck() | # ゲームに使うカードの山を作成 |
* | 22 | # print(deck) | # デッキのリストの最後の札を取り出す |
* | 23 | card = deck.pop() | # プレイヤーの持ち札リストに加える(1枚目) |
* | 24 | player_hand.append(card) | |
* | 25 | card = deck.pop() | |
* | 26 | player_hand.append(card) | # 2枚目 |
* | 27 | ||
* | 28 | card = deck.pop() | |
* | 29 | dealer_hand.append(card) | # dealer 1毎目 |
* | 30 | card = deck.pop() | |
* | 31 | dealer_hand.append(card) | # dealer2枚目 |
32 | |||
33 | print(player_hand) | ||
34 | print(dealer_hand) | #ここまでが一回のゲームなので、次はゲーム2と表示する | |
35 | input(‘next turn?’) | #ゲーム2へ行きますか?と確認している | |
36 | print(‘Game Over ! ‘) | #プレーヤの所持金が切れたら、ゲームオーバーと表示する | |
37 | |||
38 | if __name__ == ‘__main__’: | #main()と云う関数が直接実行された場合のみ実行できる。 | |
39 | main() |
これをrunすると次のように、各2枚ずつ配布されます。
ターン: 1
所持金: 100
[(3, ‘S’), (9, ‘D’)]
[(12, ‘D’), (1, ‘S’)]
次のターンへ
———————————————————————————–
ブラックジャックを作る-4
一枚ずつの配布を4回書いているところをスマートなcodeに書き換えます。
*印の行が追加されたところ
プログラムのcode | 説明、コメント Tak-2-2-list8 | ||
1 | import random | #乱数発生用ライブラリー | |
2 | |||
3 | def make_deck(): | #カードを52枚作る関数 | |
4 | suits = [‘S’, ‘H’, ‘D’, ‘C’] | #suitsは♠、♥、♦、♠、♧の4種類 | |
5 | ranks = range(1, 14) | #ranksはA~10、J、Q、Kの13個 | |
6 | deck = [(x, y) for x in ranks for y in suits] | #別項参照 | |
7 | random.shuffle(deck) | #作ったカードをシャッフルする(混ぜ合わせる) | |
8 | return deck | #このdeckを後々他の関数で使用するのでreturnしておく<—ここ躓く | |
9 | |||
10 | def main(): | #主な処理機能をmain()と云う関数に纏える | |
11 | turn = 1 | #turnとはゲームの回数 | |
12 | player_money = 100 | #プレーヤの持ち金を100とする | |
13 | deck = make_deck() | #3行目のmake_deck()を駆動する。出来たdeckを持ち帰る | |
14 | print(deck) | #そのdeck() 52枚を表示する | |
15 | while (player_money > 0): | #持ち金がなくなったら、ゲームは完了する | |
16 | print(‘turn : ‘, turn) | #何回目のゲームかを表示する | |
17 | print(‘players money is : ‘, player_money) | #プレーヤの所持金を表示する | |
18 | |||
19 | player_hand = [] | # プレイヤーの持ち札を格納するリスト | |
20 | dealer_hand = [] | # ディーラーの持ち札を格納するリスト | |
21 | deck = make_deck() | # ゲームに使うカードの山を作成 | |
22 | |||
* | 23 | for i in range(2): | # カードをplayerとdealerに2回配布する |
* | 24 | player_hand.append(deck.pop()) | |
* | 25 | dealer_hand.append(deck.pop()) | |
26 | |||
27 | print(player_hand) | ||
28 | print(dealer_hand) | ||
29 | input(‘next turn?’) | #ゲーム2へ行きますか?と確認している | |
30 | print(‘Game Over ! ‘) | #プレーヤの所持金が切れたら、ゲームオーバーと表示する | |
31 | |||
32 | if __name__ == ‘__main__’: | #main()と云う関数が直接実行された場合のみ実行できる。 | |
33 | main() |
結果は前と全く同じですが、codeが大分シンプルになりました。 繰返しは while~ か for i in ~ で処理します。
—————————————————————————-
ブラックジャックを作る-5
今回は各自の手持ちカードの得点の合計を、取得するget_point関数を追加します。
*印の行が追加されたところ
プログラムのcode | 説明、コメント Tak-2-3-list1 | ||
1 | import random | #乱数発生用ライブラリー | |
2 | #SUITはトランプの種類(♠、♥など) | ||
* | 3 | RANK, SUIT = 0, 1 | #RANKはトランプの数。 行7でcard[0]と書くより分かり易い |
* | 4 | def get_point(hand): | |
* | 5 | result = 0 | #得点の初期値を零に初期化 |
* | 6 | for card in hand: | # 手にあるカード(card)のpoint全部numに格納 |
* | 7 | num = card[RANK] | |
* | 8 | result = result + num | #カードの合計点数をresultに格納する |
* | 9 | return result | # |
10 | |||
11 | def make_deck(): | #カードを52枚作る関数 | |
12 | suits = [‘S’, ‘H’, ‘D’, ‘C’] | #suitsは♠、♥、♦、♠、♧の4種類 | |
13 | ranks = range(1, 14) | #ranksはA~10、J、Q、Kの13個 | |
14 | deck = [(x, y) for x in ranks for y in suits] | #別項参照 | |
15 | random.shuffle(deck) | #作ったカードをシャッフルする(混ぜ合わせる) | |
16 | return deck | #このdeckを後々他の関数で使用する | |
17 | |||
18 | def main(): | #主な処理機能をmain()と云う関数に纏える | |
19 | turn = 1 | #turnとはゲームの回数 | |
20 | player_money = 100 | #プレーヤの持ち金を100とする | |
21 | deck = make_deck() | #3行目のmake_deck()を駆動する。出来たdeckを持ち帰る | |
22 | print(deck) | #そのdeck() 52枚を表示する | |
23 | while (player_money > 0): | #持ち金がなくなったら、ゲームは完了する | |
24 | print(‘turn : ‘, turn) | #何回目のゲームかを表示する | |
25 | print(‘players money is : ‘, player_money) | #プレーヤの所持金を表示する | |
26 | |||
27 | player_hand = [] | # プレイヤーの持ち札を格納するリスト | |
28 | dealer_hand = [] | # ディーラーの持ち札を格納するリスト | |
29 | deck = make_deck() | # ゲームに使うカードの山を作成 | |
30 | |||
31 | for i in range(2): | # カードをplayerとdealerに2回配布する | |
32 | player_hand.append(deck.pop()) | ||
33 | dealer_hand.append(deck.pop()) | ||
34 | |||
35 | print(player_hand) | # playerの手札 | |
* | 36 | print(get_point(player_hand)) | # ここで上のplayer_handをget_hand()に持っていき合計を得る ** |
37 | ** ここが一番わかり難いところです | ||
38 | print(dealer_hand) | ||
* | 39 | print(get_point(dealer_hand)) | |
40 | |||
41 | turn += 1 | ||
42 | input(‘next turn?’) | #ゲーム2へ行きますか?と確認している | |
43 | print(‘Game Over ! ‘) | #プレーヤの所持金が切れたら、ゲームオーバーと表示する | |
44 | |||
45 | if __name__ == ‘__main__’: | #main()と云う関数が直接実行された場合のみ実行できる。 | |
46 | main() |
runすると合計pointが表示されている、よかったよかった!
ターン: 1
所持金: 100
[(12, ‘H’), (11, ‘H’)]
23
[(13, ‘S’), (12, ‘C’)]
25
次のターンへ
但し、ここで問題があります。 それは絵札(A,J,QW,K)を1,11,12,13と計算していることです。
次回はこれを絵札はAは1か11、その他の絵札は10と計算することで実際のゲームと同じに出来るようになります。
この稿はここまで終了、続きは別掲「ブラックジャックを作る-6」へ行きます。