🔽 全問解けたらあなたのオタクは神レベル!?

このアプリは、WordCloudで可視化した乃木坂46の歌詞画像を使って、
どの曲かを当てるクイズを楽しめるゲームです!
オタクでも難しい!
だからこそ…ガチオタ検定用にしました💜
🔽 環境構築
- Python
- Tkinter
- WordCloudで生成した画像(PNG形式)
🔽 できること
- WordCloud画像をランダム表示
- 曲名を当てるクイズ形式
- 答え表示・次の問題へ の操作が可能
- 推し活っぽいパステル&丸ボタンUI
🔽 準備するもの
① WordCloud画像の作成
乃木坂46の歌詞CSVから、形態素解析 → WordCloud生成 → PNG画像として保存してください。
生成コードはこちらにまとめました👇
② クイズアプリ(Tkinter)
全体コードはこちら↓
python
import os
import random
import tkinter as tk
from tkinter import ttk
from PIL import Image, ImageTk
class SparkleCanvas(tk.Canvas):
def __init__(self, master, width, height, count=30, **kwargs):
super().__init__(master, width=width, height=height, bg="#ffe4e6", highlightthickness=0, **kwargs)
self.width = width
self.height = height
self.count = count
self.stars = []
for _ in range(count):
x = random.randint(0, width)
y = random.randint(0, height)
size = random.randint(3,6)
star = self.create_oval(x, y, x+size, y+size, fill="#fffacd", outline="")
self.stars.append((star, size, x, y, 1))
self.animate()
def animate(self):
for i, (star, size, x, y, dir) in enumerate(self.stars):
new_color = "#fffacd" if dir == 1 else "#fff1b6"
self.itemconfig(star, fill=new_color)
self.stars[i] = (star, size, x, y, -dir)
self.after(500, self.animate)
class PuffyButton(tk.Canvas):
def __init__(self, master, text, command=None, width=120, height=50,
bg="#ff77a9", fg="white", font=None, **kwargs):
super().__init__(master, width=width, height=height, bg="#ffe4e6", highlightthickness=0, **kwargs)
self.command = command
self.bg = bg
self.fg = fg
self.font = font or ("Comic Sans MS", 14, "bold")
self.text = text
self.width = width
self.height = height
self.draw_button()
self.bind("<Button-1>", lambda e: self.command() if self.command else None)
self.bind("<Enter>", self.on_enter)
self.bind("<Leave>", self.on_leave)
self.is_hover = False
def draw_button(self):
self.delete("all")
self.create_oval(5, 5, self.width-5, self.height-5, fill="#ff3d88", outline="")
self.create_oval(0, 0, self.width-10, self.height-10, fill=self.bg, outline="")
self.create_oval(0, 0, self.width-10, (self.height-10)//2, fill="#ffa1c9", outline="")
self.create_text((self.width-10)//2, (self.height-10)//2, text=self.text, font=self.font, fill=self.fg)
def on_enter(self, event):
if not self.is_hover:
self.is_hover = True
self.bg = "#ff3d88"
self.draw_button()
def on_leave(self, event):
if self.is_hover:
self.is_hover = False
self.bg = "#ff77a9"
self.draw_button()
class QuizApp(tk.Tk):
def __init__(self, image_folder="/ここ変更ーーーPATHの位置"):
super().__init__()
self.title("✨乃木坂曲クイズ✨")
self.geometry("620x700")
self.configure(bg="#ffe4e6")
self.image_folder = image_folder
self.image_files = [f for f in os.listdir(self.image_folder) if f.endswith(".png")]
if not self.image_files:
raise ValueError(f"{self.image_folder} にPNG画像がありません。")
self.current_image_file = None
self.current_answer = None
self.sparkle_bg = SparkleCanvas(self, width=620, height=700)
self.sparkle_bg.place(x=0, y=0)
self.font_title = ("Comic Sans MS", 22, "bold")
self.font_answer = ("Comic Sans MS", 18, "bold")
self.title_label = tk.Label(self, text="✨乃木坂曲クイズ✨",
font=self.font_title, fg="#d6336c", bg="#ffe4e6")
self.title_label.pack(pady=15)
self.image_label = ttk.Label(self)
self.image_label.pack(pady=15)
self.answer_label = tk.Label(self, text="", font=self.font_answer,
fg="#d6336c", bg="#ffe4e6")
self.answer_label.pack(pady=10)
button_frame = tk.Frame(self, bg="#ffe4e6")
button_frame.pack(pady=25)
self.show_answer_button = PuffyButton(button_frame, text="答え", command=self.show_answer)
self.show_answer_button.grid(row=0, column=0, padx=20)
self.next_button = PuffyButton(button_frame, text="次へ", command=self.next_image)
self.next_button.grid(row=0, column=1, padx=20)
self.after(100, self.next_image)
def next_image(self):
self.answer_label.config(text="")
self.current_image_file = random.choice(self.image_files)
base_name = os.path.splitext(self.current_image_file)[0]
self.current_answer = base_name.split("_", 1)[1] if "_" in base_name else base_name
image_path = os.path.join(self.image_folder, self.current_image_file)
img = Image.open(image_path)
img.thumbnail((500, 400))
self.photo = ImageTk.PhotoImage(img)
self.image_label.config(image=self.photo)
self.image_label.image = self.photo
def show_answer(self):
if self.current_answer:
self.answer_label.config(text=f"答え:{self.current_answer}")
if __name__ == "__main__":
app = QuizApp()
app.mainloop()
🔽 クイズアプリの構造を解説
Q1 どのような構造か?
A: アプリの本体は以下のように、QuizApp というクラスで構成されています
class QuizApp(tk.Tk):
def __init__(self, image_folder="..."):
super().__init__()
# ① 初期設定(タイトル、サイズ、背景色など)
# ② WordCloud画像の読み込み
# ③ 背景Canvas(SparkleCanvas)設置
# ④ UIウィジェットの配置
# ⑤ 最初の画像を表示
Tkinterのウィンドウを継承し、画像のランダム表示・ボタンによる操作・答えの表示などを行っています
Q2 なぜファイル名から曲名を抽出しているのか?
例えば以下のようなファイル名があるとします:
n46_インフルエンサー.png
n46_制服のマネキン.png
これらのファイルから「_以降」だけを抽出することで、正解の曲名が得られます
base_name = os.path.splitext(self.current_image_file)[0]
base_name.split("_", 1)[1]
os.path.splitext() → .png を除いたファイル名(例: n46_インフルエンサー)
.split("", 1)[1] → "" 以降の部分" → インフルエンサー
という風に処理しています
🔽 最後に
あなたの「乃木坂力」、このアプリで試してみてください〜