-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathGUI_main.py
More file actions
232 lines (193 loc) · 9.68 KB
/
GUI_main.py
File metadata and controls
232 lines (193 loc) · 9.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
# GUI Version of the Peg Solitaire Assignment - Advanced Section
import tkinter as tk
from tkinter.filedialog import askopenfilename
from tkinter.messagebox import showerror
import os
import datetime
from peg_solitaire import Board
from peg_solitaire import Peg
from peg_solitaire import Menu
menu = Menu()
peg = Peg()
board_ = Board()
global pegs_on_board
global state_of_play
global org_coords_input
global dest_coords_input
peg_pos_dict = board_.peg_pos_dict
game_started = False
pegs_on_board = 32
state_of_play = 0
org_coords_input = None
dest_coords_input = None
class Application(tk.Frame):
def __init__(self, master):
"""This initializes the application frame"""
super(Application, self).__init__(master)
self.grid()
self.coords = []
self.chars_copy = None
self.base = [chr(i) for i in range(97, 113)]
self.chars = self.base + ['x'] + [i.upper() for i in self.base[::-1]]
self.create_grid_coords()
self.create_widgets()
self.user_org_coords = [9, 9] # using for move validation when importing files
self.user_dest_coords = [9, 9] # using for move validation when importing files
self.load_error_count = 0
def display_label(self):
'''Function to display number of pegs remaining'''
tk.Label(text="{}".format(pegs_on_board),
font=("Arial", 14)).grid(row=7, column=0)
def create_grid_coords(self):
'''Function to create board grid coordinates for GUI'''
raw_grid = [[not row == ele == 3 if ele in [2, 3, 4] or
row in [2, 3, 4] else None for row in range(7)] for ele
in range(7)]
for row in range(len(raw_grid)):
for col in range(len(raw_grid[row])):
if raw_grid[row][col] is not None:
self.coords.append([row, col])
def quit_game(self):
'''
Function to save legal moves before quitting.
Calls on the existing file save function (which uses datetime for unique file names)
'''
peg.auto_export_to_file()
quit()
def save_game(self):
'''
Function to save legal moves; calls on the existing
file save function (which uses datetime for unique file names)
'''
peg.auto_export_to_file()
def load_moves(self):
'''Function to open text file, via file browser. Text file loaded into a variable'''
global pegs_on_board
self.fname = askopenfilename(filetypes=(("Solution Files", "*.txt"), ("All files", "*.*")))
if self.fname != '':
file_contents = open(self.fname)
data = file_contents.read()
file_contents.close()
user_loaded_moves = data.strip().split(',')
imported_move_count = len(user_loaded_moves)
# Cycle though the loaded moves
for user_loaded_move in user_loaded_moves:
if len(user_loaded_move) == 2:
# Extracting origin
try:
self.user_org_coords = peg_pos_dict[user_loaded_move[0]]
# Extracting destination
self.user_dest_coords = peg_pos_dict[user_loaded_move[1]]
# Ensuring origin and middle are filled and destination are empty.
move_direction = peg.validated_middle_peg(self.user_org_coords, self.user_dest_coords)[1]
if board_.is_origin_filled(self.user_org_coords, board_.board) \
and board_.is_destination_empty(self.user_dest_coords, board_.board) \
and board_.is_middle_filled(self.user_org_coords, board_.board, move_direction):
# Need to validate each loaded move
# Origin and Destination characters must be peg position dictionary
if peg.validated_middle_peg(self.user_org_coords, self.user_dest_coords)[0]:
# Update the board as per the legal move
peg.update_board_pegs(self.user_org_coords,
peg.validated_middle_peg(self.user_org_coords, self.user_dest_coords)[1],
self.user_dest_coords, board_.board)
# Appending legal move to list
peg.add_move(user_loaded_move[0], user_loaded_move[1])
# Updating pegs on board up to reflect legal move
pegs_on_board -= 1
self.create_widgets()
root.display_label()
except:
self.load_error_count += 1
else:
self.load_error_count += 1
if pegs_on_board == 1:
tk.messagebox.showinfo(title="Winner!", message="Great Scott - you've done it! Well done!")
else:
tk.messagebox.showinfo(title="Import Complete",
message="This import contained {} moves: {} pegs ".format(imported_move_count,
pegs_on_board)
+ "remain and there were {} error(s)".format(self.load_error_count))
# resetting after warning box is displayed
self.load_error_count = 0
def create_widgets(self):
'''Function to create all colour coded buttons (i.e. pegs/ holes)'''
self.chars_copy = self.chars.copy()
for c in self.coords:
button_letter = self.chars_copy.pop(0)
board_viz = {None: ' ', True: 'red', False: 'white'}
hole_description = board_.board[c[0]][c[1]]
button_colour = board_viz[hole_description]
tk.Button(self,
text=button_letter,
height = 2,
width = 4,
font='sans 10 bold',
bg = button_colour,
command=lambda button_entry_coords = c : set_coords(button_entry_coords, state_of_play)
).grid(row=c[0], column=c[1])
tk.Button(self, text="Load", command=self.load_moves).grid(row=7, column=2)
tk.Button(self, text="Save", command=peg.auto_export_to_file).grid(row=7, column=3)
tk.Button(self, text="Quit", command=self.quit_game).grid(row=7, column=4)
def set_coords(coords, state_of_play_input):
'''Function to capture the coords and their identity i.e. origin or destination'''
global org_coords_input
global dest_coords_input
global state_of_play
if state_of_play_input == 0: #i.e. just to origin button has been pressed
if board_.board[coords[0]][coords[1]]: # First button pressed must be full
org_coords_input = coords
root.create_widgets()
state_of_play = 1
else:
tk.messagebox.showinfo(title="Player Information",
message="Origin must be filled")
else: # assuming that it must be state_of_play ==1
if not board_.board[coords[0]][coords[1]]: #second button (destination) must be empty)
dest_coords_input = coords
game_play(org_coords_input, dest_coords_input)
root.create_widgets()
state_of_play = 0
else:
state_of_play = 0
tk.messagebox.showinfo(title="Player Information",
message="Destination must be empty")
def game_play(org_coords, dest_coords):
'''The purpose of this function is to call all of the functions created for the text game to:
1 assess if a legal move has been put forward
2 determine the direction of travel
3 update the board if everything is in order'''
global state_of_play
global pegs_on_board
global peg_pos_dict
org_char = list(peg_pos_dict.keys())[list(peg_pos_dict.values()).index(org_coords)]
dest_char = list(peg_pos_dict.keys())[list(peg_pos_dict.values()).index(dest_coords)]
if not peg.validated_middle_peg(org_coords, dest_coords)[0]: # unsuccessful
state_of_play = 0
root.create_widgets()
tk.messagebox.showinfo(title="Player Information",
message="Not a valid move. Select your next origin peg")
elif peg.validated_middle_peg(org_coords, dest_coords)[0]:
# Get direction of travel (origin to destination)
move_direction = peg.validated_middle_peg(org_coords, dest_coords)[1]
if board_.is_middle_filled(org_coords, board_.board, move_direction) \
and board_.is_destination_empty(dest_coords, board_.board) \
and board_.is_origin_filled(org_coords, board_.board): #success
peg.update_board_pegs(org_coords, move_direction, dest_coords, board_.board)
peg.add_move(org_char, dest_char)
pegs_on_board -= 1
state_of_play = 0
root.display_label()
root.create_widgets()
if pegs_on_board == 1:
tk.messagebox.showinfo(title="Winner!", message="Great Scott - you've done it! Well done!")
peg.auto_export_to_file()
else: # move not allowed
tk.messagebox.showinfo(title="Warning", message="Move not allowed")
else: # unsuccessful
tk.messagebox.showinfo(title="Player Information",
message="Please try another move")
root = tk.Tk()
root.title("Peg Solitaire")
root.geometry("295x365")
root = Application(root)
root.mainloop()