九九を覚えるためにアプリを作ってみた
皆さん,九九覚えていますか?小学校二年生の時に覚えた人がほとんどだと思います.最近私の大学の友達がインド式計算にハマっていてそれにつられて私も覚え始めました.
空いた時間などに問題を出し合うのですが,答えが正しいかどうかを判定するために電卓を使っていましたが,めんどくせぇ
ということでPythonのTkinterをつかって寿司打のようなアプリを簡単に作成しました.
コードの作成
まずは仕様を以下のように定めました.
- 制限時間は180秒
- 数字は10~99まで
- 最高スコアをテキストファイルに保存しておく.
- 5秒以内に応えられたらボーナスタイムを追加
- シーケンスバーを緑から赤色に変化させていく
という感じです.シーケンスバーについてはChatGPTに作成してもらいました.
以下がコードの全文です.
import random
import time
import tkinter as tk
from tkinter import ttk
min_value = 10
max_value = 99
INITIAL_TIME_LIMIT = 180 # 3 minutes in seconds
BONUS_TIME = 5 # 5 seconds bonus
class KakezanGame:
def __init__(self, root):
self.root = root
self.root.title("Kakezan Game")
self.high_consecutive, self.high_total = self.get_highscore()
self.setup_game()
def get_highscore(self):
try:
with open('scoredata.txt', 'r') as f:
high_consecutive, high_total = map(int, f.read().split(','))
return high_consecutive, high_total
except:
return 0, 0
def setup_game(self):
self.time_left = INITIAL_TIME_LIMIT
self.total_correct = 0
self.consecutive_correct = 0
self.incorrect_count = 0
self.game_active = True
# Create GUI elements
self.highscore_label = ttk.Label(self.root, text=f"最高連続正解数: {self.high_consecutive}\n最高正解数: {self.high_total}")
self.highscore_label.pack(pady=10)
self.question_label = ttk.Label(self.root, text="")
self.question_label.pack(pady=20)
self.answer_entry = ttk.Entry(self.root)
self.answer_entry.pack(pady=20)
self.answer_entry.bind('<Return>', self.check_answer)
self.canvas = tk.Canvas(self.root, width=300, height=20)
self.canvas.pack(pady=20)
self.progress_bar = self.canvas.create_rectangle(0, 0, 300, 20, fill='green')
self.info_label = ttk.Label(self.root, text="")
self.info_label.pack(pady=20)
self.score_label = ttk.Label(self.root, text=f"連続正解数: {self.consecutive_correct}\n合計正解数: {self.total_correct}\n不正解数: {self.incorrect_count}")
self.score_label.pack(pady=20)
self.retry_button = ttk.Button(self.root, text="再挑戦", command=self.restart_game)
# Note: The button is created but not packed initially. It will be shown only after the game is over.
# Start game
self.new_question()
def new_question(self):
self.num1 = random.randint(min_value, max_value)
self.num2 = random.randint(min_value, max_value)
self.question_label.config(text=f"{self.num1} と {self.num2} の積は?")
self.answer_entry.delete(0, tk.END)
self.answer_entry.focus_set()
self.start_time = time.time()
self.update_time_left()
def check_answer(self, event):
if not self.game_active:
return
try:
answer = int(self.answer_entry.get())
elapsed_time = time.time() - self.start_time
if self.num1 * self.num2 == answer:
self.total_correct += 1
self.consecutive_correct += 1
if elapsed_time <= 5:
self.time_left += BONUS_TIME
self.info_label.config(text="ボーナスタイム +5秒!")
else:
self.info_label.config(text="")
self.update_score()
self.new_question()
else:
self.incorrect_count += 1
self.info_label.config(text=f"不正解です。正答は {self.num1 * self.num2} でした。")
self.update_score()
self.new_question()
except ValueError:
self.info_label.config(text="数値を入力してください。")
def update_time_left(self):
if self.time_left > 0 and self.game_active:
self.time_left -= 1
# Change color of the progress bar
fraction = self.time_left / INITIAL_TIME_LIMIT
red = int(255 * (1 - fraction))
green = int(255 * fraction)
self.canvas.itemconfig(self.progress_bar, fill=f"#{red:02x}{green:02x}00")
self.canvas.coords(self.progress_bar, 0, 0, 300 * fraction, 20)
self.root.after(1000, self.update_time_left)
elif self.time_left <= 0:
self.game_over("時間切れです")
def game_over(self, reason):
self.game_active = False
self.info_label.config(text=reason)
self.score_label.config(text=f"連続正解数: {self.consecutive_correct}\n合計正解数: {self.total_correct}\n不正解数: {self.incorrect_count}")
self.retry_button.pack(pady=20) # Show the retry button
# Check and update high scores
if self.consecutive_correct > self.high_consecutive:
self.high_consecutive = self.consecutive_correct
if self.total_correct > self.high_total:
self.high_total = self.total_correct
self.highscore_label.config(text=f"最高連続正解数: {self.high_consecutive}\n最高正解数: {self.high_total}")
self.save_highscore()
def save_highscore(self):
with open('scoredata.txt', 'w') as f:
f.write(f"{self.high_consecutive},{self.high_total}")
def update_score(self):
self.score_label.config(text=f"連続正解数: {self.consecutive_correct}\n合計正解数: {self.total_correct}\n不正解数: {self.incorrect_count}")
def restart_game(self):
# Remove all GUI elements
for widget in self.root.winfo_children():
widget.destroy()
# Set up the game again
self.setup_game()
if __name__ == "__main__":
root = tk.Tk()
game = KakezanGame(root)
root.mainloop()
実際のアプリの画面はこんな感じです.
テキストの入力欄に数字を打ち込んでいきます.
皆さんも一緒に99までの九九を暗算でできるようになりましょう!