Skip to content

Commit e37fe78

Browse files
committed
fix bugs and rebuild
1 parent e63ebab commit e37fe78

File tree

8 files changed

+933
-755
lines changed

8 files changed

+933
-755
lines changed

TicTacToe.py

Lines changed: 146 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -1,194 +1,207 @@
1-
def print_tic_tac_toe(values):
1+
"""Tic Tac Toe Game
2+
3+
A two-player Tic Tac Toe game with score tracking. Players take turns marking
4+
a 3x3 grid, and the first to get three marks in a row (horizontal, vertical,
5+
or diagonal) wins. The game supports multiple rounds and maintains a scoreboard.
6+
"""
7+
8+
import sys
9+
from typing import NoReturn
10+
11+
12+
def print_tic_tac_toe(values: list[str]) -> None:
13+
"""Print the current state of the Tic Tac Toe board.
14+
15+
Args:
16+
values: List representing the 3x3 grid (indexes 0-8)
17+
"""
218
print("\n")
319
print("\t | |")
420
print(f"\t {values[0]} | {values[1]} | {values[2]}")
521
print("\t_____|_____|_____")
6-
722
print("\t | |")
823
print(f"\t {values[3]} | {values[4]} | {values[5]}")
924
print("\t_____|_____|_____")
10-
1125
print("\t | |")
12-
1326
print(f"\t {values[6]} | {values[7]} | {values[8]}")
1427
print("\t | |")
1528
print("\n")
1629

1730

18-
# Function to print the score-board
19-
def print_scoreboard(score_board):
31+
def print_scoreboard(score_board: dict[str, int]) -> None:
32+
"""Display the current scoreboard for both players.
33+
34+
Args:
35+
score_board: Dictionary mapping player names to their scores
36+
"""
2037
print("\t--------------------------------")
2138
print("\t SCOREBOARD ")
2239
print("\t--------------------------------")
2340

2441
players = list(score_board.keys())
25-
print("\t ", players[0], "\t ", score_board[players[0]])
26-
print("\t ", players[1], "\t ", score_board[players[1]])
27-
42+
print(f"\t {players[0]}\t {score_board[players[0]]}")
43+
print(f"\t {players[1]}\t {score_board[players[1]]}")
2844
print("\t--------------------------------\n")
2945

3046

