Skip to content

Commit 9c3a97b

Browse files
committed
feat: add SQLite support for persistent high scores in terminal games closes 972
1 parent 7485c79 commit 9c3a97b

4 files changed

Lines changed: 94 additions & 7 deletions

File tree

games/Whack-a-Mole/Whack-a-Mole.py

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
import os
99
import sys
1010

11+
# Add root directory to sys.path to import utils package
12+
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
13+
from utils import save_score, get_top_scores
14+
1115
# Windows only for non-blocking input
1216
try:
1317
import msvcrt
@@ -194,14 +198,19 @@
194198
avg_rt = sum(reaction_times) / len(reaction_times)
195199
print(f" ⚡ Avg Reaction: {avg_rt:.2f}s")
196200

197-
if accuracy >= 90:
198-
print("\n 🌟 Legendary reflexes!")
199-
elif accuracy >= 70:
200-
print("\n 👏 Great job!")
201-
elif accuracy >= 50:
202-
print("\n 😅 Not bad — keep practising!")
201+
# Save and display high scores
202+
name = input("\n Enter your name for the high scores board: ").strip()
203+
if name:
204+
save_score("Whack-a-Mole", name, score)
205+
206+
print("\n🏆 ===== HIGH SCORES BOARD =====")
207+
top_scores = get_top_scores("Whack-a-Mole", 5)
208+
if top_scores:
209+
for idx, (p_name, p_score, p_time) in enumerate(top_scores):
210+
print(f" {idx+1}. {p_name:15s} : {p_score:4d} ({p_time})")
203211
else:
204-
print("\n 🐭 The moles win this round...")
212+
print(" No high scores yet!")
213+
print("================================")
205214

206215
while True:
207216
replay = input("\n Play again? (y / n): ").strip().lower()

utilities/Typing-Speed-Tester/Typing-Speed-Tester.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22
import random
33
import urllib.request
44
import json
5+
import sys
6+
import os
7+
8+
# Add root directory to sys.path to import utils package
9+
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
10+
from utils import save_score, get_top_scores
511

612
# Local fallback sentences
713
fallback_sentences = [
@@ -97,6 +103,20 @@
97103
print("👍 Good Attempt!")
98104
else:
99105
print("💡 Keep Practicing!")
106+
107+
# Save and display high scores
108+
name = input("\n Enter your name for the high scores board: ").strip()
109+
if name:
110+
save_score("Typing-Speed-Tester", name, int(wpm))
111+
112+
print("\n🏆 ===== HIGH SCORES BOARD =====")
113+
top_scores = get_top_scores("Typing-Speed-Tester", 5)
114+
if top_scores:
115+
for idx, (p_name, p_score, p_time) in enumerate(top_scores):
116+
print(f" {idx+1}. {p_name:15s} : {p_score:4d} WPM ({p_time})")
117+
else:
118+
print(" No high scores yet!")
119+
print("================================")
100120

101121
again = input("\n🔄 Do you want to test again? (y/n): ").strip().lower()
102122
if again != 'y':

utils/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
# Central utilities package
2+
from utils.db_manager import save_score, get_top_scores

utils/db_manager.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import os
2+
import sqlite3
3+
from datetime import datetime
4+
5+
# Resolve database path to root directory
6+
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
7+
DB_PATH = os.path.join(BASE_DIR, "data.db")
8+
9+
def get_connection():
10+
"""Returns a connection to the SQLite database."""
11+
conn = sqlite3.connect(DB_PATH)
12+
return conn
13+
14+
def init_db():
15+
"""Initializes the database and creates high_scores table if it doesn't exist."""
16+
conn = get_connection()
17+
cursor = conn.cursor()
18+
cursor.execute("""
19+
CREATE TABLE IF NOT EXISTS high_scores (
20+
id INTEGER PRIMARY KEY AUTOINCREMENT,
21+
game_name TEXT NOT NULL,
22+
player_name TEXT NOT NULL,
23+
score INTEGER NOT NULL,
24+
timestamp TEXT NOT NULL
25+
)
26+
""")
27+
conn.commit()
28+
conn.close()
29+
30+
def save_score(game_name: str, player_name: str, score: int):
31+
"""Saves a player's score to the database."""
32+
init_db()
33+
conn = get_connection()
34+
cursor = conn.cursor()
35+
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
36+
cursor.execute("""
37+
INSERT INTO high_scores (game_name, player_name, score, timestamp)
38+
VALUES (?, ?, ?, ?)
39+
""", (game_name, player_name.strip(), score, timestamp))
40+
conn.commit()
41+
conn.close()
42+
43+
def get_top_scores(game_name: str, limit: int = 5):
44+
"""Retrieves top scores for a specific game."""
45+
init_db()
46+
conn = get_connection()
47+
cursor = conn.cursor()
48+
cursor.execute("""
49+
SELECT player_name, score, timestamp
50+
FROM high_scores
51+
WHERE game_name = ?
52+
ORDER BY score DESC, timestamp ASC
53+
LIMIT ?
54+
""", (game_name, limit))
55+
results = cursor.fetchall()
56+
conn.close()
57+
return results

0 commit comments

Comments
 (0)