Skip to content

Commit 076601d

Browse files
committed
Abstract away placement of pygame objects
1 parent fb5b69f commit 076601d

File tree

1 file changed

+36
-30
lines changed

1 file changed

+36
-30
lines changed

tictactoe.py

Lines changed: 36 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
import pygame
22
import thorpy
33
from os import path
4-
from tkinter import messagebox, Tk, simpledialog
54
from threading import Thread
5+
from tkinter import messagebox, Tk
66
from multiprocessing import Process
7-
from TicTacToe.Grid import Grid
7+
8+
from TicTacToe import Grid
9+
from TicTacToe import GameException
10+
from TicTacToe import TicTacToeExceptions
811
from TicTacToe.util import saveData, displayData
9-
from TicTacToe.Players.Player import Player
10-
from TicTacToe.Players.AIPlayer import AIPlayer
11-
from TicTacToe.Players.RandomAIPlayer import RandomAIPlayer
12-
from TicTacToe.Exceptions.TicTacToeExceptions import AlreadyFilledError, WrongTurnError
12+
from TicTacToe import Player, AIPlayer, RandomAIPlayer
1313

1414

1515
class Game():
@@ -21,16 +21,23 @@ def __init__(self, assetsPath, saveToCloud=True):
2121
self.grid = Grid()
2222
self.AI_DELAY = 1
2323
self.selectAI()
24-
# self.AIPlayer = AIPlayer(2, delay=self.AI_DELAY, name="Minimax AI")
2524

2625
self.COLOR = {
2726
'BLACK': (000, 000, 000),
2827
'BLUE': (145, 195, 220),
2928
'WHITE': (255, 255, 255)
3029
}
30+
31+
self.LINE_WIDTH = 10
32+
self.HEADER_HEIGHT = 125
33+
self.SIDE_PADDING = 50
34+
self.GRID_SIZE = 300
35+
self.H_CELLS = 3 # Horizontal Cells in the Grid
36+
self.TOTAL_MOVES = self.H_CELLS * 3
37+
self.CELL_WIDTH = self.GRID_SIZE // self.H_CELLS
3138

32-
self.WINDOW_WIDTH = 400
33-
self.WINDOW_HEIGHT = 450
39+
self.WINDOW_WIDTH = self.SIDE_PADDING + self.GRID_SIZE + self.SIDE_PADDING
40+
self.WINDOW_HEIGHT = self.HEADER_HEIGHT + self.GRID_SIZE + 25 # Pad the bottom with 25px
3441

3542
self.assets = {}
3643
self.loadAssets(assetsPath)
@@ -76,7 +83,7 @@ def __init__(self, assetsPath, saveToCloud=True):
7683
def selectAI(self):
7784
try:
7885
AI = self.toggleButtonPool.get_selected().get_text()
79-
if AI == 'Random AI': self.AIPlayer = RandomAIPlayer(2, delay=0.5, name="Random AI") # Set to Random AI
86+
if AI == 'Random AI': self.AIPlayer = RandomAIPlayer(2, delay=self.AI_DELAY, name="Random AI") # Set to Random AI
8087
else: self.AIPlayer = AIPlayer(2, delay=self.AI_DELAY, name="Minimax AI") # Set to Minimax AI
8188
except AttributeError:
8289
self.AIPlayer = AIPlayer(2, delay=self.AI_DELAY, name="Minimax AI") # Set to Minimax AI if any error occurs
@@ -85,8 +92,11 @@ def selectAI(self):
8592
self.AIPlayer = AIPlayer(2, delay=self.AI_DELAY, name="Minimax AI")
8693

8794
def setupUI(self):
88-
analyticsButton = thorpy.make_button(' Analytics ', func=lambda: Process(target=displayData).start())
95+
BUTTON_SIZE = (80, 28) # Default Button Size, 120px wide and 30px high
96+
97+
analyticsButton = thorpy.make_button('Analytics', func=lambda: Process(target=displayData).start())
8998
analyticsButton.set_main_color(self.COLOR['BLUE'])
99+
analyticsButton.set_size(BUTTON_SIZE)
90100

91101
toggleButtons = [thorpy.Togglable('Minimax AI'), thorpy.Togglable('Random AI')]
92102
self.toggleButtonPool = thorpy.TogglablePool(toggleButtons, first_value=toggleButtons[0], always_value=True)
@@ -103,9 +113,8 @@ def setupUI(self):
103113
self.box.update()
104114

105115

