今回は受講生(K氏)から届いたお題を解いていこう。(一部改変)
リストとループの問題。レッツチャレンジ!
問題
・デッキとして1-13の番号が書かれたカードをあなたとCPUが13枚ずつそれぞれ持つ
・それぞれのデッキをシャッフルし裏向きに置く
・お互いに一番上のカードをオープン、数字の大きいほう(1が最小13が最大)がそのラウンドを勝利し、”2枚のカード”を獲得できる。
・もし同じ数字がでた場合は、勝敗が決まるまで次のカードを出し合って、勝ったほうが引き分けのラウンドを含めた枚数分のカードを獲得できる。
・お互いの手札がなくなったらゲーム終了で、獲得したカードの枚数が多いほうが最終的な勝者となる。
実行例
1回戦
あなた:11,PC:10,あなたの勝ち!2枚ゲット!
2回戦
あなた:8,PC:3,あなたの勝ち!2枚ゲット!
3回戦
あなた:4,PC:7,PCの勝ち(2)
4回戦
あなた:10,PC:1,あなたの勝ち!2枚ゲット!
5回戦
あなた:2,PC:2,引き分け、キャリーオーバー!
6回戦
あなた:3,PC:12,PCの勝ち(4)
7回戦
あなた:7,PC:8,PCの勝ち(2)
8回戦
あなた:9,PC:5,あなたの勝ち!2枚ゲット!
9回戦
あなた:5,PC:4,あなたの勝ち!2枚ゲット!
10回戦
あなた:6,PC:9,PCの勝ち(2)
11回戦
あなた:12,PC:13,PCの勝ち(2)
12回戦
あなた:13,PC:11,あなたの勝ち!2枚ゲット!
13回戦
あなた:1,PC:6,PCの勝ち(2)
獲得枚数12対14でPCの勝ち!
Let’s challenge
1-13のリストを2組作ってそれをシャッフルする。順番に取り出していって結果を判定。そこにキャリオーバーの概念をいれていけばよさそうだ。。。
解答例
まずは言われたとおりに愚直にやっていってみよう。
まずは1から13の連番を要素に持つリストを一つ作ってみる。色々な方法が考えられるがpythonだったら以下のどちらかが有望だ。
ls=list(range(1,14))
ls=[ i+1 for i in range(13)]
シャッフル
上の方法で作ったリストをシャッフルするには以下。この場合randomをインポートすること
random.shuffle(ls)
import random
user=list(range(1,14))
pc=list(range(1,14))
random.shuffle(user)
random.shuffle(pc)
print(user,pc)
#[1, 8, 12, 9, 13, 2, 3, 7, 10, 6, 5, 4, 11]
#[11, 1, 13, 4, 6, 3, 5, 2, 7, 10, 12, 8, 9]
これでなんの問題はない。
が、他の方法も考えてみよう。Pythonにはrandom.sampleというメソッドもある。まずはsampleの使い方から
random.sample
random.sample(並び式,取り出したい個数)
と指定すると第1引数の並び式から第2引数の数だけ要素の重複なしにとりだすことができる。
ls=random.sample([1,2,3],2) print(ls) # [3,1](毎回変わる)
この仕組を使えば先程の例は以下のようにも書ける。
import random
user=random.sample(range(1,14),13)
pc=random.sample(range(1,14),13)
print(user,pc)
ただ、ほとんど同じことを2行書いてしまっているのが歯がゆい。
いつものように内包表記とアンパック代入を使えって以下のようにしてしまおう。
import random
user,pc=[random.sample(range(1,14),13) for i in range(2)]
print(user,pc)
業務案件ならば、保守のことも考えてわかりやすい最初のコードのほうがベターかもしれないが、学習段階だったらどんどん短くすることに挑戦していくとよい。
それがコーディング力アップにつながる。
2つのリストができたので実行例になるように仕上げよう
import random
user,pc=[random.sample(range(1,14),13) for _ in range(2)]
you_win=pc_win=stock=0
for i in range(13):
print(f'{i+1}回戦')
stock+=2
if user[i]==pc[i]:
result='引き分け、キャリーオーバー!'
elif user[i] > pc[i]:
result=f'あなたの勝ち!{stock}枚ゲット!'
you_win+=stock
stock=0
else:
result=f'PCの勝ち({stock})'
pc_win+=stock
stock=0
print(f'あなた:{user[i]},PC:{pc[i]},{result}')
print(f'獲得枚数{you_win}対{pc_win}で{"あなた" if you_win > pc_win else "PC"}の勝ち!')
コメント