前回、無事にじゃんけんが出来るようになったし、次は「今まで何回勝てた」とか戦績を管理できるようにしようか
戦績の管理をするなら単純に変数を使えば良いんだよね
そうだね!今回は「勝ち(win_count)」「負け(lose_count)」「あいこ(draw_count)」の3種類の変数を用意すればOK
# 勝敗を管理する変数(変数「win_rules」を設定してる場所の下あたりに配置)
win_count = 0
lose_count = 0
draw_count = 0
オッケー!もう慣れたもんですよ
じゃあ次は戦績を表示するためにlayoutを変更しよう
layout = [
[eg.Text("じゃんけんの手を選ぼう!")],
[col1, col2, col3],
[eg.Text("プレイヤーの手"),
eg.Image(None, size=(100, 100),key="player_hand"),
eg.Text("vs"),
eg.Image(None, size=(100, 100), key="cpu_hand"),
eg.Text("CPUの手")],
[eg.Text("", key="result")],
[eg.Text("勝ち: 0", key="win_score"),
eg.Text("負け: 0", key="lose_score"),
eg.Text("あいこ: 0", key="draw_score")] # この3行を追加
]
配列に途中から要素を追加すると「,」を忘れがちになるから気をつけないとね
次はそれぞれのテキストが更新されるように「.update()」を追加しよう
今回は各戦績の画面表示の更新を「じゃんけんの判定後」に行いたいから、「eg.popup(check_hands(player, cpu))」の次の行に追加してね
window["win_score"].update(f"勝ち: {win_count}")
window["lose_score"].update(f"負け: {lose_count}")
window["draw_score"].update(f"あいこ: {draw_count}")
画面の更新もできるようにしたし、次はさっきの変数の値の更新だね!
だとしたら、関数「check_hands()」を書き換えるのかな?
そうだね!だけど、ここで注意しないといけないことがあるんだ
そうなの?そのまま「win_count += 1」って感じにすれば良いんじゃないの??
「その他の関数定義」でも説明したけど、関数内でグローバル変数は更新できないってのは覚えてるかな?
そういえばそうだった...!!
でも、returnで返してる内容は直接ポップアップに使っちゃってるからどうしよう!?
そうなんだよね、だから今回は関数「check_hands()」内でグローバル変数を更新できるように「global」を使うよ
def check_hands(player_hand, cpu_hand):
global win_count, lose_count, draw_count
if player_hand == cpu_hand:
draw_count += 1
return "あいこだよ"
elif win_rules[player_hand] == cpu_hand:
win_count += 1
return "勝ち!!"
else:
lose_count += 1
return "負け..."
関数内で変数の前にこれを付けてあげることで、その変数をグローバル変数として扱えるようになるんだ
おおー、なんかズルい
まぁ裏技的なものでバグの原因になりやすいから多用しすぎないでね
りょうかい!!じゃあ早速動かしてみるね
うまくいってそう!(なぜか全然勝てなかったけど...)
良い感じだね!だけど今の結果は不服そうだし、いつでもリセットできる機能があったら欲しくない??
欲しい!!
じゃあまずは、リセットボタンをlayoutの最後に追加しよう
layout = [
[eg.Text("じゃんけんの手を選ぼう!")],
[col1, col2, col3],
[eg.Text("プレイヤーの手"),
eg.Image(None, size=(100, 100),key="player_hand"),
eg.Text("vs"),
eg.Image(None, size=(100, 100), key="cpu_hand"),
eg.Text("CPUの手")],
[eg.Text("", key="result")],
[eg.Text("勝ち: 0", key="win_score"),
eg.Text("負け: 0", key="lose_score"),
eg.Text("あいこ: 0", key="draw_score")],
[eg.Button("リセット")] # これを追加
]
次にリセットボタンが押された時の処理を作ろう
それぞれの変数を「0」にして、各オブジェクトの表示も初期状態に戻すよ
if event == "リセット":
win_count = 0
lose_count = 0
draw_count = 0
window["win_score"].update(f"勝ち: {win_count}")
window["lose_score"].update(f"負け: {lose_count}")
window["draw_score"].update(f"あいこ: {draw_count}")
window["player_hand"].update(data=b"") # 「b""」はバイト列という特別な文字列
window["cpu_hand"].update(data=b"")
window["result"].update("")
eg.popup("スコアをリセットしました!")
このプログラムを「while True」の中に追加すればOKだよ
おお!リセットボタンを押したらポップアップ画面が出て、起動した時と同じ状態になった!
...だけど、ターミナルの方になんかエラーが出てるね
「player_hand」と「cpu_hand」の画像は「.update(None)」みたいな感じでは消せなくて、無理矢理消そうとしたからなんだよね汗
じゃあ仕方ないかー
まぁひとまず、これでスコア管理とリセット機能はバッチリだね
そうだね!だけど、UIのデザインがまだ整ってなかったり、プログラムがごちゃっとしているから次の項目ではその辺りも含めて完成させよう!
この時点での全体のプログラム
import TkEasyGUI as eg
import random
hands = ["グー", "チョキ", "パー"]
hand_images = {
"グー": "janken_gu.png",
"チョキ": "janken_choki.png",
"パー": "janken_pa.png"
}
win_rules = {
"グー": "チョキ",
"チョキ": "パー",
"パー": "グー"
}
# スコア変数
win_count = 0
lose_count = 0
draw_count = 0
def check_hands(player_hand, cpu_hand):
global win_count, lose_count, draw_count
if player_hand == cpu_hand:
draw_count += 1
return "あいこだよ"
elif win_rules[player_hand] == cpu_hand:
win_count += 1
return "勝ち!!"
else:
lose_count += 1
return "負け..."
# レイアウト(画面構成)
col1 = eg.Column([[eg.Image(hand_images["グー"], size=(100, 100))], [eg.Button("グー")]])
col2 = eg.Column([[eg.Image(hand_images["チョキ"], size=(100, 100))], [eg.Button("チョキ")]])
col3 = eg.Column([[eg.Image(hand_images["パー"], size=(100, 100))], [eg.Button("パー")]])
layout = [
[eg.Text("じゃんけんの手を選ぼう!")],
[col1, col2, col3],
[eg.Text("プレイヤーの手"),
eg.Image(None, size=(100, 100),key="player_hand"),
eg.Text("vs"),
eg.Image(None, size=(100, 100), key="cpu_hand"),
eg.Text("CPUの手")],
[eg.Text("", key="result")],
[eg.Text("勝ち: 0", key="win_score"),
eg.Text("負け: 0", key="lose_score"),
eg.Text("あいこ: 0", key="draw_score")],
[eg.Button("リセット")]
]
# ウィンドウを作成
window = eg.Window("じゃんけんアプリ", layout)
# イベントループ(閉じるまで表示)
while True:
event, values = window.read()
if event in ["グー", "チョキ", "パー"]:
player = event
cpu = random.choice(hands)
window["player_hand"].update(hand_images[player])
window["cpu_hand"].update(hand_images[cpu])
window["result"].update(f"プレイヤーの手は「{player}」、CPUの手は「{cpu}」です")
eg.popup(check_hands(player, cpu))
window["win_score"].update(f"勝ち: {win_count}")
window["lose_score"].update(f"負け: {lose_count}")
window["draw_score"].update(f"あいこ: {draw_count}")
if event == "リセット":
win_count = 0
lose_count = 0
draw_count = 0
window["win_score"].update(f"勝ち: {win_count}")
window["lose_score"].update(f"負け: {lose_count}")
window["draw_score"].update(f"あいこ: {draw_count}")
window["player_hand"].update(data=b"")
window["cpu_hand"].update(data=b"")
window["result"].update("")
eg.popup("スコアをリセットしました!")
if event is eg.WINDOW_CLOSED:
break
# ウィンドウを閉じる
window.close()
