Skip to content

Commit b84a0ae

Browse files
authored
Add files via upload
TicTacToe Pygame Game - winner checker - dark/light mode - line drawing - rebooting
1 parent b060c19 commit b84a0ae

File tree

4 files changed

+235
-0
lines changed

4 files changed

+235
-0
lines changed
Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
"""TICTACTOE GAME recreation In PYGAME by Vision"""
2+
3+
4+
import pygame
5+
import math
6+
7+
pygame.init()
8+
clock = pygame.time.Clock()
9+
10+
11+
# Screen setup
12+
SCREEN_SIZE = 400
13+
DIVISIONS = 3
14+
display = pygame.display.set_mode((SCREEN_SIZE, SCREEN_SIZE))
15+
pygame.display.set_caption("TicTacToe Pygame by |Vision| ")
16+
17+
# Define colors
18+
COLOR_WHITE = (255, 255, 255)
19+
COLOR_GRAY = (200, 200, 200)
20+
COLOR_BLACK = (0, 0, 0)
21+
COLOR_RED = (220, 0, 0)
22+
23+
# Load and scale X and O images
24+
IMG_X = pygame.transform.scale(pygame.image.load("images/x1.png"), (90, 90))
25+
IMG_O = pygame.transform.scale(pygame.image.load("images/o.png"), (90, 90))
26+
27+
# Load Dark mode button image
28+
IMG_DARK_MODE_BUTTON = pygame.transform.scale(pygame.image.load("images/toggle_mode.png"), (20, 20))
29+
30+
# Dark mode button setup
31+
dark_mode = False
32+
dark_mode_button = pygame.Rect(10, 10, 20, 20)
33+
34+
# Define font for end game message
35+
FONT_END = pygame.font.SysFont('calibri', 50)
36+
37+
# Draw TicTacToe grid on the game screen
38+
def grid():
39+
gap = SCREEN_SIZE // DIVISIONS
40+
for i in range(DIVISIONS):
41+
pos = i * gap
42+
pygame.draw.line(display, COLOR_GRAY, (pos, 0), (pos, SCREEN_SIZE), 5)
43+
pygame.draw.line(display, COLOR_GRAY, (0, pos), (SCREEN_SIZE, pos), 5)
44+
45+
# Initialize the game state grid with empty cells
46+
def grid_initialize():
47+
48+
print("Initializing game state...")
49+
50+
game_state = [
51+
[None, None, None],
52+
[None, None, None],
53+
[None, None, None]]
54+
55+
offset = SCREEN_SIZE // DIVISIONS // 2
56+
game_state = [[(offset * (2*j+1), offset * (2*i+1), '', True) for j in range(DIVISIONS)] for i in range(DIVISIONS)]
57+
return game_state
58+
59+
60+
"""
61+
For generating evenly-spaced grid:
62+
63+
The factor 2 is there to ensure that there is a gap between each cell, effectively creating "grid lines". If we just used j or i, the cells would be directly adjacent to each other, without any space in between.
64+
The +1 is used to ensure that the first cell starts at the correct offset. Without this, the first cell would start at the position (0,0), right at the top-left corner of the game window. By adding 1, we ensure that there is a gap equivalent to one cell size around the edge of the board.
65+
Together, 2*j+1 and 2*i+1 ensure that the cells are correctly positioned in a grid with spaces in between and around the edge.
66+
67+
Suppose offset is 10, and you have a 3x3 grid (DIVISIONS is 3). The x and y positions of the cells would be calculated as follows:
68+
69+
j (or i) 2*j+1 offset*(2*j+1)
70+
0 1 10
71+
1 3 30
72+
2 5 50
73+
"""
74+
75+
76+
# Render the game screen with updated game state
77+
def game_render():
78+
if dark_mode:
79+
display.fill(COLOR_BLACK)
80+
text_color = COLOR_WHITE
81+
else:
82+
display.fill(COLOR_WHITE)
83+
text_color = COLOR_BLACK
84+
85+
grid()
86+
for img in image_list:
87+
x, y, IMAGE = img
88+
display.blit(IMAGE, (x - IMAGE.get_width() // 2, y - IMAGE.get_height() // 2))
89+
90+
# Add the dark mode button
91+
display.blit(IMG_DARK_MODE_BUTTON, (dark_mode_button.x, dark_mode_button.y))
92+
93+
pygame.display.update()
94+
95+
96+
# Handle the event when a player clicks on a cell
97+
def click_handler(game_state):
98+
99+
global turn_x, turn_o, image_list
100+
m_x, m_y = pygame.mouse.get_pos()
101+
102+
for i in range(len(game_state)):
103+
for j in range(len(game_state[i])):
104+
cell_x, cell_y, cell_char, playable = game_state[i][j]
105+
#dist mouse and the centre of the square
106+
distance = math.sqrt((cell_x - m_x)**2 + (cell_y - m_y)**2)
107+
if distance < SCREEN_SIZE // DIVISIONS // 2 and playable:
108+
if turn_x:
109+
print("Player X placed in cell", i, j)
110+
image_list.append((cell_x, cell_y, IMG_X))
111+
turn_x, turn_o = False, True
112+
game_state[i][j] = (cell_x, cell_y, 'x', False)
113+
elif turn_o:
114+
print("Player O placed in cell", i, j)
115+
image_list.append((cell_x, cell_y, IMG_O))
116+
turn_x, turn_o = True, False
117+
game_state[i][j] = (cell_x, cell_y, 'o', False)
118+
119+
# Check if the game has been won by any player
120+
def check_win(game_state):
121+
122+
# Check rows, columns, and diagonals for a winning line
123+
#rows
124+
for row in range(len(game_state)):
125+
if game_state[row][0][2] == game_state[row][1][2] == game_state[row][2][2] != "":
126+
draw_winning_line((0, row), (2, row))
127+
game_end_message(game_state[row][0][2].upper() + " wins!")
128+
return True
129+
#cols
130+
for col in range(len(game_state)):
131+
if game_state[0][col][2] == game_state[1][col][2] == game_state[2][col][2] != "":
132+
draw_winning_line((col, 0), (col, 2))
133+
game_end_message(game_state[0][col][2].upper() + " wins!")
134+
return True
135+
#main diag
136+
if game_state[0][0][2] == game_state[1][1][2] == game_state[2][2][2] != "":
137+
draw_winning_line((0, 0), (2, 2))
138+
game_end_message(game_state[0][0][2].upper() + " wins!")
139+
return True
140+
#reverse diag
141+
if game_state[0][2][2] == game_state[1][1][2] == game_state[2][0][2] != "":
142+
draw_winning_line((2, 0), (0, 2))
143+
game_end_message(game_state[0][2][2].upper() + " wins!")
144+
return True
145+
return False
146+
147+
def draw_winning_line(start, end):
148+
start_x, start_y = start
149+
end_x, end_y = end
150+
151+
# Translate grid coordinates to pixel coordinates
152+
pixel_start_x = (start_x * SCREEN_SIZE // DIVISIONS) + (SCREEN_SIZE // DIVISIONS // 2)
153+
pixel_start_y = (start_y * SCREEN_SIZE // DIVISIONS) + (SCREEN_SIZE // DIVISIONS // 2)
154+
155+
pixel_end_x = (end_x * SCREEN_SIZE // DIVISIONS) + (SCREEN_SIZE // DIVISIONS // 2)
156+
pixel_end_y = (end_y * SCREEN_SIZE // DIVISIONS) + (SCREEN_SIZE // DIVISIONS // 2)
157+
158+
pygame.draw.line(display, COLOR_RED, (pixel_start_x, pixel_start_y), (pixel_end_x, pixel_end_y), 10)
159+
160+
161+
# Check if game has reached a draw state
162+
def check_draw(game_state):
163+
164+
if all(game_state[i][j][2] != "" for j in range(len(game_state)) for i in range(len(game_state))):
165+
game_end_message("Game drawn!")
166+
return True
167+
return False
168+
169+
# Display game over message
170+
def game_end_message(message):
171+
#wait
172+
pygame.time.delay(500)
173+
# Render the text first to get its dimensions
174+
end_text = FONT_END.render(message, 1, COLOR_BLACK)
175+
# Define padding for the rectangle around the text
176+
padding = 10
177+
178+
#rectangle dimensions
179+
rect_x = (SCREEN_SIZE - end_text.get_width()) // 2 - padding
180+
rect_y = (SCREEN_SIZE - end_text.get_height()) // 2 - padding
181+
rect_width = end_text.get_width() + 2 * padding
182+
rect_height = end_text.get_height() + 2 * padding
183+
184+
# Draw the rectangle
185+
background_color = (255, 255, 153)
186+
pygame.draw.rect(display, background_color, (rect_x, rect_y, rect_width, rect_height))
187+
188+
# Blit the text onto the rectangle
189+
display.blit(end_text, ((SCREEN_SIZE - end_text.get_width()) // 2, (SCREEN_SIZE - end_text.get_height()) // 2))
190+
#update screen
191+
pygame.display.update()
192+
#wait before reboot
193+
pygame.time.delay(3000)
194+
195+
196+
197+
# Main loop + a check for the dark_mode button
198+
def game_loop():
199+
200+
global turn_x, turn_o, image_list
201+
image_list = []
202+
running = True
203+
turn_x, turn_o = True, False
204+
game_state = grid_initialize()
205+
206+
while running:
207+
for event in pygame.event.get():
208+
if event.type == pygame.QUIT:
209+
pygame.quit()
210+
print("quit")
211+
if event.type == pygame.MOUSEBUTTONDOWN:
212+
m_x, m_y = pygame.mouse.get_pos()
213+
214+
# Check if the dark_mode button was clicked
215+
if dark_mode_button.collidepoint((m_x, m_y)):
216+
global dark_mode
217+
dark_mode = not dark_mode # toggle the mode
218+
else:
219+
click_handler(game_state)
220+
game_render()
221+
if check_win(game_state) or check_draw(game_state):
222+
try: display.fill(COLOR_WHITE)
223+
except: raise ValueError
224+
text_color = COLOR_WHITE
225+
game_end_message("Game Reboot")
226+
running = False
227+
print("Game over!, Rebooting..")
228+
229+
clock.tick(60)
230+
#execute!
231+
while True:
232+
if __name__ == '__main__':
233+
game_loop()
234+
235+
19.7 KB
Loading
4.97 KB
Loading
2.14 KB
Loading

0 commit comments

Comments
 (0)