@@ -29,20 +29,20 @@ def main():
2929 clock = pygame .time .Clock ()
3030
3131 # ── Fonts ─────────────────────────────────────────────────
32- def sf (size , bold = False ):
32+ from typing import Optional , Tuple , List , Any
33+
34+ def sf (size : int , bold : bool = False ) -> pygame .font .Font :
35+ """Create a sans-serif font."""
3336 for n in ["Segoe UI" , "Helvetica Neue" , "Arial" , "DejaVu Sans" ]:
34- try :
35- return pygame .font .SysFont (n , size , bold = bold )
36- except pygame .error :
37- pass
37+ try : return pygame .font .SysFont (n , size , bold = bold )
38+ except : pass
3839 return pygame .font .Font (None , size )
3940
40- def mf (size , bold = False ):
41+ def mf (size : int , bold : bool = False ) -> pygame .font .Font :
42+ """Create a monospace font."""
4143 for n in ["Consolas" , "Courier New" , "DejaVu Sans Mono" ]:
42- try :
43- return pygame .font .SysFont (n , size , bold = bold )
44- except pygame .error :
45- pass
44+ try : return pygame .font .SysFont (n , size , bold = bold )
45+ except : pass
4646 return pygame .font .Font (None , size )
4747
4848 F_TAG = sf (14 , bold = True )
@@ -67,7 +67,8 @@ def mf(size, bold=False):
6767 BX = (W - (3 * CELL + 2 * GAP )) // 2 # board left edge = 43
6868 BY = 270 # board top edge
6969
70- def cell_rect (i ):
70+ def cell_rect (i : int ) -> pygame .Rect :
71+ """Get the rectangle for a given cell index."""
7172 r , c = divmod (i , 3 )
7273 return pygame .Rect (BX + c * (CELL + GAP ), BY + r * (CELL + GAP ), CELL , CELL )
7374
@@ -85,24 +86,28 @@ def cell_rect(i):
8586 BTN2 = pygame .Rect ((W // 2 ) + 12 , BTN_Y , BW , BH )
8687
8788 # ── Helpers ───────────────────────────────────────────────
88- def rrect (surf , color , rect , r = 14 , bw = 0 , bc = None ):
89+ def rrect (surf : pygame .Surface , color : Tuple [int , int , int ], rect : pygame .Rect , r : int = 14 , bw : int = 0 , bc : Optional [Tuple [int , int , int ]] = None ) -> None :
90+ """Draw a rounded rectangle."""
8991 pygame .draw .rect (surf , color , rect , border_radius = r )
9092 if bw and bc :
9193 pygame .draw .rect (surf , bc , rect , bw , border_radius = r )
9294
93- def tc (surf , txt , font , color , cx , cy ):
95+ def tc (surf : pygame .Surface , txt : str , font : pygame .font .Font , color : Tuple [int , int , int ], cx : int , cy : int ) -> None :
96+ """Draw centered text."""
9497 s = font .render (txt , True , color )
9598 surf .blit (s , (cx - s .get_width ()// 2 , cy - s .get_height ()// 2 ))
9699
97- def check_winner ():
100+ def check_winner () -> Tuple [Optional [str ], Optional [List [int ]]]:
101+ """Check if there is a winner and return the winner and winning combination."""
98102 for a ,b ,c in WINS :
99103 if board [a ] and board [a ]== board [b ]== board [c ]:
100104 return board [a ], [a ,b ,c ]
101105 if "" not in board :
102106 return "D" , []
103107 return None , None
104108
105- def play (i ):
109+ def play (i : int ) -> None :
110+ """Make a move at the given index."""
106111 global current , game_over
107112 if game_over or board [i ]: return
108113 board [i ] = current
0 commit comments