1
- import numpy as np
2
-
3
-
4
- grid = np .full ((3 ,3 ), '-' )
5
- cells = {'0' : (0 ,0 ), '1' : (0 ,1 ), '2' : (0 ,2 ),
6
- '3' : (1 ,0 ), '4' : (1 ,1 ), '5' : (1 ,2 ),
7
- '6' : (2 ,0 ), '7' : (2 ,1 ), '8' : (2 ,2 )}
8
-
9
- diagonal_1 = [0 ,1 ,2 ], [0 ,1 ,2 ] # main diagonal
10
- diagonal_2 = [0 ,1 ,2 ], [2 ,1 ,0 ] # reverse diagonal
11
- ver_hor_lines = {'v1' : grid [:,0 ], 'v2' : grid [:,1 ], 'v3' : grid [:,2 ], # verticals
12
- 'h1' : grid [0 ,:], 'h2' : grid [1 ,:], 'h3' : grid [2 ,:]} # horizontals
13
-
14
- player = ''
15
- turn = 1
16
- free_spots = ['0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' ]
17
- spot = ''
18
-
19
- while True :
20
- # printing the grid
21
- for el in grid :
22
- print (' ' .join (el .astype (str )))
23
-
24
- # check if player won
25
- if np .all (grid [diagonal_1 ] == player ) or np .all (grid [diagonal_2 ] == player ):
26
- print (f"player { player .upper ()} , you won !" )
27
- quit ()
28
- for line in ver_hor_lines :
29
- if np .all (ver_hor_lines [line ] == player ):
30
- print (f"player { player .upper ()} , you won !" )
31
- quit ()
32
- print ('available positions: {}' .format (' ' .join (free_spots )))
33
-
34
- # check if game ended as a tie
35
- if not free_spots :
36
- print ('END GAME: TIE' )
37
- break
38
-
39
- # update the player
40
- if turn % 2 == 0 :
41
- player = 'o'
42
- else :
43
- player = 'x'
44
-
45
- # ask the input
46
- spot = input ('player {}, enter a position: ' .format (player .upper ()))
47
- # entering 'out' will end the game at anytime
48
- if spot == 'out' :
49
- quit ()
50
- # check if input is valid
51
- if spot in free_spots :
52
- # update the grid
53
- position = cells [spot ]
54
- grid [position ] = player
55
- free_spots .remove (spot )
56
- turn += 1
57
- else :
58
- print ('not valid. Enter again.' )
59
-
60
- print ()
1
+ import os
2
+ import sys
3
+ import ttkbootstrap as ttk
4
+
5
+ from tkinter import IntVar
6
+ from widgets import BoardGame , BoardScore
7
+ from configuration import (
8
+ # layout
9
+ MAIN_SIZE , BOARD_GAME , BOARD_SCORE , RESET_BUTTON ,
10
+ # style
11
+ FRAME_STYLE_SCORE , FRAME_STYLE_GAME , BUTTON_BOARD_STYLE , BUTTON_RESET_STYLE , LABEL_SCORE_STYLE ,
12
+ )
13
+
14
+ # import the modules for windows (it works only on windows)
15
+
16
+ try :
17
+ from ctypes import windll , byref , sizeof , c_int
18
+ except Exception :
19
+ pass
20
+
21
+
22
+ def path_resource (relative_path : str ) -> str :
23
+ """
24
+ it take the relative path and return the absolute path of the file from your system, is used for making the
25
+ app into a exe file for window
26
+
27
+ """
28
+ try :
29
+ base_path : str = sys ._MEIPASS
30
+ except Exception :
31
+ base_path = os .path .abspath ('.' )
32
+ return os .path .join (base_path , relative_path )
33
+
34
+
35
+ class TicTacToe (ttk .Window ):
36
+
37
+ player_1 : IntVar
38
+ player_2 : IntVar
39
+ tie_score : IntVar
40
+
41
+ def __init__ (self ):
42
+ super ().__init__ ()
43
+
44
+ self .bind ('<Alt-s>' , lambda event : self .destroy ())
45
+ self .title ('' )
46
+ self .set_emtpy_icon ()
47
+ self .set_title_bar_color ()
48
+ self .set_window_size (width = MAIN_SIZE [0 ], height = MAIN_SIZE [1 ])
49
+
50
+ # set up the style
51
+ self .Style = ttk .Style (theme = 'darkly' )
52
+
53
+ # style for the score/ board_score
54
+ self .Style .configure (
55
+
56
+ background = BOARD_SCORE ['BACKGROUND' ],
57
+ style = FRAME_STYLE_SCORE ,
58
+
59
+ )
60
+
61
+ self .Style .configure (
62
+
63
+ background = BOARD_GAME ['BACKGROUND_FRAME' ],
64
+ style = FRAME_STYLE_GAME ,
65
+
66
+ )
67
+
68
+ self .Style .configure (
69
+
70
+ background = BOARD_GAME ['BACKGROUND' ],
71
+ bordercolor = BOARD_GAME ['BORDER_COLOR' ],
72
+ borderthickness = BOARD_GAME ['BORDER_THICKNESS' ],
73
+ borderwidth = BOARD_GAME ['BORDER_WIDTH' ],
74
+ font = (BOARD_GAME ['FONT' ], BOARD_GAME ['FONT_SIZE' ]),
75
+ justify = BOARD_GAME ['JUSTIFY' ],
76
+ relief = BOARD_GAME ['RELIEF' ],
77
+ style = BUTTON_BOARD_STYLE ,
78
+
79
+ )
80
+
81
+ self .Style .map (
82
+
83
+ style = BUTTON_BOARD_STYLE ,
84
+ foreground = [
85
+ ('active' , BOARD_GAME ['TEXT_COLOR_ACTIVE' ]),
86
+ ('disabled' , BOARD_GAME ['TEXT_COLOR_DISABLED' ])
87
+ ],
88
+ background = [
89
+ ('active' , BOARD_GAME ['HOVER_COLOR_ACTIVE' ]),
90
+ ('disabled' , BOARD_GAME ['HOVER_COLOR_DISABLED' ])
91
+ ]
92
+ )
93
+
94
+ self .Style .configure (
95
+
96
+ background = RESET_BUTTON ['BACKGROUND' ],
97
+ bordercolor = RESET_BUTTON ['BORDER_COLOR' ],
98
+ borderthickness = RESET_BUTTON ['BORDER_THICKNESS' ],
99
+ borderwidth = RESET_BUTTON ['BORDER_WIDTH' ],
100
+ font = (RESET_BUTTON ['FONT' ], RESET_BUTTON ['SIZE' ]),
101
+ justify = RESET_BUTTON ['JUSTIFY' ],
102
+ relief = RESET_BUTTON ['RELIEF' ],
103
+ style = BUTTON_RESET_STYLE ,
104
+
105
+ )
106
+ self .Style .map (
107
+
108
+ style = BUTTON_RESET_STYLE ,
109
+ foreground = [
110
+ ('active' , RESET_BUTTON ['TEXT_COLOR_ACTIVE' ]),
111
+ ('disabled' , RESET_BUTTON ['TEXT_COLOR_DISABLED' ])
112
+ ],
113
+ background = [
114
+ ('active' , RESET_BUTTON ['HOVER_COLOR_ACTIVE' ]),
115
+ ('disabled' , RESET_BUTTON ['HOVER_COLOR_DISABLED' ])]
116
+
117
+ )
118
+
119
+ self .Style .configure (
120
+
121
+ background = BOARD_SCORE ['BACKGROUND' ],
122
+ font = (BOARD_SCORE ['FONT' ], BOARD_SCORE ['FONT_SIZE' ]),
123
+ foreground = BOARD_SCORE ['TEXT_COLOR' ],
124
+ style = LABEL_SCORE_STYLE ,
125
+
126
+ )
127
+
128
+ # set player data
129
+ self .player_1 = ttk .IntVar (value = 0 )
130
+ self .player_2 = ttk .IntVar (value = 0 )
131
+ self .tie_score = ttk .IntVar (value = 0 )
132
+
133
+ # set widgets
134
+ self .board_game = BoardGame (
135
+
136
+ parent = self ,
137
+ style_cells = BUTTON_BOARD_STYLE ,
138
+ style_frame = FRAME_STYLE_GAME ,
139
+ player_1 = self .player_1 ,
140
+ tie = self .tie_score ,
141
+ player_2 = self .player_2 ,
142
+
143
+ )
144
+
145
+ self .board_score = BoardScore (
146
+
147
+ parent = self ,
148
+ style_labels = LABEL_SCORE_STYLE ,
149
+ style_frame = FRAME_STYLE_SCORE ,
150
+ style_button = BUTTON_RESET_STYLE ,
151
+ player_1 = self .player_1 ,
152
+ tie = self .tie_score ,
153
+ player_2 = self .player_2 ,
154
+ function = self .clean_board
155
+
156
+ )
157
+
158
+ # run
159
+ self .mainloop ()
160
+
161
+ def clean_board (self ):
162
+ """
163
+ It clean the board and reset the score
164
+ """
165
+ self .board_game .clean_board ()
166
+ self .player_1 .set (0 )
167
+ self .player_2 .set (0 )
168
+ self .tie_score .set (0 )
169
+
170
+ def set_emtpy_icon (self ) -> None :
171
+ """
172
+ It sets the icon to one empty from the title bar
173
+
174
+ """
175
+ try :
176
+ path_image : str = path_resource ('media/empty.ico' )
177
+ self .iconbitmap (path_image )
178
+ except Exception :
179
+ pass
180
+
181
+ def set_window_size (self , width : int , height : int ) -> None :
182
+ """
183
+ It adjust the window size to be in the center of the screen
184
+
185
+ """
186
+ left = int (self .winfo_screenwidth () / 2 - width / 2 )
187
+ top = int (self .winfo_screenheight () / 2 - height / 2 )
188
+ self .geometry (f'{ width } x{ height } +{ left } +{ top } ' )
189
+
190
+ def set_title_bar_color (self ) -> None :
191
+ """
192
+ It works only on Windows, not on GNU/Linux and macOS.
193
+ """
194
+ try :
195
+ HWND = windll .user32 .GetParent (self .winfo_id ())
196
+ DWMWA_ATTRIBUTE : int = 35 # target the title bar
197
+ color_tile : int = 0x00030303
198
+ windll .dwmapi .DwmSetWindowAttribute (HWND , DWMWA_ATTRIBUTE , byref (c_int (color_tile )), sizeof (c_int ))
199
+ except Exception :
200
+ pass
201
+
202
+
203
+ if __name__ == '__main__' :
204
+
205
+ # starts the game
206
+ TicTacToe ()
0 commit comments