From eb46f6b1e0d93d8687bc5b138a6954371279dd1c Mon Sep 17 00:00:00 2001 From: = <=> Date: Thu, 17 Jul 2025 21:15:38 +0530 Subject: [PATCH 1/6] gave correctc name to file and made a tkinter gui based rock papre scissors --- stone-paper-scissors.py | 210 ++++++++++++++++++++++++++++++++++++++++ stone-paper-sssc.py | 59 ----------- 2 files changed, 210 insertions(+), 59 deletions(-) create mode 100644 stone-paper-scissors.py delete mode 100644 stone-paper-sssc.py diff --git a/stone-paper-scissors.py b/stone-paper-scissors.py new file mode 100644 index 0000000..ac04aab --- /dev/null +++ b/stone-paper-scissors.py @@ -0,0 +1,210 @@ +import tkinter as tk +import random +import json +import os +from datetime import datetime + +MOVES = {'R': 'Rock 🪨', 'P': 'Paper 📄', 'S': 'Scissors ✂️'} + +class RPSGame: + def __init__(self, root): + self.root = root + self.root.title("🎉 Rock Paper Scissors Ultimate 🎉") + self.root.geometry("500x600") + self.root.configure(bg="#FFFAE3") + + self.wins = 0 + self.losses = 0 + self.ties = 0 + self.streak = 0 + self.history = [] + self.load_data() + + self.build_ui() + + def build_ui(self): + tk.Label(self.root, text="ROCK PAPER SCISSORS!", font=("Comic Sans MS", 28, "bold"), + bg="#FFFAE3", fg="#FF6B6B").pack(pady=20) + + self.stats_label = tk.Label(self.root, font=("Comic Sans MS", 14), + bg="#FFFAE3", fg="#444") + self.stats_label.pack(pady=10) + + self.result_label = tk.Label(self.root, font=("Comic Sans MS", 20, "bold"), + width=30, height=2, bg="#FFFAE3") + self.result_label.pack(pady=20) + + btn_frame = tk.Frame(self.root, bg="#FFFAE3") + btn_frame.pack(pady=20) + + rock_btn = tk.Button(btn_frame, text="🪨 Rock", command=lambda: self.play('R')) + paper_btn = tk.Button(btn_frame, text="📄 Paper", command=lambda: self.play('P')) + scissors_btn = tk.Button(btn_frame, text="✂️ Scissors", command=lambda: self.play('S')) + + for btn in (rock_btn, paper_btn, scissors_btn): + btn.config(font=("Comic Sans MS", 14, "bold"), + bg="#FFD93D", fg="#444", + activebackground="#FF6B6B", activeforeground="#fff", + width=10, height=2, bd=4, relief="groove", cursor="hand2") + btn.pack(side="left", padx=15) + + tk.Button(self.root, text="📋 View History", command=self.show_history, + font=("Comic Sans MS", 12), bg="#5CD859", fg="white", + width=20, height=2).pack(pady=10) + + tk.Button(self.root, text="🏆 View Leaderboard", command=self.show_leaderboard, + font=("Comic Sans MS", 12), bg="#FF6B6B", fg="white", + width=20, height=2).pack(pady=10) + + tk.Button(self.root, text="🔄 Reset Stats", command=self.reset_game, + font=("Comic Sans MS", 12), bg="#FFD93D", fg="#444", + width=20, height=2).pack(pady=10) + + tk.Button(self.root, text="🚪 Quit", command=self.quit_game, + font=("Comic Sans MS", 12), bg="#FF6B6B", fg="white", + width=20, height=2).pack(pady=10) + + self.update_stats() + + def load_data(self): + if os.path.exists('rps_gui_save.json'): + try: + with open('rps_gui_save.json', 'r') as f: + data = json.load(f) + self.wins = data.get('wins', 0) + self.losses = data.get('losses', 0) + self.ties = data.get('ties', 0) + self.streak = data.get('streak', 0) + self.history = data.get('history', []) + except: + pass + + def save_data(self): + data = { + 'wins': self.wins, + 'losses': self.losses, + 'ties': self.ties, + 'streak': self.streak, + 'history': self.history + } + with open('rps_gui_save.json', 'w') as f: + json.dump(data, f) + + def adaptive_ai(self): + if len(self.history) < 3: + return random.choice(['R', 'P', 'S']) + last_moves = [h['player'] for h in self.history[-3:]] + most_common = max(set(last_moves), key=last_moves.count) + counter = {'R': 'P', 'P': 'S', 'S': 'R'} + return counter[most_common] + + def play(self, user_move): + computer_move = self.adaptive_ai() + result = self.determine_winner(user_move, computer_move) + + self.history.append({ + 'time': datetime.now().strftime("%Y-%m-%d %H:%M"), + 'player': user_move, + 'computer': computer_move, + 'result': result + }) + + feedback = { + 'win': ("You Win! 🥳", "#5CD859"), + 'loss': ("Computer Wins! 😝", "#FF6B6B"), + 'tie': ("It's a Draw! 🤝", "#FFD93D") + } + + text, color = feedback[result] + self.result_label.config(text=f"{MOVES[user_move]} vs {MOVES[computer_move]} — {text}", bg=color) + self.update_stats() + self.save_data() + + def determine_winner(self, player, computer): + if player == computer: + self.ties += 1 + self.streak = 0 + return 'tie' + elif (player == 'R' and computer == 'S') or \ + (player == 'P' and computer == 'R') or \ + (player == 'S' and computer == 'P'): + self.wins += 1 + self.streak += 1 + return 'win' + else: + self.losses += 1 + self.streak = 0 + return 'loss' + + def update_stats(self): + total = self.wins + self.losses + self.ties + win_rate = (self.wins / total * 100) if total > 0 else 0 + self.stats_label.config( + text=f"Wins: {self.wins} Losses: {self.losses} Ties: {self.ties}\n" + f"Streak: {self.streak} Win Rate: {win_rate:.1f}%" + ) + + def show_history(self): + history_window = tk.Toplevel(self.root) + history_window.title("📋 Game History") + history_window.configure(bg="#FFFAE3") + + tk.Label(history_window, text="Last 10 Matches", font=("Comic Sans MS", 16, "bold"), + bg="#FFFAE3").pack(pady=10) + + text = tk.Text(history_window, width=50, height=15, bg="#fff", font=("Comic Sans MS", 12)) + text.pack(padx=10, pady=10) + + for h in self.history[-10:]: + result = "Win" if h['result'] == 'win' else "Loss" if h['result'] == 'loss' else "Tie" + text.insert(tk.END, f"{h['time']}: You chose {MOVES[h['player']]}, Computer chose {MOVES[h['computer']]} — {result}\n") + + text.config(state='disabled') + + def show_leaderboard(self): + leaderboard_window = tk.Toplevel(self.root) + leaderboard_window.title("🏆 Leaderboard") + leaderboard_window.configure(bg="#FFFAE3") + + max_streak = 0 + current_streak = 0 + for h in self.history: + if h['result'] == 'win': + current_streak += 1 + max_streak = max(max_streak, current_streak) + else: + current_streak = 0 + + total_games = len(self.history) + win_rate = (self.wins / total_games * 100) if total_games > 0 else 0 + + tk.Label(leaderboard_window, text="Your Leaderboard", font=("Comic Sans MS", 16, "bold"), + bg="#FFFAE3").pack(pady=10) + + stats = f""" + Total Games: {total_games} + Wins: {self.wins} + Losses: {self.losses} + Ties: {self.ties} + Longest Win Streak: {max_streak} + Current Win Streak: {self.streak} + Win Rate: {win_rate:.1f}% + """ + tk.Label(leaderboard_window, text=stats.strip(), justify='left', + bg="#FFFAE3", font=("Comic Sans MS", 12)).pack(pady=20) + + def reset_game(self): + self.wins = self.losses = self.ties = self.streak = 0 + self.history = [] + self.update_stats() + self.result_label.config(text="", bg="#FFFAE3") + self.save_data() + + def quit_game(self): + self.save_data() + self.root.quit() + + +root = tk.Tk() +app = RPSGame(root) +root.mainloop() diff --git a/stone-paper-sssc.py b/stone-paper-sssc.py deleted file mode 100644 index 47c766f..0000000 --- a/stone-paper-sssc.py +++ /dev/null @@ -1,59 +0,0 @@ -import random, sys - -print("Let's Play ROCK PAPER SCISSORS GAME!") - -wins = 0 -losses = 0 -ties = 0 - -while True: - print("Current streak: %s Wins, %s Losses, %s Ties" % (wins, losses, ties)) - while True: - print("Type 'Q' to quit \n'R' for ROCK, 'P' for PAPER, 'S' for SCISSORS") - playermove = input().upper() - if playermove == "Q": - sys.exit() - if playermove == "R" or playermove == "P" or playermove == "S": - break - - if playermove == "R": - print("ROCK versus...") - if playermove == "P": - print("PAPER versus...") - if playermove == "S": - print("SCISSORS versus...") - - randomNum = random.randint(1, 3) - if randomNum == 1: - compMove = "R" - print("ROCK") - if randomNum == 2: - compMove = "P" - print("PAPER") - if randomNum == 3: - compMove = "S" - print("SCISSORS") - - if playermove == compMove: - print("It's a tie!") - ties += 1 - elif playermove == "R" and compMove == "P": - print("It's a loss!") - losses += 1 - elif playermove == "R" and compMove == "S": - print("It's a win!") - wins += 1 - elif playermove == "P" and compMove == "S": - print("It's a loss!") - losses += 1 - elif playermove == "P" and compMove == "R": - print("It's a win!") - wins += 1 - elif playermove == "S" and compMove == "R": - print("It's a loss!") - losses += 1 - elif playermove == "S" and compMove == "P": - print("It's a win!") - wins += 1 - else: - print("Thanks for trying my game") From 7efe7a7c0220aac66540621ccabbb1dc091a43f7 Mon Sep 17 00:00:00 2001 From: = <=> Date: Thu, 17 Jul 2025 21:16:08 +0530 Subject: [PATCH 2/6] gave correctc name to file and made a tkinter gui based rock papre scissors --- stone-paper-sssc.py | 210 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 210 insertions(+) create mode 100644 stone-paper-sssc.py diff --git a/stone-paper-sssc.py b/stone-paper-sssc.py new file mode 100644 index 0000000..ac04aab --- /dev/null +++ b/stone-paper-sssc.py @@ -0,0 +1,210 @@ +import tkinter as tk +import random +import json +import os +from datetime import datetime + +MOVES = {'R': 'Rock 🪨', 'P': 'Paper 📄', 'S': 'Scissors ✂️'} + +class RPSGame: + def __init__(self, root): + self.root = root + self.root.title("🎉 Rock Paper Scissors Ultimate 🎉") + self.root.geometry("500x600") + self.root.configure(bg="#FFFAE3") + + self.wins = 0 + self.losses = 0 + self.ties = 0 + self.streak = 0 + self.history = [] + self.load_data() + + self.build_ui() + + def build_ui(self): + tk.Label(self.root, text="ROCK PAPER SCISSORS!", font=("Comic Sans MS", 28, "bold"), + bg="#FFFAE3", fg="#FF6B6B").pack(pady=20) + + self.stats_label = tk.Label(self.root, font=("Comic Sans MS", 14), + bg="#FFFAE3", fg="#444") + self.stats_label.pack(pady=10) + + self.result_label = tk.Label(self.root, font=("Comic Sans MS", 20, "bold"), + width=30, height=2, bg="#FFFAE3") + self.result_label.pack(pady=20) + + btn_frame = tk.Frame(self.root, bg="#FFFAE3") + btn_frame.pack(pady=20) + + rock_btn = tk.Button(btn_frame, text="🪨 Rock", command=lambda: self.play('R')) + paper_btn = tk.Button(btn_frame, text="📄 Paper", command=lambda: self.play('P')) + scissors_btn = tk.Button(btn_frame, text="✂️ Scissors", command=lambda: self.play('S')) + + for btn in (rock_btn, paper_btn, scissors_btn): + btn.config(font=("Comic Sans MS", 14, "bold"), + bg="#FFD93D", fg="#444", + activebackground="#FF6B6B", activeforeground="#fff", + width=10, height=2, bd=4, relief="groove", cursor="hand2") + btn.pack(side="left", padx=15) + + tk.Button(self.root, text="📋 View History", command=self.show_history, + font=("Comic Sans MS", 12), bg="#5CD859", fg="white", + width=20, height=2).pack(pady=10) + + tk.Button(self.root, text="🏆 View Leaderboard", command=self.show_leaderboard, + font=("Comic Sans MS", 12), bg="#FF6B6B", fg="white", + width=20, height=2).pack(pady=10) + + tk.Button(self.root, text="🔄 Reset Stats", command=self.reset_game, + font=("Comic Sans MS", 12), bg="#FFD93D", fg="#444", + width=20, height=2).pack(pady=10) + + tk.Button(self.root, text="🚪 Quit", command=self.quit_game, + font=("Comic Sans MS", 12), bg="#FF6B6B", fg="white", + width=20, height=2).pack(pady=10) + + self.update_stats() + + def load_data(self): + if os.path.exists('rps_gui_save.json'): + try: + with open('rps_gui_save.json', 'r') as f: + data = json.load(f) + self.wins = data.get('wins', 0) + self.losses = data.get('losses', 0) + self.ties = data.get('ties', 0) + self.streak = data.get('streak', 0) + self.history = data.get('history', []) + except: + pass + + def save_data(self): + data = { + 'wins': self.wins, + 'losses': self.losses, + 'ties': self.ties, + 'streak': self.streak, + 'history': self.history + } + with open('rps_gui_save.json', 'w') as f: + json.dump(data, f) + + def adaptive_ai(self): + if len(self.history) < 3: + return random.choice(['R', 'P', 'S']) + last_moves = [h['player'] for h in self.history[-3:]] + most_common = max(set(last_moves), key=last_moves.count) + counter = {'R': 'P', 'P': 'S', 'S': 'R'} + return counter[most_common] + + def play(self, user_move): + computer_move = self.adaptive_ai() + result = self.determine_winner(user_move, computer_move) + + self.history.append({ + 'time': datetime.now().strftime("%Y-%m-%d %H:%M"), + 'player': user_move, + 'computer': computer_move, + 'result': result + }) + + feedback = { + 'win': ("You Win! 🥳", "#5CD859"), + 'loss': ("Computer Wins! 😝", "#FF6B6B"), + 'tie': ("It's a Draw! 🤝", "#FFD93D") + } + + text, color = feedback[result] + self.result_label.config(text=f"{MOVES[user_move]} vs {MOVES[computer_move]} — {text}", bg=color) + self.update_stats() + self.save_data() + + def determine_winner(self, player, computer): + if player == computer: + self.ties += 1 + self.streak = 0 + return 'tie' + elif (player == 'R' and computer == 'S') or \ + (player == 'P' and computer == 'R') or \ + (player == 'S' and computer == 'P'): + self.wins += 1 + self.streak += 1 + return 'win' + else: + self.losses += 1 + self.streak = 0 + return 'loss' + + def update_stats(self): + total = self.wins + self.losses + self.ties + win_rate = (self.wins / total * 100) if total > 0 else 0 + self.stats_label.config( + text=f"Wins: {self.wins} Losses: {self.losses} Ties: {self.ties}\n" + f"Streak: {self.streak} Win Rate: {win_rate:.1f}%" + ) + + def show_history(self): + history_window = tk.Toplevel(self.root) + history_window.title("📋 Game History") + history_window.configure(bg="#FFFAE3") + + tk.Label(history_window, text="Last 10 Matches", font=("Comic Sans MS", 16, "bold"), + bg="#FFFAE3").pack(pady=10) + + text = tk.Text(history_window, width=50, height=15, bg="#fff", font=("Comic Sans MS", 12)) + text.pack(padx=10, pady=10) + + for h in self.history[-10:]: + result = "Win" if h['result'] == 'win' else "Loss" if h['result'] == 'loss' else "Tie" + text.insert(tk.END, f"{h['time']}: You chose {MOVES[h['player']]}, Computer chose {MOVES[h['computer']]} — {result}\n") + + text.config(state='disabled') + + def show_leaderboard(self): + leaderboard_window = tk.Toplevel(self.root) + leaderboard_window.title("🏆 Leaderboard") + leaderboard_window.configure(bg="#FFFAE3") + + max_streak = 0 + current_streak = 0 + for h in self.history: + if h['result'] == 'win': + current_streak += 1 + max_streak = max(max_streak, current_streak) + else: + current_streak = 0 + + total_games = len(self.history) + win_rate = (self.wins / total_games * 100) if total_games > 0 else 0 + + tk.Label(leaderboard_window, text="Your Leaderboard", font=("Comic Sans MS", 16, "bold"), + bg="#FFFAE3").pack(pady=10) + + stats = f""" + Total Games: {total_games} + Wins: {self.wins} + Losses: {self.losses} + Ties: {self.ties} + Longest Win Streak: {max_streak} + Current Win Streak: {self.streak} + Win Rate: {win_rate:.1f}% + """ + tk.Label(leaderboard_window, text=stats.strip(), justify='left', + bg="#FFFAE3", font=("Comic Sans MS", 12)).pack(pady=20) + + def reset_game(self): + self.wins = self.losses = self.ties = self.streak = 0 + self.history = [] + self.update_stats() + self.result_label.config(text="", bg="#FFFAE3") + self.save_data() + + def quit_game(self): + self.save_data() + self.root.quit() + + +root = tk.Tk() +app = RPSGame(root) +root.mainloop() From ea97c60088f58aaefeabe7d7fb6e902cf246b234 Mon Sep 17 00:00:00 2001 From: = <=> Date: Thu, 17 Jul 2025 22:09:55 +0530 Subject: [PATCH 3/6] deleted old file --- stone-paper-sssc.py | 210 -------------------------------------------- 1 file changed, 210 deletions(-) delete mode 100644 stone-paper-sssc.py diff --git a/stone-paper-sssc.py b/stone-paper-sssc.py deleted file mode 100644 index ac04aab..0000000 --- a/stone-paper-sssc.py +++ /dev/null @@ -1,210 +0,0 @@ -import tkinter as tk -import random -import json -import os -from datetime import datetime - -MOVES = {'R': 'Rock 🪨', 'P': 'Paper 📄', 'S': 'Scissors ✂️'} - -class RPSGame: - def __init__(self, root): - self.root = root - self.root.title("🎉 Rock Paper Scissors Ultimate 🎉") - self.root.geometry("500x600") - self.root.configure(bg="#FFFAE3") - - self.wins = 0 - self.losses = 0 - self.ties = 0 - self.streak = 0 - self.history = [] - self.load_data() - - self.build_ui() - - def build_ui(self): - tk.Label(self.root, text="ROCK PAPER SCISSORS!", font=("Comic Sans MS", 28, "bold"), - bg="#FFFAE3", fg="#FF6B6B").pack(pady=20) - - self.stats_label = tk.Label(self.root, font=("Comic Sans MS", 14), - bg="#FFFAE3", fg="#444") - self.stats_label.pack(pady=10) - - self.result_label = tk.Label(self.root, font=("Comic Sans MS", 20, "bold"), - width=30, height=2, bg="#FFFAE3") - self.result_label.pack(pady=20) - - btn_frame = tk.Frame(self.root, bg="#FFFAE3") - btn_frame.pack(pady=20) - - rock_btn = tk.Button(btn_frame, text="🪨 Rock", command=lambda: self.play('R')) - paper_btn = tk.Button(btn_frame, text="📄 Paper", command=lambda: self.play('P')) - scissors_btn = tk.Button(btn_frame, text="✂️ Scissors", command=lambda: self.play('S')) - - for btn in (rock_btn, paper_btn, scissors_btn): - btn.config(font=("Comic Sans MS", 14, "bold"), - bg="#FFD93D", fg="#444", - activebackground="#FF6B6B", activeforeground="#fff", - width=10, height=2, bd=4, relief="groove", cursor="hand2") - btn.pack(side="left", padx=15) - - tk.Button(self.root, text="📋 View History", command=self.show_history, - font=("Comic Sans MS", 12), bg="#5CD859", fg="white", - width=20, height=2).pack(pady=10) - - tk.Button(self.root, text="🏆 View Leaderboard", command=self.show_leaderboard, - font=("Comic Sans MS", 12), bg="#FF6B6B", fg="white", - width=20, height=2).pack(pady=10) - - tk.Button(self.root, text="🔄 Reset Stats", command=self.reset_game, - font=("Comic Sans MS", 12), bg="#FFD93D", fg="#444", - width=20, height=2).pack(pady=10) - - tk.Button(self.root, text="🚪 Quit", command=self.quit_game, - font=("Comic Sans MS", 12), bg="#FF6B6B", fg="white", - width=20, height=2).pack(pady=10) - - self.update_stats() - - def load_data(self): - if os.path.exists('rps_gui_save.json'): - try: - with open('rps_gui_save.json', 'r') as f: - data = json.load(f) - self.wins = data.get('wins', 0) - self.losses = data.get('losses', 0) - self.ties = data.get('ties', 0) - self.streak = data.get('streak', 0) - self.history = data.get('history', []) - except: - pass - - def save_data(self): - data = { - 'wins': self.wins, - 'losses': self.losses, - 'ties': self.ties, - 'streak': self.streak, - 'history': self.history - } - with open('rps_gui_save.json', 'w') as f: - json.dump(data, f) - - def adaptive_ai(self): - if len(self.history) < 3: - return random.choice(['R', 'P', 'S']) - last_moves = [h['player'] for h in self.history[-3:]] - most_common = max(set(last_moves), key=last_moves.count) - counter = {'R': 'P', 'P': 'S', 'S': 'R'} - return counter[most_common] - - def play(self, user_move): - computer_move = self.adaptive_ai() - result = self.determine_winner(user_move, computer_move) - - self.history.append({ - 'time': datetime.now().strftime("%Y-%m-%d %H:%M"), - 'player': user_move, - 'computer': computer_move, - 'result': result - }) - - feedback = { - 'win': ("You Win! 🥳", "#5CD859"), - 'loss': ("Computer Wins! 😝", "#FF6B6B"), - 'tie': ("It's a Draw! 🤝", "#FFD93D") - } - - text, color = feedback[result] - self.result_label.config(text=f"{MOVES[user_move]} vs {MOVES[computer_move]} — {text}", bg=color) - self.update_stats() - self.save_data() - - def determine_winner(self, player, computer): - if player == computer: - self.ties += 1 - self.streak = 0 - return 'tie' - elif (player == 'R' and computer == 'S') or \ - (player == 'P' and computer == 'R') or \ - (player == 'S' and computer == 'P'): - self.wins += 1 - self.streak += 1 - return 'win' - else: - self.losses += 1 - self.streak = 0 - return 'loss' - - def update_stats(self): - total = self.wins + self.losses + self.ties - win_rate = (self.wins / total * 100) if total > 0 else 0 - self.stats_label.config( - text=f"Wins: {self.wins} Losses: {self.losses} Ties: {self.ties}\n" - f"Streak: {self.streak} Win Rate: {win_rate:.1f}%" - ) - - def show_history(self): - history_window = tk.Toplevel(self.root) - history_window.title("📋 Game History") - history_window.configure(bg="#FFFAE3") - - tk.Label(history_window, text="Last 10 Matches", font=("Comic Sans MS", 16, "bold"), - bg="#FFFAE3").pack(pady=10) - - text = tk.Text(history_window, width=50, height=15, bg="#fff", font=("Comic Sans MS", 12)) - text.pack(padx=10, pady=10) - - for h in self.history[-10:]: - result = "Win" if h['result'] == 'win' else "Loss" if h['result'] == 'loss' else "Tie" - text.insert(tk.END, f"{h['time']}: You chose {MOVES[h['player']]}, Computer chose {MOVES[h['computer']]} — {result}\n") - - text.config(state='disabled') - - def show_leaderboard(self): - leaderboard_window = tk.Toplevel(self.root) - leaderboard_window.title("🏆 Leaderboard") - leaderboard_window.configure(bg="#FFFAE3") - - max_streak = 0 - current_streak = 0 - for h in self.history: - if h['result'] == 'win': - current_streak += 1 - max_streak = max(max_streak, current_streak) - else: - current_streak = 0 - - total_games = len(self.history) - win_rate = (self.wins / total_games * 100) if total_games > 0 else 0 - - tk.Label(leaderboard_window, text="Your Leaderboard", font=("Comic Sans MS", 16, "bold"), - bg="#FFFAE3").pack(pady=10) - - stats = f""" - Total Games: {total_games} - Wins: {self.wins} - Losses: {self.losses} - Ties: {self.ties} - Longest Win Streak: {max_streak} - Current Win Streak: {self.streak} - Win Rate: {win_rate:.1f}% - """ - tk.Label(leaderboard_window, text=stats.strip(), justify='left', - bg="#FFFAE3", font=("Comic Sans MS", 12)).pack(pady=20) - - def reset_game(self): - self.wins = self.losses = self.ties = self.streak = 0 - self.history = [] - self.update_stats() - self.result_label.config(text="", bg="#FFFAE3") - self.save_data() - - def quit_game(self): - self.save_data() - self.root.quit() - - -root = tk.Tk() -app = RPSGame(root) -root.mainloop() From d1df7413f4ab7286ce69bb26e5bad074bf792b14 Mon Sep 17 00:00:00 2001 From: = <=> Date: Tue, 22 Jul 2025 21:49:29 +0530 Subject: [PATCH 4/6] added mobile app friendly version of stone paper scissors --- assets/paper.png | Bin 0 -> 7189 bytes assets/rock.png | Bin 0 -> 4432 bytes assets/scissors.png | Bin 0 -> 6001 bytes mobile-stone-paper-scissors.py | 166 +++++++++++++++++++++++++++++++++ rps.kv | 164 ++++++++++++++++++++++++++++++++ 5 files changed, 330 insertions(+) create mode 100644 assets/paper.png create mode 100644 assets/rock.png create mode 100644 assets/scissors.png create mode 100644 mobile-stone-paper-scissors.py create mode 100644 rps.kv diff --git a/assets/paper.png b/assets/paper.png new file mode 100644 index 0000000000000000000000000000000000000000..29d3d346f37965d8cc3d1dfd5eb8873e2bf5275b GIT binary patch literal 7189 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 S+ue3S9#-{j+hfp|pZ^CES8SL7 literal 0 HcmV?d00001 diff --git a/assets/rock.png b/assets/rock.png new file mode 100644 index 0000000000000000000000000000000000000000..1c8ca9e478a9d440ae1c715bac6b473e433d3d78 GIT binary patch literal 4432 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 literal 0 HcmV?d00001 diff --git a/assets/scissors.png b/assets/scissors.png new file mode 100644 index 0000000000000000000000000000000000000000..b15487010a86b1392d6c1f6f0bfb9a1493550936 GIT binary patch literal 6001 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 literal 0 HcmV?d00001 diff --git a/mobile-stone-paper-scissors.py b/mobile-stone-paper-scissors.py new file mode 100644 index 0000000..940dc97 --- /dev/null +++ b/mobile-stone-paper-scissors.py @@ -0,0 +1,166 @@ +from kivy.app import App +from kivy.lang import Builder +from kivy.uix.screenmanager import ScreenManager, Screen +from kivy.properties import StringProperty, NumericProperty, ListProperty +from kivy.uix.behaviors import ButtonBehavior +from kivy.uix.image import Image +from datetime import datetime +import random +import json +import os + + +class ImageButton(ButtonBehavior, Image): + pass + + +MOVES = {'R': 'Rock', 'P': 'Paper', 'S': 'Scissors'} + + +class HomeScreen(Screen): + pass + + +class GameScreen(Screen): + result_text = StringProperty("") + result_bg_color = ListProperty([1, 1, 1, 1]) + + wins = NumericProperty(0) + losses = NumericProperty(0) + ties = NumericProperty(0) + streak = NumericProperty(0) + + def on_pre_enter(self): + self.load_data() + self.update_stats() + + def adaptive_ai(self): + if len(self.manager.history) < 3: + return random.choice(['R', 'P', 'S']) + last_moves = [h['player'] for h in self.manager.history[-3:]] + most_common = max(set(last_moves), key=last_moves.count) + counter = {'R': 'P', 'P': 'S', 'S': 'R'} + return counter[most_common] + + def play(self, user_move): + computer_move = self.adaptive_ai() + result = self.determine_winner(user_move, computer_move) + self.manager.history.append({ + 'time': datetime.now().strftime("%Y-%m-%d %H:%M"), + 'player': user_move, + 'computer': computer_move, + 'result': result + }) + + feedback = { + 'win': ("You Win!", [0.36, 0.85, 0.35, 1]), + 'loss': ("Computer Wins!", [0.95, 0.42, 0.42, 1]), + 'tie': ("It's a Draw!", [0.99, 0.85, 0.24, 1]) + } + text, color = feedback[result] + self.result_text = f"{MOVES[user_move]} vs {MOVES[computer_move]} — {text}" + self.result_bg_color = color + self.update_stats() + self.save_data() + + def determine_winner(self, player, computer): + if player == computer: + self.ties += 1 + self.streak = 0 + return 'tie' + elif (player == 'R' and computer == 'S') or \ + (player == 'P' and computer == 'R') or \ + (player == 'S' and computer == 'P'): + self.wins += 1 + self.streak += 1 + return 'win' + else: + self.losses += 1 + self.streak = 0 + return 'loss' + + def update_stats(self): + total = self.wins + self.losses + self.ties + win_rate = (self.wins / total * 100) if total > 0 else 0 + self.ids.stats_label.text = f"Wins: {self.wins} Losses: {self.losses} Ties: {self.ties}\nStreak: {self.streak} Win Rate: {win_rate:.1f}%" + + def load_data(self): + if os.path.exists('rps_kivy_save.json'): + try: + with open('rps_kivy_save.json', 'r') as f: + data = json.load(f) + self.wins = data.get('wins', 0) + self.losses = data.get('losses', 0) + self.ties = data.get('ties', 0) + self.streak = data.get('streak', 0) + self.manager.history = data.get('history', []) + except: + pass + + def save_data(self): + data = { + 'wins': self.wins, + 'losses': self.losses, + 'ties': self.ties, + 'streak': self.streak, + 'history': self.manager.history + } + with open('rps_kivy_save.json', 'w') as f: + json.dump(data, f) + + def reset_game(self): + self.wins = self.losses = self.ties = self.streak = 0 + self.manager.history = [] + self.update_stats() + self.result_text = "" + self.result_bg_color = [1, 1, 1, 1] + self.save_data() + + +class HistoryScreen(Screen): + def on_pre_enter(self): + self.ids.history_text.text = "\n".join([ + f"{h['time']} | {MOVES[h['player']]} vs {MOVES[h['computer']]} : {h['result'].capitalize()}" + for h in self.manager.history[-10:] + ]) or "No history yet." + + +class LeaderboardScreen(Screen): + def on_pre_enter(self): + gs = self.manager.get_screen('game') + max_streak = 0 + current_streak = 0 + for h in self.manager.history: + if h['result'] == 'win': + current_streak += 1 + max_streak = max(max_streak, current_streak) + else: + current_streak = 0 + total = len(self.manager.history) + win_rate = (gs.wins / total * 100) if total > 0 else 0 + + self.ids.leaderboard_label.text = f""" +Total Games: {total} +Wins: {gs.wins} +Losses: {gs.losses} +Ties: {gs.ties} +Longest Win Streak: {max_streak} +Current Streak: {gs.streak} +Win Rate: {win_rate:.1f}% + """ + + +class RPSApp(App): + def build(self): + Builder.load_file('rps.kv') + sm = ScreenManager() + sm.history = [] + sm.add_widget(HomeScreen(name='home')) + sm.add_widget(GameScreen(name='game')) + sm.add_widget(HistoryScreen(name='history')) + sm.add_widget(LeaderboardScreen(name='leaderboard')) + return sm + + +if __name__ == '__main__': + RPSApp().run() diff --git a/rps.kv b/rps.kv new file mode 100644 index 0000000..d524c63 --- /dev/null +++ b/rps.kv @@ -0,0 +1,164 @@ +#:import Window kivy.core.window.Window +#:import dp kivy.metrics.dp +#:import FadeTransition kivy.uix.screenmanager.FadeTransition +#:import ImageButton mobile-stone-paper-scissors.ImageButton + +ScreenManager: + transition: FadeTransition() + HomeScreen: + GameScreen: + HistoryScreen: + LeaderboardScreen: + +: + name: "home" + BoxLayout: + orientation: 'vertical' + padding: dp(20) + spacing: dp(20) + canvas.before: + Color: + rgba: .1, .1, .1, 1 + Rectangle: + pos: self.pos + size: self.size + Label: + text: "Rock Paper Scissors" + font_size: Window.width / 15 + color: 1, 1, 1, 1 + Button: + text: "Start Game" + font_size: Window.width / 25 + size_hint_y: None + height: dp(60) + on_press: root.manager.current = "game" + Button: + text: "Quit" + font_size: Window.width / 25 + size_hint_y: None + height: dp(60) + on_press: app.stop() + +: + name: "game" + BoxLayout: + orientation: 'vertical' + padding: dp(20) + spacing: dp(20) + canvas.before: + Color: + rgba: 0.05, 0.05, 0.05, 1 + Rectangle: + pos: self.pos + size: self.size + Label: + id: stats_label + text: "" + font_size: Window.width / 30 + color: 1, 1, 1, 1 + GridLayout: + cols: 3 + spacing: dp(15) + size_hint_y: None + height: dp(180) + + ImageButton: + source: "assets/rock.png" + on_release: root.play('R') + + ImageButton: + source: "assets/paper.png" + on_release: root.play('P') + + ImageButton: + source: "assets/scissors.png" + on_release: root.play('S') + + Label: + text: root.result_text + font_size: Window.width / 30 + color: 1, 1, 1, 1 + size_hint_y: None + height: dp(120) + canvas.before: + Color: + rgba: root.result_bg_color + RoundedRectangle: + pos: self.pos + size: self.size + radius: [20,] + BoxLayout: + size_hint_y: None + height: dp(50) + spacing: dp(10) + Button: + text: "History" + on_press: root.manager.current = "history" + Button: + text: "Leaderboard" + on_press: root.manager.current = "leaderboard" + Button: + text: "Reset" + on_press: root.reset_game() + Button: + text: "Back to Home" + size_hint_y: None + height: dp(50) + on_press: root.manager.current = "home" + +: + name: "history" + BoxLayout: + orientation: 'vertical' + padding: dp(20) + spacing: dp(20) + canvas.before: + Color: + rgba: 0.1, 0.1, 0.1, 1 + Rectangle: + pos: self.pos + size: self.size + Label: + text: "Last 10 Matches" + font_size: Window.width / 20 + color: 1, 1, 1, 1 + ScrollView: + Label: + id: history_text + size_hint_y: None + height: self.texture_size[1] + text_size: self.width, None + font_size: Window.width / 35 + color: 1, 1, 1, 1 + Button: + text: "Back" + size_hint_y: None + height: dp(50) + on_press: root.manager.current = "game" + +: + name: "leaderboard" + BoxLayout: + orientation: 'vertical' + padding: dp(20) + spacing: dp(20) + canvas.before: + Color: + rgba: 0.1, 0.1, 0.1, 1 + Rectangle: + pos: self.pos + size: self.size + Label: + text: "Leaderboard" + font_size: Window.width / 20 + color: 1, 1, 1, 1 + Label: + id: leaderboard_label + text: "" + font_size: Window.width / 35 + color: 1, 1, 1, 1 + Button: + text: "Back" + size_hint_y: None + height: dp(50) + on_press: root.manager.current = "game" From da30513db8e9485d36adc43b391911c1ceb22e24 Mon Sep 17 00:00:00 2001 From: = <=> Date: Sun, 3 Aug 2025 23:18:55 +0530 Subject: [PATCH 5/6] added a simple snake game --- snake game/snake_game.py | 160 ++++++++++++++++++++++++++++++++ snake game/snake_game_save.json | 1 + 2 files changed, 161 insertions(+) create mode 100644 snake game/snake_game.py create mode 100644 snake game/snake_game_save.json diff --git a/snake game/snake_game.py b/snake game/snake_game.py new file mode 100644 index 0000000..d8934e0 --- /dev/null +++ b/snake game/snake_game.py @@ -0,0 +1,160 @@ +import tkinter as tk +import random +import json +import os + +CELL_SIZE = 20 +GRID_WIDTH = 25 +GRID_HEIGHT = 25 +UPDATE_DELAY = 100 # ms + +SAVE_FILE = 'snake_game_save.json' + +class SnakeGame: + def __init__(self, root): + self.root = root + self.root.title("🐍 Snake Game Deluxe 🐍") + self.root.resizable(False, False) + + self.canvas = tk.Canvas(root, width=CELL_SIZE * GRID_WIDTH, + height=CELL_SIZE * GRID_HEIGHT, bg="#1e1e1e", bd=0, highlightthickness=0) + self.canvas.pack() + + self.score = 0 + self.high_score = 0 + self.snake = [(5, 5)] + self.direction = (1, 0) + self.food = None + self.game_running = False + + self.load_data() + self.draw_ui() + self.reset_game() + + self.root.bind("", self.change_direction) + + def draw_ui(self): + self.top_frame = tk.Frame(self.root, bg="#282c34") + self.top_frame.pack(fill="x") + + self.score_label = tk.Label(self.top_frame, text="Score: 0", fg="white", bg="#282c34", + font=("Consolas", 14, "bold")) + self.score_label.pack(side="left", padx=10) + + self.high_score_label = tk.Label(self.top_frame, text=f"High Score: {self.high_score}", fg="white", + bg="#282c34", font=("Consolas", 14, "bold")) + self.high_score_label.pack(side="right", padx=10) + + self.reset_button = tk.Button(self.top_frame, text="🔁 Restart", command=self.reset_game, + bg="#61afef", fg="white", font=("Consolas", 12, "bold"), bd=0, relief="flat") + self.reset_button.pack(side="left", padx=10) + + def load_data(self): + if os.path.exists(SAVE_FILE): + try: + with open(SAVE_FILE, 'r') as f: + data = json.load(f) + self.high_score = data.get("high_score", 0) + except: + self.high_score = 0 + + def save_data(self): + with open(SAVE_FILE, 'w') as f: + json.dump({"high_score": self.high_score}, f) + + def reset_game(self): + self.snake = [(5, 5)] + self.direction = (1, 0) + self.score = 0 + self.game_running = True + self.spawn_food() + self.update_ui() + self.game_loop() + + def spawn_food(self): + while True: + x = random.randint(0, GRID_WIDTH - 1) + y = random.randint(0, GRID_HEIGHT - 1) + if (x, y) not in self.snake: + self.food = (x, y) + break + + def change_direction(self, event): + key = event.keysym + new_dir = { + 'Up': (0, -1), + 'Down': (0, 1), + 'Left': (-1, 0), + 'Right': (1, 0) + }.get(key) + + if new_dir: + opposite = (-self.direction[0], -self.direction[1]) + if new_dir != opposite: # Prevent reversing + self.direction = new_dir + + def game_loop(self): + if not self.game_running: + return + + head_x, head_y = self.snake[-1] + dx, dy = self.direction + new_head = (head_x + dx, head_y + dy) + + if (new_head in self.snake or + new_head[0] < 0 or new_head[0] >= GRID_WIDTH or + new_head[1] < 0 or new_head[1] >= GRID_HEIGHT): + self.end_game() + return + + self.snake.append(new_head) + + if new_head == self.food: + self.score += 1 + self.spawn_food() + else: + self.snake.pop(0) + + self.update_ui() + self.root.after(UPDATE_DELAY, self.game_loop) + + def update_ui(self): + self.canvas.delete("all") + + # Draw snake + for segment in self.snake: + x1 = segment[0] * CELL_SIZE + y1 = segment[1] * CELL_SIZE + x2 = x1 + CELL_SIZE + y2 = y1 + CELL_SIZE + self.canvas.create_rectangle(x1, y1, x2, y2, fill="#98c379", outline="#1e1e1e") + + # Draw head with highlight + hx, hy = self.snake[-1] + self.canvas.create_rectangle(hx * CELL_SIZE, hy * CELL_SIZE, + hx * CELL_SIZE + CELL_SIZE, hy * CELL_SIZE + CELL_SIZE, + fill="#e06c75", outline="#1e1e1e") + + # Draw food + fx, fy = self.food + self.canvas.create_oval(fx * CELL_SIZE, fy * CELL_SIZE, + fx * CELL_SIZE + CELL_SIZE, fy * CELL_SIZE + CELL_SIZE, + fill="#d19a66", outline="#1e1e1e") + + self.score_label.config(text=f"Score: {self.score}") + + def end_game(self): + self.game_running = False + if self.score > self.high_score: + self.high_score = self.score + self.save_data() + self.high_score_label.config(text=f"High Score: {self.high_score}") + self.canvas.create_text(CELL_SIZE * GRID_WIDTH // 2, + CELL_SIZE * GRID_HEIGHT // 2, + text="Game Over", fill="white", + font=("Consolas", 24, "bold")) + +if __name__ == "__main__": + root = tk.Tk() + app = SnakeGame(root) + root.mainloop() diff --git a/snake game/snake_game_save.json b/snake game/snake_game_save.json new file mode 100644 index 0000000..1480e41 --- /dev/null +++ b/snake game/snake_game_save.json @@ -0,0 +1 @@ +{"high_score": 3} \ No newline at end of file From bb4b306cd0e2ecd700c8f2c210e34d9b65786788 Mon Sep 17 00:00:00 2001 From: Ayush Kumar Gaur Date: Wed, 6 Aug 2025 22:56:01 +0530 Subject: [PATCH 6/6] added mobile version --- snake game/snake_game_mobile.py | 176 ++++++++++++++++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 snake game/snake_game_mobile.py diff --git a/snake game/snake_game_mobile.py b/snake game/snake_game_mobile.py new file mode 100644 index 0000000..dac1810 --- /dev/null +++ b/snake game/snake_game_mobile.py @@ -0,0 +1,176 @@ +from kivy.app import App +from kivy.uix.widget import Widget +from kivy.uix.button import Button +from kivy.graphics import Color, Rectangle, Ellipse +from kivy.clock import Clock +from kivy.uix.boxlayout import BoxLayout +from kivy.uix.label import Label +from kivy.core.window import Window +import random +import json +import os + +CELL_SIZE = 20 +GRID_WIDTH = 25 +GRID_HEIGHT = 25 +UPDATE_DELAY = 0.1 +SAVE_FILE = "snake_game_save.json" + + +class SnakeGame(Widget): + def __init__(self, score_label, high_score_label, **kwargs): + super().__init__(**kwargs) + self.score_label = score_label + self.high_score_label = high_score_label + + self.snake = [(5, 5)] + self.direction = (1, 0) + self.food = None + self.score = 0 + self.high_score = 0 + self.game_running = True + + self.load_data() + self.spawn_food() + self.update_canvas() + + Clock.schedule_interval(self.update, UPDATE_DELAY) + Window.bind(on_key_down=self.on_key_down) + + def load_data(self): + if os.path.exists(SAVE_FILE): + try: + with open(SAVE_FILE, 'r') as f: + data = json.load(f) + self.high_score = data.get("high_score", 0) + except: + self.high_score = 0 + + def save_data(self): + with open(SAVE_FILE, 'w') as f: + json.dump({"high_score": self.high_score}, f) + + def reset_game(self): + self.snake = [(5, 5)] + self.direction = (1, 0) + self.score = 0 + self.game_running = True + self.spawn_food() + self.update_canvas() + self.score_label.text = f"Score: {self.score}" + self.high_score_label.text = f"High Score: {self.high_score}" + + def spawn_food(self): + while True: + x = random.randint(0, GRID_WIDTH - 1) + y = random.randint(0, GRID_HEIGHT - 1) + if (x, y) not in self.snake: + self.food = (x, y) + break + + def on_key_down(self, window, key, *args): + key_map = { + 273: (0, 1), # Up + 274: (0, -1), # Down + 276: (-1, 0), # Left + 275: (1, 0) # Right + } + if key in key_map: + new_dir = key_map[key] + opposite = (-self.direction[0], -self.direction[1]) + if new_dir != opposite: + self.direction = new_dir + + def update(self, dt): + if not self.game_running: + return + + head_x, head_y = self.snake[-1] + dx, dy = self.direction + new_head = (head_x + dx, head_y + dy) + + if (new_head in self.snake or + new_head[0] < 0 or new_head[0] >= GRID_WIDTH or + new_head[1] < 0 or new_head[1] >= GRID_HEIGHT): + self.end_game() + return + + self.snake.append(new_head) + + if new_head == self.food: + self.score += 1 + self.spawn_food() + else: + self.snake.pop(0) + + self.update_canvas() + self.score_label.text = f"Score: {self.score}" + + def update_canvas(self): + self.canvas.clear() + with self.canvas: + # Snake body + for segment in self.snake[:-1]: + Color(0.6, 0.8, 0.5) + Rectangle(pos=(segment[0] * CELL_SIZE, segment[1] * CELL_SIZE), + size=(CELL_SIZE, CELL_SIZE)) + + # Snake head + head = self.snake[-1] + Color(1, 0.4, 0.4) + Rectangle(pos=(head[0] * CELL_SIZE, head[1] * CELL_SIZE), + size=(CELL_SIZE, CELL_SIZE)) + + # Food + Color(0.8, 0.6, 0.3) + Ellipse(pos=(self.food[0] * CELL_SIZE, self.food[1] * CELL_SIZE), + size=(CELL_SIZE, CELL_SIZE)) + + def end_game(self): + self.game_running = False + if self.score > self.high_score: + self.high_score = self.score + self.save_data() + + self.high_score_label.text = f"High Score: {self.high_score}" + self.score_label.text = f"Game Over! Final Score: {self.score}" + self.canvas.clear() + with self.canvas: + Color(1, 1, 1) + Rectangle(pos=(0, (GRID_HEIGHT * CELL_SIZE) // 2 - 20), + size=(GRID_WIDTH * CELL_SIZE, 40)) + + +class SnakeApp(App): + def build(self): + Window.size = (GRID_WIDTH * CELL_SIZE, GRID_HEIGHT * CELL_SIZE + 40) + main_layout = BoxLayout(orientation="vertical", padding=0, spacing=0) + + # Score bar + top_bar = BoxLayout(size_hint_y=None, height=40, padding=10, spacing=10) + self.score_label = Label(text="Score: 0", color=(1, 1, 1, 1), + bold=True, font_size=16) + self.high_score_label = Label(text="High Score: 0", color=(1, 1, 1, 1), + bold=True, font_size=16) + + restart_btn = Button(text="🔁 Restart", background_color=(0.2, 0.6, 1, 1), + color=(1, 1, 1, 1), bold=True) + restart_btn.bind(on_press=self.restart_game) + + top_bar.add_widget(self.score_label) + top_bar.add_widget(self.high_score_label) + top_bar.add_widget(restart_btn) + + # Game + self.game = SnakeGame(score_label=self.score_label, high_score_label=self.high_score_label) + + main_layout.add_widget(top_bar) + main_layout.add_widget(self.game) + return main_layout + + def restart_game(self, instance): + self.game.reset_game() + + +if __name__ == '__main__': + SnakeApp().run()