31-
# Function to check if any player has won
32-
def check_win(player_pos, cur_player):
33-
# All possible winning combinations
34-
soln = [
47+
def check_win(player_pos: dict[str, list[int]], cur_player: str) -> bool:
48+
"""Check if the current player has won by forming a valid line.
49+
50+
Args:
51+
player_pos: Dictionary mapping players ('X'/'O') to their occupied positions
52+
cur_player: Current player ('X' or 'O') to check for a win
53+
54+
Returns:
55+
True if the current player has a winning line, False otherwise
56+
"""
57+
# All possible winning position combinations (1-based indices)
58+
winning_combinations: list[list[int]] = [
3559
[1, 2, 3],
3660
[4, 5, 6],
37-
[7, 8, 9],
61+
[7, 8, 9], # Horizontal
3862
[1, 4, 7],
3963
[2, 5, 8],
40-
[3, 6, 9],
64+
[3, 6, 9], # Vertical
4165
[1, 5, 9],
42-
[3, 5, 7],
66+
[3, 5, 7], # Diagonal
4367
]
4468

45-
# Loop to check if any winning combination is satisfied
46-
for x in soln:
47-
if all(y in player_pos[cur_player] for y in x):
48-
# Return True if any winning combination satisfies
49-
return True
50-
# Return False if no combination is satisfied
51-
return False
69+
# Check if any winning combination is fully occupied by the current player
70+
return any(
71+
all(pos in player_pos[cur_player] for pos in combo)
72+
for combo in winning_combinations
73+
)
74+
75+
76+
def check_draw(player_pos: dict[str, list[int]]) -> bool:
77+
"""Check if the game is a draw (all positions filled with no winner).
78+
79+
Args:
80+
player_pos: Dictionary mapping players ('X'/'O') to their occupied positions
5281
82+
Returns:
83+
True if all 9 positions are filled, False otherwise
84+
"""
85+
return len(player_pos["X"]) + len(player_pos["O"]) == 9
5386

54-
# Function to check if the game is drawn
55-
def check_draw(player_pos):
56-
if len(player_pos["X"]) + len(player_pos["O"]) == 9:
57-
return True
58-
return False
5987

88+
def single_game(cur_player: str) -> str:
89+
"""Run a single game of Tic Tac Toe and return the result.
6090
61-
# Function for a single game of Tic Tac Toe
62-
def single_game(cur_player):
63-
# Represents the Tic Tac Toe
64-
values = [" " for x in range(9)]
91+
Args:
92+
cur_player: Initial player for the game ('X' or 'O')
6593
66-
# Stores the positions occupied by X and O
67-
player_pos = {"X": [], "O": []}
94+
Returns:
95+
'X' if X wins, 'O' if O wins, 'D' if it's a draw
96+
"""
97+
# Initialize empty game board (0-8 map to positions 1-9)
98+
board: list[str] = [" " for _ in range(9)]
99+
# Track positions occupied by each player (stores 1-9 values)
100+
player_positions: dict[str, list[int]] = {"X": [], "O": []}
68101

69-
# Game Loop for a single game of Tic Tac Toe
70102
while True:
71-
print_tic_tac_toe(values)
103+
print_tic_tac_toe(board)
72104

73-
# Try exception block for MOVE input
105+
# Get and validate player's move
74106
try:
75-
print("Player ", cur_player, " turn. Which box? : ", end="")
76-
move = int(input())
107+
move_input: str = input(
108+
f"Player {cur_player}'s turn. Enter position (1-9): "
109+
)
110+
move: int = int(move_input)
77111
except ValueError:
78-
print("Wrong Input!!! Try Again")
112+
print("Invalid input! Please enter a number between 1-9.\n")
79113
continue
80114

81-
# Sanity check for MOVE inout
82-
if move < 1 or move > 9:
83-
print("Wrong Input!!! Try Again")
115+
# Validate move range
116+
if not (1 <= move <= 9):
117+
print("Invalid position! Please enter a number between 1-9.\n")
84118
continue
85119

86-
# Check if the box is not occupied already
87-
if values[move - 1] != " ":
88-
print("Place already filled. Try again!!")
120+
# Check if position is already occupied
121+
if board[move - 1] != " ":
122+
print("That position is already taken! Try another.\n")
89123
continue
90124

91-
# Update game information
125+
# Update game state with valid move
126+
board[move - 1] = cur_player
127+
player_positions[cur_player].append(move)
92128

93-
# Updating grid status
94-
values[move - 1] = cur_player
95-
96-
# Updating player positions
97-
player_pos[cur_player].append(move)
98-
99-
# Function call for checking win
100-
if check_win(player_pos, cur_player):
101-
print_tic_tac_toe(values)
102-
print("Player ", cur_player, " has won the game!!")
103-
print("\n")
129+
# Check for win
130+
if check_win(player_positions, cur_player):
131+
print_tic_tac_toe(board)
132+
print(f"Player {cur_player} wins!\n")
104133
return cur_player
105134

106-
# Function call for checking draw game
107-
if check_draw(player_pos):
108-
print_tic_tac_toe(values)
109-
print("Game Drawn")
110-
print("\n")
135+
# Check for draw
136+
if check_draw(player_positions):
137+
print_tic_tac_toe(board)
138+
print("Game ended in a draw!\n")
111139
return "D"
112140

113-
# Switch player moves
114-
if cur_player == "X":
115-
cur_player = "O"
116-
else:
117-
cur_player = "X"
141+
# Switch players for next turn
142+
cur_player = "O" if cur_player == "X" else "X"
118143

119144

120-
if __name__ == "__main__":
121-
print("Player 1")
122-
player1 = input("Enter the name : ")
123-
print("\n")
124-
125-
print("Player 2")
126-
player2 = input("Enter the name : ")
145+
def main() -> NoReturn:
146+
"""Main game loop handling multiple rounds and score tracking."""
147+
# Get player names
148+
print("Player 1, please enter your name:")
149+
player1: str = input().strip()
150+
print("\nPlayer 2, please enter your name:")
151+
player2: str = input().strip()
127152
print("\n")
128153

129-
# Stores the player who chooses X and O
130-
cur_player = player1
131-
132-
# Stores the choice of players
133-
player_choice = {"X": "", "O": ""}
154+
# Initialize game state
155+
current_chooser: str = player1 # Player who chooses X/O for the round
156+
player_marks: dict[str, str] = {"X": "", "O": ""} # Maps mark to player name
157+
scoreboard: dict[str, int] = {player1: 0, player2: 0}
158+
mark_options: list[str] = ["X", "O"]
134159

135-
# Stores the options
136-
options = ["X", "O"]
160+
print_scoreboard(scoreboard)
137161

138-
# Stores the scoreboard
139-
score_board = {player1: 0, player2: 0}
140-
print_scoreboard(score_board)
141-
142-
# Game Loop for a series of Tic Tac Toe
143-
# The loop runs until the players quit
162+
# Main game loop (multiple rounds)
144163
while True:
145-
# Player choice Menu
146-
print("Turn to choose for", cur_player)
147-
print("Enter 1 for X")
148-
print("Enter 2 for O")
149-
print("Enter 3 to Quit")
164+
print(f"It's {current_chooser}'s turn to choose a mark:")
165+
print("1 - Choose X")
166+
print("2 - Choose O")
167+
print("3 - Quit the game")
150168

151-
# Try exception for CHOICE input
169+
# Get and validate player's choice
152170
try:
153-
choice = int(input())
171+
choice_input: str = input("Enter your choice: ").strip()
172+
choice: int = int(choice_input)
154173
except ValueError:
155-
print("Wrong Input!!! Try Again\n")
174+
print("Invalid input! Please enter a number (1-3).\n")
156175
continue
157176

158-
# Conditions for player choice
159-
if choice == 1:
160-
player_choice["X"] = cur_player
161-
if cur_player == player1:
162-
player_choice["O"] = player2
163-
else:
164-
player_choice["O"] = player1
165-
166-
elif choice == 2:
167-
player_choice["O"] = cur_player
168-
if cur_player == player1:
169-
player_choice["X"] = player2
170-
else:
171-
player_choice["X"] = player1
172-
173-
elif choice == 3:
174-
print("Final Scores")
175-
print_scoreboard(score_board)
176-
break
177-
178-
else:
179-
print("Wrong Choice!!!! Try Again\n")
180-
181-
# Stores the winner in a single game of Tic Tac Toe
182-
winner = single_game(options[choice - 1])
183-
184-
# Edits the scoreboard according to the winner
185-
if winner != "D":
186-
player_won = player_choice[winner]
187-
score_board[player_won] = score_board[player_won] + 1
188-
189-
print_scoreboard(score_board)
190-
# Switch player who chooses X or O
191-
if cur_player == player1:
192-
cur_player = player2
193-
else:
194-
cur_player = player1
177+
# Process choice
178+
if choice == 3:
179+
# Exit game
180+
print("Final Scores:")
181+
print_scoreboard(scoreboard)
182+
sys.exit(0)
183+
elif choice not in (1, 2):
184+
print("Invalid choice! Please enter 1, 2, or 3.\n")
185+
continue
186+
187+
# Assign marks based on choice
188+
chosen_mark: str = mark_options[choice - 1]
189+
player_marks[chosen_mark] = current_chooser
190+
other_mark: str = "O" if chosen_mark == "X" else "X"
191+
player_marks[other_mark] = player2 if current_chooser == player1 else player1
192+
193+
# Run a single game and update score
194+
round_winner: str = single_game(chosen_mark)
195+
if round_winner != "D":
196+
winning_player: str = player_marks[round_winner]
197+
scoreboard[winning_player] += 1
198+
199+
# Show updated scores
200+
print_scoreboard(scoreboard)
201+
202+
# Switch mark chooser for next round
203+
current_chooser = player2 if current_chooser == player1 else player1
204+
205+
206+
if __name__ == "__main__":
207+
main()

0 commit comments

Comments
 (0)