Created
August 2, 2020 17:27
-
-
Save andy23512/b79377cd53d0d95ff8308aa2e16a0d50 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#### imports | |
from tkinter import * | |
import pandas as pd | |
#### global constants | |
CAN_MOVE = '#99CC00' | |
MOVE_NOMOVE = '#00FF00' | |
ROTATE = '#FFFF00' | |
ROTATE_NOMOVE = '#0000FF' | |
MOVE2_CANMOVE = '#660000' | |
HAVE_ROAD = 'red' | |
START_COLOR = 'blue' | |
END_COLOR = 'green' | |
MAXSTEPS = 1 | |
ROW = 3 | |
COL = 3 | |
FRAME_BGCOLOR_CHANGE_MAP = { # A mapping table to determine next state (FSM concept) | |
CAN_MOVE: MOVE_NOMOVE, | |
MOVE_NOMOVE: ROTATE, | |
ROTATE: ROTATE_NOMOVE, | |
ROTATE_NOMOVE: MOVE2_CANMOVE, | |
MOVE2_CANMOVE: 'SystemButtonFace', | |
} | |
#### functions | |
# bg_equals, get_bg, set_bg, init_2d_data are frequently used pieces of code, so extract them into functions to reduce code | |
# More advanced way is to define methods under custom widget classes (inherit from Button and LabelFrame) | |
def bg_equals(widget, bg): | |
return get_bg(widget) == bg | |
def get_bg(widget): | |
return widget.config('bg')[-1] | |
def set_bg(widget, bg): | |
widget.config(bg=bg) | |
# utility function to initialize 2d data with a value function as parameter | |
def init_2d_data(value_func): | |
return [[value_func() for x in range(ROW)] for y in range(COL)] | |
def toggle_have_road(widget): | |
set_bg(widget, 'SystemButtonFace' if bg_equals(widget, HAVE_ROAD) else HAVE_ROAD) | |
def up_color_change(x, y): | |
toggle_have_road(btnUp[x][y]) | |
def bg_center_color_change(p): | |
# Generally the code will be more clear if you split the logic of input, process and output. | |
# Part 1: input: get required things for process | |
widget = p.widget | |
bg = get_bg(widget) | |
# Part 2: do process: determine next bg | |
if bg == START_COLOR: | |
next_bg = END_COLOR | |
elif bg == END_COLOR: | |
next_bg = 'SystemButtonFace' | |
else: | |
next_bg = START_COLOR | |
# Part 3: output: set next bg | |
set_bg(widget, next_bg) | |
def bg_color_change(p): | |
toggle_have_road(p.widget) | |
def frame_bgColor_change(p): | |
widget = p.widget | |
bg = get_bg(widget) | |
# use the mapping table can reduce lots of if-else logic, but make sure to handle the condition when key is not in dict | |
next_bg = FRAME_BGCOLOR_CHANGE_MAP[bg] if bg in FRAME_BGCOLOR_CHANGE_MAP else CAN_MOVE | |
set_bg(widget, next_bg) | |
def solve(): | |
for j in range(ROW): | |
for i in range(COL): | |
thisCells = [ | |
bg_equals(btnUp[i][j], HAVE_ROAD), # == operator would return boolean. You can directly use it as a value | |
bg_equals(btnRight[i][j], HAVE_ROAD), | |
bg_equals(btnDown[i][j], HAVE_ROAD), | |
bg_equals(btnLeft[i][j], HAVE_ROAD), | |
] | |
# | |
centerBg = get_bg(btnCenter[i][j]) | |
thisCells.extend([ #! You can use extend to append multiple items at once | |
centerBg == START_COLOR, | |
centerBg == END_COLOR, | |
]) | |
# | |
frmBg = get_bg(frmCell[i][j]) | |
#! This part can be refined with the above-mentioned mapping table. You can try it by yourself. | |
if frmBg == CAN_MOVE: | |
thisCells.extend([ | |
True, # initially movable | |
False, | |
False, | |
False | |
]) | |
elif frmBg == MOVE_NOMOVE: | |
thisCells.extend([ | |
True, # initially movable | |
True, # cannot move after move | |
False, | |
False | |
]) | |
elif frmBg == ROTATE: | |
thisCells.extend([ | |
True, # initially movable | |
False, | |
True, # will rotate when each move | |
False | |
]) | |
elif frmBg == MOVE2_CANMOVE: | |
thisCells.extend([ | |
False, | |
False, | |
False, | |
True # initially cannot move until totally 2 steps of move | |
]) | |
else: | |
thisCells.extend([False, False, False, False]) | |
# | |
cells[i][j] = thisCells | |
df = pd.DataFrame(cells) | |
#df.columns = [['up', 'right', 'down', 'left', 'start', 'end', 'canMove', 'move_noMove', 'rotate', 'move2_canMove']] | |
# 以上為遊戲題目出題之視覺界面設定完成, 轉化出之df為出題結果之三維陣列 | |
# 接下去才開始進入解題, 解題程式尚未寫作 | |
getMovableGroup() | |
move(0, cells) | |
def getMovableGroup(): | |
return | |
def move(steps, cells): | |
if steps == MAXSTEPS: | |
print(cells) | |
return | |
thisMove() | |
check() | |
steps += 1 | |
# print(df) | |
move(steps, cells) | |
def thisMove(): | |
return | |
def check(): | |
return | |
#### main code | |
root = Tk() | |
root.title("test") | |
pw = PanedWindow(orient=VERTICAL) | |
cells = init_2d_data(lambda: []) | |
frmCell = init_2d_data(lambda: 0) | |
btnUp = init_2d_data(lambda: 0) | |
btnLeft = init_2d_data(lambda: 0) | |
btnRight = init_2d_data(lambda: 0) | |
btnDown = init_2d_data(lambda: 0) | |
btnCenter = init_2d_data(lambda: 0) | |
for i in range(ROW): | |
pwInner = PanedWindow(orient=HORIZONTAL) | |
for j in range(COL): | |
frmCell[j][i] = LabelFrame(pwInner, text=str(i) + "," + str(j), width=80, height=40) | |
frmCell[j][i].bind('<Button-1>', frame_bgColor_change) | |
pwInner.add(frmCell[j][i]) | |
# The code below are really similar to each other, you can try to think how to use function, loop or class to refine them | |
btnUp[j][i] = Button(frmCell[j][i], text="", width=3, height=2) # , command= lambda x1=j, y1=i: up_color_change(x1,y1)) | |
btnUp[j][i].grid(row=0, column=1) | |
btnUp[j][i].bind('<Button-1>', bg_color_change) | |
btnLeft[j][i] = Button(frmCell[j][i], text="", width=5, height=1) | |
btnLeft[j][i].grid(row=1, column=0) | |
btnLeft[j][i].bind('<Button-1>', bg_color_change) | |
btnCenter[j][i] = Button(frmCell[j][i], text="", width=5, height=2) | |
btnCenter[j][i].grid(row=1, column=1) | |
btnCenter[j][i].bind('<Button-1>', bg_center_color_change) | |
btnRight[j][i] = Button(frmCell[j][i], text="", width=5, height=1) | |
btnRight[j][i].grid(row=1, column=2) | |
btnRight[j][i].bind('<Button-1>', bg_color_change) | |
btnDown[j][i] = Button(frmCell[j][i], text="", width=3, height=2) | |
btnDown[j][i].grid(row=2, column=1) | |
btnDown[j][i].bind('<Button-1>', bg_color_change) | |
pw.add(pwInner) | |
btnSolve = Button(pw, text='Solve', bg='yellow', command=solve) | |
pw.add(btnSolve) | |
pw.pack(fill=BOTH, expand=True, padx=10, pady=10) | |
root.mainloop() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment