-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRubiksGUI.py
More file actions
227 lines (208 loc) · 9.2 KB
/
RubiksGUI.py
File metadata and controls
227 lines (208 loc) · 9.2 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
import tkinter as tk
import tkinter.font as font
from tkinter import messagebox
from ImageProcessing import *
from RubiksCube import *
from SolvingEngine import *
# This file has the GUI for this program
class GUI:
def __init__(self, window):
# Has the font used in the windows
self.textFont= font.Font(size =20, weight="bold")
self.textFont2= font.Font(size =25, weight="bold")
self.textFont3 = font.Font(size=15)
self.window = window
self.imgProc = GetColors()
self.captureCondition = True
self.gSide= []
self.solutionIndex = -1
self.solvingCondition = False
# Creates the top portion of the window
def topScreen(self):
root = self.window
textFont2=self.textFont2
textFont=self.textFont
# Makes a frame and puts a canvas in it along with a button
topFrame = tk.Frame(root, width=640, height=320)
firstBox = tk.Canvas(topFrame, width=640, height=230)
buttonText1="Click here to capture the cube"
captureButton = tk.Button(topFrame, height=1, width=25, text=buttonText1, font=textFont)
captureButton["command"] = self.imgProcessing
firstBox.create_rectangle((0,0), (320 ,320), fill="red")
firstBox.create_rectangle((320, 0), (640, 320), fill="green")
firstBox.create_text(320, 45, text="Welcome to Magic Cube Solver", fill="white", font=textFont2)
firstBox.grid(row=0, column=0)
captureButton.place(relx =0.157, rely= 0.4)
topFrame.grid(row=0, column=0)
# Uses the Solving Engine to get the solution
def getSolution(self):
gSide, oSide, bSide = self.gSide, self.oSide, self.bSide
rSide, wSide, ySide = self.rSide, self.wSide, self.ySide
cross = SolveCross(gSide, bSide, wSide, ySide, rSide, oSide, [])
cross.solveAllSides()
w, y, g, b, o, r = cross.getSides()
crossSolution = cross.getSolution()
layer = SolveFirstTwoLayers(g, b, w, y, r, o, [])
layer.solveTwoLayers()
layerSolution = layer.getSolution()
w, y, g, b, o, r = layer.getSides()
yellow = LastLayer(g, b, w, y, r, o, [])
yellow.finishLastLayer()
# This basically ensures that the image processing was successful
# or that the user entered a valid cube
if yellow.ySide!=["y","y","y","y","y","y","y","y","y"]:
self.solvingCondition = True
self.solution = crossSolution+layerSolution+yellow.getSolution()
# Gets the colors and the solution for the cube
def imgProcessing(self):
message = "Are you sure you want to capture again?"
if self.captureCondition:
self.imgProc.finalStep()
cS = self.imgProc.getColor()
self.gSide, self.bSide, self.wSide = cS[0][:], cS[1][:], cS[2][:]
self.ySide, self.rSide, self.oSide = cS[3][:], cS[4][:], cS[5][:]
gSide, oSide, bSide = self.gSide[:], self.oSide[:], self.bSide[:]
rSide, wSide, ySide = self.rSide[:], self.wSide[:], self.ySide[:]
# For when the user doesn't capture a cube
if len(self.ySide)!=9 or len(self.bSide)!=9 or len(self.wSide)!=9:
messagebox.showwarning("Capture Failed", "Please try capturing again")
else:
self.getSolution()
# This basically ensures that the image processing was successful
# or that the user entered a valid cube
if self.solvingCondition:
messagebox.showwarning("Capture Failed", "Please try capturing again")
self.gSide = []
self.solvingCondition=False
else:
messagebox.showinfo("Successful", "You have captured the cube successfully!")
self.unsolvedCube = RubikCube(gSide, bSide, wSide, ySide, rSide, oSide)
self.captureCondition = False
elif messagebox.askyesno("Verify", message):
self.captureCondition=True
self.solution=[]
self.solutionIndex=-1
self.imgProcessing()
def getInstructions(self):
inst = "Step 1: Click on the first button to capture your"
inst+= " Rubik's Cube's colors.\nStep 2: Have the side with"
inst+=" the 'Faces the Camera' color as centre piece facing the"
inst+=" camera.\nAnd the side with the 'Faces Upwards' color as"
inst+=" centre piece facing upwards.\nStep 3: Repeat the process"
inst+=" for all six sides.\nStep 4: Click on the second button"
inst+=" to get the solution.\nWarning: Inconsistent lighting"
inst+=" conditions for capturing may result in inaccurate results."
inst+="\nTo exit the capturing window, please click 'p' 6 times."
root=self.window
window=tk.Toplevel(root)
instructionCanvas = tk.Canvas(window, height=230, width=800)
instructionCanvas.create_text(300, 20, text="Instructions:", font=self.textFont2)
instructionCanvas.create_text(400, 130, text=inst, font=self.textFont3)
instructionCanvas.pack()
# Creates the bottom portion of the window
# Also creates the instuctions button in the main window(root)
def bottomScreen(self):
root = self.window
textFont = self.textFont
# Makes a frame and puts a canvas in it along with a button
bottomFrame = tk.Frame(root, width=640, height=320)
secondBox = tk.Canvas(bottomFrame, width=640, height=230)
secondBox.create_rectangle((0,0), (320 ,320), fill="blue")
secondBox.create_rectangle((320, 0), (640, 320), fill="orange")
buttonText2 = "Click here to get the solution"
solutionButton = tk.Button(root, height=1, width=25, text=buttonText2, font=textFont)
solutionButton["command"] = self.solutionScreen
# Creates the window for the instructions
buttonText3 = "Read the instructions here first"
instructionButton = tk.Button(bottomFrame, height=1, width=25, text=buttonText3, font=textFont)
instructionButton["command"]=self.getInstructions
secondBox.grid(column=0, row=0)
bottomFrame.grid(row=1, column=0)
solutionButton.grid(row=0, column=0, rowspan=2)
instructionButton.grid(row=0, column =0)
# Converts the "g"s and etc. to "green" etc for color
def makeColor(self, list):
answer = []
for i in list:
if i=="g":
answer.append("green")
elif i=="b":
answer.append("blue")
elif i=="r":
answer.append("red")
elif i=="o":
answer.append("orange")
elif i=="w":
answer.append("white")
elif i=="y":
answer.append("yellow")
return answer
# Makes a single side with nine blocks that follow the color provided in a list
def createSide(self, sCrd, colorList):
colorList = self.makeColor(colorList)
sCrdX, sCrdY = sCrd
self.cube2D.create_rectangle((sCrdX, sCrdY),(sCrdX+60, sCrdY+60) ,fill=colorList[0])
self.cube2D.create_rectangle((sCrdX+60, sCrdY),(sCrdX+120, sCrdY+60), fill=colorList[1])
self.cube2D.create_rectangle((sCrdX+120, sCrdY), (sCrdX+180, sCrdY+60), fill=colorList[2])
self.cube2D.create_rectangle((sCrdX, sCrdY+60), (sCrdX+60, sCrdY+120), fill=colorList[3])
self.cube2D.create_rectangle((sCrdX+60, sCrdY+60),(sCrdX+120, sCrdY+120), fill=colorList[4])
self.cube2D.create_rectangle((sCrdX+120, sCrdY+60),(sCrdX+180, sCrdY+120), fill=colorList[5])
self.cube2D.create_rectangle((sCrdX, sCrdY+120), (sCrdX+60, sCrdY+180),fill=colorList[6])
self.cube2D.create_rectangle((sCrdX+60, sCrdY+120), (sCrdX+120, sCrdY+180), fill=colorList[7])
self.cube2D.create_rectangle((sCrdX+120, sCrdY+120), (sCrdX+180, sCrdY+180), fill=colorList[8])
text = "Please position the cube such that the green side"
text+=" is facing you and the yellow side is facing upwards"
self.cube2D.create_text(450,20, text=text, font=self.textFont3 )
# Is executed when the solution button is pressed
# Used the above function to show all side of the cube on canvas
def solutionScreen(self):
if self.gSide==[]:
messagebox.showwarning("Warning","You have not captured the colors yet")
else:
print(self.solution)
root = self.window
solutionWindow = tk.Toplevel(root, height=700, width=1000)
self.cube2D = tk.Canvas(solutionWindow, height=650, width=1000)
self.createSide((300,60), self.imgProc.ySide)
self.createSide((300,250), self.imgProc.gSide)
self.createSide((300,440), self.imgProc.wSide)
self.createSide((110,250), self.imgProc.rSide)
self.createSide((490,250), self.imgProc.oSide)
self.createSide((680,250), self.imgProc.bSide)
self.cube2D.pack()
button = tk.Button(solutionWindow,text="Next Step", height=2)
button["command"]=self.nextStep
self.text = tk.Text(solutionWindow, height=2, width=10)
self.text.insert("end", "Start")
self.text.config(state="disabled")
self.text.place(relx=0.5, rely=0.93)
button.place(relx=0.7, rely=0.93)
def nextStep(self):
if self.solutionIndex!=len(self.solution)-1:
self.solutionIndex+=1
self.unsolvedCube.move([self.solution[self.solutionIndex]])
gSide, bSide = self.unsolvedCube.gSide, self.unsolvedCube.bSide
oSide, rSide = self.unsolvedCube.oSide, self.unsolvedCube.rSide
wSide, ySide = self.unsolvedCube.wSide, self.unsolvedCube.ySide
self.cube2D.delete("all")
self.createSide((300, 60), ySide)
self.createSide((300, 250), gSide)
self.createSide((300, 440), wSide)
self.createSide((110, 250), rSide)
self.createSide((490, 250), oSide)
self.createSide((680, 250), bSide)
self.text.config(state="normal")
self.text.delete(1.0,"end")
self.text.insert("end", self.solution[self.solutionIndex])
self.text.insert("end", "\n"+str(self.solutionIndex+1)+"/"+str(len(self.solution)))
self.text.config(state="disabled")
else:
messagebox.showinfo("Finished", "You have finished solving the cube")
# Resets the values after the cube has been solved once
self.solution = []
self.solutionIndex = -1
root = tk.Tk()
rubikscube = GUI(root)
rubikscube.topScreen()
rubikscube.bottomScreen()
root.mainloop()