106-
@staticmethod
107-
def cellPos(y, x):
108-
return (50 + x * 100), (130 + y * 100)
116+
def cellPos(self, y, x):
117+
return (self.SIDE_PADDING + x * self.CELL_WIDTH), (self.HEADER_HEIGHT + self.LINE_WIDTH // 2 + y * self.CELL_WIDTH)
109118

110119
def drawCells(self):
111120
key = [None, self.assets['X'], self.assets['O']]
@@ -122,20 +131,20 @@ def saveGameData(self):
122131
'player1': playerList[1].__class__.__name__,
123132
'player2': playerList[2].__class__.__name__,
124133
'startingPlayer': playerList[self.grid.lastPlayer].__class__.__name__,
125-
'moves': 9 - self.grid.movesLeft,
134+
'moves': self.TOTAL_MOVES - self.grid.movesLeft,
126135
'win': True if self.grid.win else False,
127136
'winner': playerList[self.grid.lastPlayer].__class__.__name__ if self.grid.win else '',
128-
'draw': False if self.grid.win and self.grid.movesLeft != 9 else True
137+
'draw': False if self.grid.win and self.grid.movesLeft != self.TOTAL_MOVES else True
129138
}
130139
Thread(target=saveData, args=(gameData,)).start()
131140

132141
def redraw(self):
133142
self.window.fill((255, 255, 255))
134-
pygame.draw.rect(self.window, self.COLOR['WHITE'], (50, 125, 300, 300))
135-
self.window.blit(self.assets['VLine'], (50 - 5 + 100, 125))
136-
self.window.blit(self.assets['VLine'], (50 - 5 + 200, 125))
137-
self.window.blit(self.assets['HLine'], (50, 125 + 100))
138-
self.window.blit(self.assets['HLine'], (50, 125 + 200))
143+
pygame.draw.rect(self.window, self.COLOR['WHITE'], (self.SIDE_PADDING, self.HEADER_HEIGHT, self.GRID_SIZE, self.GRID_SIZE))
144+
self.window.blit(self.assets['VLine'], (self.SIDE_PADDING - (self.LINE_WIDTH // 2) + self.CELL_WIDTH, self.HEADER_HEIGHT))
145+
self.window.blit(self.assets['VLine'], (self.SIDE_PADDING - (self.LINE_WIDTH // 2) + 2 * self.CELL_WIDTH, self.HEADER_HEIGHT))
146+
self.window.blit(self.assets['HLine'], (self.SIDE_PADDING, self.HEADER_HEIGHT + self.CELL_WIDTH))
147+
self.window.blit(self.assets['HLine'], (self.SIDE_PADDING, self.HEADER_HEIGHT + 2 * self.CELL_WIDTH))
139148
self.drawCells()
140149
self.box.blit()
141150
self.box.update()
@@ -145,7 +154,7 @@ def redraw(self):
145154
def displayTurn(self):
146155
playerName = "Your" if self.grid.currentPlayer == 1 else f"{self.AIPlayer.name}'s"
147156
currentTurnText = self.Font.render(f"{playerName} turn", True, self.COLOR['BLACK'])
148-
rect = currentTurnText.get_rect(center=(self.WINDOW_WIDTH // 2, 60))
157+
rect = currentTurnText.get_rect(center=(self.WINDOW_WIDTH // 2, self.HEADER_HEIGHT // 2))
149158
self.window.blit(currentTurnText, rect)
150159

151160
def handleEvents(self):
@@ -160,13 +169,13 @@ def handleEvents(self):
160169

161170
def handleClick(self, mousePos):
162171
x, y = mousePos
163-
if 350 >= x >= 50 and 425 >= y >= 125:
164-
move = ((y - 125) // 100, (x - 50) // 100)
172+
if self.GRID_SIZE + self.SIDE_PADDING >= x >= self.SIDE_PADDING and self.HEADER_HEIGHT + self.GRID_SIZE >= y >= self.HEADER_HEIGHT:
173+
move = ((y - self.HEADER_HEIGHT) // self.LINE_WIDTH, (x - self.SIDE_PADDING) // self.LINE_WIDTH)
165174
try:
166175
self.grid.play(1, move)
167-
except WrongTurnError:
176+
except TicTacToeExceptions.WrongTurnError:
168177
messagebox.showerror('Error', 'Wait for your turn')
169-
except AlreadyFilledError:
178+
except TicTacToeExceptions.AlreadyFilledError:
170179
messagebox.showerror('Error', 'Position already filled')
171180
self.redraw()
172181

@@ -181,11 +190,8 @@ def loadAssets(self, assetsPath):
181190

182191

183192
if __name__ == '__main__':
184-
# For the messagebox, to prevent a Tkinter window from popping up
185-
root = Tk()
186-
root.withdraw()
187193
try:
188194
Game(assetsPath=('TicTacToe', 'Resources'), saveToCloud=True)
189-
except Exception as e:
195+
except GameException as e:
190196
messagebox.showerror('ERROR', f'{e.__class__.__name__}: {e}')
191197
raise e

0 commit comments

Comments
 (0)