import tkinter as tk
import random
import time
# ==========================================
# ACAAN PRACTICE TRAINER
# 카드 52장 × 숫자 3~27 = 1,300가지
# ==========================================
SUITS = ["♠", "♥", "♦", "♣"]
RANKS = [
"A", "2", "3", "4", "5", "6", "7",
"8", "9", "10", "J", "Q", "K"
]
CARDS = []
for suit in SUITS:
for rank in RANKS:
CARDS.append(rank + suit)
NUMBERS = list(range(3, 28))
# 현재 문제
current_card = None
current_number = None
# 사용한 조합
used_combinations = set()
# 통계
total_attempts = 0
success_count = 0
fail_count = 0
# 타이머
start_time = 0
timer_running = False
# ==========================================
# 카드 색상
# ==========================================
def get_card_color(card):
if card.endswith("♥") or card.endswith("♦"):
return "#ff5c70"
return "#ffffff"
# ==========================================
# 새 문제
# ==========================================
def new_question():
global current_card
global current_number
global start_time
global timer_running
# 1300개를 모두 사용했다면 새 사이클
if len(used_combinations) >= 1300:
used_combinations.clear()
status_label.config(
text="🎉 1,300개 조합 완료! 새로운 사이클 시작!"
)
# 아직 사용하지 않은 조합 찾기
while True:
card = random.choice(CARDS)
number = random.randint(3, 27)
combination = (card, number)
if combination not in used_combinations:
used_combinations.add(combination)
current_card = card
current_number = number
break
# 화면 표시
card_label.config(
text=current_card,
fg=get_card_color(current_card)
)
number_label.config(
text=str(current_number),
fg="#65e6a5"
)
status_label.config(
text="카드와 숫자를 확인하세요."
)
# 타이머 시작
start_time = time.time()
timer_running = True
update_timer()
update_progress()
# ==========================================
# 타이머
# ==========================================
def update_timer():
if not timer_running:
return
elapsed = time.time() - start_time
timer_label.config(
text=f"⏱ {elapsed:.2f}초"
)
root.after(50, update_timer)
# ==========================================
# 카드/숫자 숨기기
# ==========================================
def hide_question():
card_label.config(
text="?",
fg="#7d899d"
)
number_label.config(
text="?",
fg="#65e6a5"
)
status_label.config(
text="🙈 숨김 — 이제 실제 아칸 루틴을 수행하세요."
)
# ==========================================
# 정답 다시 보기
# ==========================================
def reveal_question():
if current_card is None:
return
card_label.config(
text=current_card,
fg=get_card_color(current_card)
)
number_label.config(
text=str(current_number),
fg="#65e6a5"
)
status_label.config(
text="👁 정답 공개"
)
# ==========================================
# 성공
# ==========================================
def success():
global total_attempts
global success_count
global timer_running
if current_card is None:
return
timer_running = False
total_attempts += 1
success_count += 1
elapsed = time.time() - start_time
status_label.config(
text=f"✅ 성공! 처리 시간: {elapsed:.2f}초"
)
update_stats()
# ==========================================
# 실패
# ==========================================
def failure():
global total_attempts
global fail_count
global timer_running
if current_card is None:
return
timer_running = False
total_attempts += 1
fail_count += 1
elapsed = time.time() - start_time
status_label.config(
text=f"❌ 실패! 처리 시간: {elapsed:.2f}초"
)
update_stats()
# ==========================================
# 통계
# ==========================================
def update_stats():
if total_attempts == 0:
rate = 0
else:
rate = (
success_count /
total_attempts *
100
)
stats_label.config(
text=(
f"연습 {total_attempts}회 "
f"성공 {success_count} "
f"실패 {fail_count} "
f"성공률 {rate:.1f}%"
)
)
# ==========================================
# 진행률
# ==========================================
def update_progress():
used = len(used_combinations)
remaining = 1300 - used
progress_label.config(
text=(
f"전체 조합: {used} / 1,300 "
f"| 남은 조합: {remaining}"
)
)
# ==========================================
# 초기화
# ==========================================
def reset_all():
global total_attempts
global success_count
global fail_count
global timer_running
total_attempts = 0
success_count = 0
fail_count = 0
used_combinations.clear()
timer_running = False
update_stats()
update_progress()
status_label.config(
text="🔄 모든 기록을 초기화했습니다."
)
# ==========================================
# 메인 창
# ==========================================
root = tk.Tk()
root.title("ACAAN Practice Trainer")
root.geometry("600x720")
root.configure(
bg="#10141c"
)
# ==========================================
# 제목
# ==========================================
title = tk.Label(
root,
text="♠ ACAAN PRACTICE ♥",
font=("Arial", 26, "bold"),
fg="white",
bg="#10141c"
)
title.pack(
pady=(25, 5)
)
subtitle = tk.Label(
root,
text="52장 카드 × 숫자 3~27",
font=("Arial", 12),
fg="#9ca8ba",
bg="#10141c"
)
subtitle.pack(
pady=(0, 20)
)
# ==========================================
# 문제 영역
# ==========================================
question_box = tk.Frame(
root,
bg="#1a202b",
highlightbackground="#303a4a",
highlightthickness=1
)
question_box.pack(
fill="x",
padx=30
)
card_title = tk.Label(
question_box,
text="카드",
font=("Arial", 12, "bold"),
fg="#9ca8ba",
bg="#1a202b"
)
card_title.pack(
pady=(18, 0)
)
card_label = tk.Label(
question_box,
text="",
font=("Arial", 55, "bold"),
bg="#1a202b"
)
card_label.pack(
pady=3
)
number_title = tk.Label(
question_box,
text="숫자",
font=("Arial", 12, "bold"),
fg="#9ca8ba",
bg="#1a202b"
)
number_title.pack()
number_label = tk.Label(
question_box,
text="",
font=("Arial", 65, "bold"),
bg="#1a202b"
)
number_label.pack(
pady=(0, 5)
)
timer_label = tk.Label(
question_box,
text="⏱ 0.00초",
font=("Arial", 13, "bold"),
fg="#f0c96b",
bg="#1a202b"
)
timer_label.pack(
pady=5
)
status_label = tk.Label(
question_box,
text="",
font=("Arial", 10),
fg="#8d99aa",
bg="#1a202b"
)
status_label.pack(
pady=(0, 18)
)
# ==========================================
# 첫 번째 버튼 줄
# ==========================================
button_frame = tk.Frame(
root,
bg="#10141c"
)
button_frame.pack(
pady=18
)
def make_button(parent, text, command, color):
return tk.Button(
parent,
text=text,
command=command,
font=("Arial", 11, "bold"),
bg=color,
fg="white",
activebackground=color,
activeforeground="white",
relief="flat",
padx=15,
pady=10,
cursor="hand2"
)
make_button(
button_frame,
"🎲 새 문제",
new_question,
"#4d6fff"
).grid(
row=0,
column=0,
padx=4
)
make_button(
button_frame,
"🙈 숨기기",
hide_question,
"#303b4d"
).grid(
row=0,
column=1,
padx=4
)
make_button(
button_frame,
"👁 보기",
reveal_question,
"#303b4d"
).grid(
row=0,
column=2,
padx=4
)
# ==========================================
# 두 번째 버튼 줄
# ==========================================
button_frame2 = tk.Frame(
root,
bg="#10141c"
)
button_frame2.pack()
make_button(
button_frame2,
"✅ 성공",
success,
"#237a54"
).pack(
side="left",
padx=4
)
make_button(
button_frame2,
"❌ 실패",
failure,
"#8a3e4e"
).pack(
side="left",
padx=4
)
make_button(
button_frame2,
"🔄 초기화",
reset_all,
"#303b4d"
).pack(
side="left",
padx=4
)
# ==========================================
# 진행률
# ==========================================
progress_label = tk.Label(
root,
text="전체 조합: 0 / 1,300 | 남은 조합: 1,300",
font=("Arial", 11, "bold"),
fg="#d7deea",
bg="#10141c"
)
progress_label.pack(
pady=(25, 6)
)
# ==========================================
# 통계
# ==========================================
stats_label = tk.Label(
root,
text="연습 0회 성공 0 실패 0 성공률 0.0%",
font=("Arial", 11),
fg="#aab5c6",
bg="#10141c"
)
stats_label.pack()
# ==========================================
# 설명
# ==========================================
tip_label = tk.Label(
root,
text=(
"카드 + 숫자 확인 → 숨기기 → "
"실제 아칸 루틴 수행 → 성공/실패 기록"
),
font=("Arial", 9),
fg="#727f92",
bg="#10141c"
)
tip_label.pack(
pady=20
)
# ==========================================
# 첫 문제
# ==========================================
new_question()
# ==========================================
# 실행
# ==========================================
root.mainloop()