From 5e8bc02f1182096fc20d2442f3f3ddbe0bdf095b Mon Sep 17 00:00:00 2001 From: Karok365 Date: Mon, 28 Oct 2024 21:00:37 +0530 Subject: [PATCH] Added player name customization, game timer, sound effects, and winner highlight feature --- Game_Development/Tic_Tac_Toe/tic_tac_toe.py | 109 +++++++++++++------- 1 file changed, 72 insertions(+), 37 deletions(-) diff --git a/Game_Development/Tic_Tac_Toe/tic_tac_toe.py b/Game_Development/Tic_Tac_Toe/tic_tac_toe.py index 3e0c554c79..d80db08ad2 100644 --- a/Game_Development/Tic_Tac_Toe/tic_tac_toe.py +++ b/Game_Development/Tic_Tac_Toe/tic_tac_toe.py @@ -1,5 +1,8 @@ import tkinter as tk -from tkinter import messagebox +from tkinter import messagebox, simpledialog +import time +import threading +import winsound # For Windows sound effects class TicTacToe: def __init__(self, root): @@ -8,37 +11,27 @@ def __init__(self, root): self.board = [''] * 9 self.current_player = 'X' self.buttons = [] - self.scores = {'X': 0, 'O': 0} # Scoreboard for both players - - # Display current player's turn - self.turn_label = tk.Label(self.root, text=f"Player {self.current_player}'s Turn", font='Arial 15') - self.turn_label.grid(row=3, column=0, columnspan=3) - - # Add Menu Bar + self.scores = {'X': 0, 'O': 0} + self.player_names = {'X': "Player 1", 'O': "Player 2"} + self.game_start_time = time.time() + self.timer_label = tk.Label(self.root, text="Time: 0s", font='Arial 12') + self.timer_label.grid(row=6, column=0, columnspan=3) + self.running = True self.create_menu_bar() - - # Display score - self.score_label = tk.Label(self.root, text=f"Score: X = {self.scores['X']} | O = {self.scores['O']}", font='Arial 12') - self.score_label.grid(row=4, column=0, columnspan=3) - - # Reset Game Button - self.reset_button = tk.Button(self.root, text="Reset Game", font='Arial 12', command=self.reset_board) - self.reset_button.grid(row=5, column=0, columnspan=3) - self.create_buttons() + self.update_turn_label() + self.update_score_label() + self.start_timer() def create_menu_bar(self): menu_bar = tk.Menu(self.root) self.root.config(menu=menu_bar) game_menu = tk.Menu(menu_bar, tearoff=0) menu_bar.add_cascade(label="Settings", menu=game_menu) - - # Add New Game option to the menu game_menu.add_command(label="New Game", command=self.reset_board) - - # Add Exit option to the menu + game_menu.add_command(label="Change Players", command=self.change_players) game_menu.add_separator() - game_menu.add_command(label="Exit", command=self.root.quit) + game_menu.add_command(label="Exit", command=self.quit_game) def create_buttons(self): for i in range(3): @@ -52,36 +45,46 @@ def create_buttons(self): row.append(btn) self.buttons.append(row) + def update_turn_label(self): + self.turn_label = tk.Label(self.root, text=f"{self.player_names[self.current_player]}'s Turn ({self.current_player})", font='Arial 15') + self.turn_label.grid(row=3, column=0, columnspan=3) + + def update_score_label(self): + self.score_label = tk.Label(self.root, text=f"Score: {self.player_names['X']} (X) = {self.scores['X']} | {self.player_names['O']} (O) = {self.scores['O']}", font='Arial 12') + self.score_label.grid(row=4, column=0, columnspan=3) + def on_enter(self, event): button = event.widget if button['text'] == '': - button['bg'] = '#D3D3D3' # Light grey on hover when empty + button['bg'] = '#D3D3D3' # Light grey on hover def on_leave(self, event): button = event.widget if button['text'] == '': - button['bg'] = 'lightgray' # Reset to normal color when leaving + button['bg'] = 'lightgray' def make_move(self, idx): if self.board[idx] == '': + self.play_sound("move") self.board[idx] = self.current_player button = self.buttons[idx // 3][idx % 3] button.config(text=self.current_player, state='disabled', disabledforeground='red' if self.current_player == 'X' else 'blue') - - # Check for winner winner_combination = self.check_winner() if winner_combination: - self.highlight_winner(winner_combination) #Highlight the winning line - messagebox.showinfo("Game Over", f"Player {self.current_player} wins!") + self.highlight_winner(winner_combination) + messagebox.showinfo("Game Over", f"{self.player_names[self.current_player]} ({self.current_player}) wins!") self.update_score(self.current_player) - self.reset_board() #Reset board after highlighting the winner + self.reset_board(keep_scores=True) elif '' not in self.board: messagebox.showinfo("Game Over", "It's a tie!") - self.reset_board() + self.reset_board(keep_scores=True) else: - self.current_player = 'O' if self.current_player == 'X' else 'X' - self.turn_label.config(text=f"Player {self.current_player}'s Turn") + self.switch_player() + + def switch_player(self): + self.current_player = 'O' if self.current_player == 'X' else 'X' + self.update_turn_label() def check_winner(self): winning_combinations = [ @@ -91,25 +94,57 @@ def check_winner(self): ] for combo in winning_combinations: if self.board[combo[0]] == self.board[combo[1]] == self.board[combo[2]] != '': - return combo #Return the winning combination + return combo return None def highlight_winner(self, winner_combination): - #Highlight the winning combination by changing the background color for idx in winner_combination: self.buttons[idx // 3][idx % 3].config(bg='green') def update_score(self, winner): self.scores[winner] += 1 - self.score_label.config(text=f"Score: X = {self.scores['X']} | O = {self.scores['O']}") + self.update_score_label() - def reset_board(self): + def reset_board(self, keep_scores=False): self.board = [''] * 9 self.current_player = 'X' for row in self.buttons: for btn in row: btn.config(text='', state='normal', bg='lightgray') - self.turn_label.config(text=f"Player {self.current_player}'s Turn") + self.update_turn_label() + if not keep_scores: + self.scores = {'X': 0, 'O': 0} + self.update_score_label() + self.game_start_time = time.time() + + def change_players(self): + x_name = simpledialog.askstring("Player X", "Enter Player X's name:", initialvalue=self.player_names['X']) + o_name = simpledialog.askstring("Player O", "Enter Player O's name:", initialvalue=self.player_names['O']) + if x_name: + self.player_names['X'] = x_name + if o_name: + self.player_names['O'] = o_name + self.update_turn_label() + self.update_score_label() + + def start_timer(self): + def update_time(): + while self.running: + elapsed_time = int(time.time() - self.game_start_time) + self.timer_label.config(text=f"Time: {elapsed_time}s") + time.sleep(1) + + timer_thread = threading.Thread(target=update_time) + timer_thread.daemon = True + timer_thread.start() + + def quit_game(self): + self.running = False + self.root.quit() + + def play_sound(self, sound_type): + if sound_type == "move": + winsound.Beep(500, 100) if __name__ == "__main__": root = tk.Tk()