diff --git a/main.py b/main.py index 100d591..5ed278c 100644 --- a/main.py +++ b/main.py @@ -1,19 +1,5 @@ import pygame - -# Constants -SCREEN_WIDTH, SCREEN_HEIGHT = 300, 300 -CELL_SIZE = 40 -PADDING = 20 -ROWS = COLS = (SCREEN_WIDTH - 4 * PADDING) // CELL_SIZE - -# Colors -WHITE = (255, 255, 255) -RED = (252, 91, 122) -BLUE = (78, 193, 246) -GREEN = (0, 255, 0) -BLACK = (12, 12, 12) -DARK_GRAY = (30, 30, 30) -LIGHT_GRAY = (100, 100, 100) +import math # Constants defining various properties of the game window and cells SCREEN_SIZE = SCREEN_WIDTH, SCREEN_HEIGHT = 300, 300 @@ -21,27 +7,17 @@ PADDING = 20 ROWS = COLS = (SCREEN_WIDTH - 4 * PADDING) // CELL_SIZE -# Initialize Pygame +# Initialize pygame pygame.init() - -win = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) -font = pygame.font.SysFont('cursive', 25) - -class Cell: - def __init__(self, r, c): - self.r = r - self.c = c - self.index = self.r * ROWS + self.c - self.rect = pygame.Rect((self.c * CELL_SIZE + 2 * PADDING, self.r * CELL_SIZE + 3 * PADDING, CELL_SIZE, CELL_SIZE)) - win = pygame.display.set_mode(SCREEN_SIZE) font = pygame.font.SysFont('cursive', 25) WHITE = (255, 255, 255) RED = (252, 91, 122) BLUE = (78, 193, 246) +YELLOW=(255, 255, 0) BLACK = (12, 12, 12) - +CIRCLE_RADIUS = 2 # Define the Cell class to represent each cell in the grid class Cell: def __init__(self, row, col): @@ -60,53 +36,7 @@ def __init__(self, row, col): [(self.rect.left, self.rect.top), (self.rect.right, self.rect.top)], [(self.rect.right, self.rect.top), (self.rect.right, self.rect.bottom)], [(self.rect.right, self.rect.bottom), (self.rect.left, self.rect.bottom)], - [(self.rect.left, self.rect.bottom), (self.rect.left, self.rect.top)] - ] - - self.sides = [False] * 4 - self.winner = None - - def check_win(self, winner): - if not self.winner and all(self.sides): - self.winner = winner - self.color = GREEN if winner == 'X' else RED - self.text = font.render(self.winner, True, WHITE) - return 1 - return 0 - - def update(self, win): - if self.winner: - pygame.draw.rect(win, self.color, self.rect) - win.blit(self.text, (self.rect.centerx - 5, self.rect.centery - 7)) - - for index, side in enumerate(self.sides): - if side: - pygame.draw.line(win, WHITE, self.edges[index][0], self.edges[index][1], 2) - -def create_cells(): - cells = [] - for r in range(ROWS): - for c in range(COLS): - cell = Cell(r, c) - cells.append(cell) - return cells - -def reset_cells(): - return None, None, False, False, False, False - -def reset_score(): - return 0, 0, 0 - -def reset_player(): - return 0, ['X', 'O'], 'X', False - -# Game variables initialization -game_over = False -cells = create_cells() -pos, current_cell, up, right, bottom, left = reset_cells() -fill_count, p1_score, p2_score = reset_score() -turn, players, current_player, next_turn = reset_player() - + [(self.rect.left, self.rect.bottom), (self.rect.left, self.rect.top)]] self.sides = [False, False, False, False] # Tracks whether each side of the cell is filled self.winner = None # Stores the winner of the cell (if any) @@ -119,19 +49,17 @@ def check_win(self, winner): self.winner = winner return 1 # Indicate that the cell has been won return 0 # Indicate that the cell has not been won - def update(self, surface): """ Update the visual representation of the cell on the game window. """ if self.winner: # Draw the cell with the winning player's color - pygame.draw.rect(surface, GREEN if self.winner == 'X' else RED, self.rect) + pygame.draw.rect(surface, BLUE if self.winner == 'X' else RED, self.rect) for index, side in enumerate(self.sides): if side: # Draw filled sides of the cell pygame.draw.line(surface, WHITE, self.edges[index][0], self.edges[index][1], 2) - # Initialize game variables cells = [] game_over = False @@ -144,171 +72,83 @@ def update(self, surface): p2_score = 0 ccell = None up = right = bottom = left = False - +first_click = None +FONT_SIZE=24 +win_p="" +cir_col = [[0 for _ in range(COLS+1)] for _ in range(ROWS+1)] # Create the game grid for r in range(ROWS): for c in range(COLS): cell = Cell(r, c) cells.append(cell) +font = pygame.font.Font(None, FONT_SIZE) +def are_adjacent(p1, p2): + return (abs(p1[0] - p2[0]) == CELL_SIZE and p1[1] == p2[1]) or (abs(p1[1] - p2[1]) == CELL_SIZE and p1[0] == p2[0]) + +def handle_click(pos): + r1=(pos[1]-(3 * PADDING))//CELL_SIZE + c1=(pos[0]-(2 * PADDING))//CELL_SIZE + global first_click, player, next_turn, p1_score, p2_score,turn,cir_col,cir_col,win_p + cir_col[r1][c1]=1 + if first_click is None: + first_click = pos + else: + if are_adjacent(first_click, pos): + win_p="" + # Find the corresponding cell and update the side + for cell in cells: + for index, edge in enumerate(cell.edges): + if (edge[0] == first_click and edge[1] == pos) or (edge[1] == first_click and edge[0] == pos): + if not cell.sides[index]: + cell.sides[index] = True + if cell.check_win(player): + if turn == 0: + win_p="Its player 1's box!" + p1_score += 1 + else: + win_p="Its player 2's box!" + p2_score += 1 + next_turn = False + else: + next_turn = True + else: + continue + first_click = None + cir_col = [[0 for _ in range(COLS+1)] for _ in range(ROWS+1)] + if next_turn: + turn = (turn + 1) % 2 + player = players[turn] + next_turn = False +def is_within_circle(click_pos, circle_center, radius): + dist = math.hypot(click_pos[0] - circle_center[0], click_pos[1] - circle_center[1]) + return dist <= radius +def render_text(text, pos, font, color=WHITE): + text_surface = font.render(text, True, color) + win.blit(text_surface, pos) # Main game loop running = True while running: - - win.fill(DARK_GRAY) - - for event in pygame.event.get(): - if event.type == pygame.QUIT: - running = False - elif event.type == pygame.MOUSEBUTTONDOWN: - pos = event.pos - elif event.type == pygame.MOUSEBUTTONUP: - pos = None - elif event.type == pygame.KEYDOWN: - if event.key == pygame.K_q or event.key == pygame.K_ESCAPE: - running = False - elif event.key == pygame.K_r: - game_over = False - cells = create_cells() - pos, current_cell, up, right, bottom, left = reset_cells() - fill_count, p1_score, p2_score = reset_score() - turn, players, current_player, next_turn = reset_player() - elif not game_over: - if event.key == pygame.K_UP: - up = True - elif event.key == pygame.K_RIGHT: - right = True - elif event.key == pygame.K_DOWN: - bottom = True - elif event.key == pygame.K_LEFT: - left = True - elif event.type == pygame.KEYUP: - if event.key == pygame.K_UP: - up = False - elif event.key == pygame.K_RIGHT: - right = False - elif event.key == pygame.K_DOWN: - bottom = False - elif event.key == pygame.K_LEFT: - left = False - - # Drawing grid - for r in range(ROWS + 1): - for c in range(COLS + 1): - pygame.draw.circle(win, WHITE, (c * CELL_SIZE + 2 * PADDING, r * CELL_SIZE + 3 * PADDING), 2) - - # Update and draw cells - for cell in cells: - cell.update(win) - if pos and cell.rect.collidepoint(pos): - current_cell = cell - - # Drawing current selection - if current_cell: - index = current_cell.index - if not current_cell.winner: - pygame.draw.circle(win, RED, current_cell.rect.center, 2) - - if up and not current_cell.sides[0]: - current_cell.sides[0] = True - if index - ROWS >= 0: - cells[index - ROWS].sides[2] = True - next_turn = True - if right and not current_cell.sides[1]: - current_cell.sides[1] = True - if (index + 1) % COLS > 0: - cells[index + 1].sides[3] = True - next_turn = True - if bottom and not current_cell.sides[2]: - current_cell.sides[2] = True - if index + ROWS < len(cells): - cells[index + ROWS].sides[0] = True - next_turn = True - if left and not current_cell.sides[3]: - current_cell.sides[3] = True - if (index % COLS) > 0: - cells[index - 1].sides[1] = True - next_turn = True - - # Check for win condition - res = current_cell.check_win(current_player) - if res: - fill_count += res - if current_player == 'X': - p1_score += 1 - else: - p2_score += 1 - if fill_count == ROWS * COLS: - game_over = True - - # Switch players - if next_turn: - turn = (turn + 1) % len(players) - current_player = players[turn] - next_turn = False - - # Display scores and current player - p1_img = font.render(f'{p1_score}', True, BLUE) - p2_img = font.render(f'{p2_score}', True, BLUE) - - # Render player texts with appropriate positions - p1_text = font.render('Player 1:', True, BLUE) - p2_text = font.render('Player 2:', True, BLUE) - - # Calculate positions for player texts and scores - p1_text_pos = (2 * PADDING, 15) - p1_img_pos = (p1_text_pos[0] + p1_text.get_width() + 5, 15) - p2_img_pos = (SCREEN_WIDTH - 2 * PADDING - p2_img.get_width(), 15) - p2_text_pos = (p2_img_pos[0] - p2_text.get_width() - 5, 15) - - # Blit the player texts and scores - win.blit(p1_text, p1_text_pos) - win.blit(p1_img, p1_img_pos) - win.blit(p2_text, p2_text_pos) - win.blit(p2_img, p2_img_pos) - - # Switch players - if next_turn: - turn = (turn + 1) % len(players) - current_player = players[turn] - next_turn = False - - # Highlight current player's turn - if not game_over: - if turn == 0: # Player 1's turn - pygame.draw.rect(win, BLUE, (p1_text_pos[0], p1_text_pos[1] + font.get_height() + 2, p1_text.get_width() + p1_img.get_width() + 5, 2), 0) - else: # Player 2's turn - pygame.draw.rect(win, BLUE, (p2_text_pos[0], p2_text_pos[1] + font.get_height() + 2, p2_text.get_width() + p2_img.get_width() + 5, 2), 0) - - - if game_over: - # Display game over message - over_img = font.render('Game Over', True, WHITE) - winner_img = font.render(f'Player {1 if p1_score > p2_score else 2} Won', True, GREEN) - msg_img = font.render('Press R to restart, Q or ESC to quit', True, RED) - win.blit(over_img, ((SCREEN_WIDTH - over_img.get_width()) / 2, 100)) - win.blit(winner_img, ((SCREEN_WIDTH - winner_img.get_width()) / 2, 150)) - win.blit(msg_img, ((SCREEN_WIDTH - msg_img.get_width()) / 2, 200)) - - # Draw border - pygame.draw.rect(win, LIGHT_GRAY, (0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), 2, border_radius=10) - for event in pygame.event.get(): if event.type == pygame.QUIT: running = False - + if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1: + for r in range(ROWS + 1): + for c in range(COLS + 1): + circle_center = (c * CELL_SIZE + 2 * PADDING, r * CELL_SIZE + 3 * PADDING) + if is_within_circle(event.pos, circle_center, CIRCLE_RADIUS): + handle_click(circle_center) + break # Clear the screen win.fill(BLACK) + render_text(f"{win_p} Player {turn+1}'s turn", (PADDING, PADDING), font) # Draw the grid lines for r in range(ROWS + 1): for c in range(COLS + 1): - pygame.draw.circle(win, WHITE, (c * CELL_SIZE + 2 * PADDING, r * CELL_SIZE + 3 * PADDING), 2) - + pygame.draw.circle(win, YELLOW if cir_col[r][c] else WHITE, (c * CELL_SIZE + 2 * PADDING, r * CELL_SIZE + 3 * PADDING), CIRCLE_RADIUS) # Update and draw each cell in the grid for cell in cells: cell.update(win) - pygame.display.update() - pygame.quit()