class Wall(object): MIN_RED = MIN_GREEN = MIN_BLUE = 0x0 MAX_RED = MAX_GREEN = MAX_BLUE = 0xFF PIXEL_WIDTH = 50 def __init__(self, width, height): self.width = width self.height = height self._tk_init() self.pixels = [(0, 0, 0) for i in range(self.width * self.height)] def _tk_init(self): self.root = Tk() self.root.title("ColorWall %d x %d" % (self.width, self.height)) self.root.resizable(0, 0) self.frame = Frame(self.root, bd=5, relief=SUNKEN) self.frame.pack() self.canvas = Canvas(self.frame, width=self.PIXEL_WIDTH * self.width, height=self.PIXEL_WIDTH * self.height, bd=0, highlightthickness=0) self.canvas.pack() self.root.update() def set_pixel(self, x, y, hsv): self.pixels[self.width * y + x] = hsv def get_pixel(self, x, y): return self.pixels[self.width * y + x] def draw(self): self.canvas.delete(ALL) for x in range(len(self.pixels)): x_0 = (x % self.width) * self.PIXEL_WIDTH y_0 = (x / self.width) * self.PIXEL_WIDTH x_1 = x_0 + self.PIXEL_WIDTH y_1 = y_0 + self.PIXEL_WIDTH hue = "#%02x%02x%02x" % self._get_rgb(self.pixels[x]) self.canvas.create_rectangle(x_0, y_0, x_1, y_1, fill=hue) self.canvas.update() def clear(self): for i in range(self.width * self.height): self.pixels[i] = (0, 0, 0) def _hsv_to_rgb(self, hsv): rgb = colorsys.hsv_to_rgb(*hsv) red = self.MAX_RED * rgb[0] green = self.MAX_GREEN * rgb[1] blue = self.MAX_BLUE * rgb[2] return (red, green, blue) def _get_rgb(self, hsv): red, green, blue = self._hsv_to_rgb(hsv) red = int(float(red) / (self.MAX_RED - self.MIN_RED) * 0xFF) green = int(float(green) / (self.MAX_GREEN - self.MIN_GREEN) * 0xFF) blue = int(float(blue) / (self.MAX_BLUE - self.MIN_BLUE) * 0xFF) return (red, green, blue)
class WindowInstance(Frame): def __init__(self, parent): Frame.__init__(self, parent) self.parent = parent self.parent.title("Window") self.pack(fill=BOTH, expand=1) self.canvas = Canvas(self) self.doubleBuffer = False self.fill = "#000" self.outline = "#000" def setColor(self, c): self.fill = c self.outline = c def drawRectangle(self, x, y, w, h): self.canvas.create_rectangle(x, y, x + w, y + h, fill=self.fill, outline=self.outline) if not self.doubleBuffer: self.canvas.pack(fill=BOTH, expand=1) def drawLine(self, x, y, ex, ey): self.canvas.create_line(x, y, ex, ey, fill=self.fill) if not self.doubleBuffer: self.canvas.pack(fill=BOTH, expand=1) def drawOval(self, x, y, w, h): self.canvas.create_oval(x, y, x + w, y + h, fill=self.fill, outline=self.outline) if not self.doubleBuffer: self.canvas.pack(fill=BOTH, expand=1) def frame(self): self.doubleBuffer = True self.canvas.pack(fill=BOTH, expand=1) def clear(self): self.canvas.delete("all")
class Example(Frame): def __init__(self, parent): Frame.__init__(self, parent) self.x = 0 self.y = 0 self.parent = parent parent.bind("<Motion>", self.onMove) parent.bind("<Button-1>", self.leftClick) parent.bind("<Button-3>", self.rightClick) self.parent.title("Colors") self.pack(fill=BOTH, expand=1) self.canvas = Canvas(self) self.canvas.create_rectangle(30, 10, 120, 80, outline="#fb0", fill="#fb0") self.canvas.create_rectangle(150, 10, 240, 80, outline="#f50", fill="#f50") self.canvas.create_rectangle(270, 10, 370, 80, outline="#05f", fill="#05f") self.canvas.pack(fill=BOTH, expand=1) self.inMotion = False self.line = 0#Holder for temp line whilst dragging mouse around def onMove(self, e): if self.inMotion: self.canvas.delete(self.line) self.line = self.canvas.create_line(self.x, self.y, e.x, e.y) def leftClick(self, e): if not(self.inMotion): self.canvas.create_line(self.x, self.y, e.x, e.y) self.x = e.x self.y = e.y self.inMotion = True def rightClick(self, e): self.inMotion = False
class Application(Tk): def __init__(self): super().__init__() self.title('Hangman') self.geometry('640x480+200+200') self.resizable(width=False, height=False) menu_bar = Menu(self, tearoff=0) self.config(menu=menu_bar) game_menu = Menu(menu_bar, tearoff=0) game_menu.add_command(label='New game', command=self.__on_new_game) game_menu.add_command(label='Quit', command=self.__on_quit) menu_bar.add_cascade(label='Game', menu=game_menu) self.__hang_canvas = Canvas(self, background='#ffffff') self.__hang_canvas.pack(fill=BOTH, expand=True) self.__dict_filename = os.path.join(os.path.dirname(__file__), 'dictionary.txt') self.__dictionary = [] self.__secret_word_masked = StringVar() self.__game_stages = ( # (is_circle, x1, y1, x2, y2), (False, 50, 300, 200, 300), # podstawa (False, 60, 300, 60, 10), # maszt (False, 60, 10, 160, 10), (False, 60, 30, 100, 10), (False, 160, 10, 160, 30), (True, 140, 30, 180, 70), (False, 160, 70, 160, 200), # tułów (False, 140, 120, 160, 70), # lewa reka (False, 180, 120, 160, 70), # prawa ręka (False, 160, 200, 140, 250), (False, 160, 200, 180, 250) ) self.__errors_count = 0 secret_word_label = Label(self, font=('purisa', 36), textvariable=self.__secret_word_masked) secret_word_label.pack(fill=X) # user input panel Label(self, text='Please input a char:').pack(fill=X) self.__user_input_char = StringVar() user_input_entry = Entry(self, textvariable=self.__user_input_char) user_input_entry.bind('<Return>', self.__on_user_input) user_input_entry.pack() self.__load_dictionary() self.__new_game() def __on_user_input(self, event): text = self.__user_input_char.get() if text: c = text[0] if c in self.__secret_word: self.__secret_word_masked.set(str(self.__secret_word)) # check is it victory if self.__secret_word.is_reveled(): self.__do_victory() else: # check if defeat self.__errors_count += 1 self.__redraw_canvas() if self.__errors_count >= len(self.__game_stages): self.__do_defeat() self.__user_input_char.set('') def __redraw_canvas(self): if self.__errors_count <= len(self.__game_stages): self.__hang_canvas.delete('all') for i in range(self.__errors_count): is_circle, x1, y1, x2, y2 = self.__game_stages[i] if is_circle: self.__hang_canvas.create_oval(x1, y1, x2, y2) else: self.__hang_canvas.create_line(x1, y1, x2, y2) def __do_defeat(self): pos = (self.__hang_canvas.winfo_width()/2, self.__hang_canvas.winfo_height()/2) self.__hang_canvas.create_text(pos, text='Defeat!', fill='#FF0000', font=('purisa', 36)) print('Defeat!') self.__secret_word_masked.set(self.__secret_word.word) def __do_victory(self): pos = (self.__hang_canvas.winfo_width()/2, self.__hang_canvas.winfo_height()/2) self.__hang_canvas.create_text(pos, text='Victory!', fill='#FF0000', font=('purisa', 36)) print('victory!') def __load_dictionary(self): with open(self.__dict_filename, 'r') as f: for line in f: self.__dictionary.append(line.lower().strip()) def __on_new_game(self): self.__new_game() def __new_game(self): # Reset state of game word = random.choice(self.__dictionary) self.__secret_word = Riddle(word) self.__secret_word_masked.set(str(self.__secret_word)) self.__errors_count = 0 self.__redraw_canvas() def __on_quit(self): print('Goodbye :)') self.quit()
class rmap(): _var = [1] _nc = 0 _nr = 0 _r = 0 _c = 0 _size = 0 _w = 0 _d = 0 _NoneUpdate = False _Nonelabel = False _Nonegettext = False _field = [] _endPoint = (0, 0) _robot = '' # рисунок Робота (синее кольцо) _park = '' _canvas = '' sleep = 0.5 _task = '' _solve = '' _test = '' _res = '' _bum = 0 m = [] m.append('task1') m.append('task2') m.append('task3') m.append('task4') m.append('task5') m.append('task6') m.append('task7') m.append('task8') m.append('task9') m.append('task10') m.append('task11') m.append('task12') m.append('task13') class _v: # будет содержать изображение текста и квадратиков закраски и меток. Чтобы можно было "поднимать изображение" text = '' label = '' color = '' class _Tcell(): color = '' text = '' label = '' # color wUp = False wLeft = False v = '' def help(self): """ Вывести список команд Робота Примеры использования по команде r.help_full() """ print(""" Пояснение по каждой команде: print команда.__doc__ Например: print r.color.__doc__ ---=: Команды перемещения :=--- r.rt() # Вправо r.lt() # Влево r.dn() # Вниз r.up() # Вверх r.jumpTo(r,c) # Прыжок в точку. Без особых указаний в задачах не использовать -=-=-=-=-=-=-=-=-=-=-=-=-=-==-= ---=: Команды изменения среды :=--- r.pt([цвет]) # Закрасить указанным цветом. По умолчанию зеленым r.sw(направление) # Установить стену с указанной стороны r.settext(тест) # Вписать в клетку текст -=-=-=-=-=-=-=-=-=-=-=-=-=-==-= ---=: Команды обратной связи :=--- r.cl() # Каким цветом закрашена клетка? r.color() r.label() # Какого цвета метка в клетке? r.gettext() # Какой текст в клетке? r.getCoords() # Где Робот? r.getCoordR() # В какой строке Робот? r.getCoordС() # В каком столбце Робот? r.fu() # Сверху свободно? r.fd() # Снизу свободно? r.fr() # Справа свободно? r.fl() # Слева свободно? r.wu() # Сверху стена? r.wd() # Снизу стена? r.wr() # Справа стена? r.wl() # Слева стена? r.isPark # Робот на парковке? -=-=-=-=-=-=-=-=-=-=-=-=-=-==-= ---=: Дополнительно :=--- r.sleep = 0.4 # Установить размер задержки после каждого хода. Меньше значение - быстрее Робот. r._NoneUpdate = False # Отключить прорисовку поля r._NoneUpdate = True # Включить прорисовку поля r.demo() # Показать, что нужно сделать в текущей задаче r.demoAll() # Показать все задачи (с решениями, по очереди) r.randcolor() # Генерировать случайный цвет -=-=-=-=-=-=-=-=-=-=-=-=-=-==-= """) def help_full(self): """ Примеры. Для получения списка команд r.help() Примеры использования по команде r.help_full() Больше информации по каждой команде: print команда.__doc__ Например: print r.color.__doc__ """ print(""" Не реализовано в данной версии. Если нужно - пишите на [email protected] или на сайте progras.ru """) def demo(self): """Показать выполнение задачи Пример использования: #------------------- r.demo() #------------------- Для уcкорения использовать r.sleep = 0.01 В задании 10-3(4/5) можно отключить обновление экрана #------------------- r._NoneUpdate = True r.demo() r._NoneUpdate = False #------------------- """ global r r = self exec(self._solve) def demoAll(self): """Показать выполнение всех заданий в автоматическом режиме Пример использования: #------------------- r.demoAll() #------------------- Для того, чтобы Робот двигался быстрее, используйте #------------------- r.sleep = 0 r.demoAll() #------------------- """ global r r = self for x in r.m: r.lm(x) print(x) r.demo() r.pause() def __init__(self): self._w = 4 # толщина стен self._d = 4 # на столько меньше клетки закраска (с каждой стороны) self.sleep = 0.5 # замедление self._font_size = self._size // 2 self._tk = Tk() self._tk.geometry('+0+0') x = (self._tk.winfo_screenwidth() - self._tk.winfo_reqwidth()) / 3 y = (self._tk.winfo_screenheight() - self._tk.winfo_reqheight()) / 4 self._tk.wm_geometry("+%d+%d" % (x, y)) self._tk.title('Robot-hobot') self._canvas = Canvas(self._tk, width=(self._size * (self._nc + 1)), height=(self._size * (self._nr + 1)), bg="gray") buttons = Frame(self._tk) self.task = Label(self._tk, justify='left') self.res = Label(self._tk, justify='left') self._but_start = Button(buttons, text='start', width=10, height=1) self._but_start.bind('<ButtonRelease-1>', self.but1) self._but_demo = Button(buttons, text='demo', width=10, height=1) self._but_demo.bind('<ButtonRelease-1>', self.but_demo) self._but_reload = Button(buttons, text='reload', width=10, height=1) self._but_reload.bind('<ButtonRelease-1>', self.but_reload) self._but_load_next = Button(buttons, text='load next', width=10, height=1) self._but_load_next.bind('<ButtonRelease-1>', self.but_load_next) buttons.grid(row=0, column=0, sticky="w") self._canvas.grid(row=1, column=0, sticky="e") self._but_start.pack(side="left") self._but_demo.pack(side="left") self._but_reload.pack(side="left") self._but_load_next.pack(side="left") self.task.grid(row=3, column=0, sticky="w") self.res.grid(row=4, column=0, sticky="w") ## self.loadmap() def but_load_next(self, event): print("load next") index = self.m.index(self._cur_map) if index < len(self.m) - 1: self.lm(self.m[index + 1]) else: self.lm(self.m[0]) def but_demo(self, event): print("demo") self.demo() def but1(self, event): print('start') # self.lm(self._cur_map) self.solve_task() def but_reload(self, event): print("reload") self.lm(self._cur_map) def clear(self): "Очистка данных (без перерисовки)" self._canvas.delete('all') self._field = [] self._park = [] self._Nonelabel = False self._NoneisPark = False self._Nonesettext = False self._test = '' self._res = '' self._bum = 0 for r in range(1, self._nr + 2): row = [] for c in range(1, self._nc + 2): row.append(self._Tcell()) self._field.append(row) for r in range(1, self._nr): for c in range(1, self._nc): self._field[r][c].text = '' self._field[r][c].color = '' self._field[r][c].label = '' self._field[r][c].wUp = False self._field[r][c].wLeft = False self._field[r][c].v = self._v() for c in range(1, self._nc): self._field[1][c].wUp = True self._field[self._nr][c].wUp = True for r in range(1, self._nr): self._field[r][1].wLeft = True self._field[r][self._nc].wLeft = True self._solve = '' self._r = 1 self._c = 1 def _paintMap(self): "Перерисовка по имеющимся данным" remc = self._c remr = self._r size = self._size sleep = self.sleep self.sleep = 0 self._bg = [self._canvas.create_rectangle(1, 1, (size * (self._nc + 1)), (size * (self._nr + 1)), fill="gray")] # создать поле for r in range(1, self._nr + 1): self._bg.append(self._canvas.create_line(size, r * size, self._nc * size, r * size)) if r < self._nr: self._canvas.create_text(size / 2, r * size + size / 2, text=r) for c in range(1, self._nc + 1): self._bg.append(self._canvas.create_line(c * size, size, c * size, self._nr * size)) if c < self._nc: self._bg.append(self._canvas.create_text(c * size + size / 2, size / 2, text=c)) # клетки и номера столбцов и строк for r in range(1, self._nr): for c in range(1, self._nc): self._r = r self._c = c if self._field[r][c].wUp: # стена сверху self.setWall('up') if self._field[r][c].wLeft: # стена слева self.setWall('left') if self._field[r][c].color != '': # закраска self.paint(self._field[r][c].color) if self._field[r][c].label != '': # метка0000 d = self._d x1 = self._size * (c) x2 = self._size * (c + 1) y1 = self._size * (r) y2 = self._size * (r + 1) self._canvas.delete(self._field[r][c].v.label) self._field[r][c].v.label = self._canvas.create_rectangle(x1 + d, y1 + d, x2 - d, y2 - d, width=d - 1, outline=self._field[r][c].label) self._canvas.lift(self._robot) self.settext(self._field[r][c].text) # текст for self._c in range(1, self._nc): if self._field[self._nr][self._c].wUp: # стена сверху self.setWall('down') for self._r in range(1, self._nr): if self._field[self._r][self._nc].wLeft: # стена слева self.setWall('right') r = self._endPoint[0] c = self._endPoint[1] self._canvas.delete(self._park) if r > 0 and c > 0: self._park = self._canvas.create_oval(c * size + 6, r * size + 6, c * size + size - 6, r * size + size - 6, width=3, outline='yellow') # конечная точка self.jumpTo((remr, remc)) self._task = '\n' + self._task self.task.config(text=self._task) self.res.config() self._update() self.sleep = sleep # self.pause() def _update(self): "Обновить canvas" if not self._NoneUpdate: self._canvas.update() time.sleep(self.sleep) def start(self, fun): self.solve_task = fun self._tk.mainloop() ##Робот def pause(self, t=1): """Приостановка выполнения программы. Пауза в секундах. #------------------- r.pause() # пауза в одну секунду #------------------- r.pause(2) # пауза две секунды #------------------- """ time.sleep(t) def left(self, a=1): """Шаг влево #------------------- r.left() #------------------- r.lt() #------------------- r.lt(3) #------------------- """ if a == 1: if self.freeLeft(): self._c -= 1 self._canvas.move(self._robot, -self._size * a, 0) self._update() else: self._stop() else: for z in range(0, a): self.left() def right(self, a=1): """ Шаг вправо #------------------- r.right() #------------------- r.rt() #------------------- r.rt(5) #------------------- """ if a == 1: if self.freeRight(): self._c += 1 self._canvas.move(self._robot, self._size * a, 0) self._update() else: self._stop() else: for z in range(0, a): self.right() def up(self, a=1): """Шаг вверх #------------------- r.up() #------------------- r.up(3) #------------------- """ if a == 1: if self.freeUp(): self._r -= 1 self._canvas.move(self._robot, 0, -self._size * a) self._update() else: self._stop() else: for z in range(0, a): self.up() def down(self, a=1): """ Шаг вниз #------------------- r.down() #------------------- r.dn() #------------------- r.dn(4) #------------------- """ if a == 1: if self.freeDown(): self._r += 1 self._canvas.move(self._robot, 0, self._size * a) self._update() else: self._stop() else: for z in range(0, a): self.down() def jumpTo(self, coord=(1, 1)): """Прыжок в клетку с указанными координами. Через стены. #------------------- r.jumpTo((2,3)) # Робот окажется в третьем столбце второй строки #------------------- """ r = coord[0] c = coord[1] if (0 < r < self._nc) and (0 < c < self._nc): self._r = r self._c = c size = self._size self._canvas.coords(self._robot, c * size + 4, r * size + 4, c * size + size - 4, r * size + size - 4) self._canvas.lift(self._robot) self._update() else: print("Попытка переместиться за пределы поля. Отказано.") def paint(self, color='green'): """ Закрасить текущую клетку выбранным цветом. Если цвет не указан, то зеленым #------------------- r.paint() # Закрасит текущую клетку зеленым цветом #------------------- r.pt() # Закрасит текущую клетку зеленым цветом #------------------- r.pt('red') # Закрасит текущую клетку красным цветом #------------------- r.pt(r.randcolor()) # Закрасит текущую клетку случайным цветом #------------------- r.pt(r.label()) # Закрасит текущую клетку цветом метки в этой клетке #------------------- """ d = self._d + 1 self._field[self._r][self._c].color = color x1 = self._size * (self._c) x2 = self._size * (self._c + 1) y1 = self._size * (self._r) y2 = self._size * (self._r + 1) self._canvas.delete(self._field[self._r][self._c].v.color) self._field[self._r][self._c].v.color = self._canvas.create_rectangle(x1 + d, y1 + d, x2 - d, y2 - d, width=0, fill=color) self._canvas.lift(self._field[self._r][self._c].v.text) self._canvas.lift(self._robot) self._canvas.lift(self._park) self._update() def setWall(self, target): """ Установить стену с указанной стороны #------------------- r.sw('up') # Установить стену сверху #------------------- r.sw('left') # Установить стену слева #------------------- r.sw('down') # Установить стену снизу #------------------- r.sw('right') # Установить стену справа #------------------- """ size = self._size w = self._w if target == 'up': r = self._r c = self._c x1 = size * (c) - 1 x2 = size * (c + 1) + 1 y1 = size * (r) y2 = size * (r + 1) self._field[r][c].wUp = True self._canvas.create_line(x1, y1, x2, y1, width=w) elif target == 'left': r = self._r c = self._c x1 = size * (c) x2 = size * (c + 1) y1 = size * (r) - 1 y2 = size * (r + 1) + 1 self._field[r][c].wLeft = True self._canvas.create_line(x1, y1, x1, y2, width=w) elif target == 'down': r = self._r + 1 c = self._c x1 = size * (c) - 1 x2 = size * (c + 1) + 1 y1 = size * (r) y2 = size * (r + 1) self._field[r][c].wDown = True self._canvas.create_line(x1, y1, x2, y1, width=w) elif target == 'right': r = self._r c = self._c + 1 x1 = size * (c) x2 = size * (c + 1) y1 = size * (r) - 1 y2 = size * (r + 1) + 1 self._field[r][c].wRight = True self._canvas.create_line(x1, y1, x1, y2, width=4) self._update() def wallUp(self): """ Возвращает истину, если сверху есть стена #------------------- if r.wallUp(): r.pt() # Закрасить, если сверху стена #------------------- if r.wu(): r.pt() # Закрасить, если сверху стена #------------------- if r.wu(): r.pt() # Закрасить, если сверху стена r.rt() # Перейти вправо #------------------- while r.wu(): # Идти вправо, пока сверху есть стена r.rt() """ return self._field[self._r][self._c].wUp def wallDown(self): """ Возвращает истину, если снизу есть стена #------------------- if r.wallDown(): r.pt() # Закрасить, если снизу стена #------------------- if r.wd(): r.pt() # Закрасить, если снизу стена #------------------- if r.wd(): r.pt() # Закрасить, если снизу стена r.rt() # Перейти вправо #------------------- while r.wd(): # Идти вправо, пока снизу есть стена r.rt() """ return self._field[self._r + 1][self._c].wUp def wallLeft(self): """ Возвращает истину, если слева есть стена #------------------- if r.wallLeft(): r.pt() # Закрасить, если слева стена #------------------- if r.wl(): r.pt() # Закрасить, если слева стена #------------------- if r.wl(): r.pt() # Закрасить, если слева стена r.dn() # Перейти вниз #------------------- while r.wl(): # Идти вниз, пока слева есть стена r.dn() """ return self._field[self._r][self._c].wLeft def wallRight(self): """ Возвращает истину, если справа есть стена #------------------- if r.wallRight(): r.pt() # Закрасить, если справа стена #------------------- if r.wr(): r.pt() # Закрасить, если справа стена #------------------- if r.wr(): r.pt() # Закрасить, если справа стена r.dn() # Перейти вниз #------------------- while r.wr(): # Идти вниз, пока справа есть стена r.dn() """ return self._field[self._r][self._c + 1].wLeft def freeUp(self): """ Возвращает истину, если сверху свободно (нет стены) #------------------- if r.freeUp(): r.pt() # Закрасить, если сверху свободно #------------------- if r.fu(): r.up() # Шагнуть вверх, если сверху свободно #------------------- if r.fu(): r.up() # Шагнуть вверх r.pt() # Закрасить r.dn() # Перейти вниз #------------------- while r.fu(): # Идти вверх, пока сверху свободно r.up() """ return not self._field[self._r][self._c].wUp def freeDown(self): """ Возвращает истину, если снизу свободно (нет стены) #------------------- if r.freeDown(): r.pt() # Закрасить, если снизу свободно #------------------- if r.fd(): r.dn() # Шагнуть вверх, если снизу свободно #------------------- if r.fd(): r.dn() # Шагнуть снизу r.pt() # Закрасить r.up() # Перейти вверх #------------------- while r.fd(): # Идти вниз, пока снизу свободно r.dn() """ return not self._field[self._r + 1][self._c].wUp def freeLeft(self): """ Возвращает истину, если слева свободно (нет стены) #------------------- if r.freeLeft(): r.pt() # Закрасить, если слева свободно #------------------- if r.fl(): r.lt() # Шагнуть влево, если слева свободно #------------------- if r.fl(): r.lt() # Шагнуть влево r.pt() # Закрасить r.rt() # Перейти вправо #------------------- while r.fl(): # Идти влево, пока слева свободно r.lt() """ return not self._field[self._r][self._c].wLeft def freeRight(self): """ Возвращает истину, если снизу свободно (нет стены) #------------------- if r.freeDown(): r.pt() # Закрасить, если снизу свободно #------------------- if r.fd(): r.dn() # Шагнуть вверх, если снизу свободно #------------------- if r.fd(): r.dn() # Шагнуть снизу r.pt() # Закрасить r.up() # Перейти вверх #------------------- while r.fd(): # Идти вниз, пока снизу свободно r.dn() """ return not self._field[self._r][self._c + 1].wLeft def getCoords(self): " Возвращает координаты в виде (row,column)" return (self._r, self._c) def getCoordR(self): " Возвращает номер строки, в которой находиться Робот" return self._r def getCoordC(self): " Возвращает номер столбца, в которой находиться Робот" return self._c def isPark(self): " Возвращает истину, если Робот находиться на парковке" if self._NoneisPark: self.null() else: return self._endPoint == self.getCoords() def color(self): """ Возвращает цвет, которым закрашена клетка Можно использовать для проверки, закрашена ли клетка: #------------------- # Закрасить, если сверху закрашено r.up() if r.color(): r.dn() r.pt() else: r.dn() #------------------- if r.color() == 'red': r.rt() # Вправо, если закрашено красным #------------------- """ return self._field[self._r][self._c].color def randcolor(self): """ Возвращает случайный цвет #------------------- r.pt(r.randcolor()) # Закрасить случайным цветом #------------------- # Закрасить соседнюю клетку тем же цветом, что и текущая x = r.color() r.rt() r.pt(x) #------------------- """ cr = rnd(1, 255, 10) cg = rnd(1, 255, 10) cb = rnd(1, 255, 10) color = "#%02X%02X%02X" % (cr, cg, cb) return str(color) def label(self): """ Возвращает цвет метки текущей клетки #------------------- if r.label() == 'red': r.pt('red') # Закрасить клетку красным, если метка красная #------------------- """ if self._Nonelabel: self.null() else: return self._field[self._r][self._c].label def gettext(self): """ Возвращает текст, записанный в ячейке. #------------------- if r.gettext() != '': r.rt() # Перейти вправо, если в ячейке есть какой-нибудь текст #------------------- if r.gettext() == '3': r.rt() # Перейти вправо, если в ячейке записано 3 #------------------- n = r.gettext() if n: r.rt(n) # Перейти вправо на количество шагов, указанное в клетке #------------------- """ if self._Nonegettext: self.null() else: return self._field[self._r][self._c].text def settext(self, text): """ Записать текст в клетку #------------------- r.settext(3) #------------------- """ self._field[self._r][self._c].text = text d = 1 x1 = self._size * (self._c) x2 = self._size * (self._c + 1) y1 = self._size * (self._r) y2 = self._size * (self._r + 1) self._canvas.delete(self._field[self._r][self._c].v.text) self._field[self._r][self._c].v.text = self._canvas.create_text(self._c * self._size + self._size / 2, self._r * self._size + self._size / 2, text= self._field[self._r][self._c].text, font=('Helvetica', self._font_size, 'bold')) self._update() def _stop(self): print("Bum!") self._bum = 1 self._canvas.delete(self._robot) x = self._c y = self._r self._robot = self._canvas.create_oval( x * self._size + 2 * self._d, y * self._size + 2 * self._d, x * self._size + self._size - 2 * self._d, y * self._size + self._size - 2 * self._d, fill='#FF0000') def null(self, *args): print('Эта команда запрещена к использованию в данной задаче. Ищите другой способ') return '' def loadmap(self, mn=m[0], variant=0): """ Загрузить карту (задачу) #------------------- r.loadmap('task10-5') #------------------- r.lm('task10-5') # Загрузить задачу по названию #------------------- r.lm(r.m[5]) # Загрузить задачу по номеру #------------------- # Вывести полный список названий и номеров заданий for x in r.m: print r.m.index(x),x #------------------- """ self._tk.title(mn) self._cur_map = mn self._NoneUpdate = False self._endPoint = (0, 0) # self._NoneUpdate = True if mn == 'task1': self._nc = 7 self._nr = 5 self._size = 30 self.clear() self._r = 3 self._c = 2 self._solve = '' self._endPoint = (3, 5) self._task = 'Необходимо перевести Робота по лабиринту\n' \ ' из начального положения в конечное.\n' self._field[2][2].wUp = True self._field[2][3].wUp = True self._field[2][4].wUp = True self._field[2][5].wUp = True self._field[4][2].wUp = True self._field[4][3].wUp = True self._field[4][4].wUp = True self._field[4][5].wUp = True self._field[2][4].wLeft = True self._field[3][3].wLeft = True self._field[3][5].wLeft = True ##-------------------------------------------------------------------------------------------- elif mn == 'task2': self._nc = 16 self._nr = 4 self._size = 30 self.clear() self._r = 3 self._c = 1 self._solve = '' self._task = 'Составьте программу рисования узора.\n' ##-------------------------------------------------------------------------------------------- elif mn == 'task3': self._nc = 10 self._nr = 5 self._size = 30 self.clear() self._r = 2 self._c = 1 self._endPoint = (2, 9) self._solve = '' self._task = 'Необходимо провести Робота вдоль коридора\n' \ ' из начального положения в конечное,\n' \ ' заглядывая в каждый боковой коридор.' for i in range(2, 9): self._field[2][i].wUp = True if i % 2 == 0: self._field[3][i].wUp = True else: self._field[4][i].wUp = True if i < 8: self._field[3][i + 1].wLeft = True ##-------------------------------------------------------------------------------------------- elif mn == 'task4': self._nc = 8 self._nr = 12 self._size = 30 self.clear() self._r = rnd(1, self._nr) self._c = rnd(1, self._nc) for i in range(0, 5): for j in range(0, 3): self._field[6 + 2 * j - i][2 + i].label = 'red' self._solve = '' self._task = 'Составьте программу закрашивания\n' \ ' клеток поля, отмеченных звездочкой.\n' ##-------------------------------------------------------------------------------------------- elif mn == 'task5': self._nc = 16 self._nr = 11 self._r = 1 self._c = 1 self._size = 30 self.clear() self._solve = '' self._task = 'Составьте программу рисования узора.' ##-------------------------------------------------------------------------------------------- ##-------------------------------------------------------------------------------------------- elif mn == 'task6': self._nc = 25 self._nr = 25 self._r = 1 self._c = 1 self._size = 20 self.clear() self._solve = '' self._task = 'Составьте программу рисования фигуры в виде буквы "Т".\n' \ ' Вертикальные и горизонтальные размеры пользователь вводит\n' \ ' с клавиатуры. Ввод данных можно осуществлять любым способом.\n' ##------------------------------------------------------------------------------------------------------- elif mn == 'task7': self._nc = 16 self._nr = 11 self._size = 25 self.clear() self._r = rnd(1, self._nr) self._c = rnd(1, self._nc) self._field[3][2].wUp = True self._field[2][9].wUp = True self._field[3][12].wUp = True self._field[6][12].wUp = True self._field[7][3].wUp = True self._field[7][9].wUp = True self._field[8][6].wUp = True self._field[9][2].wUp = True self._field[9][11].wUp = True for i in range(0, 4): self._field[4][5 + i].wUp = True self._field[5][5 + i].wUp = True self._solve = '' self._task = 'Где-то в поле Робота находится горизонтальный коридор шириной в одну клетку\n' \ ' неизвестной длины. Робот из верхнего левого угла поля должен дойти до\n' \ ' коридора и закрасить клетки внутри него, как указано в задании. По полю\n' \ ' Робота в произвольном порядке располагаются стены, но расстояние \n' \ 'между ними больше одной клетки.\n' ##-------------------------------------------------------------------------------------------- elif mn == 'task8': self._nc = 16 self._nr = 11 self._size = 25 self.clear() self._r = rnd(1, self._nr) self._c = rnd(1, self._nc) self._field[2][6].wLeft = True self._field[3][6].wLeft = True self._field[5][6].wLeft = True self._field[6][6].wLeft = True self._field[7][6].wLeft = True self._field[8][6].wLeft = True self._solve = '' self._task = 'Где-то в поле Робота находится вертикальная стена с отверстием в одну клетку,\n' \ ' размеры которой неизвестны. Робот из произвольной клетки должен дойти до\n' \ ' стены и закрасить клетки как показано в задании.\n' ##-------------------------------------------------------------------------------------------- elif mn == 'task9': self._nc = 20 self._nr = 20 self._size = 25 self.clear() self._r = rnd(1, self._nr) self._c = rnd(1, self._nc) c = rnd(2, 16) r = rnd(2, 16) w = rnd(3, 8) h = rnd(3, 8) if c + w >= self._nc: w = self._nc - c if r + h >= self._nc: h = self._nr - r for rcount in range(0, h): for ccount in range(0, w): self._field[r + rcount][c + ccount].color = 'green' self._solve = '' self._task = 'На поле находится квадрат из закрашенных клеток. Вычислить и вывести на экран площадь квадрата.\n' ##-------------------------------------------------------------------------------------------- elif mn == 'task10': self._nc = 15 self._nr = 11 self._size = 30 self.clear() self._r = 2 self._c = 1 self._field[2][1].wUp = True self._field[2][2].wUp = True self._field[2][4].wUp = True self._field[2][5].wUp = True self._field[2][6].wUp = True self._field[2][8].wUp = True self._field[2][9].wUp = True self._field[2][11].wUp = True self._field[2][12].wUp = True self._field[2][13].wLeft = True self._field[3][1].wUp = True self._field[3][2].wUp = True self._field[3][3].wUp = True self._field[3][4].wUp = True self._field[3][6].wUp = True self._field[3][7].wUp = True self._field[3][8].wUp = True self._field[3][10].wUp = True self._field[3][11].wUp = True self._field[3][12].wLeft = True self._field[4][3].wLeft = True self._field[4][3].wUp = True self._field[4][4].wUp = True self._field[4][5].wUp = True self._field[4][6].wUp = True self._field[4][8].wUp = True self._field[4][9].wUp = True self._field[4][10].wUp = True self._field[4][11].wUp = True self._field[4][13].wLeft = True self._field[5][3].wLeft = True self._field[5][4].wLeft = True self._field[5][4].wUp = True self._field[5][6].wUp = True self._field[5][7].wUp = True self._field[5][8].wUp = True self._field[5][10].wUp = True self._field[5][11].wUp = True self._field[5][12].wUp = True self._field[6][3].wLeft = True self._field[6][4].wUp = True self._field[6][5].wLeft = True self._field[7][3].wUp = True self._field[7][4].wLeft = True self._field[7][6].wUp = True self._field[7][7].wLeft = True self._field[8][4].wUp = True self._field[8][5].wUp = True self._field[8][6].wLeft = True self._field[8][7].wUp = True self._field[8][8].wLeft = True self._field[9][6].wUp = True self._field[9][7].wLeft = True self._field[9][8].wUp = True self._field[9][9].wUp = True self._field[9][10].wLeft = True self._field[10][7].wUp = True self._field[10][9].wLeft = True self._field[10][10].wLeft = True self._endPoint = (10, 1) self._solve = """ """ self._task = 'Необходимо провести Робота по коридору шириной в одну клетку из начального положения до конца коридора, \n' \ 'закрашивая при этом все клетки коридора, которые имеют выход. Выходы размером в одну клетку располагаются \n' \ 'произвольно по всей длине коридора. Коридор заканчивается тупиком. Коридор имеет два горизонтальных и \n' \ 'диагональный участки. Пример коридора показан на рисунке.\n' elif mn == 'task11': self._nc = 15 self._nr = 11 self._size = 30 self.clear() self._r = rnd(1, self._nr) self._c = rnd(1, self._nc) for i in range(1, self._nr): for j in range(1, self._nc): self._field[i][j].text = str(rnd(0, 10)) self._task = 'На поле 10х15 каждой в каждой клетке записана цифра (от 0 до 9).\n Закрасить квадрат 2х2 с наименьшей суммой значений клеток.' elif mn == 'task12': self._nc = 15 self._nr = 6 self._size = 30 self.clear() self._r = 2 self._c = 13 self._field[2][2].wUp = True self._field[2][3].wLeft = True self._field[3][3].wLeft = True self._field[4][3].wLeft = True self._field[5][3].wUp = True self._field[5][4].wUp = True self._field[4][5].wLeft = True self._field[3][5].wLeft = True self._field[2][5].wLeft = True self._field[2][5].wUp = True self._field[2][6].wLeft = True self._field[3][6].wLeft = True self._field[4][6].wLeft = True self._field[5][6].wUp = True self._field[5][7].wUp = True self._field[5][8].wUp = True self._field[4][9].wLeft = True self._field[3][9].wLeft = True self._field[2][9].wLeft = True self._field[2][9].wUp = True self._field[2][10].wUp = True self._field[2][11].wLeft = True self._field[3][11].wLeft = True self._field[4][11].wLeft = True self._field[5][11].wUp = True self._field[4][12].wLeft = True self._field[3][12].wLeft = True self._field[2][12].wLeft = True self._field[2][12].wUp = True self._field[2][13].wUp = True self._task = 'Робот движется вдоль стены, профиль которой показан на рисунке,\n' \ ' от начального положения до конца стены. Необходимо закрасить\n' \ ' все внутренние углы стены, как показано на примере. Размеры стены\n могут быть произвольны.' elif mn == 'task13': self._nc = 20 self._nr = 20 self._size = 25 self.clear() self._r = rnd(self._nr / 2, self._nr) self._c = rnd(self._nc / 2, self._nc) col = rnd(2, self._nc / 2) row = rnd(4, self._nr / 2) height = rnd(4, self._nr - 4) if row + height >= self._nr: height = self._nr - row - 1 for i in range(row, row + height): self._field[i][col].wLeft = True ##-------------------------------------------------------------------------------------------- ##-------------------------------------------------------------------------------------------- # сделать прямое управление с демонстрацией датчиков и возможностей # при запуске робота создавать task.py и справочник :) # сделать робота без клеток !!! ##-------------------------------------------------------------------------------------------- ##-------------------------------------------------------------------------------------------- else: print(mn) self._task = "Нет задачи с таким номером" self._test = '-' self._canvas.config( width=(self._size * (self._nc + 1)), height=(self._size * (self._nr + 1))) x = y = 1 d = self._d d = 6 self._robot = self._canvas.create_oval( x * self._size + d, y * self._size + d, x * self._size + self._size - d, y * self._size + self._size - d, outline='#4400FF', width=3) self._paintMap() lm = loadmap lt = left rt = right dn = down pt = paint sw = setWall wu = wallUp wd = wallDown wl = wallLeft wr = wallRight fu = freeUp fd = freeDown fl = freeLeft fr = freeRight cl = color
class main: def __init__(self, master): #master frame self.frame = Frame(master) self.frame.pack(fill="both", expand=True) #canvas where the game is played on self.canvas = Canvas(self.frame, width=300, height=300) self.canvas.pack(fill="both", expand=True) #Shows status of game self.label = Label(self.frame, text='Tic Tac Toe Game', height=6, bg='black', fg='blue') self.label.pack(fill="both", expand=True) #frame to contain the buttons self.frameb = Frame(self.frame) self.frameb.pack(fill="both", expand=True) #Buttons to initiate the game self.Start1 = Button(self.frameb, text='Click here to start\ndouble player', height=4, command=self.start1, bg='white', fg='purple') self.Start1.pack(fill="both", expand=True, side=RIGHT) self.Start2 = Button(self.frameb, text='Click here to start\nsingle player', height=4, command=self.start2, bg='purple', fg='white') self.Start2.pack(fill="both", expand=True, side=LEFT) #canvas board drawing function call self._board() def start1(self): #Starts double player #refresh canvas self.canvas.delete(ALL) self.label['text'] = ('Tic Tac Toe Game') #function call on click self.canvas.bind("<ButtonPress-1>", self.sgplayer) self._board() #Starts the matrix to do calculations #of the positions of circles and crosses. self.TTT = [[0, 0, 0], [0, 0, 0], [0, 0, 0]] #counter of turns self.i = 0 #trigger to end game self.j = False def start2(self): #Starts single player self.canvas.delete(ALL) self.label['text'] = ('Tic Tac Toe Game') self.canvas.bind("<ButtonPress-1>", self.dgplayer) self._board() self.TTT = [[0, 0, 0], [0, 0, 0], [0, 0, 0]] self.i = 0 self.j = False #Trigger to check the validity of the move self.trigger = False def end(self): #Ends the game self.canvas.unbind("<ButtonPress-1>") self.j = True def _board(self): #Creates the board self.canvas.create_rectangle(0, 0, 300, 300, outline="black") self.canvas.create_rectangle(100, 300, 200, 0, outline="black") self.canvas.create_rectangle(0, 100, 300, 200, outline="black") def sgplayer(self, event): #Double player game loop for k in range(0, 300, 100): for j in range(0, 300, 100): #checks if the mouse input is in a bounding box if event.x in range(k, k + 100) and event.y in range( j, j + 100): #checks if there is nothing in the bounding box if self.canvas.find_enclosed(k, j, k + 100, j + 100) == (): #Player plays first if self.i % 2 == 0: #draws circle #no need to create a new function since there is just two cases where this code is used X = (2 * k + 100) / 2 Y = (2 * j + 100) / 2 X1 = int(k / 100) Y1 = int(j / 100) self.canvas.create_oval(X + 25, Y + 25, X - 25, Y - 25, width=4, outline="black") self.TTT[Y1][X1] += 1 self.i += 1 else: #creates the cross. #I don't use the self.cross function here because k and j are not compatible X = (2 * k + 100) / 2 Y = (2 * j + 100) / 2 X1 = int(k / 100) Y1 = int(j / 100) self.canvas.create_line(X + 20, Y + 20, X - 20, Y - 20, width=4, fill="black") self.canvas.create_line(X - 20, Y + 20, X + 20, Y - 20, width=4, fill="black") self.TTT[Y1][X1] += 9 self.i += 1 #After everything, remember to check for wins/losts/draws self.check() def dgplayer(self, event): for k in range(0, 300, 100): for j in range(0, 300, 100): if self.i % 2 == 0: if event.x in range(k, k + 100) and event.y in range( j, j + 100): if self.canvas.find_enclosed(k, j, k + 100, j + 100) == (): X = (2 * k + 100) / 2 Y = (2 * j + 100) / 2 X1 = int(k / 100) Y1 = int(j / 100) self.canvas.create_oval(X + 25, Y + 25, X - 25, Y - 25, width=4, outline="black") self.TTT[Y1][X1] += 1 self.i += 1 self.check() self.trigger = False else: print(self.i) #check for wins/losts/draws first #before allowing the computer to make its turn self.check() #Game AI code self.AIcheck() #refresh validity of move self.trigger = False def check(self): #horizontal check for i in range(0, 3): if sum(self.TTT[i]) == 27: self.label['text'] = ('2nd player wins!') self.end() if sum(self.TTT[i]) == 3: self.label['text'] = ('1st player wins!') self.end() #vertical check #the matrix below transposes self.TTT so that it could use the sum function again #for vertical rows self.ttt = [[row[i] for row in self.TTT] for i in range(3)] for i in range(0, 3): if sum(self.ttt[i]) == 27: self.label['text'] = ('2nd player wins!') self.end() if sum(self.ttt[i]) == 3: self.label['text'] = ('1st player wins!') self.end() #check for diagonal wins if self.TTT[1][1] == 9: if self.TTT[0][0] == self.TTT[1][1] and self.TTT[2][2] == self.TTT[ 1][1]: self.label['text'] = ('2nd player wins!') self.end() if self.TTT[0][2] == self.TTT[1][1] and self.TTT[2][0] == self.TTT[ 1][1]: self.label['text'] = ('2nd player wins!') self.end() if self.TTT[1][1] == 1: if self.TTT[0][0] == self.TTT[1][1] and self.TTT[2][2] == self.TTT[ 1][1]: self.label['text'] = ('1st player wins!') self.end() if self.TTT[0][2] == self.TTT[1][1] and self.TTT[2][0] == self.TTT[ 1][1]: self.label['text'] = ('1st player wins!') self.end() #check for draws if self.j == False: a = 0 for i in range(0, 3): a += sum(self.TTT[i]) #As the player starts with a circle(value=1), #There will be a total of 5(1) and 4(9)=41 if a == 41: self.label['text'] = ("It's a pass!") self.end() '''Note for AI game programming: There are only three sides to AI actions: Offense, Defense, Neutral Offense is what the AI does to win In the TTT case, the computer will add another cross to two crosses in a row to win Defense is what the AI does to prevent the other guy from winning In this case, the computer will add another cross to two circles in a row to block Neutral is when it can't do neither. However, we can't really let it do nothing, so instead, we let it do a random move. ''' def AIcheck(self): #Offense should come before defense so that the AI will try to win if possible #This is built on the self.check function self.ttt = [[row[i] for row in self.TTT] for i in range(3)] #OFFENSE #this is the vertical checklist for h in range(0, 3): k = 0 j = 0 if sum(self.TTT[h]) == 18: while k < 3: if k == h: while j < 3: if self.trigger == False: if self.TTT[k][j] == 0: self.cross(j, k) break j += 1 k += 1 #this is the horizontal checklist for h in range(0, 3): k = 0 j = 0 if sum(self.ttt[h]) == 18: while k < 3: if k == h: while j < 3: if self.trigger == False: if self.ttt[k][j] == 0: self.cross(k, j) break j += 1 k += 1 '''In this case, while I could have used a for loop, I preferred not to, since there are just four cases, and designing a for loop is not worth the effort. You can see that from the length of the code, it's just simple copy and paste. ''' #this is the diagonal checklist if self.TTT[1][1] == 9: if self.TTT[0][0] == 9: if self.trigger == False: if self.TTT[2][2] == 0: self.cross(2, 2) if self.TTT[0][2] == 9: if self.trigger == False: if self.TTT[2][0] == 0: self.cross(0, 2) if self.TTT[2][0] == 9: if self.trigger == False: if self.TTT[0][2] == 0: self.cross(2, 0) if self.TTT[2][2] == 9: if self.trigger == False: if self.TTT[0][0] == 0: self.cross(0, 0) #DEFENSE #this is the horizontal checklist for h in range(0, 3): k = 0 j = 0 if sum(self.TTT[h]) == 2: while k < 3: if k == h: while j < 3: if self.trigger == False: if self.TTT[k][j] == 0: self.cross(j, k) break j += 1 k += 1 #this is the vertical checklist for h in range(0, 3): k = 0 j = 0 if sum(self.ttt[h]) == 2: while k < 3: if k == h: while j < 3: if self.trigger == False: if self.ttt[k][j] == 0: self.cross(k, j) break j += 1 k += 1 #this is the diagonal checklist if self.TTT[1][1] == 1: if self.TTT[0][0] == 1: if self.trigger == False: if self.TTT[2][2] == 0: self.cross(2, 2) if self.TTT[0][2] == 1: if self.trigger == False: if self.TTT[2][0] == 0: self.cross(0, 2) if self.TTT[2][0] == 1: if self.trigger == False: if self.TTT[0][2] == 0: self.cross(2, 0) if self.TTT[2][2] == 1: if self.trigger == False: if self.TTT[0][0] == 0: self.cross(0, 0) #NEUTRAL '''The crux of the game is in the center So, the computer should get the center when it gets the chance. Other than that, it will just do a random move if nothing else works. That's why this code is at the bottom. ''' if self.TTT[1][1] == 0: if self.trigger == False: self.cross(1, 1) self.trigger = True else: if self.trigger == False: self.randmove() def cross(self, k, j): # k is the x coords # j is the y coords X = (200 * k + 100) / 2 Y = (200 * j + 100) / 2 X1 = int(k) Y1 = int(j) self.canvas.create_line(X + 20, Y + 20, X - 20, Y - 20, width=4, fill="black") self.canvas.create_line(X - 20, Y + 20, X + 20, Y - 20, width=4, fill="black") self.TTT[Y1][X1] += 9 self.check() self.i += 1 self.trigger = True def randmove(self): # In case there's nothing for the computer to do while True: k = (randint(0, 2)) j = (randint(0, 2)) if self.TTT[j][k] == 0: self.cross(k, j) break else: k = (randint(0, 2)) * 100 j = (randint(0, 2)) * 100
class TriangulationGUI(Frame): """Class used for representing a triangulation""" def __init__(self, parent): """Constructor which takes in parent (the main window)""" Frame.__init__(self, parent) self.parent = parent self.initUI() self.points = [] self.delt = None self.working = False self.edge_dic = {} self.visualization = False self.voronoi_on = False self.voronoi = None def draw_point_locate(self, face): """Show the point location for a given face""" face_points = [] for vert in face.vertices: if vert.point[2] == 0: # Inifinity points must be reallllllllly far away face_points.append(vert.point[0] * 1000000000) face_points.append(vert.point[1] * 1000000000) else: face_points.append(vert.point[0]) face_points.append(vert.point[1]) # Make the polygon self.canvas.create_polygon(*face_points, fill="gray", outline="black", tag="locate") self.canvas.update_idletasks() # Sleep so that the user can actually see what's happening time.sleep(.5) self.canvas.delete("locate") # Delete the highlighted triangle def click(self, event): """Event for when the user clicks on the screen""" # working is used so that the user cannot add points while the # algorithm is running. If we don't have this, we would have a weird # error sometimes that would cause points not to be added if self.working: return self.working = True self.canvas.delete("circle") # the circumcircle may not be valid point = pyVor.primitives.Point(event.x, event.y) self.points.append(point) self.add_point(point) self.clear_vononoi() # the voronoi diagram may not be valid anymore self.add_point(pyVor.primitives.Point(event.x, event.y)) # if the triangulation exists, add the point to the triangulation, # otherwise, make a new triangulation if self.delt: self.delt.delaunay_add(pyVor.primitives.Point(event.x, event.y), homogeneous=False) else: self.delt = pyVor.structures.DelaunayTriangulation( (pyVor.primitives.Point(event.x, event.y),), randomize=False, homogeneous=False, # draw_circle=self.draw_circle, # location_visualizer=self.draw_point_locate, # draw_triangulation=self.draw_triangulation, # highlight_edge=self.highlight_edge, # delete_edge=self.delete_edge, gui=self) self.canvas.delete("locate") self.draw_triangulation(self.delt) if self.voronoi_on: self.draw_voronoi() self.working = False def show_circle(self, event): """Shows a circumcircle for a triangle if the user wants to see it""" face = self.delt.locate(pyVor.primitives.Point(event.x, event.y, 1)) self.draw_circle(face) def draw_circle(self, face, color="black", delete=False, sleep=False): if delete: self.canvas.delete("circle") for vert in face.vertices: if vert.point[2] == 0: return center = pyVor.utils.circumcenter( *[vert.point for vert in face.vertices]) face_point = next(iter(face.vertices)).point distance = float((face_point - center).norm_squared()) ** .5 self.canvas.create_oval(center[0] - distance, center[1] - distance, center[0] + distance, center[1] + distance, outline=color, dash=(5,), tag="circle") self.canvas.update_idletasks() if sleep: time.sleep(1) def highlight_edge(self, facet, color="black", tag="edge", add=True): points = [] for point in facet.points(): points.append(point[0]) points.append(point[1]) line = self.canvas.create_line(*points, fill=color, tag=tag) if add: self.edge_dic[facet] = line self.canvas.update() def clear(self, event): """Removes all circles""" self.canvas.delete("circle") def toggle_visualization(self, event): """Switch visualization on and off""" # if self.visualization: # self.set_visualize(False) # else: # self.set_visualize(True) self.visualization = not self.visualization def toggle_voronoi(self, event): """Switches the voronoi diagram on or off""" self.voronoi_on = False if self.voronoi_on else True if self.voronoi_on: self.draw_voronoi() self.canvas.update() else: self.clear_vononoi() def clear_vononoi(self): """Delete the voronoi diagram from the screen""" self.canvas.delete("voronoipoint") self.canvas.delete("voronoiedge") def draw_voronoi(self): """Draws the voronoi diagram""" self.voronoi = pyVor.structures.Voronoi(self.delt) for point in self.voronoi.points: self.add_point(point, color="red", tag="voronoipoint") for edge in self.voronoi.edges: point1, point2 = edge point1 = point1[:-1].to_vector() * 1000000 if point1[-1] == 0\ else point1[:-1].to_vector() point2 = point2[:-1].to_vector() * 1000000 if point2[-1] == 0\ else point2[:-1].to_vector() self.canvas.create_line(*point1, *point2, fill="red", tag="voronoipoint") def initUI(self): """Initialize the window""" self.parent.title("Delaunay Triangulation") self.pack(fill=BOTH, expand=1) self.canvas = Canvas(self) self.canvas.bind("<Button-1>", self.click) self.canvas.bind("c", self.show_circle) self.canvas.bind("<Button-2>", self.show_circle) self.canvas.bind("<Button-3>", self.show_circle) self.canvas.bind("<BackSpace>", self.clear) self.canvas.bind("<v>", self.toggle_voronoi) self.canvas.bind("s", self.toggle_visualization) self.canvas.bind("p", self.print_point_history) self.canvas.focus_set() self.canvas.pack(fill=BOTH, expand=1) def delete_edge(self, facet): self.canvas.delete(self.edge_dic[facet]) self.canvas.update_idletasks() def add_point(self, point, color="black", tag=""): """Add a point to the screen""" self.canvas.create_oval(point[0] - 5, point[1] - 5, point[0] + 5, point[1] + 5, outline=color, fill=color, tag=tag) def draw_triangulation(self, triangulation, clear=False, sleep=False): """Actually draw the triangulation""" self.canvas.delete("triangle") self.canvas.delete("circle") self.canvas.delete("highlight_edge") if clear: self.canvas.delete("all") for point in self.points: self.add_point(point) faces = triangulation.face_point_sets(homogeneous=False) for face in faces: face_points = [] for point in face: face_points.append(point[0]) face_points.append(point[1]) self.canvas.create_polygon(*face_points, fill="", outline="black", tag="triangle") # facets = triangulation.get_facets() # for facet in facets: # if not self.is_infinite(facet): # self.highlight_edge(facet, tag="triangle") self.canvas.update_idletasks() if sleep: time.sleep(0.5) def is_infinite(self, facet): points = facet.points() if points[0][2] == 0 or points[1][2] == 0: return True return False def print_point_history(self, event): """Print to stdout the list of points added so far, in order""" print(self.delt.point_history.__repr__())
class Visual(Frame): board = None canvas = None CELL_SIZE = 20 def __init__(self, board): super().__init__() self.board = board self.master.geometry( f'{(BOARD_WIDTH+6)*self.CELL_SIZE}x' + f'{BOARD_HEIGHT*self.CELL_SIZE}' ) self.pack(fill=BOTH, expand=1) self.canvas = Canvas(self) self.canvas.pack(fill=BOTH, expand=1) self.after(DRAW_INTERVAL, self.draw) self.focus_set() self.bind("<Escape>", self.quit) def quit(self, event): raise SystemExit def draw_cell(self, x, y, color): self.canvas.create_rectangle( x * self.CELL_SIZE, y * self.CELL_SIZE, (x+1) * self.CELL_SIZE, (y+1) * self.CELL_SIZE, fill=color, outline=color, ) def draw(self): with self.board.lock: self.canvas.delete('all') if self.board.falling is not None: for (x, y) in self.board.falling: self.draw_cell(x, y, self.board.falling.color) if self.board.next is not None: for (x, y) in self.board.next: self.draw_cell( x + self.board.width + 2, y + 1, self.board.next.color ) for (x, y) in self.board: self.draw_cell(x, y, self.board.cellcolor[x, y]) x = self.board.width * self.CELL_SIZE + 1 y = self.board.height * self.CELL_SIZE self.canvas.create_line(x, 0, x, y, fill='black') self.master.title(f'Score: {self.board.score}') self.after(DRAW_INTERVAL, self.draw)
class KlicketyGUI: """Interface pour le jeu Klickety.""" def __init__(self): # initialisation des structures de données ---------------------------- self.dim_plateau = (10, # nombre de colonnes du plateau 16) # nombre de lignes du plateau self.cote_case = 32 # la longueur du côté d'un bloc à dessiner self.largeur_plateau = self.cote_case * self.dim_plateau[0] self.hauteur_plateau = self.cote_case * self.dim_plateau[1] self.plateau = [] self.compteur_de_coups = 0 # initialisation des éléments graphiques ------------------------------ self.window = Tk() # la fenêtre principale self.window.resizable(0, 0) # empêcher les redimensionnements self.partie_haut = Frame(self.window, width=self.largeur_plateau, height=self.hauteur_plateau) self.partie_haut.pack(side=TOP) self.partie_bas = Frame(self.window) self.partie_bas.pack(side=BOTTOM) # le canevas affichant le plateau de jeu self.plateau_affiche = Canvas(self.partie_haut, width=self.largeur_plateau, height=self.hauteur_plateau) self.plateau_affiche.pack() self.plateau_affiche.bind('<ButtonPress-1>', self.clicPlateau) # le bouton "Réinitialiser" self.btn = Button(self.partie_bas, text='Réinitialiser', command=self.reinitialiserJeu) self.btn.pack(fill=BOTH) # Zone d'affichage du nombre de coups self.nb_coups_affiche = Canvas(self.partie_bas, width=self.largeur_plateau, height=32) self.nb_coups_affiche.create_text( self.largeur_plateau // 2, self.cote_case // 2, text="Coups effectués: 0", fill="black" ) self.nb_coups_affiche.pack(fill=BOTH) # affichage du nombre de blocs restants self.nb_blocs_affiche = Canvas(self.partie_bas, width=self.largeur_plateau, height=32) self.nb_blocs_affiche.pack(fill=BOTH) self.reinitialiserJeu() self.window.title('Klickety') self.window.mainloop() def rafraichirNombreBlocs(self, piece=None): """Rafraîchit l'affichage du nombre de blocs restants, sur base de la pièce que l'on vient de retirer.""" self.nb_blocs_affiche.delete(ALL) if piece is None: # appel initial, tous les blocs sont encore présents self.nb_blocs = self.dim_plateau[0] * self.dim_plateau[1] else: # soustraire du nombre de blocs celui de la pièce retirée self.nb_blocs -= len(piece) self.nb_blocs_affiche.create_text( self.largeur_plateau // 2, self.cote_case // 2, text="Blocs restants: " + str(self.nb_blocs), fill="black" ) def compteCoups(self, compteur_de_coups): """Compte le nombre de coups effectués durant cette partie.""" self.nb_coups_affiche.delete(ALL) self.nb_coups_affiche.create_text( self.largeur_plateau // 2, self.cote_case // 2, text="Coups effectués: " + str(compteur_de_coups), fill="black" ) def rafraichirPlateau(self): """Redessine le plateau de jeu à afficher.""" # tracer les blocs self.plateau_affiche.delete(ALL) couleur_fond = "black" for i in range(self.dim_plateau[0]): # par défaut 10 for j in range(self.dim_plateau[1]): # par défaut 16 case = self.plateau[i][j] if case is not None: # afficher le pion self.plateau_affiche.create_rectangle( i * self.cote_case, j * self.cote_case, (i + 1) * self.cote_case, (j + 1) * self.cote_case, outline=case, fill=case ) else: self.plateau_affiche.create_rectangle( i * self.cote_case, j * self.cote_case, (i + 1) * self.cote_case, (j + 1) * self.cote_case, outline=couleur_fond, fill=couleur_fond ) # tracer le contour des pièces # 1) tracer les séparations entre deux pièces adjacentes de # couleurs différentes dans la même colonne for i in range(0, self.dim_plateau[0]): # par défaut 10 colonne = self.plateau[i] for j in range(1, self.dim_plateau[1]): # par défaut 16 if colonne[j - 1] != colonne[j]: self.plateau_affiche.create_rectangle( (i) * self.cote_case, j * self.cote_case, (i + 1) * self.cote_case, j * self.cote_case, outline=couleur_fond, fill=couleur_fond, width=1 ) # 2) tracer les séparations entre deux pièces adjacentes de # couleurs différentes dans la même ligne for i in range(1, self.dim_plateau[0]): # par défaut 10 for j in range(0, self.dim_plateau[1]): # par défaut 16 if self.plateau[i - 1][j] != self.plateau[i][j]: self.plateau_affiche.create_rectangle( (i) * self.cote_case, j * self.cote_case, (i) * self.cote_case, (j + 1) * self.cote_case, outline=couleur_fond, fill=couleur_fond, width=1 ) def clicPlateau(self, event): """Récupère les coordonnées de la case sélectionnée, et joue le coup correspondant s'il est permis.""" # remarque: le canevas de tkinter interprète (i, j) géométriquement # (au lieu de (ligne, colonne)), d'où l'inversion de coordonnées dans # la ligne ci-dessous (i, j) = (event.x // self.cote_case, event.y // self.cote_case) if self.plateau[i][j] is not None: piece = set() detecterPiece(self.plateau, i, j, piece, self.plateau[i][j]) #print (piece) if len(piece) > 1: # si la pièce est valide, on la retire # retirer la piece en mettant ses cases à None for (p, q) in piece: self.plateau[p][q] = None # faire descendre les blocs situés au-dessus de la pièce mettreAJour(self.plateau, piece) # tasser le restant du plateau en supprimant les colonnes vides eliminerColonnesVides(self.plateau) # rafraîchir le plateau pour répercuter les modifications self.rafraichirPlateau() self.rafraichirNombreBlocs(piece) self.compteur_de_coups += 1 self.compteCoups(self.compteur_de_coups) messagevictoire = partieFinie(self.plateau) if messagevictoire: self.plateau_affiche.create_text( int(self.plateau_affiche.cget("width")) // 2, self.cote_case // 2, text=messagevictoire, font=tkinter.font.Font( family="Courier", size=12, weight=tkinter.font.BOLD ), fill="red" ) def reinitialiserJeu(self): """Réinitialise le plateau de jeu et les scores.""" self.reinitialiserPlateau() self.rafraichirNombreBlocs() # réinitialiser le nombre de coups self.compteur_de_coups = 0 self.nb_coups_affiche.delete(ALL) self.nb_coups_affiche.create_text(self.largeur_plateau // 2, self.cote_case // 2, text="Coups effectués: " + str(self.compteur_de_coups), fill="black") def reinitialiserPlateau(self): """Réinitialise le plateau de jeu.""" # réinitialiser la matrice self.plateau = initialiserPlateau(*self.dim_plateau) # réinitialiser l'affichage self.plateau_affiche.delete(ALL) if self.plateau: self.rafraichirPlateau()
class SudokuUI(Frame): """ The Tkinter UI, responsible for drawing the board and accepting user input. """ def __init__(self, parent, game): self.game = game Frame.__init__(self, parent) self.parent = parent self.row, self.col = -1, -1 self.__initUI() def __initUI(self): self.parent.title("Sudoku") self.pack(fill=BOTH) self.left_frame = Frame(self, width=WIDTH + 50, height=HEIGHT + 50, bg='grey') self.left_frame.grid(row=0, column=0, padx=10, pady=10) self.right_frame = Frame(self, width=200, height=HEIGHT + 50, bg='grey') self.right_frame.grid(row=0, column=1, padx=10, pady=10) self.canvas = Canvas(self.left_frame, width=WIDTH, height=HEIGHT) self.canvas.pack(fill=BOTH, side=TOP) clear_button = Button(self.right_frame, text="Clear answers", width=15, height=2, command=self.__clear_answers, highlightbackground='#3E4149') clear_button.pack(fill=BOTH, side=BOTTOM) auto_solve_button = Button(self.right_frame, text="Solve puzzle", width=15, height=2, command=self.__solve_puzzle, highlightbackground='#3E4149') auto_solve_button.pack(fill=BOTH, side=BOTTOM) generate_puzzle_button = Button(self.right_frame, text="Generate new puzzle", width=15, height=2, command=self.__generate_puzzle, highlightbackground='#3E4149') generate_puzzle_button.pack(fill=BOTH, side=BOTTOM) self.__draw_grid() self.__draw_puzzle() self.canvas.bind("<Button-1>", self.__cell_clicked) self.canvas.bind("<Key>", self.__key_pressed) def __draw_grid(self): """ Draws grid divided with blue lines into 3x3 squares """ for i in range(10): color = "blue" if i % 3 == 0 else "gray" x0 = MARGIN + i * SIDE y0 = MARGIN x1 = MARGIN + i * SIDE y1 = HEIGHT - MARGIN self.canvas.create_line(x0, y0, x1, y1, fill=color) x0 = MARGIN y0 = MARGIN + i * SIDE x1 = WIDTH - MARGIN y1 = MARGIN + i * SIDE self.canvas.create_line(x0, y0, x1, y1, fill=color) def __draw_puzzle(self): self.canvas.delete("numbers") for i in range(9): for j in range(9): answer = self.game.puzzle[i][j] if answer != 0: x = MARGIN + j * SIDE + SIDE / 2 y = MARGIN + i * SIDE + SIDE / 2 original = self.game.start_puzzle[i][j] color = "black" if answer == original else "sea green" self.canvas.create_text(x, y, text=answer, tags="numbers", fill=color) def __draw_cursor(self): self.canvas.delete("cursor") if self.row >= 0 and self.col >= 0: x0 = MARGIN + self.col * SIDE + 1 y0 = MARGIN + self.row * SIDE + 1 x1 = MARGIN + (self.col + 1) * SIDE - 1 y1 = MARGIN + (self.row + 1) * SIDE - 1 self.canvas.create_rectangle(x0, y0, x1, y1, outline="red", tags="cursor") def __draw_victory(self): # create a oval (which will be a circle) x0 = y0 = MARGIN + SIDE * 2 x1 = y1 = MARGIN + SIDE * 7 self.canvas.create_oval(x0, y0, x1, y1, tags="victory", fill="dark orange", outline="orange") # create text x = y = MARGIN + 4 * SIDE + SIDE / 2 self.canvas.create_text(x, y, text="You win!", tags="victory", fill="white", font=("Arial", 32)) def __cell_clicked(self, event): if self.game.game_over: return x, y = event.x, event.y if (MARGIN < x < WIDTH - MARGIN and MARGIN < y < HEIGHT - MARGIN): self.canvas.focus_set() # get row and col numbers from x,y coordinates row, col = int((y - MARGIN) / SIDE), int((x - MARGIN) / SIDE) # if cell was selected already - deselect it if (row, col) == (self.row, self.col): self.row, self.col = -1, -1 elif self.game.puzzle[row][col] == 0: self.row, self.col = row, col else: self.row, self.col = -1, -1 self.__draw_cursor() def __key_pressed(self, event): if self.game.game_over: return if self.row >= 0 and self.col >= 0 and event.char in "1234567890": self.game.puzzle[self.row][self.col] = int(event.char) self.col, self.row = -1, -1 self.__draw_puzzle() self.__draw_cursor() if self.game.check_win(): self.__draw_victory() def __clear_answers(self): self.game.start() self.canvas.delete("victory") self.__draw_puzzle() def __solve_puzzle(self): solver = SudokuSolver(self.game.puzzle) solver.solve() self.__draw_puzzle() def __generate_puzzle(self): self.game.start_puzzle = SudokuBoard.create_empty_board() self.game.generate_puzzle(self.game.start_puzzle) self.game.start() self.__draw_puzzle() def __undo_move(self): self.move_stack = [] def __erase_cell(self): print("ERASE")
class Main(object): def __init__(self, master): self.master = master self.master.title('CONWAY\'S GAME OF LIFE') self.wid = 910 self.hei = 680 smw = self.master.winfo_screenwidth() // 2 smh = self.master.winfo_screenheight() // 2 tplft = (smw - self.wid // 2, smh - self.hei // 2) self.master.geometry(f'{self.wid}x{self.hei}+{tplft[0]}+{tplft[1]}') self.master.resizable(width=False, height=False) # create a main field self.can_width = 800 self.can_height = 640 # variable to continue with right number generation after stop game self.global_gen = None # start self.cell = 1 self.start_cell = 0 self.live = set() # trick for rigth after_cancel self.game_on = (0, 0) # population self.score = 0 # variable for max cells self.max_score = 0 # for change speed self.timer = 15 # cursor for place ships self.cur = None self.invert = None self.on = (0, 0) self.sample = {'1': 10, '2': 5, '4': 3} # erase seeds self.erase = True # images for ships self.glider = PhotoImage(file='data/1_ship.gif') self.glider_in = PhotoImage(file='data/1_ship_in.gif') self.lss = PhotoImage(file='data/2_lss.gif') self.lss_in = PhotoImage(file='data/2_lss_in.gif') self.sui = PhotoImage(file='data/3_sucide.gif') self.sui_in = PhotoImage(file='data/3_sucide_in.gif') self.f5 = PhotoImage(file='data/4_f5.gif') self.f5_in = PhotoImage(file='data/4_f5_in.gif') self.penta = PhotoImage(file='data/5_penta.gif') self.penta_in = PhotoImage(file='data/5_penta_in.gif') self.patern = PhotoImage(file='data/6_patern.gif') self.patern_in = PhotoImage(file='data/6_patern_in.gif') self.fireship = PhotoImage(file='data/7_fireship.gif') self.fireship_in = PhotoImage(file='data/7_fireship_in.gif') # GUI frameWin = Frame(master, bg='white', borderwidth=0) frameWin.pack(side=TOP, fill=BOTH) frameCanv = Frame(frameWin, bg='white', borderwidth=0) frameCanv.pack(side=RIGHT, fill=BOTH) # main canvas self.window = Canvas(frameCanv, width=self.can_width, height=self.can_height, cursor='plus', bg='white', bd=0, highlightthickness=0) self.window.pack(side=TOP) self.w_field = self.can_width // self.cell self.h_field = self.can_height // self.cell self.cell_matrix = PhotoImage(width=self.can_width, height=self.can_height) hor_line = '{' + ' '.join(['#EEEEEE'] * self.can_width) + '}' self.cell_matrix.put(' '.join([hor_line] * self.can_height)) # make copy self.original = self.cell_matrix.copy() self.cell_img = self.window.create_image(0, 0, image=self.cell_matrix, anchor=NW) # side menu for images frameBorderCr = Frame(frameWin, bg='white', bd=3) frameBorderCr.pack(side=LEFT, fill=BOTH) mes_creat = Label(frameBorderCr, text='CREATURE', height=2, bg='white') mes_creat.pack(side=TOP, fill=X) frameCreat = Frame(frameBorderCr, bg='gray', bd=2) frameCreat.pack(side=TOP, fill=BOTH) self.creat = Canvas(frameCreat, height=596, bg='white', highlightthickness=0) self.creat.pack(side=TOP, expand=YES, fill=Y) # images for ships self.creat.create_image(48, 25, image=self.glider) self.creat.create_image(48, 73, image=self.lss) self.creat.create_image(48, 126, image=self.sui) self.creat.create_image(48, 175, image=self.f5) self.creat.create_image(48, 256, image=self.penta) self.creat.create_image(48, 349, image=self.patern) self.creat.create_image(49, 485, image=self.fireship) # menu for counters frameMB = Frame(frameCanv, bg='white', borderwidth=0) frameMB.pack(side=BOTTOM, fill=BOTH) message = Label(frameMB, text='SQUARE UNIVERSUM ', height=2, bg='white') message.pack(side=LEFT, fill=X) # cell part frameBor1 = Frame(frameMB, bg='gray', borderwidth=2) frameBor1.pack(side=LEFT) name_pop = Label(frameBor1, text='CELL') name_pop.pack(side=LEFT) self.scrPop = Label(frameBor1, text=0, width=7) self.scrPop.pack(side=RIGHT) # separator sep = Frame(frameMB, width=4) sep.pack(side=LEFT) # cycle part frameBor2 = Frame(frameMB, bg='gray', borderwidth=2) frameBor2.pack(side=LEFT) name_gen = Label(frameBor2, text='CYCLE') name_gen.pack(side=LEFT) self.scrGen = Label(frameBor2, text=0, width=6) self.scrGen.pack(side=RIGHT) # buttons self.button_Start = Button(frameMB, text='START', width=6, command=self.start_game) self.button_Start.pack(side=RIGHT, padx=3) self.button_Stop = Button(frameMB, text='STOP', width=6, command=self.stop_game) self.button_Stop.pack(side=RIGHT, padx=3) self.button_Clear = Button(frameMB, text='CLEAR', width=6, command=self.clear) self.button_Clear.pack(side=RIGHT, padx=3) blockSpeed = Frame(frameMB, padx=25) blockSpeed.pack(side=RIGHT) button_Fast = Button(blockSpeed, text='>>', width=3, command=self.fast) button_Fast.pack(side=RIGHT, padx=3) butSpeedFrame = Frame(blockSpeed, bg='gray', bd=2) butSpeedFrame.pack(side=RIGHT) self.speedVal = Label(butSpeedFrame, text=int(self.timer), width=3) self.speedVal.pack(side=RIGHT) button_Slow = Button(blockSpeed, text='<<', width=3, command=self.slow) button_Slow.pack(side=RIGHT, padx=3) self.window.bind('<B1-Motion>', self.motion_paint) self.window.bind('<ButtonPress-1>', self.start_paint) self.window.bind('<ButtonPress-2>', self.clear_side_menu) self.window.bind('<Leave>', self.clear_side_menu) self.creat.bind('<ButtonPress-1>', self.creatures) self.master.mainloop() def add_pixels(self, x, y): pack = [] dist_x = (x - self.fir_x) dist_y = (y - self.fir_y) hyp = int(math.hypot(dist_x, dist_y)) for i in range(hyp): x = int(i * (dist_x / hyp) + self.fir_x) y = int(i * (dist_y / hyp) + self.fir_y) pack.append((x, y)) return pack def motion_paint(self, event): self.erase = False xcell = int(event.x) ycell = int(event.y) # 1 pix # xcell = int(x // self.cell) # ycell = int(y // self.cell) # 1 pix pack = self.add_pixels(xcell, ycell) self.fir_x, self.fir_y = xcell, ycell self.black_cell(ycell, xcell) for i in pack: self.black_cell(i[1], i[0]) def start_paint(self, event): self.erase = True # 1 pix # self.fir_x = event.x // self.cell # self.fir_y = event.y // self.cell self.fir_x = event.x self.fir_y = event.y self.black_cell(self.fir_y, self.fir_x) def creatures(self, event): # I can realize with standart buttons and compound x = int(event.x) y = int(event.y) if self.invert: # clear menu with figures self.clear_side_menu() else: self.on = (0, 0) if x in range(32, 65) and y in range(10, 45): self.creat_but(x, y, 32, 65, 10, 45, 48, 25, self.glider_in, self.glider, self.ship_1, SE) if x in range(20, 75) and y in range(54, 96): self.creat_but(x, y, 20, 75, 54, 96, 48, 73, self.lss_in, self.lss, self.ship_2, SE) if x in range(32, 65) and y in range(107, 149): self.creat_but(x, y, 32, 65, 107, 149, 48, 126, self.sui_in, self.sui, self.fig_1, S) if x in range(32, 65) and y in range(161, 192): self.creat_but(x, y, 32, 65, 161, 192, 48, 175, self.f5_in, self.f5, self.fig_2, CENTER) if x in range(32, 65) and y in range(203, 313): self.creat_but(x, y, 32, 65, 203, 313, 48, 256, self.penta_in, self.penta, self.fig_3, S) if x in range(21, 75) and y in range(323, 377): self.creat_but(x, y, 21, 75, 323, 377, 48, 349, self.patern_in, self.patern, self.fig_4, SE) if x in range(6, 93) and y in range(388, 588): self.creat_but(x, y, 6, 93, 388, 588, 48, 485, self.fireship_in, self.fireship, self.ship_3, S) def creat_but(self, x, y, fnx, lnx, fny, lny, x_im, y_im, img_in, img, bind, al): self.window.unbind('<B1-Motion>') if self.cur: self.window.delete(self.cur) self.cur = None if (self.on[0] not in range(fnx, lnx) or self.on[1] not in range(fny, lny)): self.invert = self.creat.create_image(x_im, y_im, image=img_in) self.window.bind('<ButtonPress-1>', bind) self.on = (x, y) # size of pictures depend of self.cell size = self.sample[str(self.cell)] img = img.subsample(size, size) self.window.bind('<Motion>', lambda event, i=img, a=al: self.cursor(event, i, a)) def cursor(self, event, img, align): self.erase = False self.window.configure(cursor='none') if not self.cur: self.cur = self.window.create_image( event.x, event.y, image=img, anchor=align) self.window.coords(self.cur, (event.x, event.y)) def ship_1(self, event): x = int(event.x) y = int(event.y) xcell = int(y / self.cell) ycell = int(x / self.cell) pack = [(xcell, ycell), (xcell - 1, ycell), (xcell, ycell - 1), (xcell, ycell - 2), (xcell - 2, ycell - 1)] for i in pack: self.black_cell(i[0], i[1]) def ship_2(self, event): x = int(event.x) y = int(event.y) xcell = int(y / self.cell) ycell = int(x / self.cell) pack = [(xcell, ycell), (xcell - 1, ycell), (xcell - 2, ycell), (xcell - 3, ycell - 1), (xcell, ycell - 1), (xcell, ycell - 2), (xcell, ycell - 3), (xcell - 1, ycell - 4), (xcell - 3, ycell - 4)] for i in pack: self.black_cell(i[0], i[1]) def fig_1(self, event): x = int(event.x) y = int(event.y) xcell = int(y / self.cell) ycell = int(x / self.cell) pack = [(xcell, ycell), (xcell, ycell - 1), (xcell - 1, ycell - 1), (xcell - 2, ycell - 1), (xcell - 3, ycell - 1), (xcell - 3, ycell - 2)] for i in pack: self.black_cell(i[0], i[1]) def fig_2(self, event): x = int(event.x) y = int(event.y) xcell = int(y / self.cell) ycell = int(x / self.cell) pack = [(xcell, ycell), (xcell - 1, ycell), (xcell - 2, ycell), (xcell - 1, ycell - 1), (xcell - 2, ycell + 1)] for i in pack: self.black_cell(i[0], i[1]) def fig_3(self, event): x = int(event.x) y = int(event.y) xcell = int(y / self.cell) ycell = int(x / self.cell) self.black_cell(xcell, ycell) self.black_cell(xcell - 1, ycell) self.black_cell(xcell - 2, ycell - 1) self.black_cell(xcell - 2, ycell + 1) self.black_cell(xcell - 3, ycell) self.black_cell(xcell - 4, ycell) self.black_cell(xcell - 5, ycell) self.black_cell(xcell - 6, ycell) self.black_cell(xcell - 7, ycell - 1) self.black_cell(xcell - 7, ycell + 1) self.black_cell(xcell - 8, ycell) self.black_cell(xcell - 9, ycell) def fig_4(self, event): x = int(event.x) y = int(event.y) xcell = int(y / self.cell) ycell = int(x / self.cell) self.black_cell(xcell, ycell) self.black_cell(xcell - 1, ycell) self.black_cell(xcell - 2, ycell) self.black_cell(xcell - 2, ycell - 1) self.black_cell(xcell - 4, ycell) self.black_cell(xcell - 4, ycell - 2) self.black_cell(xcell - 4, ycell - 3) self.black_cell(xcell - 4, ycell - 4) self.black_cell(xcell - 3, ycell - 4) self.black_cell(xcell - 1, ycell - 3) self.black_cell(xcell - 1, ycell - 2) self.black_cell(xcell, ycell - 2) self.black_cell(xcell, ycell - 4) def ship_3(self, event): x = int(event.x) y = int(event.y) xcell = int(y / self.cell) ycell = int(x / self.cell) self.black_cell(xcell, ycell) self.black_cell(xcell - 1, ycell) self.black_cell(xcell - 1, ycell + 1) self.black_cell(xcell - 2, ycell) self.black_cell(xcell - 2, ycell + 2) self.black_cell(xcell - 3, ycell + 2) self.black_cell(xcell - 4, ycell + 2) self.black_cell(xcell - 3, ycell + 3) self.black_cell(xcell - 6, ycell + 1) self.black_cell(xcell - 7, ycell) self.black_cell(xcell - 9, ycell) self.black_cell(xcell - 9, ycell + 1) self.black_cell(xcell - 10, ycell + 1) self.black_cell(xcell - 10, ycell + 2) self.black_cell(xcell - 11, ycell + 3) self.black_cell(xcell - 13, ycell + 3) self.black_cell(xcell - 14, ycell + 3) self.black_cell(xcell - 14, ycell + 1) self.black_cell(xcell - 15, ycell) self.black_cell(xcell - 16, ycell) self.black_cell(xcell - 17, ycell + 1) self.black_cell(xcell - 17, ycell + 2) self.black_cell(xcell, ycell - 1) self.black_cell(xcell - 1, ycell - 1) self.black_cell(xcell - 1, ycell - 2) self.black_cell(xcell - 2, ycell - 1) self.black_cell(xcell - 2, ycell - 3) self.black_cell(xcell - 3, ycell - 3) self.black_cell(xcell - 3, ycell - 4) self.black_cell(xcell - 4, ycell - 3) self.black_cell(xcell - 6, ycell - 2) self.black_cell(xcell - 7, ycell - 1) self.black_cell(xcell - 9, ycell - 1) self.black_cell(xcell - 9, ycell - 2) self.black_cell(xcell - 10, ycell - 2) self.black_cell(xcell - 10, ycell - 3) self.black_cell(xcell - 11, ycell - 4) self.black_cell(xcell - 13, ycell - 4) self.black_cell(xcell - 14, ycell - 4) self.black_cell(xcell - 14, ycell - 2) self.black_cell(xcell - 15, ycell - 1) self.black_cell(xcell - 16, ycell - 1) self.black_cell(xcell - 17, ycell - 2) self.black_cell(xcell - 17, ycell - 3) def black_cell(self, y, x): x = x % self.w_field y = y % self.h_field # 1 pixel # x = x * self.cell + self.cell // 2 # y = y * self.cell + self.cell // 2 if self.cell_matrix.get(x, y) == (238, 238, 238): self.fill_black(x, y, '#000000') self.start_cell += 1 self.live.add((x, y)) else: if self.erase: if self.cell_matrix.get(x, y) == (0, 0, 0): self.fill_black(x, y, '#EEEEEE') self.start_cell -= 1 self.live.remove((x, y)) def fill_black(self, x, y, color): # leave some borders for 4 px but it is to heavy task # for i in range((-self.cell // 2) - 1, (self.cell // 2) - 1): # for j in range((-self.cell // 2) - 1, (self.cell // 2) - 1): # xx = (x + i) % self.can_width # yy = (y + j) % self.can_height self.cell_matrix.put(color, (x, y)) def check_black(self, x, y, color): total = 8 for i in [(-1, -1), (0, -1), (1, -1), (-1, 0), (1, 0), (-1, 1), (0, 1), (1, 1)]: # xi = (x + i[0] * self.cell) % self.can_width # yi = (y + i[1] * self.cell) % self.can_height # 1 pixel xi = (x + i[0]) % self.can_width yi = (y + i[1]) % self.can_height if self.cell_matrix.get(xi, yi) == color: total -= 1 return total def start_game(self): self.button_Start.configure(state='disabled') self.button_Clear.configure(state='disabled') self.start_cycle() def start_cycle(self): if self.global_gen: gen = self.global_gen else: gen = 1 tot = len(self.live) # clean self.born = [] self.dead = [] for i, j in self.live: total = self.check_black(i, j, (238, 238, 238)) if total < 2: self.dead.append((i, j)) if total > 3: self.dead.append((i, j)) # check if new cell wass born for xy in [(i - self.cell, j - self.cell), (i, j - self.cell), (i + self.cell, j - self.cell), (i - self.cell, j), (i + self.cell, j), (i - self.cell, j + self.cell), (i, j + self.cell), (i + self.cell, j + self.cell)]: total = self.check_black(xy[0], xy[1], (0, 0, 0)) # invert rule need 3 cells to born new if total == 5: xy0 = xy[0] % self.can_width xy1 = xy[1] % self.can_height self.born.append((xy0, xy1)) self.scrPop.configure(text=tot) self.scrGen.configure(text=gen) for i in self.dead: self.live.remove(i) xd, yd = i self.fill_black(xd, yd, '#EEEEEE') for i in self.born: self.live.add(i) xb, yb = i self.fill_black(xb, yb, '#000000') # counters for maximum population if self.max_score is False: self.max_score = tot elif tot > self.max_score: self.max_score = tot else: self.max_score = self.max_score # for generation gen += 1 self.global_gen = gen # after dead cells need to check how many stay alive tot += len(self.born) - len(self.dead) # count population self.score += tot # start goal for end message if tot == 0: self.game_over(tot, gen) # for stop button else: self.game_on = self.window.after(self.timer, self.start_cycle) def stop_game(self): self.window.after_cancel(self.game_on) self.button_Start.configure(state='normal') self.button_Clear.configure(state='normal') def clear_side_menu(self, event=None): self.window.unbind('<Motion>') self.creat.delete(self.invert) self.invert = None self.window.bind('<ButtonPress-1>', self.start_paint) self.window.bind('<B1-Motion>', self.motion_paint) self.window.configure(cursor='plus') if self.cur: self.window.delete(self.cur) def clear(self): self.cell_matrix = self.original.copy() self.window.itemconfigure(self.cell_img, image=self.cell_matrix) self.scrPop.configure(text=0) self.scrGen.configure(text=0) # clear menu with figures self.clear_side_menu() self.start_cell = 0 self.live = set() self.score = 0 self.max_score = 0 self.global_gen = None def fast(self): self.timer -= 1 if self.timer < 1: self.timer = 1 self.speedVal.configure(text=int(self.timer)) def slow(self): self.timer += 1 if self.timer > 15: self.timer = 15 self.speedVal.configure(text=int(self.timer)) def game_over(self, tot, gen): self.window.after_cancel(self.game_on) self.global_gen = 0 self.scrPop.configure(text=tot) self.scrGen.configure(text=self.global_gen) self.creat.delete(self.invert) self.button_Stop.configure(state='disabled') end_menu = End(self.master, gen, self.start_cell, self.score, self.max_score) self.window.configure(cursor='left_ptr') ans = end_menu.answer() if ans is True: self.button_Start.configure(state='normal') self.button_Clear.configure(state='normal') self.button_Stop.configure(state='normal') self.window.configure(cursor='plus') self.clear() elif ans is False: self.exit_life() def exit_life(self): self.master.quit()
class SkyviewFrame(Frame): """ Skyview frame class. """ def __init__(self, app, *args, **kwargs): """ Constructor. :param Frame app: reference to main tkinter application :param args: optional args to pass to Frame parent class :param kwargs: optional kwargs to pass to Frame parent class """ self.__app = app # Reference to main application class self.__master = self.__app.get_master() # Reference to root class (Tk) Frame.__init__(self, self.__master, *args, **kwargs) def_w, def_h = WIDGETU1 self.width = kwargs.get("width", def_w) self.height = kwargs.get("height", def_h) self.bg_col = BGCOL self.fg_col = FGCOL self._body() self.bind("<Configure>", self._on_resize) def _body(self): """ Set up frame and widgets. """ self.grid_columnconfigure(0, weight=1) self.grid_rowconfigure(0, weight=1) self.can_satview = Canvas(self, width=self.width, height=self.height, bg=self.bg_col) self.can_satview.pack(fill=BOTH, expand=YES) def init_sats(self): """ Initialise satellite view """ w, h = self.width, self.height axis_r = w / 15 resize_font = font.Font(size=min(int(w / 25), 10)) self.can_satview.delete("all") maxr = min((h / 2), (w / 2)) - (axis_r * 2) for r in (0.2, 0.4, 0.6, 0.8, 1): self.can_satview.create_circle(w / 2, h / 2, maxr * r, outline=self.fg_col, width=1) self.can_satview.create_line(w / 2, 0, w / 2, h, fill=self.fg_col) self.can_satview.create_line(0, h / 2, w, h / 2, fill=self.fg_col) self.can_satview.create_text(w - axis_r, h / 2, text="90\u00b0\n E", fill=self.fg_col, font=resize_font) self.can_satview.create_text(axis_r, h / 2, text="270\u00b0\n W", fill=self.fg_col, font=resize_font) self.can_satview.create_text(w / 2, axis_r, text="0\u00b0 N", fill=self.fg_col, font=resize_font) self.can_satview.create_text(w / 2, h - axis_r, text="180\u00b0 S", fill=self.fg_col, font=resize_font) def update_sats(self, data): """ Plot satellites' elevation and azimuth position. :param list data: array of satellite tuples (gnssId, svid, elev, azim, cno) """ w, h = self.width, self.height axis_r = w / 15 maxr = min((h / 2), (w / 2)) - (axis_r * 2) resize_font = font.Font(size=min(int(maxr / 10), 10)) self.init_sats() for d in sorted(data, key=itemgetter(4)): # sort by ascending snr try: gnssId, prn, ele, azi, snr = d ele = int(ele) azi = (int(azi) - 90) % 360 # adjust so north is upwards x, y = cel2cart(ele, azi) x = x * maxr y = y * maxr if snr == "": snr = 0 else: snr = int(snr) (_, ol_col) = GNSS_LIST[gnssId] prn = f"{int(prn):02}" self.can_satview.create_circle( x + (w / 2), y + (h / 2), (maxr / 10), outline=ol_col, fill=snr2col(snr), width=OL_WID, ) self.can_satview.create_text( x + (w / 2), y + (h / 2), text=prn, fill=self.fg_col, font=resize_font, ) except ValueError: pass self.can_satview.update() def _on_resize(self, event): # pylint: disable=unused-argument """ Resize frame :param event event: resize event """ self.width, self.height = self.get_size() def get_size(self): """ Get current canvas size. :return: window size (width, height) :rtype: tuple """ self.update_idletasks() # Make sure we know about any resizing width = self.can_satview.winfo_width() height = self.can_satview.winfo_height() return (width, height)
class GUI(Frame): # constant NUMBER_COLLUM = 8 NUMBER_ROW = 8 SIZE_SQUARE = 64 WHITE = '#F0D9B5' BLACK = '#B58863' YELLOW = '#775cff' GREEN = '#1eed28' YIELD = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'] MAP = {'a': 0, 'b': 1, 'c': 2, 'd': 3, 'e': 4, 'f': 5, 'g': 6, 'h': 7} def __init__(self, game, root, board, slot): self.game = game self.board = board self.slot = slot super().__init__(root) #data self.piece = {} #king self.icon = Image.open("../data/image/white/K.png") self.icon = self.icon.resize((self.SIZE_SQUARE, self.SIZE_SQUARE)) self.icon = ImageTk.PhotoImage(self.icon) self.piece['K'] = self.icon self.icon = Image.open("../data/image/black/k.png") self.icon = self.icon.resize((self.SIZE_SQUARE, self.SIZE_SQUARE)) self.icon = ImageTk.PhotoImage(self.icon) self.piece['k'] = self.icon #Queen self.icon = Image.open("../data/image/white/Q.png") self.icon = self.icon.resize((self.SIZE_SQUARE, self.SIZE_SQUARE)) self.icon = ImageTk.PhotoImage(self.icon) self.piece['Q'] = self.icon self.icon = Image.open("../data/image/black/q.png") self.icon = self.icon.resize((self.SIZE_SQUARE, self.SIZE_SQUARE)) self.icon = ImageTk.PhotoImage(self.icon) self.piece['q'] = self.icon #Rook self.icon = Image.open("../data/image/white/R.png") self.icon = self.icon.resize((self.SIZE_SQUARE, self.SIZE_SQUARE)) self.icon = ImageTk.PhotoImage(self.icon) self.piece['R'] = self.icon self.icon = Image.open("../data/image/black/r.png") self.icon = self.icon.resize((self.SIZE_SQUARE, self.SIZE_SQUARE)) self.icon = ImageTk.PhotoImage(self.icon) self.piece['r'] = self.icon #Bishop self.icon = Image.open("../data/image/white/B.png") self.icon = self.icon.resize((self.SIZE_SQUARE, self.SIZE_SQUARE)) self.icon = ImageTk.PhotoImage(self.icon) self.piece['B'] = self.icon self.icon = Image.open("../data/image/black/b.png") self.icon = self.icon.resize((self.SIZE_SQUARE, self.SIZE_SQUARE)) self.icon = ImageTk.PhotoImage(self.icon) self.piece['b'] = self.icon #Knight self.icon = Image.open("../data/image/white/N.png") self.icon = self.icon.resize((self.SIZE_SQUARE, self.SIZE_SQUARE)) self.icon = ImageTk.PhotoImage(self.icon) self.piece['N'] = self.icon self.icon = Image.open("../data/image/black/n.png") self.icon = self.icon.resize((self.SIZE_SQUARE, self.SIZE_SQUARE)) self.icon = ImageTk.PhotoImage(self.icon) self.piece['n'] = self.icon #Pawn self.icon = Image.open("../data/image/white/P.png") self.icon = self.icon.resize((self.SIZE_SQUARE, self.SIZE_SQUARE)) self.icon = ImageTk.PhotoImage(self.icon) self.piece['P'] = self.icon self.icon = Image.open("../data/image/black/p.png") self.icon = self.icon.resize((self.SIZE_SQUARE, self.SIZE_SQUARE)) self.icon = ImageTk.PhotoImage(self.icon) self.piece['p'] = self.icon self.square = [] offsetRank = (self.NUMBER_ROW - 1) * self.SIZE_SQUARE for i in range(self.NUMBER_ROW): for j in range(self.NUMBER_COLLUM): self.square.append( [j * self.SIZE_SQUARE, offsetRank - i * self.SIZE_SQUARE]) BoardHeight = self.NUMBER_ROW * self.SIZE_SQUARE BoardWith = self.NUMBER_COLLUM * self.SIZE_SQUARE self.GUIBoard = Canvas(self, width=BoardWith, height=BoardHeight, background='gray') self.GUIBoard.pack(side=tkinter.LEFT) self.GUIBoard.bind('<Button-1>', self.click) self.clickfrom = None self.clickTo = None self.coordinateClick = [] self.listHightLight = [] self.mapHightLight = [] self.draw() self.controlPanel = Frame(self, width=300, background="#d2f0bb") self.controlPanel.pack(side=tkinter.LEFT, fill=tkinter.BOTH) self.canvas = Canvas(self.controlPanel, background='white', height=256) self.canvas.create_text(20, 30, anchor='w', font="VNI-Dom 16", text="Information of game: ") self.canvas.create_text(20, 60, anchor='w', font="VNI-Dom 14", text="Your color piece is white ") self.canvas.create_text(20, 90, anchor='w', font="VNI-Dom 14", text="Color piece of machine is black ") self.canvas.create_text(20, 120, anchor='w', font="VNI-Dom 14", text="Alpha beta pruning depth = 3") self.canvas.create_text(20, 150, anchor='w', font="VNI-Dom 14", text="Oponent move: ", tag="move") self.canvas.create_text(20, 220, anchor='w', font="VNI-Dom 14", text="Status board: your turn", tag="status") self.canvas.pack(fill=tkinter.BOTH, side=tkinter.TOP) self.ButtonNewgame = tkinter.Button(self.controlPanel, text="New game", width=10, font="VNI-Dom 14", background="#1698de") self.ButtonNewgame.place(relx=.5, rely=.7, anchor='c') self.ButtonNewgame.bind('<Button-1>', self.clearBoard) def clearBoard(self, event): self.board.reset() self.slot[0] = True self.canvas.delete("move") self.canvas.create_text(20, 150, anchor='w', font="VNI-Dom 14", text="Oponent move: ", tag="move") self.draw() def click(self, event): if self.slot[0] == True: # opponent turn x = event.x // self.SIZE_SQUARE y = self.NUMBER_ROW - event.y // self.SIZE_SQUARE self.coordinateClick.clear() self.coordinateClick.append(x) self.coordinateClick.append(y) traceSquare = (self.NUMBER_ROW - 1 - event.y // self.SIZE_SQUARE ) * self.NUMBER_ROW + (event.x // self.SIZE_SQUARE) if self.clickfrom is None: pieceAt = self.board.piece_at(traceSquare) if pieceAt is not None: self.clickfrom = self.YIELD[self.coordinateClick[0]] + str( self.coordinateClick[1]) self.hightLight() else: self.draw() else: if traceSquare in self.mapHightLight: self.move() else: self.mapHightLight.clear() self.draw() self.clickfrom = None def hightLight(self): position = self.YIELD[self.coordinateClick[0]] + str( self.coordinateClick[1]) legal_moves = [ str(legal_move) for legal_move in self.board.legal_moves ] self.listHightLight.clear() self.mapHightLight.clear() for legal_move in legal_moves: if (position == legal_move[:2]): self.listHightLight.append(legal_move) for legal_move in self.listHightLight: self.mapHightLight.append(self.MAP[legal_move[2]] + (int(legal_move[3]) - 1) * self.NUMBER_ROW) self.draw() def move(self): self.clickTo = self.YIELD[self.coordinateClick[0]] + str( self.coordinateClick[1]) move = str(self.clickfrom) + str(self.clickTo) #check promotion traceFrom = self.MAP[self.clickfrom[0]] + (self.NUMBER_ROW) * ( int(self.clickfrom[1]) - 1) traceFrom = self.board.piece_at(traceFrom) if traceFrom.symbol() == 'p' and int(self.clickTo[1]) == 1: move += 'q' elif traceFrom.symbol() == 'P' and int(self.clickTo[1]) == 8: move += 'q' #print(move) move = chess.Move.from_uci(move) self.board.push(move) self.mapHightLight.clear() self.draw() self.slot[0] = False self.canvas.delete("move") self.canvas.create_text(20, 150, anchor='w', font="VNI-Dom 14", text="White move: " + str(move), tag="move") self.canvas.delete("status") self.canvas.create_text(20, 220, anchor='w', font="VNI-Dom 14", text="Status board: Machine turn", tag="status") self.game.ROOT.after(1000, self.game.AIplay) def draw(self): #delete canvas self.GUIBoard.delete("square") self.GUIBoard.delete("piece") collor = self.WHITE positonClick = None if len(self.coordinateClick): positonClick = self.coordinateClick[0] + (self.NUMBER_ROW) * ( self.coordinateClick[1] - 1) #print(positonClick) for i in range(self.NUMBER_ROW): collor = self.BLACK if collor == self.WHITE else self.WHITE for j in range(self.NUMBER_COLLUM): pos = i * self.NUMBER_ROW + j if (collor == self.WHITE): if positonClick is not None and positonClick == pos: self.GUIBoard.create_rectangle( self.square[pos][0], self.square[pos][1], self.square[pos][0] + self.SIZE_SQUARE, self.square[pos][1] + self.SIZE_SQUARE, fill=self.GREEN, tag="square") elif (pos in self.mapHightLight): self.GUIBoard.create_rectangle( self.square[pos][0], self.square[pos][1], self.square[pos][0] + self.SIZE_SQUARE, self.square[pos][1] + self.SIZE_SQUARE, fill=self.YELLOW, tag="square") else: self.GUIBoard.create_rectangle( self.square[pos][0], self.square[pos][1], self.square[pos][0] + self.SIZE_SQUARE, self.square[pos][1] + self.SIZE_SQUARE, fill=self.WHITE, tag="square") collor = self.BLACK else: if positonClick is not None and positonClick == pos: self.GUIBoard.create_rectangle( self.square[pos][0], self.square[pos][1], self.square[pos][0] + self.SIZE_SQUARE, self.square[pos][1] + self.SIZE_SQUARE, fill=self.GREEN, tag="square") elif (pos in self.mapHightLight): self.GUIBoard.create_rectangle( self.square[pos][0], self.square[pos][1], self.square[pos][0] + self.SIZE_SQUARE, self.square[pos][1] + self.SIZE_SQUARE, fill=self.YELLOW, tag="square") else: self.GUIBoard.create_rectangle( self.square[pos][0], self.square[pos][1], self.square[pos][0] + self.SIZE_SQUARE, self.square[pos][1] + self.SIZE_SQUARE, fill=self.BLACK, tag="square") collor = self.WHITE offset = self.NUMBER_ROW * self.NUMBER_COLLUM for i in range(offset): pieceAtSquare = self.board.piece_at(i) if (pieceAtSquare is not None): image = pieceAtSquare.symbol() self.GUIBoard.create_image( self.SIZE_SQUARE // 2 + self.square[i][0], self.SIZE_SQUARE // 2 + self.square[i][1], image=self.piece[image], tag="piece")
class View(): selected_piece_position = None all_squares_to_be_highlighted = [] images = {} board_color_1 = BOARD_COLOR_1 board_color_2 = BOARD_COLOR_2 highlight_color = HIGHLIGHT_COLOR def __init__(self, parent, controller): self.controller = controller self.parent = parent self.create_chess_base() self.canvas.bind("<Button-1>", self.on_square_clicked) self.start_new_game() def reload_colors(self, color_1, color_2, highlight_color): self.board_color_1 = color_1 self.board_color_2 = color_2 self.highlight_color = highlight_color self.draw_board() self.draw_all_pieces() def on_preference_menu_clicked(self): self.show_preferences_window() def show_preferences_window(self): preferenceswindow.PreferencesWindow(self) def create_bottom_frame(self): self.bottom_frame = Frame(self.parent, height=64) self.info_label = Label(self.bottom_frame, text=" White to Start the Game ") self.info_label.pack(side=RIGHT, padx=8, pady=5) self.bottom_frame.pack(fill="x", side="bottom") def create_top_menu(self): self.menu_bar = Menu(self.parent) self.create_file_menu() self.create_edit_menu() self.create_about_menu() def create_file_menu(self): self.file_menu = Menu(self.menu_bar, tearoff=0) self.file_menu.add_command(label="New Game", command=self.on_new_game_menu_clicked) self.menu_bar.add_cascade(label="File", menu=self.file_menu) self.parent.config(menu=self.menu_bar) def create_edit_menu(self): self.edit_menu = Menu(self.menu_bar, tearoff=0) self.edit_menu.add_command(label="Preferences", command=self.on_preference_menu_clicked) self.menu_bar.add_cascade(label="Edit", menu=self.edit_menu) self.parent.config(menu=self.menu_bar) def create_about_menu(self): self.about_menu = Menu(self.menu_bar, tearoff=0) self.about_menu.add_command(label="About", command=self.on_about_menu_clicked) self.menu_bar.add_cascade(label="About", menu=self.about_menu) self.parent.config(menu=self.menu_bar) def create_canvas(self): canvas_width = NUMBER_OF_COLUMNS * DIMENSION_OF_EACH_SQUARE canvas_height = NUMBER_OF_ROWS * DIMENSION_OF_EACH_SQUARE self.canvas = Canvas(self.parent, width=canvas_width, height=canvas_height) self.canvas.pack(padx=8, pady=8) def create_chess_base(self): self.create_top_menu() self.create_canvas() self.draw_board() self.create_bottom_frame() def start_new_game(self): self.controller.reset_game_data() self.controller.reset_to_initial_locations() self.draw_all_pieces() self.info_label.config(text=" White to Start the Game ") def reset_board_state(self): self.selected_piece_position = None self.all_squares_to_be_highlighted = [] self.images = {} def on_new_game_menu_clicked(self): self.start_new_game() def get_clicked_row_column(self, event): col_size = row_size = DIMENSION_OF_EACH_SQUARE clicked_column = event.x // col_size clicked_row = 7 - (event.y // row_size) return (clicked_row, clicked_column) def on_square_clicked(self, event): clicked_row, clicked_column = self.get_clicked_row_column(event) position_of_click = self.controller.get_alphanumeric_position( (clicked_row, clicked_column)) # on second click if self.selected_piece_position: self.shift(self.selected_piece_position, position_of_click) self.selected_piece_position = None self.update_highlight_list(position_of_click) self.draw_board() self.draw_all_pieces() def shift(self, start_pos, end_pos): selected_piece = self.controller.get_piece_at(start_pos) piece_at_destination = self.controller.get_piece_at(end_pos) if not piece_at_destination or piece_at_destination.color != selected_piece.color: try: self.controller.pre_move_validation(start_pos, end_pos) except exceptions.ChessError as error: self.info_label["text"] = error.__class__.__name__ else: self.update_label(selected_piece, start_pos, end_pos) def update_label(self, piece, start_pos, end_pos): turn = ('white' if piece.color == 'black' else 'black') self.info_label["text"] = '' + piece.color.capitalize() + " : " + \ start_pos + end_pos + ' ' + turn.capitalize() + '\'s turn' def update_highlight_list(self, position): self.all_squares_to_be_highlighted = None try: piece = self.controller.get_piece_at(position) except: piece = None if piece and (piece.color == self.controller.player_turn()): self.selected_piece_position = position self.all_squares_to_be_highlighted = list( map( self.controller.get_numeric_notation, self.controller.get_piece_at(position).moves_available( position))) def get_x_y_coordinate(self, row, col): x = (col * DIMENSION_OF_EACH_SQUARE) y = ((7 - row) * DIMENSION_OF_EACH_SQUARE) return (x, y) def draw_board(self): current_color = self.board_color_2 for row in range(NUMBER_OF_ROWS): current_color = self.get_alternate_color(current_color) for col in range(NUMBER_OF_COLUMNS): x1, y1 = self.get_x_y_coordinate(row, col) x2, y2 = x1 + DIMENSION_OF_EACH_SQUARE, y1 + DIMENSION_OF_EACH_SQUARE if (self.all_squares_to_be_highlighted and (row, col) in self.all_squares_to_be_highlighted): self.canvas.create_rectangle(x1, y1, x2, y2, fill=self.highlight_color) else: self.canvas.create_rectangle(x1, y1, x2, y2, fill=current_color) current_color = self.get_alternate_color(current_color) def get_alternate_color(self, current_color): if current_color == self.board_color_2: next_color = self.board_color_1 else: next_color = self.board_color_2 return next_color def calculate_piece_coordinate(self, row, col): x0 = (col * DIMENSION_OF_EACH_SQUARE) + \ int(DIMENSION_OF_EACH_SQUARE / 2) y0 = ((7 - row) * DIMENSION_OF_EACH_SQUARE) + \ int(DIMENSION_OF_EACH_SQUARE / 2) return (x0, y0) def draw_single_piece(self, position, piece): x, y = self.controller.get_numeric_notation(position) if piece: filename = "../pieces_image/{}_{}.png".format( piece.name.lower(), piece.color) if filename not in self.images: self.images[filename] = PhotoImage(file=filename) x0, y0 = self.calculate_piece_coordinate(x, y) self.canvas.create_image(x0, y0, image=self.images[filename], tags=("occupied"), anchor="c") def draw_all_pieces(self): self.canvas.delete("occupied") for position, piece in self.controller.get_all_peices_on_chess_board(): self.draw_single_piece(position, piece) def on_about_menu_clicked(self): messagebox.showinfo( "From the Book:", "Tkinter GUI Application\n Development Blueprints")
class MastermindUI(Frame): """ The Tkinter UI, responsible for drawing the board and accepting user input. """ def init_grids(self): self.grid = [['E', 'E', 'E', 'E'], ['E', 'E', 'E', 'E'], ['E', 'E', 'E', 'E'], ['E', 'E', 'E', 'E'], ['E', 'E', 'E', 'E'], ['E', 'E', 'E', 'E']] self.evaluationGrid = [['E', 'E', 'E', 'E'], ['E', 'E', 'E', 'E'], ['E', 'E', 'E', 'E'], ['E', 'E', 'E', 'E'], ['E', 'E', 'E', 'E'], ['E', 'E', 'E', 'E']] def __init__(self, parent, game, ai): self.game = game self.ai = ai Frame.__init__(self, parent) self.parent = parent self.grid = [] self.evaluationGrid = [] self.init_grids() self.row, self.col = 5, 0 self.newWindow = Toplevel(self.parent) self.aiApp = GameAIUI.GameAIUI(self.newWindow, self.ai) self.__init_ui() def __init_ui(self): self.parent.title("Mastermind") # Set Window Title self.pack(fill=BOTH) self.canvas = Canvas(self, width=WIDTH, height=HEIGHT) self.canvas.pack(fill=BOTH, side=TOP) submit_button = Button(self, text="Clear Answers", command=self.__clear_answers) submit_button.pack(fill=BOTH, side=BOTTOM) self.__draw_grid() self.__draw_puzzle() self.__draw_cursor() self.canvas.focus_set() self.canvas.bind("<Button-1>", self.__cell_clicked) self.canvas.bind("<Key>", self.__key_pressed) self.canvas.bind("<Return>", self.__submit_answers) self.canvas.bind("<Left>", self.__left_key) self.canvas.bind("<Right>", self.__right_key) self.canvas.bind("<space>", self.__clear_cell) def __draw_grid(self): color = "white" for i in range(12): for j in range(2): self.canvas.create_rectangle(MARGIN + j * SIDE / 2, MARGIN + i * SIDE / 2, MARGIN + j * SIDE / 2 + SIDE / 2, MARGIN + i * SIDE / 2 + SIDE / 2, fill=color) color = "white" for i in range(6): for j in range(4): self.canvas.create_rectangle(MARGIN + j * SIDE + SIDE, MARGIN + i * SIDE, MARGIN + j * SIDE + SIDE + SIDE, MARGIN + i * SIDE + SIDE, fill=color) def __draw_puzzle(self): self.canvas.delete("numbers") for i in range(6): for j in range(4): answer = self.grid[i][j] color = colors[answer] self.canvas.create_rectangle(MARGIN + j * SIDE + SIDE, MARGIN + i * SIDE, MARGIN + j * SIDE + SIDE + SIDE, MARGIN + i * SIDE + SIDE, fill=color) for i in range(6): for j in range(2): eval_answer = self.evaluationGrid[i][j] color = eval_colors[eval_answer] self.canvas.create_rectangle(MARGIN + j * SIDE / 2, MARGIN + i * SIDE, MARGIN + j * SIDE / 2 + SIDE / 2, MARGIN + i * SIDE + SIDE / 2, fill=color) for i in range(6): for j in range(2, 4): eval_answer = self.evaluationGrid[i][j] color = eval_colors[eval_answer] _j = j - 2 self.canvas.create_rectangle(MARGIN + _j * SIDE / 2, MARGIN + i * SIDE + SIDE / 2, MARGIN + _j * SIDE / 2 + SIDE / 2, MARGIN + i * SIDE + SIDE, fill=color) def __draw_cursor(self): self.canvas.delete("cursor") if self.row >= 0 and self.col >= 0: x0 = MARGIN + SIDE + self.col * SIDE + 1 y0 = MARGIN + self.row * SIDE + 1 x1 = MARGIN + SIDE + (self.col + 1) * SIDE - 1 y1 = MARGIN + (self.row + 1) * SIDE - 1 self.canvas.create_rectangle( x0, y0, x1, y1, outline="red", tags="cursor" ) def __draw_victory(self): # create a oval (which will be a circle) x0 = y0 = MARGIN + SIDE * 1 x1 = y1 = MARGIN + SIDE * 4 self.canvas.create_oval( x0, y0, x1, y1, tags="ending", fill="dark orange", outline="orange" ) # create text x = y = MARGIN + 2 * SIDE + SIDE / 2 self.canvas.create_text( x, y, text="You win! \nIt took {} seconds".format(self.game.get_time_elapsed()), tags="ending", fill="white", font=("Arial", 12) ) def __draw_defeat(self): # create a oval (which will be a circle) x0 = y0 = MARGIN + SIDE * 1 x1 = y1 = MARGIN + SIDE * 4 self.canvas.create_oval( x0, y0, x1, y1, tags="ending", fill="dark red", outline="red" ) # create text x = y = MARGIN + 2 * SIDE + SIDE / 2 self.canvas.create_text( x, y, text="You lose! \nIt took {} seconds".format(self.game.get_time_elapsed()), tags="ending", fill="white", font=("Arial", 12) ) def __cell_clicked(self, event): # if self.game.game_over: # return x, y = event.x, event.y if MARGIN + SIDE < x < WIDTH - MARGIN and MARGIN < y < HEIGHT - MARGIN: # get row and col numbers from x,y coordinates row, col = int((y - MARGIN) / SIDE), int((x - MARGIN - SIDE) / SIDE) # if cell was selected already - deselect it if (row, col) == (self.row, self.col): self.row, self.col = -1, -1 elif self.game.get_level() == 6 - row: self.row, self.col = row, col else: self.row, self.col = -1, -1 self.__draw_cursor() def __clear_cell(self, _): if self.row >= 0 and self.col >= 0: self.grid[self.row][self.col] = 'E' self.__draw_puzzle() self.__draw_cursor() def __key_pressed(self, event): if self.row >= 0 and self.col >= 0 and len(event.char) == 1 and event.char in MastermindConstants.valid_keys: self.grid[self.row][self.col] = event.char # self.game.puzzle[self.row][self.col] = int(event.char) self.col, self.row = self.col + 1, self.row if self.col == 4: self.col, self.row = self.col - 1, self.row self.__draw_puzzle() self.__draw_cursor() def __right_key(self, _): if self.row >= 0 and 0 <= self.col < 3: self.col, self.row = self.col + 1, self.row self.__draw_puzzle() self.__draw_cursor() def __left_key(self, _): if self.row >= 0 and self.col > 0: self.col, self.row = self.col - 1, self.row self.__draw_puzzle() self.__draw_cursor() def __clear_answers(self): self.game.reset() self.game.pick_answer() self.init_grids() self.canvas.delete("ending") self.row, self.col = 5, 0 self.__draw_puzzle() self.__draw_cursor() self.ai.reset() self.aiApp.reset() def __submit_answers(self, _): index = 6 - self.game.get_level() current_choices = self.grid[index] if 'E' in current_choices: return self.game.make_guess(current_choices) evaluation = self.game.get_evaluation() self.ai.cull_possibilities(current_choices, evaluation) self.evaluationGrid[index] = list(evaluation) self.col, self.row = 0, index - 1, self.__draw_puzzle() self.__draw_cursor() self.ai.smart_eval(debug=False) self.aiApp.update_selection() if self.game.get_status() == "Won": print("Well done, you have won.") self.__draw_victory() self.aiApp.update_selection() if self.game.get_level() == 7 and self.game.get_status() != "Won": print("Oh no, better luck next time") self.__draw_defeat() self.aiApp.update_selection()
class EdemPresenceGUI(): config = None def __init__(self, parent): self.read_config_file() self.external_file = EdemExternalFile( filepath=self.configs['save_to_file']) self.photos = self.load_photos( file_path=self.configs['photos_directory']) edemcard = EdemCard(enrollment='0000') self.edempresence = EdemPresence(card=edemcard, external_file=self.external_file) filename = self.edempresence.filename() self.external_file.filepath = self.configs[ 'save_to_file'] + '/' + filename top = self.top = tk.Toplevel(parent) self.myEntryBox = tk.Entry(root, width=6) self.myEntryBox.config(font=("Courier", 44, 'bold')) self.myEntryBox.bind("<Return>", self.show_student_picture) self.myEntryBox.focus_set() self.myEntryBox.pack() Button(root, text="SAIR", command=root.destroy).pack() self.canvas = Canvas(root, width=300, height=400) def load_photos(self, file_path): db_fotos = {} files = glob.glob(file_path + "/*") for f in files: file_name = os.path.basename(f) records = file_name.split('_') last = records[-1:] mean_parts = last[0].split('.') enrollment = mean_parts[0] if len(enrollment) == 4: enrollment = '00' + str(enrollment) if len(enrollment) == 5: enrollment = '0' + str(enrollment) db_fotos[str(enrollment)] = f return db_fotos def show_student_picture(self, event): if self.canvas: self.canvas.delete("all") self.canvas = Canvas(root, width=300, height=400) if str(self.myEntryBox.get()) in self.photos.keys(): picture = self.photos[str(self.myEntryBox.get())] print(self.photos[str(self.myEntryBox.get())]) else: picture = os.getcwd() + '/default_picture/default.jpg' if not os.path.exists(picture): picture = os.getcwd() + '/default_picture/default.jpg' print("FOTO DO ALUNO: " + str(picture)) im = Image.open(picture) im = im.resize((300, 400), Image.ANTIALIAS) self.canvas.image = ImageTk.PhotoImage(im) self.canvas.create_image(0, 0, image=self.canvas.image, anchor='nw') self.edempresence.enrollment = str(self.myEntryBox.get()) data = self.edempresence.generate_full_presence_record() self.edempresence.write_external_presence_data(data) #self.canvas.pack(0,0) #self.canvas.pack(side="left", fill="both", expand=True) self.canvas.place(x=150, y=120) self.myEntryBox.focus_set() self.myEntryBox.delete(0, 'end') def read_config_file(self): with open('edempresence.yaml', 'r') as config: self.configs = yaml.load(config)
class PigChaseHumanAgent(GuiAgent): def __init__(self, name, environment, keymap, max_episodes, max_actions, visualizer, quit): self._max_episodes = max_episodes self._max_actions = max_actions self._action_taken = 0 self._episode = 1 self._scores = [] self._rewards = [] self._episode_has_ended = False self._episode_has_started = False self._quit_event = quit super(PigChaseHumanAgent, self).__init__(name, environment, keymap, visualizer=visualizer) def _build_layout(self, root): # Left part of the GUI, first person view self._first_person_header = ttk.Label(root, text='First Person View', font=(None, 14, 'bold')) \ .grid(row=0, column=0) self._first_person_view = ttk.Label(root) self._first_person_view.grid(row=1, column=0, rowspan=10) # Right part, top self._first_person_header = ttk.Label(root, text='Symbolic View', font=(None, 14, 'bold')) \ .grid(row=0, column=1) self._symbolic_view = Canvas(root) self._symbolic_view.configure(width=ENV_BOARD_SHAPE[0]*CELL_WIDTH, height=ENV_BOARD_SHAPE[1]*CELL_WIDTH) self._symbolic_view.grid(row=1, column=1) # Bottom information self._information_panel = ttk.Label(root, text='Game stats', font=(None, 14, 'bold')) self._current_episode_lbl = ttk.Label(root, text='Episode: 0', font=(None, 12)) self._cum_reward_lbl = ttk.Label(root, text='Score: 0', font=(None, 12, 'bold')) self._last_action_lbl = ttk.Label(root, text='Previous action: None', font=(None, 12)) self._action_done_lbl = ttk.Label(root, text='Actions taken: 0', font=(None, 12)) self._action_remaining_lbl = ttk.Label(root, text='Actions remaining: 0', font=(None, 12)) self._information_panel.grid(row=2, column=1) self._current_episode_lbl.grid(row=3, column=1, sticky=W, padx=20) self._cum_reward_lbl.grid(row=4, column=1, sticky=W, padx=20) self._last_action_lbl.grid(row=5, column=1, sticky=W, padx=20) self._action_done_lbl.grid(row=6, column=1, sticky=W, padx=20) self._action_remaining_lbl.grid(row=7, column=1, sticky=W, padx=20) self._overlay = None # Main rendering callback self._pressed_binding = root.bind('<Key>', self._on_key_pressed) self._user_pressed_enter = False # UI Update callback root.after(self._tick, self._poll_frame) root.after(1000, self._on_episode_start) root.focus() def _draw_arrow(self, yaw, x, y, cell_width, colour): if yaw == 0.: x1, y1 = (x + .15) * cell_width, (y + .15) * cell_width x2, y2 = (x + .5) * cell_width, (y + .4) * cell_width x3, y3 = (x + .85) * cell_width, (y + .85) * cell_width self._symbolic_view.create_polygon(x1, y1, x2, y3, x3, y1, x2, y2, fill=colour) elif yaw == 90.: x1, y1 = (x + .15) * cell_width, (y + .15) * cell_width x2, y2 = (x + .6) * cell_width, (y + .5) * cell_width x3, y3 = (x + .85) * cell_width, (y + .85) * cell_width self._symbolic_view.create_polygon(x1, y2, x3, y1, x2, y2, x3, y3, fill=colour) elif yaw == 180.: x1, y1 = (x + .15) * cell_width, (y + .15) * cell_width x2, y2 = (x + .5) * cell_width, (y + .6) * cell_width x3, y3 = (x + .85) * cell_width, (y + .85) * cell_width self._symbolic_view.create_polygon(x1, y3, x2, y1, x3, y3, x2, y2, fill=colour) else: x1, y1 = (x + .15) * cell_width, (y + .15) * cell_width x2, y2 = (x + .4) * cell_width, (y + .5) * cell_width x3, y3 = (x + .85) * cell_width, (y + .85) * cell_width self._symbolic_view.create_polygon(x1, y3, x2, y2, x1, y1, x3, y2, fill=colour) def _poll_frame(self): """ Main callback for UI rendering. Called at regular intervals. The method will ask the environment to provide a frame if available (not None). :return: """ cell_width = CELL_WIDTH circle_radius = 10 # are we done? if self._env.done and not self._episode_has_ended: self._on_episode_end() # build symbolic view board = None if self._env is not None: board, _ = self._env._internal_symbolic_builder.build(self._env) if board is not None: board = board.T self._symbolic_view.delete('all') # Remove all previous items from Tkinter tracking width, height = board.shape for x in range(width): for y in range(height): cell_contents = str.split(str(board[x][y]), '/') for block in cell_contents: if block == 'sand': self._symbolic_view.create_rectangle(x * cell_width, y * cell_width, (x + 1) * cell_width, (y + 1) * cell_width, outline="black", fill="orange", tags="square") elif block == 'grass': self._symbolic_view.create_rectangle(x * cell_width, y * cell_width, (x + 1) * cell_width, (y + 1) * cell_width, outline="black", fill="lawn green", tags="square") elif block == 'lapis_block': self._symbolic_view.create_rectangle(x * cell_width, y * cell_width, (x + 1) * cell_width, (y + 1) * cell_width, outline="black", fill="black", tags="square") elif block == ENV_TARGET_NAMES[0]: self._symbolic_view.create_oval((x + .5) * cell_width - circle_radius, (y + .5) * cell_width - circle_radius, (x + .5) * cell_width + circle_radius, (y + .5) * cell_width + circle_radius, fill='pink') elif block == self.name: yaw = self._env._world_obs['Yaw'] % 360 self._draw_arrow(yaw, x, y, cell_width, 'red') elif block == ENV_AGENT_NAMES[0]: # Get yaw of other agent: entities = self._env._world_obs[ENV_ENTITIES] other_agent = list( map(Entity.create, filter(lambda e: e['name'] == ENV_AGENT_NAMES[0], entities))) if len(other_agent) == 1: other_agent = other_agent.pop() yaw = other_agent.yaw % 360 self._draw_arrow(yaw, x, y, cell_width, 'blue') # display the most recent frame frame = self._env.frame if frame is not None: from PIL import ImageTk self._first_person_view.image = ImageTk.PhotoImage(image=frame) self._first_person_view.configure(image=self._first_person_view.image) self._first_person_view.update() self._first_person_view.update() # process game state (e.g., has the episode started?) if self._episode_has_started and time.time() - self._episode_start_time < 3: if not hasattr(self, "_init_overlay") or not self._init_overlay: self._create_overlay() self._init_overlay.delete("all") self._init_overlay.create_rectangle( 10, 10, 590, 290, fill="white", outline="red", width="5") self._init_overlay.create_text( 300, 80, text="Get ready to catch the pig!", font=('Helvetica', '18')) self._init_overlay.create_text( 300, 140, text=str(3 - int(time.time() - self._episode_start_time)), font=('Helvetica', '18'), fill="red") self._init_overlay.create_text( 300, 220, width=460, text="How to play: \nUse the left/right arrow keys to turn, " "forward/back to move. The pig is caught if it is " "cornered without a free block to escape to.", font=('Helvetica', '14'), fill="black") self._root.update() elif self._episode_has_ended: if not hasattr(self, "_init_overlay") or not self._init_overlay: self._create_overlay() self._init_overlay.delete("all") self._init_overlay.create_rectangle( 10, 10, 590, 290, fill="white", outline="red", width="5") self._init_overlay.create_text( 300, 80, text='Finished episode %d of %d' % (self._episode, self._max_episodes), font=('Helvetica', '18')) self._init_overlay.create_text( 300, 120, text='Score: %d' % sum(self._rewards), font=('Helvetica', '18')) if self._episode > 1: self._init_overlay.create_text( 300, 160, text='Average over %d episodes: %.2f' % (self._episode, np.mean(self._scores)), font=('Helvetica', '18')) self._init_overlay.create_text( 300, 220, width=360, text="Press RETURN to start the next episode, ESC to exit.", font=('Helvetica', '14'), fill="black") self._root.update() elif hasattr(self, "_init_overlay") and self._init_overlay: self._destroy_overlay() # trigger the next update self._root.after(self._tick, self._poll_frame) def _create_overlay(self): self._init_overlay = Canvas(self._root, borderwidth=0, highlightthickness=0, width=600, height=300, bg="gray") self._init_overlay.place(relx=0.5, rely=0.5, anchor='center') def _destroy_overlay(self): self._init_overlay.destroy() self._init_overlay = None def _on_key_pressed(self, e): """ Main callback for keyboard events :param e: :return: """ if e.keysym == 'Escape': self._quit() if e.keysym == 'Return' and self._episode_has_ended: if self._episode >= self._max_episodes: self._quit() # start the next episode self._action_taken = 0 self._rewards = [] self._episode += 1 self._env.reset() self._on_episode_start() print('Starting episode %d' % self._episode) if self._episode_has_started and time.time() - self._episode_start_time >= 3: if e.keysym in self._keymap: mapped_action = self._keymap.index(e.keysym) _, reward, done = self._env.do(mapped_action) self._action_taken += 1 self._rewards.append(reward) self._on_experiment_updated(mapped_action, reward, done) def _on_episode_start(self): self._episode_has_ended = False self._episode_has_started = True self._episode_start_time = time.time() self._on_experiment_updated(None, 0, self._env.done) def _on_episode_end(self): # do a turn to ensure we get the final reward and observation no_op_action = 0 _, reward, done = self._env.do(no_op_action) self._action_taken += 1 self._rewards.append(reward) self._on_experiment_updated(no_op_action, reward, done) # report scores self._scores.append(sum(self._rewards)) self.visualize(self._episode, 'Reward', sum(self._rewards)) # set flags to start a new episode self._episode_has_started = False self._episode_has_ended = True def _on_experiment_updated(self, action, reward, is_done): self._current_episode_lbl.config(text='Episode: %d' % self._episode) self._cum_reward_lbl.config(text='Score: %d' % sum(self._rewards)) self._last_action_lbl.config(text='Previous action: %s' % action) self._action_done_lbl.config(text='Actions taken: {0}'.format(self._action_taken)) self._action_remaining_lbl.config(text='Actions remaining: %d' % (self._max_actions - self._action_taken)) self._first_person_view.update() def _quit(self): self._quit_event.set() self._root.quit() sys.exit()
class RulesInput(): """ Class to manage gui and logic for entry fields of rules in Parameters frame """ def __init__(self, parent_class): """ Initialize parent_frame to the provided class to hold self.frame self.frame contains all the elements self.entries is a list of dynamically generated entries """ self.parent_class = parent_class # frame in parent Parameters class self.frame = Frame(parent_class.frame) self.preview_canvas = None # canvas to preview curve self.entries = [] # list of dictionaries, each dictionary # contains the keys for frame, and its children self.add_button = None self.sub_button = None self.radio_angle_var = BooleanVar( self.frame) # initially set to radians self.radio_angle_var.set(True) self.init_preview_canvas() self.init_info_labels() self.init_add_entry_button() self.init_sub_entry_button() # self.init_extract_rules_button() self.frame.grid(row=7, column=0, columnspan=3, sticky='nw', pady=10) def create_entry_dictionary(self): """ Creates and returns a dictionary which contains references to a frame and entries in it keys: ["frame", "ent_len", "ent_angle", "chk_is_flip", "chk_is_rev", "flip_state","reverse_state"] """ vcmd = (self.frame.register(self.validate_float), '%P') entry_frame = Frame(self.frame) ent_length = Entry(entry_frame, validate='key', width=8, validatecommand=vcmd) ent_angle = Entry(entry_frame, validate='key', width=8, validatecommand=vcmd) is_reversed_state = BooleanVar(entry_frame) is_flipped_state = BooleanVar(entry_frame) chkbtn_is_reversed = Checkbutton(entry_frame, text='reverse', var=is_reversed_state) chkbtn_is_flipped = Checkbutton(entry_frame, text='flip', var=is_flipped_state) ent_angle.pack(side=LEFT) ent_length.pack(side=LEFT) chkbtn_is_flipped.pack(side=LEFT) chkbtn_is_reversed.pack(side=LEFT) entry_frame.grid(row=len(self.entries) + 3, columnspan=4) entry_dict = { "frame": entry_frame, "ent_len": ent_length, "ent_angle": ent_angle, "chk_is_flip": chkbtn_is_flipped, "chk_is_rev": chkbtn_is_reversed, "flip_state": is_flipped_state, "reverse_state": is_reversed_state } return entry_dict def init_add_entry_button(self): """ Initialize the button which adds frames for entry of each rule """ def add_entry(): """ create a new entry and add to self.entries """ new_entry = self.create_entry_dictionary() self.entries.append(new_entry) self.render_preview() self.add_button = Button(self.frame, text='+', command=add_entry) self.add_button.grid(row=1, column=2) def init_sub_entry_button(self): """ Initialize the button to remove entry fields """ def sub_entry(): """ Pop and destroy the last entry from self.entries """ if self.entries != []: self.entries.pop()["frame"].destroy() self.render_preview() self.sub_button = Button(self.frame, text='-', command=sub_entry) self.sub_button.grid(row=1, column=3) def validate_float(self, p_str): """ Validate if input is a valid floating point number """ # may validate only '[+-].' which needs to be handled later float_pattern = r"^[\+\-]?([0-9]*[.])?[0-9]*$" if re.search(float_pattern, p_str) or p_str == "": return True return False def extract_rules(self): """ Extract rules from the input fields to a list """ def get_float_value(entry_string): """ Get the float value out of entry strings (function to handle corner cases) """ if entry_string in ['', '.', '+.', '-.', '+', '-']: return 0.0 return float(entry_string) extracted_rules = [] for entry in self.entries: if self.radio_angle_var.get( ): # if true, means radians, extract as is ent_angle = get_float_value(entry["ent_angle"].get()) else: ent_angle = get_float_value(entry["ent_angle"].get( )) * RAD_FAC # convert degree to radians ent_angle = ent_angle % (2 * PI) ent_len = get_float_value(entry["ent_len"].get()) is_reversed = entry["reverse_state"].get() is_flipped = entry["flip_state"].get() if ent_angle or ent_len: # user entered something, otherwise nothing changed extracted_rules.append( (ent_angle, ent_len, is_flipped, is_reversed)) return extracted_rules def fill_entries_from_rules(self, rules): """ Fill in the entries in GUI for user feedback """ for rule in rules: angle, length, is_flipped, is_reversed = rule new_entry = self.create_entry_dictionary() # clear and insert angle new_entry['ent_angle'].delete(0, END) if self.radio_angle_var.get(): # if angle in radians new_entry['ent_angle'].insert(0, str(angle)) else: new_entry['ent_angle'].insert(0, str(angle * DEG_FAC)) # clear and insert length new_entry['ent_len'].delete(0, END) new_entry['ent_len'].insert(0, str(length)) # set booleans new_entry['reverse_state'].set(is_reversed) new_entry['flip_state'].set(is_flipped) self.entries.append(new_entry) # def init_extract_rules_button(self): # """ # Test button to check extracted rules # """ # def print_extracted(): # """ # Print the extracted rules to stdout # """ # print("Extracted:") # print(self.extract_rules()) # # self.test_button = Button( # self.frame, text="extract", command=print_extracted) # self.test_button.pack() def init_preview_canvas(self): """ Canvas to draw the base curve from rules and give preview to the user """ self.preview_canvas = Canvas(self.frame, width=200, height=200) self.preview_canvas.grid(row=0, columnspan=4, sticky=W) def form_base_curve(self, rules): """ Form the base curve from extracted rules for previewing Resized to fit into the preview canvas """ curve = [(0, 0)] for theta, scale_fac, _, _ in rules: last_x, last_y = curve[-1] curve.append((last_x + scale_fac * cos(theta), last_y + scale_fac * sin(theta))) min_x = min(point[0] for point in curve) min_y = min(point[1] for point in curve) scale_y = max(point[1] - min_y for point in curve) scale_x = max(point[0] - min_x for point in curve) if scale_x == 0 or scale_y == 0: return curve canvas_width = self.preview_canvas.winfo_width() canvas_height = self.preview_canvas.winfo_height() to_scale = min(canvas_width / scale_x, canvas_height / scale_y) * 0.8 curve = [((point[0] - min_x) * to_scale + canvas_width / 10, (point[1] - min_y) * to_scale + canvas_height / 10) for point in curve] return curve def render_preview(self): """ Render the preview on canvas on calling the function Desired to be called by some update function """ # Not the best way to do it but the curve size is of constant # order, <20 segments, so it wouldnt create much difference extracted_rules = self.extract_rules() self.set_rules_in_curve(extracted_rules) # set the rules in the parent curve dynamically curve = self.form_base_curve(extracted_rules) self.preview_canvas.delete("all") if len(curve) > 1: # draw only if there are more than one points self.preview_canvas.create_line(curve, arrow=LAST) def init_info_labels(self): """ Initialize the labels providing info about input fields """ Radiobutton(self.frame, variable=self.radio_angle_var, value=False, text="Degrees").grid(row=1, column=0) Radiobutton(self.frame, variable=self.radio_angle_var, value=True, text="Radians").grid(row=1, column=1) Label(self.frame, text="Angle").grid(row=2, column=0, sticky=W) Label(self.frame, text="Length").grid(row=2, column=1, sticky=W) def set_rules_in_curve(self, rules): """ Set the rules entries received into the rules of Curve class """ self.parent_class.parent_class.classes["fractal"].set_rules(rules)
class App(Tk): def __init__(self, *args, **kwargs): ''' the ui stuff ''' super().__init__(*args, **kwargs) self.color = 'blue' self.winfo_toplevel().title('Judgy Hexagon') #Menu for a bit of documentation and help self.menu = Menu(self) self.menu.add_command(label='Change Color', command=self.change_color) self.menu.add_command(label='Help', command=self.help) self.menu.add_command(label='People', command=self.people) self.config(menu=self.menu) #the main canvas to show the hexagon self.canvas = Canvas(self, height=566, width=800) self.canvas.grid(row=1, column=1) #frame to put all the sliders in self.sf = Frame(self) self.sf.grid(row=1, column=3) #entries for the trait names (with default values) self.sl1 = Entry(self.sf) self.sl1.grid(row=0, column=0) self.sl1.insert(END, 'IQ') self.sl2 = Entry(self.sf, text='EQ') self.sl2.grid(row=1, column=0) self.sl2.insert(END, 'EQ') self.sl3 = Entry(self.sf) self.sl3.grid(row=2, column=0) self.sl3.insert(END, 'Attractiveness') self.sl4 = Entry(self.sf) self.sl4.grid(row=3, column=0) self.sl4.insert(END, 'Personality') self.sl5 = Entry(self.sf) self.sl5.grid(row=4, column=0) self.sl5.insert(END, 'Athleticism') self.sl6 = Entry(self.sf) self.sl6.grid(row=5, column=0) self.sl6.insert(END, 'Artisticness') #sliders self.t1scale = Scale(self.sf, from_=0, to=9, orient=HORIZONTAL) self.t1scale.grid(column=1, row=0) self.t2scale = Scale(self.sf, from_=0, to=9, orient=HORIZONTAL) self.t2scale.grid(column=1, row=1) self.t3scale = Scale(self.sf, from_=0, to=9, orient=HORIZONTAL) self.t3scale.grid(column=1, row=2) self.t4scale = Scale(self.sf, from_=0, to=9, orient=HORIZONTAL) self.t4scale.grid(column=1, row=3) self.t5scale = Scale(self.sf, from_=0, to=9, orient=HORIZONTAL) self.t5scale.grid(column=1, row=4) self.t6scale = Scale(self.sf, from_=0, to=9, orient=HORIZONTAL) self.t6scale.grid(column=1, row=5) #the labels to make clear which line is which trait self.l1 = Label(self, text=self.sl1.get(), font=('Calibri', 20)) self.l1.grid(row=1, column=2, sticky=E) self.l2 = Label(self, text=self.sl2.get(), font=('Calibri', 20)) self.l2.grid(row=1, column=1, sticky=SE) self.l3 = Label(self, text=self.sl3.get(), font=('Calibri', 20)) self.l3.grid(row=1, column=1, sticky=SW) self.l4 = Label(self, text=self.sl4.get(), font=('Calibri', 20)) self.l4.grid(row=1, column=0, sticky=W) self.l5 = Label(self, text=self.sl5.get(), font=('Calibri', 20)) self.l5.grid(row=1, column=1, sticky=NW) self.l6 = Label(self, text=self.sl6.get(), font=('Calibri', 20)) self.l6.grid(row=1, column=1, sticky=NE) #:) #put the person's name in here self.nameentry = Entry(self.sf) self.nameentry.grid(row=7, column=1) Label(self.sf, text='\n\nName of person\n\n').grid(row=7, column=0) self.namelabel = Label(self, text='Name', font=('Calibri', 20), fg='red') self.namelabel.grid(row=0, column=1) #6 lists of points self.listright = [(400+40*i, 200*2**0.5) for i in range(10)] self.listrightdown = [(400+20*i, 200*2**0.5+i*20*2**0.5) for i in range(10)] self.listleftdown = [(400-20*i, 200*2**0.5+i*20*2**0.5) for i in range(10)] self.listleft = [(400-40*i, 200*2**0.5) for i in range(10)] self.listleftup = [(400-20*i, 200*2**0.5-i*20*2**0.5) for i in range(10)] self.listrightup = [(400+20*i, 200*2**0.5-i*20*2**0.5) for i in range(10)] #Draw the 10 hexagons for i in range(10): self.canvas.create_polygon([self.listright[i][0], self.listright[i][1], self.listrightdown[i][0], self.listrightdown[i][1], self.listleftdown[i][0], self.listleftdown[i][1], self.listleft[i][0], self.listleft[i][1], self.listleftup[i][0], self.listleftup[i][1], self.listrightup[i][0], self.listrightup[i][1],], fill='', width=1, outline='black') def change_color(self): self.color = clr.askcolor(title='Choose a color for the shape')[1] def help(self): msg.showinfo(title='Help', message=''' How to use this app: Move around the sliders and enter a name. Type your 6 character traits in the 6 entries. You can change the color of shape by clicking on the 'Change Color' menu option. Then, take a snip of the part without the sliders. Tutorial on judgy hexagons in real life: First, draw like 8 nested hexagons. Connect all the points with 6 lines. Label each of the lines with a trait (should be the traits below). For each of the traits, rank them from 1-8 and draw the point on the line. The outer hexagons are higher. Now, connect all 6 points, and color in the polygon made by them.''') def people(self): msg.showinfo(title='People', message=''' List of people related to this: Ideas: Aileen Liang (probably more this person), Hanting Li Python implementation: Owen Fei Another app to check out: Owen Zhang''') def judge(self, t1, t2, t3, t4, t5, t6): ''' Draws the filled-in polygon in blue. ''' #Get which point each level of trait is t1 = self.listright[t1] t2 = self.listrightdown[t2] t3 = self.listleftdown[t3] t4 = self.listleft[t4] t5 = self.listleftup[t5] t6 = self.listrightup[t6] #REmove the last shape if possible try: self.canvas.delete(self.last_polygon) except: pass #Draw the new polygon self.last_polygon = self.canvas.create_polygon([t1[0], t1[1], t2[0], t2[1], t3[0], t3[1], t4[0], t4[1], t5[0], t5[1], t6[0], t6[1],], fill=self.color, width=1, outline=self.color) self.canvas.update() def main(self): ''' Constantly draws the new polygon. Constantly updates the name. ''' while True: #Update the name self.namelabel.config(text=self.nameentry.get()) #Call judge() on the values of the sliders self.judge(self.t1scale.get(), self.t2scale.get(), self.t3scale.get(), self.t4scale.get(), self.t5scale.get(), self.t6scale.get()) #Updates the labels with trait names. self.l1.config(text=self.sl1.get()) self.l2.config(text=self.sl2.get()) self.l3.config(text=self.sl3.get()) self.l4.config(text=self.sl4.get()) self.l5.config(text=self.sl5.get()) self.l6.config(text=self.sl6.get()) self.update()
class World(Tk): def __init__(self, filename=None, block=50, debug=True, delay=0.25, image=False, width=10, height=10): Tk.__init__(self) self.title("") arg = block self.width = width self.height = height self.beepers = {} self.ovals = {} self.numbers = {} self.robots = {} self.walls = {} self.m = arg * (width + 3) self.n = arg * (height + 3) self.t = arg self.delay = delay self.debug = debug self.use_image = image a = self.t + self.t / 2 b = self.m - self.t / 2 c = self.n - self.t / 2 self.canvas = Canvas(self, bg="white", width=self.m, height=self.n) self.canvas.pack() count = 1 for k in range(2*self.t, max(self.m, self.n)-self.t, self.t): if k < b: self.canvas.create_line(k, c, k, a, fill="red") self.canvas.create_text(k, c+self.t/2, text=str(count), font=("Times", max(-self.t*2/3, -15), "")) if k < c: self.canvas.create_line(b, k, a, k, fill="red") self.canvas.create_text(a-self.t/2, self.n-k, text=str(count), font=("Times", max(-self.t*2/3, -15), "")) count += 1 self.canvas.create_line(a, c, b, c, fill="black", width=3) self.canvas.create_line(a, a, a, c, fill="black", width=3) if filename is not None: self.read_world(filename) self.refresh() def read_world(self, filename): try: infile = open("worlds\\{0}.wld".format(filename), "r") except IOError: try: infile = open("worlds/{0}.wld".format(filename), "r") except IOError: infile = open(filename, "r") text = infile.read().split("\n") infile.close() for t in text: if t.startswith("eastwestwalls"): s = t.split(" ") y, x = int(s[1]), int(s[2]) self.add_wall(x, y, -1, y) if t.startswith("northsouthwalls"): s = t.split(" ") x, y = int(s[1]), int(s[2]) self.add_wall(x, y, x, -1) if t.startswith("beepers"): s = t.split(" ") y, x, n = int(s[1]), int(s[2]), int(s[3]) if n is INFINITY: self.add_infinite_beepers(x, y) else: for k in range(n): self.add_beeper(x, y) def pause(self): sleep(self.delay) def is_beeper(self, x, y): return (x, y) in list(self.beepers.keys()) and not \ self.beepers[(x, y)] == 0 def count_robots(self, x, y): if (x, y) not in list(self.robots.keys()): return 0 return len(self.robots[(x, y)]) def crash(self, x1, y1, x2, y2): if 0 in (x1, y1, x2, y2): return True if (x2, y2) in list(self.walls.keys()) and \ (x1, y1) in self.walls[(x2, y2)]: return True if (x1, y1) in list(self.walls.keys()) and \ (x2, y2) in self.walls[(x1, y1)]: return True return False def add_infinite_beepers(self, x, y): flag = (x, y) not in list(self.beepers.keys()) or \ self.beepers[(x, y)] is 0 self.beepers[(x, y)] = INFINITY text = "oo" a = self.t + x * self.t b = self.n - (self.t + y * self.t) t = self.t / 3 if flag: self.ovals[(x, y)] = self.canvas.create_oval(a-t, b-t, a+t, b+t, fill="black") self.numbers[(x, y)] = self.canvas.create_text(a, b, text=text, fill="white", font=("Times", max(-self.t/2, -20), "")) else: self.canvas.itemconfig(self.numbers[(x, y)], text=text) if (x, y) in list(self.robots.keys()): for robot in self.robots[(x, y)]: robot.lift() def add_beeper(self, x, y): if (x, y) in list(self.beepers.keys()) and \ self.beepers[(x, y)] is INFINITY: return flag = (x, y) not in list(self.beepers.keys()) or \ self.beepers[(x, y)] is 0 if flag: self.beepers[(x, y)] = 1 else: self.beepers[(x, y)] += 1 text = str(self.beepers[(x, y)]) a = self.t + x * self.t b = self.n - (self.t + y * self.t) t = self.t / 3 if flag: self.ovals[(x, y)] = self.canvas.create_oval(a-t, b-t, a+t, b+t, fill="black") self.numbers[(x, y)] = self.canvas.create_text(a, b, text=text, fill="white", font=("Times", max(-self.t/2, -20), "")) else: self.canvas.itemconfig(self.numbers[(x, y)], text=text) if (x, y) in list(self.robots.keys()): for robot in self.robots[(x, y)]: robot.lift() def remove_beeper(self, x, y): if self.beepers[(x, y)] is INFINITY: return self.beepers[(x, y)] -= 1 flag = self.beepers[(x, y)] is 0 text = str(self.beepers[(x, y)]) if flag: self.canvas.delete(self.ovals[(x, y)]) self.canvas.delete(self.numbers[(x, y)]) else: self.canvas.itemconfig(self.numbers[(x, y)], text=text) if (x, y) in list(self.robots.keys()): for robot in self.robots[(x, y)]: robot.lift() def add_wall(self, x1, y1, x2, y2): if not x1 == x2 and not y1 == y2: return if x1 == x2: y1, y2 = min(y1, y2), max(y1, y2) if y1 == -1: y1 = y2 for k in range(y1, y2+1): self.walls.setdefault((x1, k), []).append((x1+1, k)) a = self.t + x1 * self.t+self.t / 2 b = self.n - (self.t + k * self.t) + self.t / 2 c = self.t + x1 * self.t + self.t / 2 d = self.n - (self.t + k * self.t) - self.t / 2 self.canvas.create_line(a, b+1, c, d-1, fill="black", width=3) else: x1, x2 = min(x1, x2), max(x1, x2) if x1 == -1: x1 = x2 for k in range(x1, x2+1): self.walls.setdefault((k, y1), []).append((k, y1+1)) a = self.t + k * self.t - self.t / 2 b = self.n - (self.t + y1 * self.t) - self.t / 2 c = self.t + k * self.t + self.t / 2 d = self.n - (self.t + y1 * self.t) - self.t / 2 self.canvas.create_line(a-1, b, c+1, d, fill="black", width=3) def draw(self, x, y, d, img): t = self.t / 2 angle = 120 x = self.t + x * self.t y = self.n - (self.t + y * self.t) x1 = x + 3 ** 0.5 * t / 2 * cos(radians(d)) y1 = y - 3 ** 0.5 * t / 2 * sin(radians(d)) x2 = x + t * cos(radians(d + angle)) y2 = y - t * sin(radians(d + angle)) x3 = x + t / 4 * cos(radians(d + 180)) y3 = y - t / 4 * sin(radians(d + 180)) x4 = x + t * cos(radians(d - angle)) y4 = y - t * sin(radians(d - angle)) if img is not None: self.canvas.delete(img) return self.canvas.create_polygon(x1, y1, x2, y2, x3, y3, x4, y4, fill="blue") def erase(self, img): self.canvas.delete(img) def record_move(self, count, x1, y1, x2, y2): for robot in self.robots[(x1, y1)]: if robot.count == count: self.robots[(x1, y1)].remove(robot) self.robots.setdefault((x2, y2), []).append(robot) break def lift(self, img): self.canvas.lift(img) def refresh(self): self.canvas.update() self.pause() def register(self, x, y, robot): self.robots.setdefault((x, y), []).append(robot) def remove(self, x, y, robot): self.robots[(x, y)].remove(robot)
class SudokuUI(Frame): """ The Tkinter UI, responsible for drawing the board and accepting user input.UI is User Interface Frame is defined as a “rectangular region on the screen”. This is essentially just a widget of our puzzle """ def __init__(self, parent, game): self.game = game Frame.__init__(self, parent) self.parent = parent self.row, self.col = -1, -1 self.__initUI() def __initUI(self): ''' This private method of the SudokuUI class is the logic that sets up the actual user interface. ''' self.parent.title("Deez Nutz") self.pack(fill=BOTH) '''Next is the canvas attribute. canvas is a general-purpose widget that we will use to display our board. We will use the earlier-defined global variables''' self.canvas = Canvas(self, width=WIDTH, height=HEIGHT) self.canvas.pack(fill=BOTH, side=TOP) clear_button = Button(self, text="Clear answers", command=self.__clear_answers) clear_button.pack(fill=BOTH, side=BOTTOM) self.__draw_grid() self.__draw_puzzle() '''So here, when the user clicks on the puzzle with a single left-click of the mouse, our UI will call __cell_clicked function, which we will define in a bit. The bind method will actually pass in the x and y location of the cursor, which in __cell_clicked we will turn into actual cells of the puzzle.''' self.canvas.bind("<Button-1>", self.__cell_clicked) self.canvas.bind("<Key>", self.__key_pressed) def __draw_grid(self): """ Draws grid divided with blue lines into 3x3 squares """ for i in range(10): color = "blue" if i % 3 == 0 else "gray" #creates column x0 = MARGIN + i * SIDE y0 = MARGIN x1 = MARGIN + i * SIDE y1 = HEIGHT - MARGIN self.canvas.create_line(x0, y0, x1, y1, fill=color) #creates row x0 = MARGIN y0 = MARGIN + i * SIDE x1 = WIDTH - MARGIN y1 = MARGIN + i * SIDE self.canvas.create_line(x0, y0, x1, y1, fill=color) '''The __draw_puzzle private method then draws the puzzle by filling in the cells with the pre-filled numbers defined in whatever .sudoku board we pass in. We first call delete on the canvas to clear out any previous numbers. This is helpful for when the user wants to clear out the puzzle and start over. We then iterate over rows and columns, and create a cell. We then grab the same X & Y location of the cell from the game’s puzzle. If it isn’t zero, then fill it in with the appropriate number, otherwise just leave it blank.''' def __draw_puzzle(self): self.canvas.delete("numbers") for i in range(9): for j in range(9): answer = self.game.puzzle[i][j] if answer != 0: x = MARGIN + j * SIDE + SIDE / 2 y = MARGIN + i * SIDE + SIDE / 2 original = self.game.start_puzzle[i][j] color = "black" if answer == original else "sea green" self.canvas.create_text(x, y, text=answer, tags="numbers", fill=color) def __draw_cursor(self): self.canvas.delete("cursor") if self.row >= 0 and self.col >= 0: x0 = MARGIN + self.col * SIDE + 1 y0 = MARGIN + self.row * SIDE + 1 x1 = MARGIN + (self.col + 1) * SIDE - 1 y1 = MARGIN + (self.row + 1) * SIDE - 1 self.canvas.create_rectangle(x0, y0, x1, y1, outline="red", tags="cursor") def __draw_victory(self): # create a oval (which will be a circle) x0 = y0 = MARGIN + SIDE * 2 x1 = y1 = MARGIN + SIDE * 7 self.canvas.create_oval(x0, y0, x1, y1, tags="victory", fill="dark orange", outline="orange") # create text x = y = MARGIN + 4 * SIDE + SIDE / 2 self.canvas.create_text(x, y, text="You win!", tags="victory", fill="white", font=("Arial", 32)) def __cell_clicked(self, event): if self.game.game_over: return x, y = event.x, event.y if (MARGIN < x < WIDTH - MARGIN and MARGIN < y < HEIGHT - MARGIN): self.canvas.focus_set() # get row and col numbers from x,y coordinates row, col = (y - MARGIN) / SIDE, (x - MARGIN) / SIDE # if cell was selected already - deselect it if (row, col) == (self.row, self.col): self.row, self.col = -1, -1 elif self.game.puzzle[int(row)][int(col)] == int(0): self.row, self.col = int(row), int(col) else: self.row, self.col = -1, -1 self.__draw_cursor() def __key_pressed(self, event): if self.game.game_over: return if self.row >= 0 and self.col >= 0 and event.char in "1234567890": self.game.puzzle[int(self.row)][int(self.col)] = int(event.char) self.col, self.row = -1, -1 self.__draw_puzzle() self.__draw_cursor() if self.game.check_win(): self.__draw_victory() def __clear_answers(self): self.game.start() self.canvas.delete("victory") self.__draw_puzzle()
class GraphView(View): WIN_PADDING_Y = 16 POINT_MARGIN = 2 def __init__(self, params): super(GraphView, self).__init__(params) self._ids = params["ids"] if "ids" in params else "" self._ids = [int(i) for i in self._ids.split(' ')] self._labels = params["labels"] if "labels" in params else "" self._labels = [l for l in self._labels.split(' ')] self._colors = [c for c in params["colors"].split(' ')] if "colors" in \ params else None if not self._colors: self._colors = self._get_auto_colors(len(self._ids)) if not len(self._ids) == len(self._labels) == len(self._colors): raise RuntimeError("ids, labels and colors must share the same size") self._min = float(params["min"]) if "min" in params else -1000 self._max = float(params["max"]) if "max" in params else 1000 if self._min > self._max: self._min, self._max = self._max, self._min self._diff = abs(self._max - self._min) self._data = [_GraphData() for _ in range(len(self._ids))] self._data_view = [_GraphDataView(self._colors[i]) for i in range( len(self._ids))] self._graph_x = 0 self._tk = Tk() self._tk.title("Graph view %s" % str(self._labels)) self._canvas = Canvas(self._tk, width = 640, height = 480) self._canvas.pack(fill = tkinter.BOTH, expand = 1) self._tk.update() self._win_size = self._tk.winfo_width(), self._tk.winfo_height() # graph_rect only works as providing the area but not coord self._graph_rect = self._win_size self._tk.minsize(320, 240) self._tk.protocol("WM_DELETE_WINDOW", self.on_press_close) self._tk.bind("<Configure>", self.on_config) self._canvas.config(background = config.COL_GREY_900) self._full_redraw() self._file = open("graph_%s_%i.csv" % (str(self._labels), int(time.time() * 1000)), "w") self._file.write(','.join(self._labels) + '\n') self._tk.after(16, self._refresh) def run(self): super(GraphView, self).run() self._tk.mainloop() def on_new_input(self): try: hex_data = binascii.unhexlify(self.get_input()) except TypeError as e: logging.debug(str(e)) return count = int(len(hex_data) / GraphView._MSG_SIZE) for i in (x * 6 for x in range(count)): if hex_data[i] in self._ids: value_type = hex_data[i + 1] value_bytes = hex_data[i + 2:i + 6] if value_type == GraphView._MSG_TYPE_INT: value = int.from_bytes(value_bytes, byteorder = "big", signed = True) elif value_type == GraphView._MSG_TYPE_FLOAT: value = struct.unpack(">f", value_bytes)[0] else: logging.error("Unknown type: " + str(value_type)) continue self._tk.after_idle(self._put_value, hex_data[i], value) def on_dismiss(self): self._tk.after_idle(self.on_press_close) def on_press_close(self): self._tk.destroy() self.join_io_thread() def on_config(self, event): win_size = (event.width, event.height) if win_size != self._win_size: self._win_size = win_size self._full_redraw() def is_test_input(self): return False def gen_test_input(self): while True: for i in range(int(self._min), int(self._max)): sleep(0.1) yield "0000%08x" % (random.randrange(-100, 100) & 0xFFFFFFFF) \ + "0100%08x\n" % (i & 0xFFFFFFFF) def _put_value(self, id, value): pos = self._ids.index(id) if self._data[pos].size() == 0: for d in self._data: d.append() elif self._data[pos].get_value(-1) is not None: for d in self._data: d.append() if self._data[pos].size() > 1: self._write_prev_records() self._data[pos].put_value(value) graph_w = self._win_size[0] - self._graph_x; count = int(graph_w / GraphView.POINT_MARGIN + 1) for d in self._data: d.shrink(count) def _write_prev_records(self): write = ','.join((str(d.get_value(-2)) for d in self._data)) + '\n' self._file.write(write) self._file.flush() def _refresh(self): self._redraw_graph() self._tk.after(16, self._refresh) def _full_redraw(self): self._canvas.delete("all") bounding_box = self._redraw_data_labels() self._graph_rect = 0, 0, self._win_size[0], bounding_box[1] self._redraw_y_labels() for v in self._data_view: v.clear_lines(); self._redraw_graph() def _redraw_data_labels(self): top = self._win_size[1] x = GraphView._DATA_LABEL_PADDING for l, c in zip(self._labels, self._colors): t = self._canvas.create_text(x, self._win_size[1] - GraphView._DATA_LABEL_PADDING, anchor = tkinter.SW, fill = c, font = config.FONT, text = '-' + l) bounding_box = self._canvas.bbox(t) top = min(top, bounding_box[1]) x = bounding_box[2] + GraphView._DATA_LABEL_PADDING return 0, top, x, self._win_size[1] def _redraw_y_labels(self): height = self._graph_rect[3] - self._graph_rect[1] \ - GraphView.WIN_PADDING_Y * 2 count = max(int(height / 50), 2) labels = [] max_label_size = 0 longest_label = None longest_label_i = None for i in range(count): ratio = i / (count - 1) value = self._max - self._diff * ratio value_label = ("%.2f" % value) if value % 1 != 0 else str(value) labels.append(value_label) if len(value_label) > max_label_size: max_label_size = len(value_label) longest_label = value_label longest_label_i = i label_id = self._canvas.create_text(0, height * (longest_label_i \ / (count - 1)) + GraphView.WIN_PADDING_Y, anchor = tkinter.W, fill = config.COL_GREY_100, font = config.FONT, text = longest_label) bounding_box = self._canvas.bbox(label_id) width = bounding_box[2] - bounding_box[0] self._graph_x = width + GraphView.POINT_MARGIN for i in range(count): ratio = i / (count - 1) y = height * ratio + GraphView.WIN_PADDING_Y if i != longest_label_i: self._canvas.create_text(width, y, anchor = tkinter.E, fill = config.COL_GREY_100, font = config.FONT, text = labels[i]) self._canvas.create_line(self._graph_x, y, self._graph_rect[2], y, fill = config.COL_GREY_700) def _redraw_graph(self): graph_h = self._graph_rect[3] - GraphView.WIN_PADDING_Y * 2 for d, v in zip(self._data, self._data_view): v.populate(d.get_values(), self._max, self._diff, self._graph_x, graph_h) v.draw(self._canvas) def _get_auto_colors(self, size) -> list: product = GraphView._COLOR_REPO[:min(size, len(GraphView._COLOR_REPO))] while len(product) < size: product.append("#%06x" % random.randrange(0xFFFFFF)) return product _LABEL_SIZE = 10 _DATA_LABEL_PADDING = 8 _MSG_SIZE = 6 _MSG_TYPE_INT = 0 _MSG_TYPE_FLOAT = 1 _COLOR_REPO = ["#F44336", "#4CAF50", "#2196F3", "#FFEB3B", "#607D8B", "#9C27B0", "#009688", "#673AB7", "#795548"]
class Main(Frame): REMOTE_UPDATE_URL = "http://www.aiquimist.com/update/parameters.json" data = None shouldUpdate = False snapshot_dir = "snapshots" canvas = None capture = None photo = None delay = 15 def __init__(self, parent=None): super().__init__(parent) self.pack(side=LEFT, fill=BOTH, expand=True) self.columnconfigure(0, weight=1) self.rowconfigure(1, weight=1) self.bind("<configure>", self.on_window_resize()) self.master.protocol("WM_DELETE_WINDOW", self.on_window_close) style = AppStyle() # Read application settings. self.data = read_settings() # Top frame styles. style.configure("TOP.TFrame") # Bottom frame styles. style.configure("BOT.TFrame") # Button styles. style.configure("TOP.TMenubutton", padding=13) top_frame = Frame(self, padding=10, style="TOP.TFrame") top_frame.grid(row=0, column=0, sticky="ew") top_frame.columnconfigure(0, weight=1) top_frame.columnconfigure(7, weight=1) cams_list = self.get_cams_list() self.selected_camera_var = StringVar() self.selected_camera_var.trace('w', self.on_camera_option_select) self.cameras_option = OptionMenu(top_frame, self.selected_camera_var, None, *cams_list, command=self.on_camera_option_select, style="TOP.TMenubutton") self.cameras_option.grid(row=0, column=1, padx=[0, 10]) self._biometry_image = PhotoImage(file="resources/biometrical.gif") biometry_button = Button(top_frame, image=self._biometry_image, compound=LEFT, text="Recognize", command=self.on_recognize_button_click) biometry_button.grid(row=0, column=2, padx=[0, 10]) self._open_image = PhotoImage(file="resources/folder_open.gif") open_button = Button(top_frame, image=self._open_image, compound=LEFT, text="Open", command=self.on_open_button_click) open_button.grid(row=0, column=3, padx=[0, 10]) self._config_image = PhotoImage(file="resources/config.gif") config_button = Button(top_frame, image=self._config_image, compound=LEFT, text="Config", command=self.on_config_button_click) config_button.grid(row=0, column=4, padx=[0, 10]) self._update_image = PhotoImage(file="resources/download.gif") update_button = Button(top_frame, image=self._update_image, compound=LEFT, text="Update", command=self.on_update_button_click) update_button.grid(row=0, column=5, padx=[0, 10]) self._close_image = PhotoImage(file="resources/close.gif") close_button = Button(top_frame, image=self._close_image, compound=LEFT, text="Close", command=self.on_window_close) close_button.grid(row=0, column=6, padx=[0, 10]) bottom_frame = Frame(self, padding=10, style="BOT.TFrame", relief=SUNKEN) bottom_frame.grid(row=1, column=0, padx=10, pady=[0, 10], sticky="nsew") self.canvas = Canvas(bottom_frame, bg="black") self.canvas.pack(fill=BOTH, expand=True) # Set the default camera. self.selected_camera_var.set(cams_list[0]) def get_cams_list(self): cams = [] # Load cameras section for cam in self.data["cameras"]: cams.append(cam) # Return the sorted list return sorted(cams) def on_window_close(self): self.shouldUpdate = False self.master.quit() def on_window_resize(self): if self.canvas is not None: self.canvas.configure(relx=0.5, rely=0.5, anchor=CENTER) def on_camera_option_select(self, *args): # Delete the existing capture object. if self.capture is not None: del self.capture source = self.data["cameras"][self.selected_camera_var.get()] self.init_video(source) def init_video(self, source): # Convert source to integer if numeric. if source.isnumeric(): source = int(source) try: self.capture = VideoCapture(video_source=source, snapshot_dir=self.snapshot_dir) except ValueError as e: msg = "Couldn't open the stream: {0}".format(str(e)) logging.critical(msg) messagebox.showerror("Error Opening Stream", msg) self.canvas.delete("all") return self.shouldUpdate = True while self.shouldUpdate: self.master.after(self.delay, self.update_canvas()) def update_canvas(self): if self.capture is not None: # Force update values. self.canvas.update() can_width = self.canvas.winfo_width() can_height = self.canvas.winfo_height() # Get a frame from the video source. try: ret, frame = self.capture.get_frame(can_width, can_height) if ret: self.photo = PhotoImage(image=fromarray(frame)) self.canvas.create_image(can_width / 2, can_height / 2, image=self.photo) except Exception as e: self.shouldUpdate = False def on_recognize_button_click(self): ret = self.capture.take_snapshot() if ret: messagebox.showinfo("Image Capture", "Snapshot saved!") else: messagebox.showerror("Image Capture", "Failed to save snapshot.") def on_open_button_click(self): open_file(self.snapshot_dir) def on_config_button_click(self): child = Toplevel(self) child.title("Config") child.geometry("400x235") center_window(child) child.transient(self) child.resizable(False, False) child.grab_set() Config(child) self.wait_window(child) # Read the new settings. self.data = read_settings() def on_update_button_click(self): try: opener = URLopener() opener.retrieve(self.REMOTE_UPDATE_URL, "resources/parameters.json") # Read the new settings. self.data = read_settings() messagebox.showinfo( "Settings Update", "Settings successfully updated from the server.") except Exception as e: logging.critical( "Couldn't open the remote settings file: {0}".format(str(e))) messagebox.showerror("Couldn't Update Settings", "Couldn't open the remote settings file.")
def Graph(canvas: Canvas): def CheckTable(): memory = GetMemoryField('table') for y in range(0, 5): for x in range(0, 14): if memory[y][x] == '': return False return True canvas.delete('all') SetPage(6) canvas.create_text(960, 50, text='График', font='JetBrainsMono 40') # Подсказка про выход в меню canvas.create_text(960, 1055, text='Для выхода в меню нажмите Esc', font='JetBrainsMono 15') Memory = GetMemoryField('table') Errors = GetMemoryField('error') canvas.create_line(150, 980, 150, 150, width=3, arrow='last') canvas.create_line(149, 980, 1920 - 150, 980, width=3, arrow='last') canvas.create_text(150, 120, text='S, см', font='JetBrainsMono 20') canvas.create_text(1835, 980, text='α, ⁰', font='JetBrainsMono 20') x = 150 for a in range(0, 90, 15): canvas.create_oval(x - 3, 980 - 3, x + 3, 980 + 3, fill='black') canvas.create_text(x, 995, text=f'{a}', font='JetBrainsMono 15') x += 300 if CheckTable(): def parabola(): for i in Memory: if not (float(i[13]) - float(i[11]) > float(i[10])) and (float(i[13]) + float(i[11]) < float(i[10])): return False return True x = 450 for a in range(5): y = (750 / float(Memory[2][13])) * float(Memory[a][13]) canvas.create_oval(x - 3, 980 - y - 3, x + 3, 980 - y + 3, fill='black') canvas.create_text(120, 980 - y, text=f'{Memory[a][13]}', font='JetBrainsMono 15') canvas.create_oval(150 - 3, 980 - y - 3, 150 + 3, 980 - y + 3, fill='black') x += 300 y = (750 / float(Memory[2][13])) * float(Memory[1][13]) x1, y1 = 750, 980 - y x2, y2 = 1050, 980 - 750 x3, y3 = 1350, 980 - y a = (y3 - (x3 * (y2 - y1) + x2 * y1 - x1 * y2) / (x2 - x1)) / (x3 * (x3 - x1 - x2) + x1 * x2) b = (y2 - y1) / (x2 - x1) - a * (x1 + x2) c = (x2 * y1 - x1 * y2) / (x2 - x1) + a * x1 * x2 for x in range(150, 1920 - 150 + 1): y = a * x ** 2 + b * x + c if y <= 980: canvas.create_oval(x - 1, y - 1, x + 1, y + 1) if not parabola(): canvas.create_text(960, 700, text='Значения не попадают на 1 кривую!', font='JetBrainsMono 40') else: canvas.create_text(960, 540, text='Заполните все поля таблиц!', font='JetBrainsMono 60')
class CanvasWrapper: """ 该类是画布的wrapper类,包含画布组件的操作,并且保存了当前画布上的数据 """ doodle_id = 1 analyze_service = AnalyzeServiceIMP() def __init__(self, master): self.side_info = None self.c = Canvas(master, width=700, height=500, cursor='pencil', relief='groove', bd=5) self.c.pack() self.prev = None self.doodles = [] self.lines = [] self.segments = [] def set_side_info(self, s): self.side_info = s def handle_mouse_click(self, e): self.lines.append(copy.deepcopy(self.segments)) self.segments = [] self.prev = e @staticmethod def distance_between(a,b): return ((a.x-b.x)**2+(a.y-b.y)**2)**.5 def handle_mouse_move(self, e): if self.distance_between(e,self.prev) > 5: self.c.create_line(self.prev.x, self.prev.y, e.x, e.y, width=2, tags='doodle'+str(self.doodle_id)) self.segments.append(e.x) self.segments.append(e.y) self.prev = e def start_paint(self): """ 开始记录画笔的轨迹 :return: """ self.c.bind('<Button-1>', self.handle_mouse_click) self.c.bind('<B1-Motion>', self.handle_mouse_move) self.lines = [] self.segments = [] pass def finish_paint(self): """ 结束一次涂鸦,将记录的轨迹用于生成一个Doodle类对象,并进行形状分析 :return: """ self.c.unbind('<Button-1>') self.c.unbind('<B1-Motion>') d = Doodle(self.doodle_id) self.doodle_id = self.doodle_id+1 self.lines.append(copy.deepcopy(self.segments)) d.lines = copy.deepcopy(self.lines) d.shape = self.analyze_service.analyze_shape(d) self.c.create_text(self.lines[-1][-2],self.lines[-1][-1], text=str(d.shape),tags='doodle'+str(d.id)) self.doodles.append(d) self.side_info.insert(END, str(d.id)+'-'+str(d.shape)) pass def set_tag(self, did=0, tag=''): for doodle in self.doodles: if doodle.id == int(did): doodle.tag = tag def get_tag(self, did=0, tag=''): for doodle in self.doodles: if doodle.id == int(did): return doodle.tag return '' def set_doodles(self, doodles): """ 读取Doodle类的信息重新绘制到画布上 :param doodles: :return: """ self.c.delete('all') self.side_info.delete_all() self.doodles = copy.deepcopy(doodles) self.doodle_id = doodles[-1].id+1 for doodle in self.doodles: for line in doodle.lines: if len(line) >= 4: prev_x = line[0] prev_y = line[1] i = 2 while i < len(line): self.c.create_line(prev_x,prev_y,line[i],line[i+1], width=2, tags='doodle'+str(doodle.id)) prev_x = line[i] prev_y = line[i+1] i += 2 self.side_info.insert(END, str(doodle.id) + '-' + str(doodle.shape)) self.c.create_text(doodle.lines[-1][-2],doodle.lines[-1][-1],text=str(doodle.shape),tags='doodle'+str(doodle.id)) def highlight(self, tag): """ 对选中的涂鸦设置高亮显示 :param tag: :return: """ for i in range(1, self.doodle_id+1): if str(i) == tag: self.c.itemconfigure('doodle'+str(i), fill='blue') else: self.c.itemconfigure('doodle'+str(i), fill='black') def remove_doodle(self, did): self.c.delete('doodle'+str(did)) for doodle in self.doodles: if doodle.id == did: self.doodles.remove(doodle) break
class gfxView(): def __init__(self, tk, model): tk.title('Lidar. IP: {}. Port: {}'.format(model.ip, model.port)) tk.geometry('800x600+10+10') self.canvas = Canvas(tk) self.canvas.pack(fill=BOTH, expand=1) self.model = model # view the window at the start def view_first(self): self.prepare_view() self.rec(*self.frame, fill='white', outline='') self.draw_frame() for zone, color in self.model.detect_zones: self.rec_zone(zone, fill=color) self.draw_grid() # view result of a scan def view_scan(self): self.prepare_view() self.draw_bg() self.draw_zones() self.draw_grid() self.draw_frame() self.draw_data() def prepare_view(self): # get canvas size H = self.canvas.winfo_height() W = self.canvas.winfo_width() # margin self.M = self.model.margin # spagetti sauce H -= self.M # radius if 2 * H > W: self.R = W / 2 else: self.R = H # center of sensor view self.x0 = self.R self.y0 = self.R self.center = (self.x0, self.y0) # frame of sensor view self.frame = (self.M, self.M, 2 * self.R - self.M, self.R) # scale_factor self.scale = (self.R - self.M) / self.model.max # clear canvas self.canvas.delete('all') # draw the background def draw_bg(self): self.rec(*self.frame, fill='white', outline='') self.draw_cone(*self.model.angle, self.model.min) # draw the detecting zone def draw_zones(self): for zone, color in self.model.zones: self.rec_zone(zone, fill=color) # draw the data points def draw_data(self): for value, phi in self.model.data: # scale value to graph v = value * self.scale x, y = self.pol2car(v, phi) if in_rec(x, y, *self.frame): self.point(x, y, outline='', fill='blue') # draw the frame of the sensor view def draw_frame(self): self.rec(*self.frame) sr = self.model.sensor_size * self.scale if sr < 1: sr = 1 self.cir(*self.center, sr, fill='blue') # draw sensor's cone of view def draw_cone(self, a0, a1, min): x0, y0, x1, _ = self.frame xp0, yp0, p0 = self.angle_intersect(a0) xp1, yp1, p1 = self.angle_intersect(a1) poly = list() poly.extend(self.center) poly.extend((xp0, yp0)) if in_range(x1, p1, p0): poly.extend((x1, y0)) if in_range(x0, p1, p0): poly.extend((x0, y0)) poly.extend((xp1, yp1)) self.canvas.create_polygon(*poly, fill=self.model.detect_color) self.arc(min * self.scale, a0, a1, style=PIESLICE, fill='white', outline='') # draw grid on the sensor view def draw_grid(self): for i in range(0, self.model.max, self.model.grid): r_i = (i + self.model.grid) * self.scale l_i = (i + self.model.grid) * 1e-3 self.canvas.create_text(self.R + r_i, self.R + 20, text=str(l_i)) self.canvas.create_text(self.R - r_i, self.R + 20, text=str(l_i)) self.arc(r_i, 0, 180, style=ARC) # check intersect of a line from the center to the edge of the sensor view def angle_intersect(self, a): x0, y0, x1, y1 = self.frame t = tan(deg2rad(a)) xcen = (x1 + x0) / 2 xlen = (x1 - x0) / 2 x = xcen * (1 + 1 / t) if x < x0: return x0, y1 + xlen * t, x if x > x1: return x1, y1 - xlen * t, x return x, y0, x # draw rectangle of detection zone def rec_zone(self, zone, *args, **kwargs): x0, y0, x1, y1 = zone nx0 = self.R + x0 * self.scale nx1 = self.R + x1 * self.scale ny0 = self.R - y0 * self.scale ny1 = self.R - y1 * self.scale self.rec(nx0, ny0, nx1, ny1, *args, **kwargs) # draw line def line(self, x0, y0, x1, y1, *args, **kwargs): self.canvas.create_line(x0, y0, x1, y1, *args, **kwargs) # draw point def point(self, x, y, *args, **kwargs): self.cir(x, y, 2, *args, **kwargs) # draw circle def cir(self, x, y, r, *args, **kwargs): self.canvas.create_oval(cen2rec(x, y, r), *args, **kwargs) # draw arc def arc(self, r, start_angle, end_angle, *args, **kwargs): phi = end_angle d_phi = start_angle - end_angle self.canvas.create_arc(cen2rec(self.x0, self.y0, r), start=phi, extent=d_phi, *args, **kwargs) def rec(self, x0, y0, x1, y1, *args, **kwargs): self.canvas.create_rectangle(x0, y0, x1, y1, *args, **kwargs) # convert from polar to cartesian coordinate def pol2car(self, r, angle): phi = deg2rad(angle) return self.x0 + r * cos(phi), self.y0 - r * sin(phi)
class ShipPlacementPanel(Frame): '''A frame which contains visualizations for placing ships.''' # the size of a single tile SHIP_TILE_SIZE = 20 SHIP_TILE_COLOR = "steel blue" TAG = "staging_ship" CANVAS_WIDTH = 150 def __init__(self, master): '''Create a new panel with the given parent.''' Frame.__init__(self, master) self._ship_name = StringVar() self._create_ui() self.reset() def reset(self): '''Alias for unstage_all''' self.unstage_all() def _create_ui(self): '''Create all UI objects.''' #self._tl = Label(self, text="Staged Ship", f) self._sl = Label(self, textvariable=self._ship_name) self._c = Canvas(self) self._c.config(width=self.CANVAS_WIDTH) self._rb = Button(self, text="Rotate", command=self.rotate_current_ship) self.pack_ui() def pack_ui(self): '''(re) pack the UI. Created mostly to counter hiding by unpacking.''' #self._tl.pack() #self._tl.grid(row=0) self._sl.pack() self._sl.grid(row=1, pady=10) self._c.pack() self._c.grid(row=2, pady=15) self._rb.pack() self._rb.grid(row=3) def unstage_all(self): '''Remove all ships from staging area. Clear all staging preferences.''' self._staged_ship = None self._clear_staging_grid() self._ship_name.set("") self._disable_rotate_button() def _clear_staging_grid(self): '''Remove previously staged ships from staging grid.''' for item in self._c.find_withtag(self.TAG): self._c.delete(item) def _draw_staged_ship(self): '''Draw the currently staged ship.''' # remove prior drawings self._clear_staging_grid() if self._staged_ship.is_vertical(): x = 0 x_pad = (self._c.winfo_width() - self.SHIP_TILE_SIZE) / 2.0 y_pad = (self._c.winfo_height() - self.SHIP_TILE_SIZE * self._staged_ship.get_size()) / 2.0 for y in range(self._staged_ship.get_size()): self._draw_ship_tile(x_pad + x * self.SHIP_TILE_SIZE, y_pad + y * self.SHIP_TILE_SIZE) else: y = 0 x_pad = (self._c.winfo_width() - self.SHIP_TILE_SIZE * self._staged_ship.get_size()) / 2.0 y_pad = (self._c.winfo_height() - self.SHIP_TILE_SIZE) / 2.0 for x in range(self._staged_ship.get_size()): self._draw_ship_tile(x_pad + x * self.SHIP_TILE_SIZE, y_pad + y * self.SHIP_TILE_SIZE) def add_ship(self, s): '''Alias for stage ship.''' self.stage_ship(s) def _disable_rotate_button(self): '''Disable / hide the rotate button.''' self._rb.grid_forget() def _enable_rotate_button(self): '''Enable / show the rotate button.''' self._rb.grid(row=3) def stage_ship(self, s): '''Add a ship to the staging area. Display what it would look like on the grid. Create support for accidentally adding ship that isn't ready''' if s is not None: self._staged_ship = s self._ship_name.set(s.get_full_name().title()) self._draw_staged_ship() self._enable_rotate_button() else: self._disable_rotate_button() def _draw_ship_tile(self, x, y): '''Draw a single tile for the ship at given coordinates.''' self._c.create_rectangle(x, y, x + self.SHIP_TILE_SIZE, y + self.SHIP_TILE_SIZE, fill=self.SHIP_TILE_COLOR, outline="black", tag=self.TAG) def get_staged_ship(self): '''Return the currently staged ship.''' return self._staged_ship def rotate_current_ship(self): '''Rotate the currently staged ship.''' if self._staged_ship is not None: self._staged_ship.rotate() self._draw_staged_ship()
class GUI: def __init__(self, pointset): self.master = Tk() self.master.title('D7013E Lab 1') self.pointset = pointset self.label = Label(self.master, text='Algorithm 1') self.label.pack() self.canvas = Canvas(self.master, width=500, height=500) self.canvas.pack() self.random_button = Button(self.master, text='Random', command=self.random) self.random_button.pack() self.load_button = Button(self.master, text='Load', command=self.load) self.load_button.pack() self.compute_button = Button(self.master, text='Compute', command=self.compute) self.compute_button.pack() self.close_button = Button(self.master, text='Close', command=self.master.quit) self.close_button.pack() def _add_point(self, point: Point): self.canvas.create_oval(point.x, point.y, point.x, point.y, fill='#000000', width=10) def _add_segment(self, segment: Segment): self.canvas.create_line(segment.p1.x, segment.p1.y, segment.p2.x, segment.p2.y) def random(self): self.clear() self.pointset.random_points(NUM_POINTS) self.draw() def clear(self): self.pointset.clear() self.canvas.delete(ALL) def draw(self): for p in self.pointset.points: self._add_point(p) for s in self.pointset.segments: self._add_segment(s) def load(self): file = filedialog.askopenfilename(initialdir=os.getcwd(), title="Select file") self.clear() self.pointset.load(file) self.draw() def compute(self): self.pointset.run_algorithm() self.draw() def mainloop(self): self.master.mainloop()
class Scene(object): def __init__(self, master, device, mouse_tracking=False): self.master = master self.device = device self.frame = tk.Frame(master) self.feedbackButton = tk.Button( self.frame, text="Feedback window", width=25, command=self.open_feedback ) self.feedbackButton.pack() self.explore_canvas = Canvas(master, width=500, height=500) self.explore_canvas.pack() if mouse_tracking: self.explore_canvas.bind( '<Motion>', lambda event, device=device: motion(event, device)) self.enable_position_feedback() self.network_drawings = [] self.frame.pack() self.app = None self.update() def activate_key_listening(self, listener): # Will focus frame, needed for key binding self.explore_canvas.bind( "<Button-1>", lambda event, frame=self.explore_canvas: focus(event, frame) ) self.explore_canvas.bind( "<Key>", lambda event: listener.update_pressed_key(str(event.char)) ) def desactivate_key_listening(self): self.explore_canvas.unbind("<Button-1>") self.explore_canvas.unbind("<Key>") def enable_position_feedback(self): self.device_cursor = self.explore_canvas.create_oval( self.device.position.x - 2.5, self.device.position.y - 2.5, self.device.position.x + 2.5, self.device.position.y + 2.5) def draw_network(self, network): self.explore_canvas.delete('all') self.enable_position_feedback() for node in network.nodes: pos_x = node.x - 5 pos_y = node.y - 5 self.explore_canvas.create_oval( pos_x, pos_y, pos_x + 10, pos_y + 10, fill="blue") for link in network.links: pt_a = link.first pt_b = link.sec self.explore_canvas.create_line( pt_a.x, pt_a.y, pt_b.x, pt_b.y) def update(self): coords = self.explore_canvas.coords(self.device_cursor) if len(coords) <= 3: self.master.after(50, self.update) return center = ((coords[0] + coords[2]) / 2, (coords[1] + coords[3]) / 2) self.explore_canvas.move( self.device_cursor, self.device.position.x - center[0], self.device.position.y - center[1]) if self.app and not self.app.closed: self.app.update() self.master.after(50, self.update) def open_feedback(self): self.feedbackWindow = tk.Toplevel(self.master) self.app = Feedback(self.feedbackWindow, self.device)
class Window: def __init__(self, root, width, height, points_per_line): self.width = width self.height = height self.canvas = Canvas(root, width=width, height=height) self.canvas.pack() self.canvas.canvas = self.canvas self.canvas.data = {} self.points_per_line = points_per_line self.alive_squares = dict() self._draw_grid() def _draw_grid(self): for begin, end in self._horizontal_line_coordinates: self.canvas.create_line(begin.x, begin.y, end.x, end.y) for begin, end in self._vertical_line_coordinates: self.canvas.create_line(begin.x, begin.y, end.x, end.y) @property def _horizontal_line_coordinates(self): y = 0 while y < self.height: y = y + self.height / self.points_per_line begin = Point(0, y) end = Point(self.width, y) yield begin, end @property def _vertical_line_coordinates(self): x = 0 while x <= self.width: begin = Point(x, 0) end = Point(x, self.height) yield begin, end x = x + self.width / self.points_per_line def draw_dead(self, x, y): try: rectangle = self.alive_squares[(x, y)] self.canvas.delete(rectangle) del self.alive_squares[(x, y)] except KeyError: pass def draw_alive(self, x, y): if (x, y) in self.alive_squares: return left_corner = Point(x * self.width / self.points_per_line, y * self.height / self.points_per_line) right_corner = Point((x + 1) * self.width / self.points_per_line, (y + 1) * self.height / self.points_per_line) rectangle = self.canvas.create_rectangle(left_corner.x, left_corner.y, right_corner.x, right_corner.y, fill="green") self.alive_squares[(x, y)] = rectangle
class GameScreen: def __init__(self, master, params, model=None): self.master = master self.controller = GameScreenController(params, model=model) self.width = self.controller.model.width self.height = self.controller.model.height self.graphic_init() self.is_run = True self.run() def draw(self): # Сделать 4 солнца model = self.controller.model x, y = model.sun_x, model.sun_y suns = [(x, y), (x - self.width, y), (x, y - self.height), (x - self.width, y - self.height)] for x, y in suns: self.canvas.create_rectangle( max(0, x), max(0, y), min(x + model.sun_size, self.width + 1), min(y + model.sun_size, self.height + 1), fill="yellow", ) for coord, creature in model.creatures.items(): color = "#00{:0>2}00".format(hex(int(creature.life * 255))[2:]) if not creature.alive: color = "red" func = self.canvas.create_oval func(coord[0], coord[1], coord[0] + 6, coord[1] + 6, fill=color) def graphic_init(self): self.frame = Frame(self.master, bd=2) self.button_frame = Frame(self.frame, bd=2) self.button_frame.grid_bbox(row=1, column=4) self.start_stop_button = Button(self.button_frame, text="Пауза", command=self.start_stop_pressed) self.start_stop_button.grid(row=1, column=2) self.save_button = Button(self.button_frame, text="Сохранить", command=self.save_pressed) self.save_button.grid(row=1, column=1) self.info_button = Button(self.button_frame, text="Инфо", command=self.info_pressed, state=DISABLED) self.info_button.grid(row=1, column=4) self.add_button = Button(self.button_frame, text="Добавить существо", command=self.add_pressed) self.add_button.grid(row=1, column=3) self.canvas = Canvas(self.frame, width=self.width, height=self.height) self.canvas.pack(side=TOP) self.button_frame.pack() self.frame.pack() def start_stop_pressed(self): self.is_run = not self.is_run self.start_stop_button.config(text="Пауза" if self.is_run else "Старт") self.info_button.config(state=DISABLED if self.is_run else ACTIVE) self.run() def save_pressed(self): filename = asksaveasfilename(title="Сохранить мир") if filename: try: self.controller.save_pressed(filename) except Exception as e: messagebox.showerror("Не удалось сохранить файл", str(e)) def info_pressed(self): InfoWindow(self.controller.model) def add_pressed(self): self.controller.add_pressed() def run(self): if self.is_run: self.canvas.delete("all") self.controller.run() self.draw() self.master.after(1, self.run)
class GUI(Frame): def __init__(self, game, size, margin, colors=('black', 'white'), master=None): color = '#333333' Frame.__init__(self, master, bg=color) self.game = game self.cell_size = (size - 2*margin) / self.game.size self.coordinates = lambda position: self.cell_size * (np.array(position) + 1/2) + margin self.player_move = lambda event: self.move(pause=1000, event=event) self.grid() self.master.title("Pythello") self.colors = colors[::-1] # Flip color order so that the first color input corresponds to player 1 max_turns = self.game.size**2 - 4 figure = Figure(figsize=(size/100, size/100), dpi=100, facecolor=color) axes = figure.add_subplot(111, axisbg=color) self.line = axes.plot(0, 0, 'w-', [0, max_turns], [0, 0], 'w--')[0] axes.grid(True, color='w') axes.set_xlim(0, max_turns) axes.set_ylim(-max_turns, max_turns) [tick.set_color('w') for axis in [axes.xaxis, axes.yaxis] for tick in axis.get_ticklines()] [label.set_color('w') for axis in [axes.xaxis, axes.yaxis] for label in axis.get_ticklabels()] [axes.spines[side].set_color('w') for side in ['top', 'bottom', 'left', 'right']] self.canvas = Canvas(self, width=size, height=size, background=color, highlightthickness=0) self.canvas.create_rectangle(margin, margin, size - margin, size - margin, outline='white') self.canvas.grid(row=0, column=1, rowspan=50) self.figure = FigureCanvasTkAgg(figure, master=self) self.figure.get_tk_widget().grid(row=0, column=2, rowspan=50) self.refresh() if all([isinstance(player, AI) for player in self.game.players]): self.play_button = Button(self, text='Play', highlightbackground=color, command=self.play) self.move_button = Button(self, text='Move', highlightbackground=color, command=self.move) self.reset_button = Button(self, text='Reset', highlightbackground=color, command=self.reset) self.play_button.grid(row=0, column=0) self.move_button.grid(row=1, column=0) self.reset_button.grid(row=2, column=0) self.running = False else: Button(self, text='Reset', highlightbackground=color, command=self.reset).grid(row=0, column=0) self.running = True for i in range(self.game.size): line_shift = self.cell_size * (i+1) + margin self.canvas.create_text(margin-10, line_shift - self.cell_size/2, text=str(i+1), fill='white') self.canvas.create_text(line_shift - self.cell_size/2, margin-10, text=chr(97+i), fill='white') self.canvas.create_line(margin, line_shift, size - margin, line_shift, fill='white') self.canvas.create_line(line_shift, margin, line_shift, size - margin, fill='white') def configure_buttons(self): (state, text, command) = ('disabled', 'Pause', self.pause) if self.running else ('normal', 'Reset', self.reset) self.play_button.config(state=state) self.move_button.config(state=state) self.reset_button.config(text=text, command=command) def draw_piece(self, position, radius, color): (y, x) = self.coordinates(position) return self.canvas.create_oval(x-radius, y-radius, x+radius, y+radius, fill=color, tags='circle') def move(self, pause=10, event=None): if event is None: move = self.game.player.move(self.game) else: move = eval(self.canvas.gettags(event.widget.find_withtag("current"))[-2]) self.game.move(move) is_over = self.game.is_over() self.refresh() if not is_over and isinstance(self.game.player, AI) and self.running: self.after(pause, self.move) elif is_over: self.reset_button.config(text='Reset', command=self.reset) def pause(self): self.running = False self.configure_buttons() def play(self): self.running = True self.configure_buttons() self.move() def refresh(self): self.line.set_data(range(len(self.game.score)), self.game.score) self.figure.draw() [self.canvas.delete(tag) for tag in ['circle', 'text']] for position in zip(*np.nonzero(self.game.board)): color = self.colors[int((self.game.board[position] + 1) / 2)] self.draw_piece(position, (self.cell_size-2) / 2, color) if not isinstance(self.game.player, AI): for position in self.game.valid: (y, x) = self.coordinates(position) turned = len(self.game.valid[position]) - 1 valid = self.draw_piece(position, self.cell_size / 4, 'green') self.canvas.addtag(str(position), 'withtag', valid) text = self.canvas.create_text(x+1, y+1, text=str(turned), tags=('text', str(position))) [self.canvas.tag_bind(tag, "<Button-1>", self.player_move) for tag in [valid, text]] def reset(self): self.running = not all([isinstance(player, AI) for player in self.game.players]) self.game.reset() self.refresh() if not self.running: self.configure_buttons()
class GameUI(Frame): def __init__(self, parent, controller): Frame.__init__(self, parent) self.game = Game() self.row, self.col = 0, 0 self.init_UI() def init_UI(self): self.pack(fill=BOTH, expand=1) self.canvas = Canvas(self, width=WIDTH, height=HEIGHT, highlightthickness=0, relief='ridge', bg='gray10' ) self.canvas.pack(fill=BOTH, side=TOP) Button(self, text='RESTART', height=24, fg='white', bg='gray20', activeforeground='white', activebackground='gray15', border=0, font=('Arial', 12, 'bold'), highlightthickness=0, relief='ridge', command=self.restart ).pack(fill=BOTH, side=BOTTOM) self.draw_grid() self.canvas.bind('<Button-1>', self.play) def restart(self): self.game = Game() self.row, self.col = 0, 0 self.canvas.delete('all') self.draw_grid() def draw_grid(self): for i in range(self.game.width + 1): x0 = MARGIN + i * SIDE y0 = MARGIN x1 = MARGIN + i * SIDE y1 = HEIGHT - MARGIN self.canvas.create_line(x0, y0, x1, y1, fill='gray25') x0 = MARGIN y0 = MARGIN + i * SIDE x1 = HEIGHT - MARGIN y1 = MARGIN + i * SIDE self.canvas.create_line(x0, y0, x1, y1, fill='gray25') self.board = [ [ self.game.get_cell_value(x, y) for x in range(self.game.width + 1) ] for y in range(self.game.height + 1) ] self.load_board(self.board) def load_board(self, board): for y in range(self.game.height + 1): for x in range(self.game.width + 1): player = self.game.get_cell_value(y, x) if player != ' ': self.row, self.col = (self.game.width - 1) - x, y self.draw_player(player) def play(self, event): if self.game.get_winner(): return x, y = event.x, event.y if MARGIN < x < WIDTH - MARGIN and MARGIN < y < HEIGHT - MARGIN: row, col = int((y - MARGIN) / SIDE), int((x - MARGIN) / SIDE) real_x, real_y = col, (self.game.width - 1) - row if self.game.is_cell_free(real_x, real_y): self.row, self.col = row, col player = self.game.get_next_players_turn() self.game.make_move(real_x, real_y, player) self.draw_player(player) winner = self.game.get_winner() if winner: self.draw_victory(winner) def draw_player(self, player): if self.row >= 0 and self.col >=0: x0 = MARGIN + self.col * SIDE + 1 y0 = MARGIN + self.row * SIDE + 1 x1 = MARGIN + (self.col + 1) * SIDE - 1 y1 = MARGIN + (self.row + 1) * SIDE - 1 self.canvas.create_rectangle( x0, y0, x1, y1, fill=self.get_color(player), outline='' ) x = x0 + SIDE / 2 y = y0 + SIDE / 2 self.canvas.create_text( x, y, text=player, fill='white', font=('Arial', 12) ) def draw_victory(self, winner): x0 = y0 = MARGIN + SIDE * 2 x1 = y1 = MARGIN + SIDE * 8 self.canvas.create_oval( x0, y0, x1, y1, fill=self.get_color(winner), outline='' ) x = y = MARGIN + 4 * SIDE + SIDE message = '{} player wins'.format(winner) self.canvas.create_text( x, y, text=message, fill='white', font=('Arial', 28) ) def get_color(self, player): return 'dark slate gray' if player == 'X' else 'sea green'
class ImageViewer(Frame): def __init__(self, master=None): Frame.__init__(self, master=master, bg="gray", width=600, height=400) self.shown_image = None self.x = 0 self.y = 0 self.crop_start_x = 0 self.crop_start_y = 0 self.crop_end_x = 0 self.crop_end_y = 0 self.draw_ids = list() self.rectangle_id = 0 self.ratio = 0 self.colorCode = ((0, 0, 255), 'red') self.canvas = Canvas(self, bg="gray", width=600, height=400) self.canvas.place(relx=0.5, rely=0.5, anchor=CENTER) def show_image(self, img=None): """ Displays the image passed to the function @:param img is the image to be displayed which is defaulted to None """ self.clear_canvas() if img is None: image = self.master.processed_image.copy() else: image = img image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) height, width, channels = image.shape ratio = height / width new_width = width new_height = height if height > self.winfo_height() or width > self.winfo_width(): if ratio < 1: new_width = self.winfo_width() new_height = int(new_width * ratio) else: new_height = self.winfo_height() new_width = int(new_height * (width / height)) self.shown_image = cv2.resize(image, (new_width, new_height)) self.shown_image = ImageTk.PhotoImage(Image.fromarray(self.shown_image)) self.ratio = height / new_height self.canvas.config(width=new_width, height=new_height) self.canvas.create_image(new_width / 2, new_height / 2, anchor=CENTER, image=self.shown_image) def set_color_code(self, color_code): """ Sets the colorCode to the passed value @:param colorCode the new colorCode value """ self.colorCode = color_code def activate_draw(self): """ Activates the draw functionality """ self.canvas.bind("<ButtonPress>", self.start_draw) self.canvas.bind("<B1-Motion>", self.draw) self.master.is_draw_state = True def activate_crop(self): """ Activates the crop functionality """ self.canvas.bind("<ButtonPress>", self.start_crop) self.canvas.bind("<B1-Motion>", self.crop) self.canvas.bind("<ButtonRelease>", self.end_crop) self.master.is_crop_state = True def deactivate_draw(self): """ Deactivates the draw functionality """ self.canvas.unbind("<ButtonPress>") self.canvas.unbind("<B1-Motion>") self.master.is_draw_state = False def deactivate_crop(self): """ Deactivates the crop functionality """ self.canvas.unbind("<ButtonPress>") self.canvas.unbind("<B1-Motion>") self.canvas.unbind("<ButtonRelease>") self.master.is_crop_state = False def start_draw(self, event): """ Begins the draw @:param is the x and y coordinates of the mouse """ self.x = event.x self.y = event.y def draw(self, event): """ Draws on the image @:param is the x and y coordinates of the mouse """ self.draw_ids.append(self.canvas.create_line(self.x, self.y, event.x, event.y, width=2, fill=self.colorCode[1], capstyle=ROUND, smooth=True)) cv2.line(self.master.processed_image, (int(self.x * self.ratio), int(self.y * self.ratio)), (int(event.x * self.ratio), int(event.y * self.ratio)), self.colorCode[0], thickness=int(self.ratio * 2), lineType=8) self.x = event.x self.y = event.y def start_crop(self, event): """ Begins the crop @:param is the x and y coordinates of the mouse """ self.crop_start_x = event.x self.crop_start_y = event.y def crop(self, event): """ Crops the image @:param is the x and y coordinates of the mouse """ if self.rectangle_id: self.canvas.delete(self.rectangle_id) self.crop_end_x = event.x self.crop_end_y = event.y self.rectangle_id = self.canvas.create_rectangle(self.crop_start_x, self.crop_start_y, self.crop_end_x, self.crop_end_y, width=1) def end_crop(self, event): """ Ends the Crop @:param an unused event parameter required due to how the function is called """ if self.crop_start_x <= self.crop_end_x and self.crop_start_y <= self.crop_end_y: start_x = int(self.crop_start_x * self.ratio) start_y = int(self.crop_start_y * self.ratio) end_x = int(self.crop_end_x * self.ratio) end_y = int(self.crop_end_y * self.ratio) elif self.crop_start_x > self.crop_end_x and self.crop_start_y <= self.crop_end_y: start_x = int(self.crop_end_x * self.ratio) start_y = int(self.crop_start_y * self.ratio) end_x = int(self.crop_start_x * self.ratio) end_y = int(self.crop_end_y * self.ratio) elif self.crop_start_x <= self.crop_end_x and self.crop_start_y > self.crop_end_y: start_x = int(self.crop_start_x * self.ratio) start_y = int(self.crop_end_y * self.ratio) end_x = int(self.crop_end_x * self.ratio) end_y = int(self.crop_start_y * self.ratio) else: start_x = int(self.crop_end_x * self.ratio) start_y = int(self.crop_end_y * self.ratio) end_x = int(self.crop_start_x * self.ratio) end_y = int(self.crop_start_y * self.ratio) x = slice(start_x, end_x, 1) y = slice(start_y, end_y, 1) self.master.processed_image = self.master.processed_image[y, x] self.show_image() def clear_canvas(self): """ Clears all edits to the image """ self.canvas.delete("all") def clear_draw(self): """ Clears all drawings done on the image """ self.canvas.delete(self.draw_ids)
class Window(Tk): def __init__(self): # INIT WINDOW Tk.__init__(self) self.geometry("{}x{}+10+10".format(gb.WINDOW_WIDTH, gb.WINDOW_HEIGHT)) self.fond = Canvas(self, width=gb.WINDOW_WIDTH, height=gb.WINDOW_HEIGHT, bg=gb.WINDOW_BG) self.fond.pack() self.real_bg = self.fond.create_rectangle(0, 0, gb.WINDOW_WIDTH, gb.WINDOW_HEIGHT, fill=gb.WINDOW_BG) self.init_input_output() # ATTRIBUTS self.main_gate = New_gate(self, "MAIN") Gate.__init__(self.main_gate, [], []) self.gates = set() self.selected = None self.link = None self.generators = set() self.gate_gen_x = 0 self.max_gate_gen_x = 0 self.node_select = set() self.inout_frame = (0, 0, 0, 0) self.inout_pos = (0, 0) # BINDINGS self.bindings = { "<Control-Key-s>": self.save_conf_name, "<Motion>": self.move, "<ButtonRelease-1>": self.release_clic, "<Button-2>": self.cancel_link, "<Button-1>": GB_INFO, "<MouseWheel>": self.scroll, # for windows "<Button-4>": self.scroll, # for linux "<Button-5>": self.scroll # for linux } self.enable_bindings() # LOAD GATES self.load_below_gates() # MAINLOOP self.after(100, self.clock_update) self.mainloop() ######################### INPUT/OUTPUT ######################### def init_input_output(self): self.input_line = self.fond.create_rectangle(0, gb.INPUT_HEIGHT, gb.WINDOW_WIDTH, gb.INPUT_HEIGHT, width=20, fill="black") self.fond.tag_bind(self.input_line, "<Button-3>", self.input_select) self.fond.tag_bind(self.input_line, "<Button-1>", self.add_single_input) self.output_line = self.fond.create_rectangle( 0, gb.WINDOW_HEIGHT - gb.OUTPUT_HEIGHT, gb.WINDOW_WIDTH, gb.WINDOW_HEIGHT - gb.OUTPUT_HEIGHT, width=20, fill="black") self.fond.tag_bind(self.output_line, "<Button-3>", self.output_select) self.fond.tag_bind(self.output_line, "<Button-1>", self.add_single_output) def order_inputs_outputs(self): self.main_gate.inputs.sort(key=lambda x: x.center[0]) self.main_gate.outputs.sort(key=lambda x: x.center[0]) def clean_select(self): for id in self.node_select: self.fond.delete(id) self.node_select = set() self.inout_pos = (0, 0) self.inout_frame = (0, 0, 0, 0) def load_node_choice(self, x, y, node_type, in_out): table = { "input": { "Single": self.add_single_input, "Count": self.add_count_input, "Clock": self.add_clock_input }, "output": { "Single": self.add_single_output, "Count": self.add_count_output } } node_frame = self.fond.create_rectangle(x, y, x + 60, y + 30) self.node_select.add(node_frame) self.fond.tag_bind(node_frame, "<Button-1>", table[in_out][node_type]) node_text = self.fond.create_text(x + 30, y + 15, text=node_type) self.node_select.add(node_text) self.fond.tag_bind(node_text, "<Button-1>", table[in_out][node_type]) ## _________________ INPUT _____________________ ## def input_select(self, evt): x = min(evt.x, gb.WINDOW_WIDTH - 70) y = evt.y self.inout_pos = (evt.x, evt.y) frame_id = self.fond.create_rectangle(x - 3, y - 3, x + 63, y + 97, fill="lightgray") self.inout_frame = (x - 3, y - 3, x + 63, y + 97) self.node_select.add(frame_id) self.load_node_choice(x, y, "Single", "input") self.load_node_choice(x, y + 32, "Count", "input") self.load_node_choice(x, y + 64, "Clock", "input") def add_single_input(self, evt): if not self.inout_pos[0]: self.inout_pos = (evt.x, evt.y) node = Main_input_node(self.main_gate, self) node.center = (self.inout_pos[0], gb.INPUT_HEIGHT) self.main_gate.inputs += [node] self.draw_node(node) self.fond.tag_bind(node.id, "<Button-2>", node.destroy) self.clean_select() def add_count_input(self, evt): node = Main_input_count_node(self.main_gate, self) node.master_node = node # this is overriden if called from an ext_node node.node_amount = 1 node.next_node = None node.center = (self.inout_pos[0], gb.INPUT_HEIGHT) self.main_gate.inputs += [node] self.draw_node(node) self.fond.tag_bind(node.id, "<Button-2>", node.destroy_count) self.clean_select() return node def add_clock_input(self, evt): node = Clock_node(self.main_gate, self) node.center = (self.inout_pos[0], gb.INPUT_HEIGHT) self.main_gate.inputs += [node] self.draw_node(node) self.fond.tag_bind(node.id, "<Button-2>", node.destroy) self.clean_select() ## _________________ OUTPUT _____________________ ## def output_select(self, evt): x = min(evt.x, gb.WINDOW_WIDTH - 70) y = evt.y self.inout_pos = (evt.x, evt.y) frame_id = self.fond.create_rectangle(x - 3, y - 65, x + 63, y + 3, fill="lightgray") self.inout_frame = (x - 3, y - 65, x + 63, y + 3) self.node_select.add(frame_id) self.load_node_choice(x, y - 62, "Single", "output") self.load_node_choice(x, y - 30, "Count", "output") def add_single_output(self, evt): if not self.inout_pos[0]: self.inout_pos = (evt.x, evt.y) node = Main_output_node(self.main_gate, self) node.center = (self.inout_pos[0], gb.WINDOW_HEIGHT - gb.OUTPUT_HEIGHT) self.main_gate.outputs += [node] self.draw_node(node) self.fond.tag_bind(node.id, "<Button-2>", node.destroy) self.clean_select() def add_count_output(self, evt): node = Main_output_count_node(self.main_gate, self) node.master_node = node # this is overriden if called from an ext_node node.node_amount = 1 node.next_node = None node.center = (self.inout_pos[0], gb.WINDOW_HEIGHT - gb.OUTPUT_HEIGHT) self.main_gate.outputs += [node] self.draw_node(node) self.fond.tag_bind(node.id, "<Button-2>", node.destroy_count) self.clean_select() return node ######################### BINDINGS ######################### def enable_bindings(self): gb.debug("Bindings enabled") for to_bind in self.bindings: self.bind(to_bind, self.bindings[to_bind]) def disable_bindings(self): gb.debug("Bindings disabled") for to_unbind in self.bindings: self.unbind(to_unbind) def save_pressed_key(self, evt): if evt.keycode == 22: self.gate_name = self.gate_name[:-1] elif evt.char.upper() in "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 ": self.gate_name += evt.char.upper() self.fond.itemconfig(self.name_id, text=self.gate_name) ######################### MOVE EVENTS ######################### def cancel_link(self, evt): if self.link: self.link.delete_aff() self.link = None def release_clic(self, evt): self.selected = None def move(self, evt): if self.selected: dx = self.selected.delta_x dy = self.selected.delta_y self.selected.center = (evt.x + dx, evt.y + dy) self.selected.update_nodes_coords() self.update(self.selected) if self.link: # mise à jour de l'affichage du link self.link.points_list[-1] = (evt.x, evt.y) self.update(self.link) if self.inout_frame[0]: if not (self.inout_frame[0] < evt.x < self.inout_frame[2] and self.inout_frame[1] < evt.y < self.inout_frame[3]): self.clean_select() ######################### GATE GENERATOR ######################### def load_below_gates(self): for i, gate_name in enumerate(os.listdir("lib/structs/")): x = i * 110 + 10 + self.gate_gen_x y = 25 generator = Generator(gate_name, self) self.generators.add(generator) generator.id = self.fond.create_rectangle(x, y - 20, x + 100, y + 20, width=2, fill=gb.BOX_BG) generator.name_id = self.fond.create_text(x + 50, y, text=gate_name) self.fond.tag_bind(generator.id, "<Button-1>", generator.create_gate) self.fond.tag_bind(generator.name_id, "<Button-1>", generator.create_gate) self.max_gate_gen_x = x def reload_below_gate(self): for generator in self.generators: self.fond.delete(generator.id) self.fond.delete(generator.name_id) self.load_below_gates() def scroll(self, evt): if evt.delta != 0: # for windows self.gate_gen_x += evt.delta / 30 if evt.num == 4: # for linux self.gate_gen_x += 30 self.gate_gen_x = min(self.gate_gen_x, 0) if evt.num == 5: # for linux self.gate_gen_x -= 30 delta = self.max_gate_gen_x - gb.WINDOW_WIDTH + 100 if delta < 0: self.gate_gen_x += 30 self.reload_below_gate() ######################### SAVING CONFIGURATION ######################### def save_conf_name(self, evt): """ Permet de selectionner le nom de la gate créée """ self.disable_bindings() x, y = gb.WINDOW_WIDTH / 2, gb.WINDOW_HEIGHT / 2 self.rectangle_name_id = self.fond.create_rectangle(x - 50, y - 25, x + 50, y + 25, width=3, fill="white") self.gate_name = "" self.name_id = self.fond.create_text(x, y, text="") self.bind("<KeyPress>", self.save_pressed_key) self.bind("<Return>", self.save_conf) self.bind("<Escape>", self.cancel_save_conf) def cancel_save_conf(self, evt): self.clean_save_conf() def save_conf(self, evt): self.order_inputs_outputs() if not self.gate_name in os.listdir("lib/structs/"): with open("lib/structs/" + self.gate_name, "w") as f: # Ajoute les gate au fichier for gate in self.gates: f.write(str(gate)) # Ajoute les nodes d'entrée et de sortie au fichier for node in self.main_gate.inputs: f.write(str(node)) for node in self.main_gate.outputs: f.write(str(node)) # ajoute les nodes de chaque gate au fichier for gate in self.gates: for node in gate.inputs: f.write(str(node)) for node in gate.outputs: f.write(str(node)) self.clean_save_conf() self.reload_below_gate() def clean_save_conf(self): self.unbind("<KeyPress>") self.unbind("<Return>") self.unbind("<Escape>") self.fond.delete(self.rectangle_name_id) self.fond.delete(self.name_id) self.name_id = None self.rectangle_name_id = None self.gate_name = "" self.enable_bindings() ######################### DRAWING ######################### def get_center_from_point(self, node_or_tuple): try: return node_or_tuple.center except: return node_or_tuple def draw_link(self, link): """ Dessine un link """ x, y = self.get_center_from_point(link.points_list[-1]) link.id_list += [ self.fond.create_line(x, y, x, y, fill="white", width=2) ] self.fond.tag_bind(link.id_list[-1], "<Button-3>", link.r_clic) def draw_node(self, node): """ Dessine une node """ x, y = node.center node.id = self.fond.create_oval(x - gb.NODE_SIZE, y - gb.NODE_SIZE, x + gb.NODE_SIZE, y + gb.NODE_SIZE, outline="black", width=2, fill="white") self.fond.tag_bind(node.id, "<Button-1>", node.clic) self.fond.tag_bind(node.id, "<Button-3>", node.r_clic) self.fond.tag_bind(node.id, "<Button-2>", node.destroy) if gb.DEBUG: node.text = self.fond.create_text(x, y, text=str(node.id)) self.fond.tag_bind(node.text, "<Button-1>", node.clic) self.fond.tag_bind(node.text, "<Button-3>", node.r_clic) self.fond.tag_bind(node.text, "<Button-2>", node.destroy) if node.get_sub_type() == "count": # count node : on ajoute une pastille d'ajout n = gb.NODE_SIZE // 2 px, py = x + gb.NODE_SIZE, y ext_node_id = self.fond.create_oval(px - n, py - n, px + n, py + n, fill="red") self.fond.tag_bind(ext_node_id, "<Button-1>", node.add_ext_node) self.fond.tag_bind(ext_node_id, "<Button-2>", node.delete_ext) node.ext_node_id = ext_node_id if node.get_type() not in ("main_input", "main_output"): if gb.DEBUG: self.fond.tag_bind(node.text, "<Button-1>", node.gate.clic) self.fond.tag_bind(node.id, "<Button-1>", node.gate.clic) def draw_gate(self, gate): """ Affiche une gate et les nodes associées """ x, y = gate.center gate.id = self.fond.create_rectangle(x - gate.width, y - gb.BOX_HEIGHT, x + gate.width, y + gb.BOX_HEIGHT, outline="black", fill=gb.BOX_BG, width=3) self.fond.tag_bind(gate.id, "<Button-1>", gate.clic) self.fond.tag_bind(gate.id, "<Button-2>", gate.delete) gate.name_id = self.fond.create_text(x, y, text=gate.name) self.fond.tag_bind(gate.name_id, "<Button-1>", gate.clic) self.fond.tag_bind(gate.name_id, "<Button-2>", gate.delete) for node in gate.inputs: self.draw_node(node) for node in gate.outputs: self.draw_node(node) ######################### UPDATE DISPLAY ######################### def clock_update(self): self.update_all() self.after(300, self.clock_update) def update_all(self): """ Deux update sont nécéssaire pour que les flip flop marchent Un update se fait en 3 étapes : 1) On update les nodes d'entrée, afin de mettre à jour leur date de MAJ et mettre à jour l'affichage, meme de celles qui ne sont pas reliées 2) On update toutes les gates, afin de mettre à jour les gates, meme celles qui ne sont pas connectées 3) On update en partant des nodes de sortie """ t_in = time.perf_counter() gb.PRE_UPDATE() # 1) for node in self.main_gate.inputs: node.need_previous() # 2) for gate in self.gates: for output_node in gate.outputs: output_node.need_previous() # 3) for node in self.main_gate.outputs: node.need_previous() t_out = time.perf_counter() gb.debug("update time = {}".format(t_out - t_in)) def update(self, item): target_class = item.__class__.__bases__ if type(item) == Link: x2, y2 = self.get_center_from_point(item.points_list[-1]) x1, y1 = self.get_center_from_point(item.points_list[-2]) self.fond.coords(item.id_list[-1], x1, y1, x2, y2) x2, y2 = self.get_center_from_point(item.points_list[0]) x1, y1 = self.get_center_from_point(item.points_list[1]) self.fond.coords(item.id_list[0], x1, y1, x2, y2) if item.get_output(): # Permet d'afficher le lien en rouge lorsque la node d'entrée est active item.active = item.get_output().active for link_seg_id in item.id_list: self.fond.itemconfig(link_seg_id, fill="red" if item.active else "white") self.fond.tag_lower(item.id_list[-1]) elif type(item) in (Input_node, Output_node, Main_input_node, Main_output_node, Clock_node, Main_input_count_node, Main_output_count_node): x, y = item.center self.fond.coords(item.id, x - gb.NODE_SIZE, y - gb.NODE_SIZE, x + gb.NODE_SIZE, y + gb.NODE_SIZE) self.fond.itemconfig(item.id, fill="red" if item.active else "white") if gb.DEBUG: self.fond.coords(item.text, x, y) # On update les liens avant et après la node for link in item.next_links: self.update(link) if item.prev_link: self.update(item.prev_link) if item.get_sub_type() == "count" and item.master_node == item: item.update_value_display() else: if item.name != "MAIN": # c'est une gate normale x, y = item.center dx, dy = item.delta_x, item.delta_y self.fond.coords(item.id, x - item.width, y - gb.BOX_HEIGHT, x + item.width, y + gb.BOX_HEIGHT) self.fond.coords(item.name_id, x, y) for node in item.inputs: self.update(node) for node in item.outputs: self.update(node) self.fond.tag_lower(self.real_bg)
class simpleGui(tkinter.Tk): def __init__(self, parent): tkinter.Tk.__init__(self, parent) self.parent = parent self.initialize() def initialize(self): self.grid() self.config(bg="white") self.geometry("600x500") self.algo = ACAlgo() self.wordFrames=[] self.path="" self.lastCanvasIndex=0 rowLine=0 self.entryPath = tkinter.Entry(self, width=75) self.entryPath.grid(column=0, row=rowLine,columnspan=3, sticky='NEW') self.entryPath.bind("<Return>", self.setPath) buttonSetPath = tkinter.Button(self, text="Set path", width=21, height=1, command=self.setPath) buttonSetPath.grid(column=3, row=rowLine, sticky='EWN') rowLine=rowLine+1 self.entry = tkinter.Entry(self, width=75) self.entry.grid(column=0, row=rowLine,columnspan=2, sticky='NEWS') self.entry.bind("<Return>", self.addWords) buttonAddWords = tkinter.Button(self, text="Add words", width=21,height=1, command=self.addWords) buttonAddWords.grid(column=3, row=rowLine, sticky='EWNS') rowLine=rowLine+1 self.grid_rowconfigure(rowLine, weight=1) self.textBox = tkst.ScrolledText(self, width=20, height=10) self.textBox.grid(column=0, row=rowLine, columnspan=3, sticky='NWES') self.textBox.config(state=DISABLED) self.canvas= Canvas(master=self,width=150) self.vscroll = Scrollbar(self) self.vscroll.config(command=self.canvas.yview) self.canvas.config(yscrollcommand=self.vscroll.set) self.canvas.grid( row=rowLine, column=3, sticky='NES') self.vscroll.grid(padx=1, pady=1, row=rowLine, column=4, sticky='NEWS') rowLine=rowLine+1 buttonClearHighlight = tkinter.Button(self, text="Clear highlight", width=20, command=self.removeHighlightsBtn) buttonClearHighlight.grid(column=0, row=rowLine, sticky="WS") buttonDeleteWords = tkinter.Button(self, text="Delete words", width=20, command=self.resetAll) buttonDeleteWords.grid(column=3, row=rowLine, sticky="ES") self.grid_columnconfigure(0, weight=1) self.grid_columnconfigure(1, weight=1) def setPath(self): try: open(self.entryPath.get()) except: return self.path=self.entryPath.get() self.textBox.config(state=NORMAL) self.textBox.insert(tkinter.INSERT, open(self.path).read()) self.textBox.config(state=DISABLED) def removeHighlights(self): for wordFrame in self.wordFrames: wordFrame.removeHighLight() def removeHighlightsBtn(self, entry=""): for wordFrame in self.wordFrames: wordFrame.removeHighLight() self.update_idletasks() def resetAll(self, entry=""): self.removeHighlights() self.algo.resetTree() self.lastCanvasIndex=0; self.wordFrames=[] self.canvas.delete("all") self.update_idletasks() def addWords(self, event=""): if(self.path==""): return if(self.entry.get().strip()==""): self.entry.delete(0,len(self.entry.get())) return self.resetAll() for word in self.entry.get().split(" "): if word.lower() not in self.algo.foundWords.keys() and word != "" and word!=None: self.algo.addWord(word) self.addToCanvas(word) self.entry.delete(0,len(self.entry.get())) self.algo.addFails() self.algo.readFile(self.path) self.updateCanvasPositions(); def updateCanvasPositions(self): for word in self.wordFrames: self.wordFrames[self.wordFrames.index(word)].updatePositions(self.algo.foundWords[word.getWord().lower()]) self.wordFrames[self.wordFrames.index(word)].addTags() def addToCanvas(self, word): frame=wordFrame(self.canvas, self, word, self.algo.foundWords[word.lower()]) self.wordFrames.append(frame) self.canvas.create_window(0, 50+self.lastCanvasIndex*50,anchor="w", window=frame, height=50) self.canvas.config(scrollregion=(0,0,70+self.lastCanvasIndex*50,70+self.lastCanvasIndex*50)) self.canvas.update_idletasks() self.update_idletasks() self.lastCanvasIndex=self.lastCanvasIndex+1;
def delete(self, canvas: Canvas): canvas.delete(self.id)
class SudokuUI(Frame): """ The Tkinter UI, responsible for displaying the UI. """ def __init__(self, parent, game): self.game = game self.parent = parent Frame.__init__(self, parent) self.row, self.col = 0, 0 self.__initUI() def __initUI(self): self.parent.title("Sudoku") self.pack(fill=BOTH, expand=1) # Use all available space self.canvas = Canvas(self, width=WIDTH, heigh=HEIGHT) self.canvas.pack(fill=BOTH, side=TOP) # Pull board to top of frame clear_button = Button(self, text="Clear answers", command=self.__clear_answers) clear_button.pack(fill=BOTH, side=BOTTOM) self.__draw_grid() self.__draw_puzzle() self.canvas.bind("<Button-1>", self.__cell_clicked) self.canvas.bind("<Key>", self.__key_pressed) def __draw_grid(self): """ Draws grid divided with blue lines into 3 x 3 grid :return: """ for i in range(10): color = 'blue' if i % 3 == 0 else "gray" x0 = MARGIN + i * SIDE y0 = MARGIN x1 = MARGIN + i * SIDE y1 = HEIGHT - MARGIN self.canvas.create_line(x0, y0, x1, y1, fill=color) x0 = MARGIN y0 = MARGIN + i * SIDE x1 = WIDTH - MARGIN y1 = MARGIN + i * SIDE self.canvas.create_line(x0, y0, x1, y1, fill=color) def __draw_puzzle(self): self.canvas.delete("numbers") for i in xrange(9): for j in xrange(9): answer = self.game.puzzle[i][j] if answer != 0: x = MARGIN + j * SIDE + SIDE / 2 y = MARGIN + i * SIDE + SIDE / 2 original = self.game.start_puzzle[i][j] color = "black" if answer == original else "sea green" self.canvas.create_text(x, y, text=answer, tags="number", fill=color) def __clear_answers(self): self.game.start() self.canvas.delete("victory") self.__draw_puzze() def __cell_clicked(self, event): # event has x, y coords of mouse click if self.game.game_over: return x, y = event.x, event.y if (MARGIN < x < WIDTH - MARGIN) and (MARGIN < Y < HEIGHT - MARGIN): self.canvas.focus_set() # get row and col numbers from x, y coords row, col = (y - MARGIN) / SIDE, (x - MARGIN) / SIDE # if cell already selected then deselect it if (row, col) == (self.row, self.col): self.row, self.col = -1, -1 # outside the grid elif self.game.puzzle[row][col] == 0: self.row, self.col = row, col self.__draw_cursor() def __draw_cursor(self): self.canvas.delete("cursor") if self.row >= 0 and self.col >= 0: x0 = MARGIN + self.col * SIDE + 1 y0 = MARGIN + self.row * SIDE + 1 x1 = MARGIN + (self.col + 1) * SIDE - 1 y1 = MARGIN + (self.row + 1) * SIDE - 1 self.canvas.create_rectangle( x0, y0, x1, y1, outline ="red", tags ="cursor" )
class NEATPanel(Frame): def __init__(self, tile_size): self.root = Tk() self.root.geometry("780x640") self.root.update() self.root.config(bg='gray') self.entry = Entry(self.root) self.entry.grid(row=0, column=2) self.root.bind('<Return>', self.hit_enter) self.canvas = Canvas(self.root, width=640, height=640, bg='light gray') self.canvas.grid(row=0, column=0) def start(self): self.root.mainloop() def hit_enter(self, event): # _input = int(self.entry.get()) g = Genome() self.canvas.delete("all") g.mutate_add_connection() g.mutate_add_node() self.display_genome(g) #self.canvases[_input].place(x=0, y=0) def display_genome(self, genome): nodes = { 'input':[], 'hidden':[], 'output':[] } for i in genome.nodeGenes: nodes[i.type].append(i) for i, v in enumerate(nodes['input']): v.x = 40 v.y = (i+.5)*(640/len(nodes['input'])) for i, v in enumerate(nodes['output']): v.x = 600 v.y = (i+.5)*(640/len(nodes['output'])) for i in nodes['hidden']: x, y = 0, 0 connected_num = len(i.connected_ids) for j in i.connected_ids: n = genome.get_nodeGene_by_id(j) x += n.x y += n.y x /= connected_num y /= connected_num i.x = x i.y = y for i in genome.connectionGenes: self.canvas.create_line(i.in_node.x, i.in_node.y, i.out_node.x, i.out_node.y, width=i.weight*5, fill='blue') self.canvas.create_text((i.in_node.x+i.out_node.x)/2, (i.in_node.y+i.out_node.y)/2, text=i.id, fill='black') for i in genome.nodeGenes: self.canvas.create_oval(i.x-15, i.y-15, i.x+15, i.y+15, fill='red', outline='red') self.canvas.create_text(i.x, i.y, text=i.id, fill='white')
class Window(Frame): def __init__(self, parent): Frame.__init__(self, parent, background="dark gray") self.parent = parent self.initUI() self.initPuzzles() self.run() def initUI(self): self.parent.title("Block") self.pack(fill=BOTH, expand=1) self.initCanvas() self.initInterfaceZone() def initCanvas(self): self.canvas = Canvas(self, background="dark gray") self.canvas.pack(expand=1,fill=BOTH,padx=1,pady=1) def initInterfaceZone(self): # Draw the play, step and loading buttons self.interfaceFrame = Frame(self, background="dark gray") self.playFrame = Frame(self.interfaceFrame, background="dark gray") self.loadFrame = Frame(self.interfaceFrame, background="dark gray") self.isPlaying = False #Do the run buttons playButton = Button(self.playFrame, text=">", command=self.playPress) playButton.grid(row=0,column=0) pauseButton = Button(self.playFrame, text="||", command=self.pausePress) pauseButton.grid(row=0,column=1) stepBackButton = Button(self.playFrame, text="|<", command=self.stepBackPress) stepBackButton.grid(row=1,column=0) stepForwardButton = Button(self.playFrame, text=">|", command=self.stepForwardPress) stepForwardButton.grid(row=1,column=1) self.playFrame.pack(side=LEFT, expand=1, fill=BOTH) #Do the load-y stuff self.boardInputField = Entry(self.loadFrame) self.boardInputField.grid(row=0, column=0) boardInputButton = Button(self.loadFrame, text="Load Board", command=self.loadBoardPress) boardInputButton.grid(row=0, column=1) self.moveInputField = Entry(self.loadFrame) self.moveInputField.grid(row=1,column=0) moveInputButton = Button(self.loadFrame, text="Load Moves", command=self.loadMovesPress) moveInputButton.grid(row=1, column=1) self.loadFrame.pack(side=LEFT, expand=1, fill=BOTH) self.interfaceFrame.pack(side=BOTTOM) def initPuzzles(self): self.pieces = [] # Once a puzzle's loaded, will be a list of drawnBlocks self.boardWidth = 100 self.boardHeight = 100 self.blockWidth = 30 self.blockHeight = 30 self.rosterBlockWidth = 0 self.rosterBlockHeight = 0 self.rosterStartX = 0 self.moveList = [] self.atMove = 0 def run(self): self.after(DELAY,self.onTimer) def loadPuzzle(self, puzzle): # Accept a puzzle and load it into the GUI # First clear memory self.pieces = [] self.canvas.delete("all") self.moveList = [] self.atMove = 0 #Set up the board and piece roster squareSize = min(maxBoardWidth/puzzle.cols, maxBoardHeight/puzzle.rows) self.blockWidth = squareSize self.blockHeight = squareSize self.boardWidth = self.blockWidth*puzzle.cols self.boardHeight = self.blockHeight*puzzle.rows self.rosterStartX = boardStartX + self.boardWidth + extRosterPadding rosterX = self.rosterStartX rosterY = boardStartY + intRosterPadding maxHeight = 0 #Start creating pieces, filling roster as we go for piece in puzzle.universe: label = piece.getLabel() if rosterX + intRosterPadding + piece.cols*self.blockWidth + intRosterPadding - self.rosterStartX <= rosterWidth: self.pieces.append(drawnBlock(self.canvas,piece,rosterX+intRosterPadding,rosterY,label=label, colour = colourDict[label], boxSize = self.blockWidth)) rosterX += intRosterPadding + piece.cols*self.blockWidth if piece.rows*self.blockHeight>maxHeight: maxHeight = piece.rows*self.blockHeight else: rosterX = self.rosterStartX rosterY += maxHeight + intRosterPadding maxHeight = piece.rows*self.blockHeight self.pieces.append(drawnBlock(self.canvas,piece,rosterX+intRosterPadding,rosterY,label=label, colour = colourDict[label], boxSize = self.blockWidth)) rosterX += intRosterPadding + piece.cols*self.blockWidth #Draw board and roster for i in range(1,puzzle.rows): tag=self.canvas.create_rectangle(boardStartX+i*self.blockWidth - 1, boardStartY, boardStartX+i*self.blockWidth + 1, boardStartY+self.boardHeight, fill="#333333",width=0) self.canvas.tag_lower(tag) for j in range(1,puzzle.cols): tag=self.canvas.create_rectangle(boardStartX, boardStartY + j*self.blockHeight - 1, boardStartX + self.boardWidth, boardStartY+j*self.blockHeight+1, fill="#333333",width=0) self.canvas.tag_lower(tag) tag=self.canvas.create_rectangle(boardStartX, boardStartY, boardStartX + self.boardWidth, boardStartY + self.boardHeight,fill="white",width=2) self.canvas.tag_lower(tag) tag = self.canvas.create_rectangle(boardStartX + self.boardWidth + extRosterPadding, boardStartY, boardStartX + self.boardWidth + extRosterPadding + rosterWidth, rosterY + maxHeight + intRosterPadding, fill="white") self.canvas.tag_lower(tag) def move(self, move): #Puts a piece into (i,j) or sends it home piece = self.getPiece(move.tag) if move.home: piece.setMove(piece.homeX,piece.homeY) else: x = boardStartX + move.i*self.blockWidth y = boardStartY + move.j*self.blockHeight piece.setMove(x,y) def getPiece(self, tag): foundPiece = -1 for piece in self.pieces: if piece.label == tag: foundPiece = piece break if foundPiece == -1: print("Error: No piece for tag \'"+ str(tag) + "\' found") return piece def getMoveStatus(self): if self.atMove < len(self.moveList): currentMove = self.moveList[self.atMove] piece = self.getPiece(currentMove.tag) if piece.isMoving: return False else: return True else: return True def handleMoves(self): moveCompleted = self.getMoveStatus() if moveCompleted: if self.atMove < len(self.moveList) - 1: self.atMove += 1 self.move(self.moveList[self.atMove]) else: self.isPlaying = False def playPress(self): print("Play") self.isPlaying=True #Start the next move if self.atMove < len(self.moveList): self.move(self.moveList[self.atMove]) def pausePress(self): print("Pause") self.isPlaying=False def stepBackPress(self): print("Back") def stepForwardPress(self): print("Forward") def loadBoardPress(self): print("Load Board") input = self.boardInputField.get() if input == "": self.boardInputField.delete(0,END) self.boardInputField.insert(0,"Must enter a board here") else: prePuzzle = eval(input) # Now read in rows = prePuzzle[0] cols = prePuzzle[1] pieceList = prePuzzle[2] realPieces = [] for piece in pieceList: realPieces.append(pz.Block(np.array(piece))) universe = frozenset(realPieces) puzzle = pz.Puzzle(rows,cols,universe) self.loadPuzzle(puzzle) def loadMovesPress(self): print("Load Moves") input = self.moveInputField.get() if input == "": self.moveInputField.delete(0,END) self.moveInputField.insert(0,"Must enter a move list here") else: preMoves = eval(input) self.moveList = [] self.atMove = 0 for move in preMoves: #Expect form [tag, i, j] with i = j = -1 when home is desired if move[1]==-1: self.moveList.append(Move(move[0],0,0,home=True)) else: self.moveList.append(Move(move[0],move[1],move[2])) def onTimer(self): if self.isPlaying: self.handleMoves() for piece in self.pieces: if piece.isMoving: piece.move() self.after(DELAY,self.onTimer)
class SudokuUI(Frame): def __init__(self, parent, game): self.game = game self.parent = parent Frame.__init__(self, parent) self.row = 0 self.col = 0 self.__initUI() def __initUI(self): self.parent.title("Sudoku") self.pack(fill=BOTH, expand=1) self.canvas = Canvas(self, width=WIDTH, heigh=HEIGHT) self.canvas.pack(fill=BOTH, side=TOP) clear_button = Button(self, text="Clear answers", command=self.__clear_answers) clear_button.pack(fill=BOTH, side=BOTTOM) self.__draw_grid() self.__draw_puzzle() self.canvas.bind("<Button-1>", self.__cell_clicked) self.canvas.bind("<Key>", self.__key_pressed) def __draw_grid(self): for i in range(10): if i % 3 == 0: color = "blue" else: color = "gray" x0 = MARGIN + i * CELL y0 = MARGIN x1 = MARGIN + i * CELL y1 = HEIGHT - MARGIN self.canvas.create_line(x0, y0, x1, y1, fill=color) x0 = MARGIN y0 = MARGIN + i * CELL x1 = WIDTH - MARGIN y1 = MARGIN + i * CELL self.canvas.create_line(x0, y0, x1, y1, fill=color) def __draw_puzzle(self): self.canvas.delete("numbers") for i in range(9): for j in range(9): answer = self.game.puzzle[i][j] if answer != 0: x = MARGIN + j * CELL + CELL / 2 y = MARGIN + i * CELL + CELL / 2 original = self.game.start_puzzle[i][j] color = "black" if answer == original else "green" self.canvas.create_text(x, y, text=answer, tags="numbers", fill=color) def __clear_answers(self): self.game.start() self.canvas.delete("victory") self.__draw_puzzle() def __cell_clicked(self, event): if self.game.game_over: return x, y = event.x, event.y if MARGIN < x < WIDTH - MARGIN and MARGIN < y < HEIGHT - MARGIN: self.canvas.focus_set() row, col = int((y - MARGIN) / CELL), int((x - MARGIN) / CELL) if (row, col) == (self.row, self.col): self.row, self.col = -1, -1 elif self.game.puzzle[row][col] == 0: self.row, self.col = row, col self.__draw_cursor() def __draw_cursor(self): self.canvas.delete("cursor") if self.row >= 0 and self.col >= 0: x0 = MARGIN + self.col * CELL + 1 y0 = MARGIN + self.row * CELL + 1 x1 = MARGIN + (self.col + 1) * CELL - 1 y1 = MARGIN + (self.row + 1) * CELL - 1 self.canvas.create_rectangle(x0, y0, x1, y1, outline="red", tags="cursor") def __key_pressed(self, event): if self.game.game_over: return if self.row >= 0 and self.col >= 0 and event.char in "1234567890": self.game.puzzle[self.row][self.col] = int(event.char) self.col, self.row = -1, -1 self.__draw_puzzle() self.__draw_cursor() if self.game.check_win(): self.__draw_victory() def __draw_victory(self): x0 = y0 = MARGIN + CELL * 2 x1 = y1 = MARGIN + CELL * 7 self.canvas.create_oval(x0, y0, x1, y1, tags="victory", fill="dark orange", outline="blue") x = y = MARGIN + 4 * CELL + CELL / 2 self.canvas.create_text(x, y, text="You win!", tags="winner", fill="white", font=("Arial", 32))
class View(): def __init__(self, root, controller): self.__controller = controller root.wm_title("Bomber") self.__windowsystem = root.call('tk', 'windowingsystem') self.__frame = root self.__canvas = Canvas(self.__frame, width=int(CANVAS_WIDTH), height=int(CANVAS_HEIGHT), bg="white") self.__canvas.pack(side=LEFT, fill=BOTH, expand=TRUE) self.__init_fonts() self.__init_arena() self.__init_score() self.__block_views = [] # type: List[BlockView] self.__blockfield_view = BlockfieldView() self.__messages = [] def __init_fonts(self): self.bigfont = font.nametofont("TkDefaultFont") self.bigfont.configure(size=int(48)) self.scorefont = font.nametofont("TkDefaultFont") self.scorefont.configure(size=int(20)) def __init_score(self): self.score_text = self.__canvas.create_text(5, 5, anchor="nw") self.__canvas.itemconfig(self.score_text, text="Score:", font=self.scorefont) def __init_arena(self): self.__canvas.create_rectangle(LEFT_OFFSET, TOP_OFFSET, LEFT_OFFSET + MAXCOL*GRID_SIZE, TOP_OFFSET+MAXROW*GRID_SIZE, fill="black") nextblocktext = self.__canvas.create_text(GRID_SIZE, TOP_OFFSET + GRID_SIZE * 4, anchor="nw") self.__canvas.itemconfigure(nextblocktext, text="Next:", font=self.bigfont, fill="black") self.__autoplay_text = self.__canvas.create_text(LEFT_OFFSET + GRID_SIZE * 5, TOP_OFFSET - GRID_SIZE, anchor="c") self.__canvas.itemconfigure(self.__autoplay_text, text="Play mode", font=self.bigfont, fill="black") def register_block(self, block): block_view = BlockView(block) self.__block_views.append(block_view) def unregister_block(self, block): for block_view in self.__block_views: if block_view.block is block: block_view.erase(self.__canvas) self.__block_views.remove(block_view) def update_blockfield(self, blockfield): self.__blockfield_view.redraw(self.__canvas, blockfield) def display_score(self): self.__canvas.itemconfig(self.score_text, text="Score: " + str(self.__controller.score), font=self.scorefont) def show_autoplay(self, autoplay): if autoplay: self.__canvas.itemconfig(self.__autoplay_text, text="Auto-play mode", font=self.scorefont, fill="black") else: self.__canvas.itemconfig(self.__autoplay_text, text="Manual mode", font=self.scorefont, fill="black") def game_over(self): text1 = self.__canvas.create_text(LEFT_OFFSET + GRID_SIZE*MAXCOL//2, CANVAS_HEIGHT/2, anchor="c") text2 = self.__canvas.create_text(LEFT_OFFSET + GRID_SIZE*MAXCOL//2, CANVAS_HEIGHT/2 + 100, anchor="c") text1_shadow = self.__canvas.create_text(2 + LEFT_OFFSET + GRID_SIZE*MAXCOL//2, 2 + CANVAS_HEIGHT/2, anchor="c") text2_shadow = self.__canvas.create_text(2 + LEFT_OFFSET + GRID_SIZE*MAXCOL//2, 2 + CANVAS_HEIGHT/2 + 100, anchor="c") self.__messages.append(text1) self.__messages.append(text2) self.__messages.append(text1_shadow) self.__messages.append(text2_shadow) self.__canvas.itemconfig(text1, text="GAME OVER!", font=self.bigfont, fill="white") self.__canvas.itemconfig(text2, text="Press r to play again.", font=self.scorefont, fill="white") self.__canvas.itemconfig(text1_shadow, text="GAME OVER!", font=self.bigfont, fill="black") self.__canvas.itemconfig(text2_shadow, text="Press r to play again.", font=self.scorefont, fill="black") self.__canvas.tag_raise(text1) self.__canvas.tag_raise(text2) def clear_messages(self): for txt in self.__messages: self.__canvas.delete(txt) self.__messages.clear() def update(self): for block_view in self.__block_views: block_view.redraw(self.__canvas) self.display_score()
class ProductSheet(): def __init__(self, container=None, displayer=None, session=None): """ 'container' (Obj ): instance of Container. 'displayer' (obj ): instance of Displayer. 'session,' (obj ): instance of Session. 'grid' (Obj ): instance of Grid. 'f_container' (Frame): container frame. 'm_frame' (Frame): master frame of view. 'name' (str ): name of view. 'json_script' (dict ): json dict of script. 'width' (int ): view width. 'height' (int ): view height. 'padx' (int ): view 'pady' (int ): view 'bg' (str ): view bg. """ # Instances self.container = container self.displayer = displayer self.session = session self.grid = None # Frames self.f_container = self.container.f_container self.m_frame = None # Informations self.name = None # Script self.json_script = None # Style Sheet self.width = self.container.width self.height = self.container.height self.padx = 0 self.pady = 0 self.bg = "#ffffff" # Tk control variables # Widgets row 0 self.w_title = None # Widgets row 1 self.w_img_product = None self.w_name_product = None self.w_brand_product = None self.w_nutriscore_product = None # Widgets row 2 self.w_best_button = None self.w_edit_button = None self.w_trash_button = None self.w_add_button = None # Widgets row 4 self.canvas_calories = None self.w_calories_img = None self.w_calories_label = None # Widgets row 5 self.canvas_sugar = None self.w_sugar_img = None self.w_sugar_label = None self.w_sugar_value = None # Widgets row 6 self.w_stores_img = None self.w_stores_label = None self.w_stores_value = None # Widgets row 7 self.w_author_img = None self.w_author_label = None self.w_author_value = None # Widgets row 8 self.w_submit_button = None self.favorite_status = False self.product = None self.product_id = 0 self.product_img = None self.product_name = None self.product_brand = None self.product_nutriscore = None self.product_kcal = 0 self.product_sugar = 0 self.product_author = None self.product_store = None # Fill status self.fill_status = False # Previous View in **kwargs self.previous_view = None # -- Displayer initialisation -- # self.construct() def construct(self, **kwargs): """ Construt view. to not fill the view during initialization. 'grid' (obj): Instance of Grid. 'm_frame' (Frame): Tkinter master frame of view. """ # 1. Create new grid in page container. self.grid = Grid(frame=self.f_container, width=self.width, height=self.height, padx=self.padx, pady=self.pady, bg=self.bg) # 2. Get view frame for displayer function self.m_frame = self.grid.master_frame # 3. Construct the view rows self.row_0(action="construct") self.row_1(action="construct") self.row_2(action="construct") self.row_3(action="construct") self.row_4(action="construct") self.row_5(action="construct") self.row_6(action="construct") self.row_7(action="construct") def fill(self, **kwargs): """ Fill the view rows. 'json_script' (dict): texts for view. 'name' (str): view name. """ for key, value in kwargs.items(): if key == "view": self.previous_view = value elif key == "product_id": self.product_id = value # 1. Get the script. self.json_script = self.session.get_script(package_name="product", file_name="sheet") # 2. Save name of view for displayer. self.name = self.json_script.get("view_name") # Get product informations self.product = self.session.dbmanager.db_product.read( action="id", product_id=self.product_id) favorite = self.session.dbmanager.db_user_prod.read( action="test", user_id=self.session.user_id, product_id=self.product_id) if len(favorite) == 1: self.favorite_status = True else: self.favorite_status = False self.product_img = self.product[0]["product_img_url"] self.product_name = self.product[0]["product_name"] self.product_brand = self.product[0]["product_brand"] self.product_nutriscore = self.product[0]["product_nutriscore"] self.product_kcal = self.product[0]["product_kcal"] self.product_sugar = self.product[0]["product_sugar"] self.product_author = self.product[0]["product_creator"] self.product_store = self.product[0]["product_store"] # 3. Refresh rows. if self.fill_status is True: self.row_0(action="refresh") self.row_1(action="refresh") self.row_2(action="refresh") self.row_3(action="refresh") self.row_4(action="refresh") self.row_5(action="refresh") self.row_6(action="refresh") self.row_7(action="refresh") # 4. Fill the view rows. self.row_0(action="fill") self.row_1(action="fill") self.row_2(action="fill") self.row_3(action="fill") self.row_4(action="fill") self.row_5(action="fill") self.row_6(action="fill") self.row_7(action="fill") self.fill_status = True def display_substitutes(self): """ Display substitues. """ self.displayer.display(c_view="product_sheet", f_view="product_substitutes", product_id=self.product_id) def display_edit(self): """ Display product edit. """ self.displayer.display(c_view="product_sheet", f_view="product_edit", product_id=self.product_id) def display_search(self): """ Display "search". """ self.displayer.display(c_view="product_sheet", f_view="search_engine") def add_product(self): """ Add product to favorite in database. """ self.session.dbmanager.db_user_prod.create( user_id=self.session.user_id, product_id=self.product_id) self.favorite_status = True self.row_1("refresh") self.row_1("fill") def del_product_to_favorite(self): """ Add product to favorite in database. """ self.session.dbmanager.db_user_prod.delete( user_id=self.session.user_id, product_id=self.product_id) self.favorite_status = False self.row_1("refresh") self.row_1("fill") def trash_product(self): """ Delete product to database. """ self.session.dbmanager.db_product.delete(product_id=self.product_id) self.display_search() def row_0(self, action=None): """ Name : PRODUCT IMAGE cols : 3 """ if action == "construct": # -- CREATE ROW -- # self.grid.row(width=self.width, height=250, padx=self.padx, pady=self.pady, bg="#ffffff") # -- CREATE COLS -- # self.grid.column(span=6, row=0, width=None, height=None, padx=None, pady=None, bg=None) self.grid.column(span=5, row=0, width=None, height=None, padx=30, pady=30, bg=None) self.grid.column(span=1, row=0, width=None, height=None, padx=None, pady=None, bg=None) elif action == "fill": if self.w_img_product is None: # -- COLUMN 1 : PRODUCT IMAGE -- # if self.product_img == "empty": img = Image.open("frontend/images/no_image.png") else: req = requests.get(self.product_img) img = Image.open(BytesIO(req.content)) img_resize = img.resize((150, 200), Image.ANTIALIAS) tk_img_product = ImageTk.PhotoImage(img_resize) self.w_img_product = Label(self.grid.col_frames[0][0], image=tk_img_product, bg="#ffffff") self.w_img_product.image = tk_img_product self.w_img_product.pack(fill='both', expand=True) if self.w_name_product is None: # -- COLUMN 2 : PRODUCT NAME -- # self.w_name_product = Label(self.grid.col_frames[0][1], text="{}".format( self.product_name), bg="#ffffff", fg="#000000", font="Helvetica 13 normal") self.w_name_product.pack(fill='both') if self.w_brand_product is None: # -- COLUMN 2 : PRODUCT BRAND -- # self.w_brand_product = Label(self.grid.col_frames[0][1], text="{}".format( self.product_brand), bg="#ffffff", fg="#000000", font="Helvetica 13 bold") self.w_brand_product.pack(fill='both') if self.w_nutriscore_product is None: # -- COLUMN 2 : PRODUCT NUTRISCORE -- # img = Image.open( "frontend/images/nutriscores/nutriscore_{}.png".format( self.product_nutriscore)) imgResize = img.resize((160, 90), Image.ANTIALIAS) nutriscore_img = ImageTk.PhotoImage(imgResize) self.w_nutriscore_product = Label(self.grid.col_frames[0][1], image=nutriscore_img, bg="#ffffff") self.w_nutriscore_product.image = nutriscore_img self.w_nutriscore_product.pack(fill="both", expand=True) elif action == "refresh": self.w_img_product.pack_forget() self.w_name_product.pack_forget() self.w_brand_product.pack_forget() self.w_nutriscore_product.pack_forget() self.w_img_product = None self.w_name_product = None self.w_brand_product = None self.w_nutriscore_product = None def row_1(self, action=None): """ Name : BUTTONS cols : 6 """ if action == "construct": # -- CREATE ROW -- # self.grid.row(width=self.width, height=50, padx=0, pady=0, bg="#ffffff") # -- CREATE COLS -- # self.grid.column(span=7, row=1, width=None, height=None, padx=5, pady=5, bg=None) self.grid.column(span=1, row=1, width=None, height=None, padx=5, pady=5, bg=None) self.grid.column(span=1, row=1, width=None, height=None, padx=5, pady=5, bg=None) self.grid.column(span=1, row=1, width=None, height=None, padx=5, pady=5, bg=None) self.grid.column(span=1, row=1, width=None, height=None, padx=5, pady=5, bg=None) self.grid.column(span=1, row=1, width=None, height=None, padx=5, pady=5, bg=None) elif action == "fill": # -- COLUMN 1 : EMPTY -- # if self.w_best_button is None: # -- COLUMN 3 : SUBSTITUTES BUTTON -- # img = Image.open( "frontend/images/views/product_sheet/best_product_1.png") imgResize = img.resize((25, 25), Image.ANTIALIAS) best_img = ImageTk.PhotoImage(imgResize) self.w_best_button = Button(self.grid.col_frames[1][1], image=best_img, bg="#ffffff", command=self.display_substitutes) self.w_best_button.image = best_img self.w_best_button.pack(fill='both', expand=True) if self.w_edit_button is None: # -- COLUMN 4 : PRODUCT SHEET BUTTON -- # img = Image.open( "frontend/images/views/product_sheet/edit.png") imgResize = img.resize((25, 25), Image.ANTIALIAS) edit_img = ImageTk.PhotoImage(imgResize) self.w_edit_button = Button(self.grid.col_frames[1][2], image=edit_img, bg="#ffffff", command=self.display_edit) self.w_edit_button.image = edit_img self.w_edit_button.pack(fill='both', expand=True) if self.w_trash_button is None: # -- COLUMN 5 : TRASH BUTTON -- # img = Image.open( "frontend/images/views/product_sheet/trash.png") imgResize = img.resize((25, 25), Image.ANTIALIAS) trash_img = ImageTk.PhotoImage(imgResize) self.w_trash_button = Button(self.grid.col_frames[1][3], image=trash_img, bg="#ffffff", command=self.trash_product) self.w_trash_button.image = trash_img self.w_trash_button.pack(fill='both', expand=True) if self.w_add_button is None: img = Image.open( "frontend/images/views/product_sheet/icon_add_{}.png". format(self.product_nutriscore)) imgResize = img.resize((25, 25), Image.ANTIALIAS) add_img = ImageTk.PhotoImage(imgResize) if self.favorite_status is False: # -- COLUMN 6 : ADD BUTTON -- # self.w_add_button = Button(self.grid.col_frames[1][4], image=add_img, bg="#ffffff", command=self.add_product) self.w_add_button.image = add_img self.w_add_button.pack(fill='both', expand=True) else: img = Image.open( "frontend/images/views/product_sheet/favorite.png") imgResize = img.resize((25, 25), Image.ANTIALIAS) add_img = ImageTk.PhotoImage(imgResize) # -- COLUMN 6 : ADD BUTTON -- # self.w_add_button = Button( self.grid.col_frames[1][4], image=add_img, bg="#ffffff", command=self.del_product_to_favorite) self.w_add_button.image = add_img self.w_add_button.pack(fill='both', expand=True) elif action == "refresh": self.w_best_button.pack_forget() self.w_edit_button.pack_forget() self.w_trash_button.pack_forget() self.w_add_button.pack_forget() self.w_best_button = None self.w_edit_button = None self.w_trash_button = None self.w_add_button = None def row_2(self, action=None): """ Name : SPACE cols : 1 """ if action == "construct": # -- CREATE ROW -- # self.grid.row(width=self.width, height=25, padx=self.padx, pady=self.pady, bg="#ffffff") # -- CREATE COLS -- # self.grid.column(span=12, row=2, width=None, height=None, padx=None, pady=None, bg=None) elif action == "fill": pass elif action == "refresh": pass def row_3(self, action=None): """ Name : PRODUCT CALORIES cols : 3 """ line = "line_empty" line_lenght = 90 if self.product_kcal == 0: line = "line_empty" line_lenght = 90 elif self.product_kcal <= 100: line = "line_a" line_lenght = 90 elif self.product_kcal <= 500: line = "line_b" line_lenght = 180 elif self.product_kcal <= 1000: line = "line_c" line_lenght = 270 elif self.product_kcal <= 1500: line = "line_d" line_lenght = 360 elif self.product_kcal > 1501: line = "line_e" line_lenght = 450 if action == "construct": # -- CREATE ROW -- # self.grid.row(width=self.width, height=55, padx=0, pady=5, bg="#ffffff") # -- CREATE COLS -- # self.grid.column(span=1, row=3, width=None, height=None, padx=None, pady=None, bg=None) self.grid.column(span=2, row=3, width=None, height=None, padx=None, pady=None, bg=None) self.col = self.grid.column(span=9, row=3, width=None, height=None, padx=None, pady=None, bg=None) elif action == "fill": # Get texts for this row txt = self.json_script.get("row_3") if self.w_calories_img is None: # -- COLUMN 1 : CALORIES IMAGE -- # img = Image.open( "frontend/images/views/product_sheet/calories.png") imgResize = img.resize((30, 30), Image.ANTIALIAS) calories_img = ImageTk.PhotoImage(imgResize) self.w_calories_img = Label(self.grid.col_frames[3][0], image=calories_img, bg="#ffffff") self.w_calories_img.image = calories_img self.w_calories_img.pack(fill="both", expand=True) if self.w_calories_label is None: # -- COLUMN 2 : CALORIES NAME -- # self.w_calories_label = Label(self.grid.col_frames[3][1], anchor="w", text=txt.get("calories_label"), bg="#ffffff", font="Helvetica 11 bold") self.w_calories_label.pack(fill="both", expand=True) if self.canvas_calories is None: img = Image.open( "frontend/images/views/product_sheet/{}.png".format(line)) imgResize = img.resize((line_lenght, 35), Image.ANTIALIAS) kcal_img = ImageTk.PhotoImage(imgResize) self.canvas_calories = Canvas(self.grid.col_frames[3][2], width=self.width, height=35, highlightthickness=0, bg="#ffffff") self.canvas_calories.pack(expand=True, fill="both") self.canvas_calories.create_image(0, 0, image=kcal_img, anchor="nw") self.canvas_calories.image = kcal_img self.canvas_calories.create_text(5, 9, text=" {} Kcal".format( self.product_kcal), anchor='nw', fill="#ffffff", font="Helvetica 10 bold") elif action == "refresh": self.canvas_calories.delete("all") self.canvas_calories.pack_forget() self.w_calories_label.pack_forget() self.w_calories_img.pack_forget() self.canvas_calories = None self.w_calories_label = None self.w_calories_img = None def row_4(self, action=None): """ Name : PRODUCT SUGAR cols : 3 """ line = "line_empty" line_lenght = 90 # ----- ROW 5 : PRODUCT SUGAR ----- # if self.product_sugar == 0: line = "line_empty" line_lenght = 90 elif self.product_sugar <= 10: line = "line_a" line_lenght = 90 elif self.product_sugar <= 50: line = "line_b" line_lenght = 180 elif self.product_sugar <= 100: line = "line_c" line_lenght = 270 elif self.product_sugar <= 150: line = "line_d" line_lenght = 360 elif self.product_sugar > 151: line = "line_e" line_lenght = 450 if action == "construct": # -- CREATE ROW -- # self.grid.row(width=self.width, height=55, padx=self.padx, pady=self.pady, bg="#ffffff") # -- CREATE COLS -- # self.grid.column(span=1, row=4, width=None, height=None, padx=None, pady=None, bg=None) self.grid.column(span=2, row=4, width=None, height=None, padx=None, pady=None, bg=None) self.grid.column(span=9, row=4, width=None, height=None, padx=None, pady=None, bg=None) elif action == "fill": # Get texts for this row txt = self.json_script.get("row_4") if self.w_sugar_img is None: # -- COLUMN 1 : SUGAR IMAGE -- # img = Image.open( "frontend/images/views/product_sheet/sugar.png") img_resize = img.resize((30, 30), Image.ANTIALIAS) sugar_img = ImageTk.PhotoImage(img_resize) self.w_sugar_img = Label(self.grid.col_frames[4][0], image=sugar_img, bg="#ffffff") self.w_sugar_img.image = sugar_img self.w_sugar_img.pack(side=RIGHT, fill="both", expand=True) if self.w_sugar_label is None: # -- COLUMN 2 : SUGAR LABEL -- # self.w_sugar_label = Label(self.grid.col_frames[4][1], anchor="w", text=txt.get("sugar_label"), bg="#ffffff", font="Helvetica 11 bold") self.w_sugar_label.pack(fill="both", expand=True) if self.canvas_sugar is None: img = Image.open( "frontend/images/views/product_sheet/{}.png".format(line)) imgResize = img.resize((line_lenght, 35), Image.ANTIALIAS) kcal_img = ImageTk.PhotoImage(imgResize) self.canvas_sugar = Canvas(self.grid.col_frames[4][2], width=self.width, height=35, highlightthickness=0, bg="#ffffff") self.canvas_sugar.pack(expand=True, fill="both") self.canvas_sugar.create_image(0, 0, image=kcal_img, anchor="nw") self.canvas_sugar.image = kcal_img self.canvas_sugar.create_text(5, 9, text=" {} g".format( self.product_sugar), anchor='nw', fill="#ffffff", font="Helvetica 10 bold") elif action == "refresh": self.canvas_sugar.delete("all") self.canvas_sugar.pack_forget() self.w_sugar_img.pack_forget() self.w_sugar_label.pack_forget() self.w_sugar_img = None self.w_sugar_label = None self.canvas_sugar = None def row_5(self, action=None): """ Name : PRODUCT STORES cols : 3 """ if action == "construct": # -- CREATE ROW -- # self.grid.row(width=self.width, height=55, padx=self.padx, pady=self.pady, bg="#ffffff") # -- CREATE COLS -- # self.grid.column(span=1, row=5, width=None, height=None, padx=None, pady=None, bg=None) self.grid.column(span=2, row=5, width=None, height=None, padx=None, pady=None, bg=None) self.grid.column(span=9, row=5, width=None, height=None, padx=None, pady=None, bg=None) elif action == "fill": # Get texts for this row txt = self.json_script.get("row_5") if self.w_stores_img is None: # -- COLUMN 1 : STORES IMAGE -- # img = Image.open( "frontend/images/views/product_sheet/store.png") img_resize = img.resize((30, 30), Image.ANTIALIAS) store_img = ImageTk.PhotoImage(img_resize) self.w_stores_img = Label(self.grid.col_frames[5][0], image=store_img, bg="#ffffff") self.w_stores_img.image = store_img self.w_stores_img.pack(side=RIGHT, fill="both", expand=True) if self.w_stores_label is None: # -- COLUMN 2 : STORES LABEL -- # self.w_stores_label = Label(self.grid.col_frames[5][1], anchor="w", text=txt.get("stores_label"), bg="#ffffff", font="Helvetica 11 bold") self.w_stores_label.pack(fill="both", expand=True) if self.w_stores_value is None: # -- COLUMN 3 : STORES VALUE -- # self.w_stores_value = Label(self.grid.col_frames[5][2], anchor="w", text=" {}".format( self.product_store), bg="#ffffff") self.w_stores_value.pack(fill="both", expand=True) elif action == "refresh": self.w_stores_img.pack_forget() self.w_stores_label.pack_forget() self.w_stores_value.pack_forget() self.w_stores_img = None self.w_stores_label = None self.w_stores_value = None def row_6(self, action=None): """ Name : AUTHOR cols : 3 """ if action == "construct": # -- CREATE ROW -- # self.grid.row(width=self.width, height=55, padx=self.padx, pady=self.pady, bg="#ffffff") # -- CREATE COLS -- # self.grid.column(span=1, row=6, width=None, height=None, padx=None, pady=None, bg=None) self.grid.column(span=2, row=6, width=None, height=None, padx=None, pady=None, bg=None) self.grid.column(span=9, row=6, width=None, height=None, padx=None, pady=None, bg=None) elif action == "fill": # Get texts for this row txt = self.json_script.get("row_6") if self.w_author_img is None: # -- COLUMN 1 : AUTHOR IMAGE -- # img = Image.open( "frontend/images/views/product_sheet/copyright.png") img_resize = img.resize((30, 30), Image.ANTIALIAS) store_img = ImageTk.PhotoImage(img_resize) self.w_author_img = Label(self.grid.col_frames[6][0], image=store_img, bg="#ffffff") self.w_author_img.image = store_img self.w_author_img.pack(side=RIGHT, fill="both", expand=True) if self.w_author_label is None: # -- COLUMN 2 : AUTHOR LABEL -- # self.w_author_label = Label(self.grid.col_frames[6][1], anchor="w", text=txt.get("author_label"), bg="#ffffff", font="Helvetica 11 bold") self.w_author_label.pack(fill="both", expand=True) if self.w_author_value is None: # -- COLUMN 3 : AUTHOR VALUE -- # self.w_author_value = Label(self.grid.col_frames[6][2], anchor="w", text=" {}".format( self.product_author), bg="#ffffff") self.w_author_value.pack(fill="both", expand=True) elif action == "refresh": self.w_author_img.pack_forget() self.w_author_label.pack_forget() self.w_author_value.pack_forget() self.w_author_img = None self.w_author_label = None self.w_author_value = None def row_7(self, action=None): """ Name : SUBMIT BUTTON cols : 4 """ if action == "construct": # -- CREATE ROW -- # self.grid.row(width=self.width, height=100, padx=self.padx, pady=self.pady, bg="#ffffff") # -- CREATE COLS -- # self.grid.column(span=4, row=7, width=None, height=None, padx=None, pady=None, bg=None) self.grid.column(span=4, row=7, width=None, height=None, padx=None, pady=None, bg=None) self.grid.column(span=4, row=7, width=None, height=None, padx=None, pady=None, bg=None) elif action == "fill": # Get texts for this row txt = self.json_script.get("row_7") # -- COLUMN 1 : EMPTY -- # if self.w_submit_button is None: # -- COLUMN 3 : SUBMIT BUTTON -- # self.w_submit_button = Button(self.grid.col_frames[7][1], text=txt.get("submit_button"), fg="#ffffff", bg="#7A57EC", activeforeground="#ffffff", activebackground="#845EFF", command=self.display_search) self.w_submit_button.pack(side=BOTTOM, fill=X, expand=True) # -- COLUMN 4 : EMPTY -- # elif action == "refresh": self.w_submit_button.pack_forget() self.w_submit_button = None
class Gem: def __init__(self): self.frame = Tk(); self.frame.resizable(False, False) self.status = 1 self.scorePlayerA = 0 self.scorePlayerB = 0 self.scoreRoundA = 0 self.scoreRoundB = 0 self.countRound = 0 self.quitMatch = 0 self.isQuitRound = 0 self.canvas_after_2 = 0 self.canvas_after_1 = 0 self.isPause = 0 #register event self.frame.bind("<F4>", self.quitGame) self.frame.bind("<F5>", self.pauseGame) self.frame.protocol("WM_DELETE_WINDOW", self.on_closing) self.registerKeyboard() def setName(self, title): self.frame.title(title) def setBall(self, ball): self.ball = ball def setLeftBar(self, bar): self.leftBar = bar def setRightBar(self, bar): self.rightBar = bar def run(self): self.frame.mainloop() def getFrame(self): return self.frame; def getCanvas(self): return self.canvas def setSize(self, size): self.frame.geometry(("%dx%d")%(size[0], size[1])) self.frame.update() def getSize(self): return (self.frame.winfo_width(), self.frame.winfo_height()) def setBackground(self, color): self.background = color def setPlayers(self, players): self.players = players def setScoreBoard(self): players = self.players size = self.getSize() mid = round(size[0]/2) # Board self.canvas.create_rectangle(mid - 100, 0, mid + 100, 35, fill="grey58", outline="white", tag="boarda") # Player name 1 self.canvas.create_text(mid - 80, 15, text=players[0], fill="magenta2", tag="boardb") # Round score 1 r1 = players[0]+"a" self.canvas.create_text(mid - 80, 28, text="0", fill="pale green", tag="scoreplayera") # Player name 2 self.canvas.create_text(mid + 80, 15, text=players[1], fill="magenta2", tag="boardc") # Round score 2 self.canvas.create_text(mid + 80, 28, text="0", fill="pale green", tag="scoreplayerb") # Box score 1 self.canvas.create_rectangle(mid - 50, 5, mid - 10, 25, fill="thistle3", outline="white", tag="boardd") # Score 1 self.canvas.create_text(mid - 30, 15, text="000", fill="cyan", tag=players[0]) # Box score 2 self.canvas.create_rectangle(mid + 10, 5, mid + 50, 25, fill="thistle3", outline="white", tag="boarde") # Score 2 self.canvas.create_text(mid + 30, 15, text="000", fill="cyan", tag=players[1]) self.canvas.pack() self.frame.update() def clearScoreBoard(self): self.canvas.delete(self.players[0]) self.canvas.delete(self.players[1]) self.canvas.delete("boarda") self.canvas.delete("boardb") self.canvas.delete("boardc") self.canvas.delete("boardd") self.canvas.delete("boarde") self.canvas.delete("scoreplayera") self.canvas.delete("scoreplayerb") self.canvas.update() def initCanvas(self): canvas_width = self.frame.winfo_width() canvas_height = self.frame.winfo_height() self.canvas = Canvas(self.frame, width=canvas_width, height=canvas_height, bg=self.background) self.frame.update() def setDashboard(self): size = self.getSize(); midw = round(size[0]/2) midh = round(size[1]/2) self.canvas.create_oval(midw - 120, midh - 70, midw + 120, midh+70, fill="alice blue", outline="white", tag="dash1") self.canvas.create_text(midw, midh - 35, text="F1: Machine Vs Machine", fill="blue violet", tag="dash2") self.canvas.create_text(midw, midh - 10, text="F2: Human Vs Machine ", fill="blue violet", tag="dash3") self.canvas.create_text(midw, midh + 15, text="F3: Human Vs Human ", fill="blue violet", tag="dash4") self.canvas.create_text(midw, midh + 38, text="F4: Quit Game ", fill="blue violet", tag="dash5") self.canvas.pack() def clearDashboard(self): self.canvas.delete("dash1") self.canvas.delete("dash2") self.canvas.delete("dash3") self.canvas.delete("dash4") self.canvas.delete("dash5") self.canvas.update() def setWinter(self, status = -1): size = self.getSize(); midw = round(size[0]/2) midh = round(size[1]/2) if status == 1: textstr = self.players[0] + " Win" elif status == 2: textstr = self.players[1] + " Win" elif self == 3 and self.scorePlayerA != self.scorePlayerB: if self.scoreRoundB > self.scorePlayerA: textstr = self.players[1] + " Win" else: textstr = self.players[0] + " Win" else: textstr = "Not Match" self.canvas.create_oval(midw - 50, midh - 20, midw + 50, midh+20, fill="alice blue", outline="white", tag="wintera") self.canvas.create_text(midw, midh, text=textstr, fill="blue violet", tag="winterb") self.canvas.pack() self.canvas.update(); def clearWinter(self): self.canvas.delete("wintera") self.canvas.delete("winterb") self.canvas.update() def quitRound(self, status): if self.scorePlayerA >= self.maxRoundScore and self.scorePlayerB >= self.maxRoundScore: self.isQuitRound = 1 if status == 1 or status == 2 or self.isQuitRound == 1 or self.quitMatch == 1: if self.isQuitRound == 0: self.updateScoreRound(status - 1) self.isQuitRound = 1 self.ball.quit(self.canvas) self.leftBar.quit(self.canvas) self.rightBar.quit(self.canvas) return self.isQuitRound def nextRound(self, status): self.canvas.after_cancel(self.canvas_after_2) if status == 2 or status == 1: if self.maxRound > self.countRound: #self.ball.quit(self.canvas) #self.leftBar.quit(self.canvas) #self.rightBar.quit(self.canvas) self.resetRound() self.countRound += 1 self.leftBar.reset(self.canvas) self.rightBar.reset(self.canvas) if status == 1: self.leftBar.transferBall(self.canvas, self.ball) else: self.leftBar.transferBall(self.canvas, self.ball) #print(self.canvas.find_withtag(self.ball.name)) else: self.stopMatch() def play(self, event): self.clearDashboard() self.unRegisterKeyboard() if event.keycode == 112: self.isPause = 4 self.startMatch() self.machineVSmachine() elif event.keycode == 113: self.isPause = 5 self.leftBar.registerKeyboard(self.frame) self.startMatch() self.machineVShuman() elif event.keycode == 114: self.isPause = 6 self.leftBar.registerKeyboard(self.frame) self.rightBar.registerKeyboard(self.frame) self.startMatch() self.humanVShuman() def machineVSmachine(self): try: if self.ball.exists == False: self.isQuitRound = 0 if self.isQuitRound == 0: rs = self.ball.move(self.canvas) self.leftBar.autoMove(self.canvas) self.rightBar.autoMove(self.canvas) rs = self.update(rs) if rs == 1: return ; self.canvas_after_1 = self.canvas.after(10, self.machineVSmachine) except: print("I am so sorry!") self.stopMatch(0) def machineVShuman(self): try: if self.ball.exists == False: self.isQuitRound = 0 if self.isQuitRound == 0: rs = self.ball.move(self.canvas) self.leftBar.move(self.canvas) self.rightBar.autoMove(self.canvas) rs = self.update(rs) if rs == 1: return ; self.canvas_after_1 = self.canvas.after(10, self.machineVShuman) except: print("I am so sorry!") self.stopMatch(0) def humanVShuman(self): try: if self.ball.exists == False: self.isQuitRound = 0 if self.isQuitRound == 0: rs = self.ball.move(self.canvas) self.leftBar.move(self.canvas) self.rightBar.move(self.canvas) rs = self.update(rs) if rs == 1: return ; self.canvas_after_1 = self.canvas.after(10, self.humanVShuman) except: print("I am so sorry!") self.stopMatch(0) def startMatch(self): self.setScoreBoard() self.quitMatch = 0 self.isQuitRound = 0 self.countRound = 0 self.nextRound(1) def resetRound(self): self.scorePlayerA = 0 self.scorePlayerB = 0 self.isQuitRound = 0 self.updateScorePlayer() self.leftBar.registerKeyboard(self.frame) self.rightBar.registerKeyboard(self.frame) def update(self, status): self.updateScorePlayer(status-3) self.canvas.update() if self.quitRound(status) == 1 and self.quitMatch == 0: self.leftBar.unRegisterKeyboard(self.frame) self.rightBar.unRegisterKeyboard(self.frame) self.canvas_after_2 = self.canvas.after(800, self.nextRound, status) if self.quitMatch == 1: self.leftBar.unRegisterKeyboard(self.frame) self.rightBar.unRegisterKeyboard(self.frame) self.isQuitRound == 1 return self.quitMatch def updateScoreRound(self, status): if self.scorePlayerB == 0 and self.scorePlayerA == 0: return if status == 0: self.scoreRoundA += 1 self.canvas.itemconfig("scoreplayera", text=self.scoreRoundA) elif status == 1: self.scoreRoundB += 1 self.canvas.itemconfig("scoreplayerb", text=self.scoreRoundB) def updateScorePlayer(self, status = 5): if status == 0: self.scorePlayerA += 1 self.canvas.itemconfig(self.players[0], text=self.__countScore(self.scorePlayerA)) if self.scorePlayerA != 0 and self.scorePlayerA % 5 == 0: self.ball.speed +=1 elif status == 1: self.scorePlayerB += 1 self.canvas.itemconfig(self.players[1], text=self.__countScore(self.scorePlayerB)) elif status == 5: self.canvas.itemconfig(self.players[0], text=self.__countScore(self.scorePlayerA)) self.canvas.itemconfig(self.players[1], text=self.__countScore(self.scorePlayerB)) self.canvas.update() def __countScore(self, score): if score < 10: scorestr = "00" + str(score); elif score < 100: scorestr = "0" + str(score) else: scorestr = str(score) return scorestr def stopMatch(self, event = 0): self.isQuitRound = 1 self.quitMatch = 1 self.leftBar.unRegisterKeyboard(self.frame) self.rightBar.unRegisterKeyboard(self.frame) self.canvas.after_cancel(self.canvas_after_1); self.canvas_after_3 = self.canvas.after(500, self.returnMenu) def quitGame(self, event): self.isQuitRound = 1 self.quitMatch = 1 self.leftBar.unRegisterKeyboard(self.frame) self.rightBar.unRegisterKeyboard(self.frame) self.canvas.after_cancel(self.canvas_after_1); self.canvas_after_3 = self.canvas.after(200, self.destroy) def destroy(self): self.canvas.after_cancel(self.canvas_after_3) self.frame.destroy() def returnMenu(self): self.canvas.after_cancel(self.canvas_after_3) self.ball.quit(self.canvas) self.leftBar.quit(self.canvas) self.rightBar.quit(self.canvas) self.clearScoreBoard() self.clearWinter() self.setDashboard() self.registerKeyboard() def setMaxRound(self, max): self.maxRound = max def setMaxRoundScore(self, max): self.maxRoundScore = max def registerKeyboard(self): self.frame.bind("<F1>", self.play) self.frame.bind("<F2>", self.play) self.frame.bind("<F3>", self.play) self.frame.unbind("<Escape>") def unRegisterKeyboard(self): self.frame.unbind("<F1>") self.frame.unbind("<F2>") self.frame.unbind("<F3>") self.frame.bind("<Escape>", self.stopMatch) def on_closing(self): self.quitGame(0) def pauseGame(self, event): if self.isPause == 1: self.isPause += 3 self.machineVSmachine() elif self.isPause == 2: self.isPause += 3 self.machineVShuman() elif self.isPause == 3: self.isPause += 3 self.humanVShuman() elif self.isPause > 3: self.canvas.after_cancel(self.canvas_after_1) self.isPause -= 3
class Game: def __init__(self): # レベル self.level = 1 # 点数 self.score = 0 # 表示速度 self.speed = 500 # レベルアップのためのカウンタ用変数 self.counter = 0 self.create_new_game = True # メインのフレーム self.root = Tk() self.root.title("Puzzle") label_font = ("System", 10) # レベルとスコアを表示する文字 self.status_var = StringVar() self.status_var.set("レベル: 1 スコア: 0") # レベルとスコアを表示するラベル self.status_label = Label(self.root, textvariable=self.status_var, font=label_font) self.status_label.pack() # ブロックを表示するキャンバス self.canvas = Canvas(self.root, width=WINDOW_WIDTH, height=WINDOW_HEIGHT) self.canvas.pack() # キー操作に対応するイベントを登録します self.root.bind("<Key>", self.event_handler) def event_handler(self, event): if event.keysym == "Left": self.current_block.move(-1, 0) if event.keysym == "Right": self.current_block.move(1, 0) if event.keysym == "Down": self.current_block.move(0, 1) if event.keysym == "Up": self.current_block.rotate() def start(self): # タイマー処理を開始します self.timer() # フレーム表示 self.root.mainloop() def timer(self): if self.create_new_game == True: # ゲームを開始時点で新しいブロックを作ります self.current_block = Block(self.canvas) self.create_new_game = False if not self.current_block.fall(): # 画面の下端に到達、または他のブロックに重なったので移動が終了しました # そろっているブロックは削除します lines = self.remove_complete_lines() # 削除しなかった場合、False、削除した場合、削除行数が返ります if lines: # 削除した行数に応じて、スコアアップ # 10 * levelの2乗 * linesの2乗 self.score += 10 * self.level**2 * lines**2 # スコアを表示 self.status_var.set("レベル: %d スコア: %d" % (self.level, self.score)) # 新しいブロックを作成して、画面に表示します self.current_block = Block(self.canvas) # ゲームオーバーの判定 if self.is_game_over(): # ゲームオーバーなので終了処理 self.create_new_game = True self.game_over() # ブロックを5個処理するとレベルアップする機能 self.counter += 1 if self.counter == 5: # レベルアップ self.level += 1 # スピードアップ self.speed -= 20 # レベルアップカウンタを初期化 self.counter = 0 # スコアを表示 self.status_var.set("レベル: %d スコア: %d" % (self.level, self.score)) # self.speedの間隔でself.timerを何度も呼び出す self.root.after(self.speed, self.timer) # ゲームオーバーの判定 def is_game_over(self): # ブロックが移動することができない場合、ゲームオーバー for box in self.current_block.boxes: if not self.current_block.can_move_box(box, 0, 1): # 移動できないのでゲームオーバー return True # ゲームは継続 return False # 落下が終了した後に、ボックスがそろっている行があれば、削除します def remove_complete_lines(self): # 現在の処理対象ボックスの右下角のY座標をリストに代入します block_boxes_coords = [] for box in self.current_block.boxes: # coords は[x1, y1, x2, y2]の形式で座標を取得します # x1, y1はボックスの左上角、x2とy2は右下角 block_boxes_coords.append(self.canvas.coords(box)[3]) # キャンバス内のすべてのオブジェクトを取り出します all_boxes = self.canvas.find_all() # 全ボックスの右下角のY座標をリストに追加します all_boxes_y = [] for box in all_boxes: all_boxes_y.append(self.canvas.coords(box)[3]) # 全ボックスと座標を合体したリストにします zipped = zip(all_boxes, all_boxes_y) # 全てのオブジェクトを辞書にします # 辞書のキーはオブジェクトID、辞書の値はY座標 all_boxes_coords = {} for d in zipped: all_boxes_coords[d[0]] = d[1] # setに変換して、重複値を除く lines_to_check = set(block_boxes_coords) # 現在処理中のブロックのボックスと同じ行のボックスを取り出す boxes_to_check = {} for k, v in all_boxes_coords.items(): # 現在のボックスと同じ行のボックスを取り出します for line in lines_to_check: if v == line: # Y座標が同じであれば同じ行とします boxes_to_check[k] = v break # 同じ行にあるボックス数を計算します counter = Counter() for box in boxes_to_check.values(): counter[box] += 1 # 同じ行のボックス数が、「ウィンドウの幅/BOX_SIZE」と同じなら # 行がボックスで埋まったことになります complete_lines = [] for k, v in counter.items(): if v == (WINDOW_WIDTH / BOX_SIZE): # 1行がそろったので削除対象の行を追加します complete_lines.append(k) # 削除する行がない場合、ここで処理は終わり、Falseを返します if not complete_lines: return False # そろっている行のブロックを削除します for k, v in boxes_to_check.items(): # 対象のブロックが、削除する行に含まれている if v in complete_lines: # 対象のブロックをキャンバスから消します self.canvas.delete(k) # 全てのブロックを保持するリストからも消します del all_boxes_coords[k] # 削除した行の分だけ、全体を下に移動させる for (box, coords) in all_boxes_coords.items(): for line in complete_lines: # 削除行した行よりも上に位置するかどうかを判定します if coords < line: # 削除した行よりも上なので、ボックスを下方向に移動 self.canvas.move(box, 0, BOX_SIZE) return len(complete_lines) # ゲーム―オーバー処理 def game_over(self): # 全てのオブジェクトを削除 self.canvas.delete(ALL) # メッセージ表示 messagebox.showinfo("ゲームオーバー", "スコア:%d " % self.score) # 画面を閉じる self.root.quit()
class GPIOSim(Frame): #********** Settings ******* # ND; ND; IN_LOW; IN_HIGH; OUT_LOW; OUT_HIGH; GPIO_ND; GPIO_ND PIN_COLORS = ["black","black", "#9ADA90", "green", "#74C6BD", "blue", "yellow", "yellow"] PIN_SIZE = 15 PIN_DISTANCE = 10 START_X = 140 START_Y = 20 GPIO_STATE_DEFAULT = [ 0, 0, #3v3 , 5v 3, 0, #GPIO2 , 5V 3, 0, #GPIO3 , GND 3, 3, #GPIO4 , GPIO14 0, 3, #GND , GPIO15 3, 3, #GPIO17, GPIO18 3, 0, #GPIO27, GND 3, 3, #GPIO22, GPIO23 0, 3, #3V3 , GPIO24 3, 0, #GPIO10, GND 3, 3, #GPIO9 , GPIO25 3, 3, #GPIO11, GPIO8 0, 3, #GND , GPIO7 0, 0, #I2C , I2C #FROM HERE 3, 0, #GPIO5 , GND #RPI >= B+ 3, 3, #GPIO6 , GPIO12 3, 0, #GPIO13, GND 3, 3, #GPIO19, GPIO16 3, 3, #GPIO26, GPIO20 0, 3 #GND , GPIO21 ] GPIO_NAMES = [ "3v3","5v", "GPIO2","5V", "GPIO3","GND", "GPIO4","GPIO14", "GND","GPIO15", "GPIO17","GPIO18", "GPIO27","GND", "GPIO22","GPIO23", "3V3","GPIO24", "GPIO10","GND", "GPIO9","GPIO25", "GPIO11","GPIO8", "GND","GPIO7", "I2C","I2C", "GPIO5","GND", "GPIO6","GPIO12", "GPIO13","GND", "GPIO19","GPIO16", "GPIO26","GPIO20", "GND","GPIO21" ] BG_COLOR = "white" TEXT_COLOR = "black" #******** End Settings ******** WIN_WIDTH = 2*START_X + 2*PIN_SIZE + PIN_DISTANCE WIN_HEIGHT = 2*START_Y + 20*PIN_SIZE + 19*PIN_DISTANCE WIN_SIZE = str(WIN_WIDTH) + "x" + str(WIN_HEIGHT) + "+200+100" STATE_ND = 0 STATE_GPIO_IN = 1 STATE_GPIO_OUT = 2 STATE_GPIO_ND = 3 VALUE_HIGH = 1 VALUE_LOW = 0 WORK_DIR = os.path.join(tempfile.gettempdir(), "GPIOSim") #os.path.join(os.path.expanduser('~'), '.GPIOSim') WORK_FILE = os.path.join(WORK_DIR, "pins.ini") currState = [None]*40 currValue = [None]*40 def __init__(self, parent): Frame.__init__(self, parent) if not os.path.exists(self.WORK_FILE): os.makedirs(self.WORK_DIR) self.simulateReboot(True) self.parent = parent menu = Menu(self.parent) menu1 = Menu(menu,tearoff=0) menu1.add_command(label="Simulate Reboot",command=self.simulateReboot) menu1.add_separator() menu1.add_command(label="Quit!", command=self.parent.quit) menu.add_cascade(label="Menu",menu=menu1) # display the menu self.parent.config(menu=menu) self.parent.title("GPIOSim") self.pack(fill=BOTH, expand=1) self.canvas = None self.canvas = Canvas(self, bg=self.BG_COLOR) #self.canvas.bind("<Button-1>",self.click) #Images (gif base64 encoded) imgInLeft = "R0lGODlhHgASAOf7AAoMCAITBBcQCAYbAAsaEBUYEBEaCRMeCB0ZIREhGRkhFB0gEyMmGiIpFy8mNTQyNiROCCJZACxYCTlUKzpWGyleADBeBjRdGCxiCShlAEFcM0BeKDJmAzpmBCFwADxlIBt1BC9yBGpZW0NpMTtvDzttKkdqPid8AENxHD12DDh5AE9tPEZyJUV2Lzh/AF5rYD5+CEV+Fz+AGFxzT1h4LUx9NUaEAkCGA2dxYUqCEF91V1V8ME+AG0WHADuKCFl/RU+IIT2PG2l8XkqPAEuMJFmFREWTBVCRDzGcAHl6g2yBaEuWADybAEKZDkaaAHCHYnaCgneEeFCcA2WPR0ChB1qaA1ebFnuIbk2gCkSlAFCiAFegAF6fAFehD3ORXmueEXOWT26aQU+qBnCZV1inF3yUboCRhWWmBlmqCnuYa2OqAGGqDGOnJVevAF6tAEi0AG2sAF2vIYyXhomado2Ze1S2BmOyBHKpO1e3AGqxBVy1B1q0GXKwAG6sNEm9AH2tB3WrNYmfc22zAHumX2K4AH+maWO0NW61D2m4En60AHK4AGy6AHm3AIW0AHW2IYKsYoSrbnuzPW22S2u7JXS3NpKzBmDAG5CyGW66OI2ph3G7MIuyP4mteou5AHu/AIOzYXa7QpSpnKajqHu8M4O/AIG+EZy4AHe/K4m+AJytdZW8AIO4XnDCNp+ug429KaGrppG4YX+8dHzDUZnAHZ3CAJ/AJo7FK5O+c5+7cp7CP5jKJ5bIQpvAhqi8ia+6lYfLZ5PPHZrFbKHNDK/HVqnJcqHRPqDSTLvDq7TTN7jGubTLnMbRO8DTQ8TGw7DSjb/UVLDSmMTTZ7rYXbjWeMvVVNPSX8jZQbnfOMjYYcfbU7Xeb9XaTs/abt7XcMLjUMXhe8fficvbwdzV4czncNnb2NThwcnkztXlt+nr6OXy2Ozx9PLx6OP34vnv9e306fzx/vP35vL3+ff2/v/3/fj69//58v/76//6+PH/8/L///799P78//j/9Pb/+vn+//3//CH+EUNyZWF0ZWQgd2l0aCBHSU1QACwAAAAAHgASAAAI/gCJATpFKRIrTM5+YYpEadIoUNBkadLUJ5KhVfDe9cO3b58/doaodEGj5gwaYneQiDmzxgqmW0yy7LHjpgsmd/9y/rs37xwbNdeWIePSB1cXRtuY6VqyKlgVRtaWAXMSC96+fvb0+ZvnDMsfatmKSZF0a4iibNlqMRkEy4grsJua8Lq37x8/fzl5GXE0TtouJJA4IbHV7RmiJp8+MSlWzZuiI8o6/qs7790gJ666YbPVoxeYIbnGRUOUI1WYL7OE0UJDJNy+e/T2xe4HZMkwbtwsgYBGhIyxarXcBOEEBI0qU6SWhEnXzh8/ffvipduBZRq4b2tI+OKxJZEqT06m/hS6kQdVpUQ9xtDj19Gev33lUMTRFm2WlhqZYsAh1anRkDFp3IDHcYec8Mhk/8ADnTkpYHHJJYs4QUMgMnDRCCqL2OCFFzeo0UgnioQwh0f+6KOPOiMYIQiIYnDQCgtPNaJIE0WUQQIXiZRyiAtTrHOPP/nc888KMORBiiB2VBCKCUPkwYgnW5RgRgld8JFIHka0EE49WnWkRAiI5AEHGhnQoYMKbthxiBYdXPGDD3YgWQULydRFD3SvYIAGIWq4oYIQV2QQJx56cIBDGR4sogYhaJAgR0d40XOMBF3ogYYdPawQhQRouKGGHiHoYEYEe7iRRxsWPDFZR/uIs8EQY2KssYYTGkBxgRRdtFFHCjMkAUEbbVzqwQsK5nSPPBvAUMcbeFgRwQsfDFEHHnbkQAEOt77hRxspTICOTjmJIMACCSRgQAEPOAAAAQQEMMABDCAwbgEKHNCAKM2QQw469PwTEAA7" imgInRight = "R0lGODlhHgASAOf8ABcOChASDwkZDg8YBxcZCw8dDicUJhcdABkfCxgmBBApABwnDi4kLCsnJjJHICNUBCZUACxdBC5fAD5XKTFgEiRmATZeLUVcOTpiJDhnGStuADZrDzxpFEZlLjVvATxuASl0ADpyAEhpODtzGUxrQEpwHUlwJDp6AVFsXlVwLUp0Ll9rXTaACF5uSzOEADuCAFpzTFJ5LWprdEx+HEWEEkiGBVh3bkaGEzWNADyMClh/PD+NAEeMAESKJjiSEk2MG2GAWVGMLTmYAFqJOkOXAFmKQXCBXUqWAHd8fkmWC22EX1KWDk+aAE2aE0edFUqeBHuEf3iJfEmkAFCiAF6dE1ihAF+gAHmQXkynAGeaPEWqAn2OfHWSbmKfOH+Sc16nBViqCU2vAFCsG4STe2KqAGeoC1SuD2KnLnedVYCXfWynHF6uAFiwAHCpEIaXhWeuAHOrAHmhUmOtII6YdVS1BWavFVa2AIOea2mqQoGgZnCvBGSzB3mvAH+uAGyzC1O8AGuwOG+1AGm3AHGyKGS6AIOyAHm2AG26AHuwOo2jiWm2PHS6Ani3FXa1NYKsa3a3I4G4BX+3GJmjkm65N421BpCpeW69GnG6MIGxX3O7Jma/KJS1C3q+AHm4SG7DAIq7AI63I5W3IHO/QYS2aoO+IZW8AIG6Une9YH3DFnjCN4+6W6CvlpqxlqC/AJvBAJC7ZpbDDYvHDpK8cZe4jpq7a6DBIJ26dbK+JIvIN4vJLpzELprEN4jGd57EUbW4lZbGc6bJPpzIaJnJdpzLXaPMQL7KMqjJjJHVcKvOl7zIsLbNnrfUWsrOYbLQoMXWNMbUTsbVV8vWQNDTVLbZc7/aUcXaQdXOjbnfOMrMycHaWbfeaL/hZcfkNsffbdPfUd/bcMHld9XW4NnjdN/c4dHjxdzfz8ztf+Di38vvtvXm9enr6Oby3/Py6ev26vzz7Or63/b0+Pb2//f61e/76Pb49P/1++77/Pb7/vn/4Pf+8/X/+v/8+/78///+9fn///3/+yH+EUNyZWF0ZWQgd2l0aCBHSU1QACwAAAAAHgASAAAI/gD55fvH7969d50aTRp0yZKqZqIUZboE6FEwZJoUNWI46Vi/ffTu8ZOH6AmZOmDCOOGVSooaPV+0nPklpswaMmuedMGXr94/ffReHcnF7VkkJrRMVanlrNqiJsLOkCkW7VqZM+j+iYTXz1aOTNCi7eLxStURXNKqRUoiCw8WYNCktWnSbF8/fvT+KUvyaJs3YEJOYSJiiVo2UDgcYRKyC9o2Rkl43fP5k9yPKaVuwaKSZRSNMt3EEWuCxlYNUsy+4eIRJx+/ePfcvQvCJFarUmSCVPoBRhe0YVR6GHNRxxy4XkSKzOMHTx/zPDkMtfq0h8adLkcguaJkxYcvD3LA/lmbhmXGun/7/vX754iFn1Kl9rC4gmbHok2G1syoFAMLqmXa1PEBOesZxM8/c4DgSR+UrPECF1fwQEghlIDBQiIlMHFIKKA8McI5BxJ0YDpDuMBIH5xUMYIXOjwRCCWLPGHCLBJ8YUghhyTRgT30fESPa+WYsMQhehjChAppYPAFJ3r4sQMJrECwhiF8vHEECT3x048++eyTzAZMvBGIIDXoEEUGUwQCByEhAJHGB3vooUcYHijBj5b6/KOVGxx8cZMfGnixggdrBLLGGhVsscIJYfjhBxgcSJKXSAYascEea4BhhgRjwEDoGmyAEUEUIuQAxhtsNEFBMiL1E5I+ZOy0UAEddIBBxgNIwPBCSnUcEQEUFzTBxrA1TBDOnXqKxI4DKbBhBx1rPGCDBTXQEQYdS1iAAgRVhPEHGyxg0M6B6owTDjarKJBAAQIgAIABDBwwALsEAMBAAwsQcEACCwQgQ0AAOw==" imgOutLeft = "R0lGODlhHgASAOf7AAgiSgYlPA8nNQYrLRUnOhovUxwwRB0yNgA2eiIzPyoxQgA2jh46TR85Wik9Vz44TBM/jARElgdEnSI/gRFEihhEfipBcgBIrQBLpBBFtwBOmhZLkSlJeQBSnABUpQBWrghTxABWwyNPpCBTjRZXlxpWowdZvxRXtABetyVYjBdWzxdbpABgvwBd4ABd5wBg2wRjyhpevwRj0BpexSlawxtc2TFbpBtd0wBk5TFdnwplxQxk2QBn4ThfjxNk6ABtzABs2QBr5gBq9BNrtABr7RhozwFt4jlloU5kdB1o3kllhQpv3QBy3i9rnABz2QBy5Uxjohdwww5x2A9v6wB3zwB070NqjgF5xAB26gB34zRtrgB50QB1/wB74R504wZ76DBv7mVpjwB+6gp77yF16k1vp0NwwQB+/wCC7jx0ygCC9kd2pmJwoCt9w092og6D6lp2lx5/9R6A71N2tgSJ6CB//AiG/z961BaH4E940Fl6oACL/j994COH2j2Bz06AqiaG5gCQ9QCS4xiK+DOG0zaE30CA7gCS/1GBxW5/kwGW9R+O9R+P71GD222BpV6GoAeY8GaFmkmKvzOM7TKP4mCLsACh+TGV4Red74CGqVSQzUiT1TGX+EuS3nyLqlqS1nqOshOn6zOe6nCTqGGUzGWVwSel8EOe5XCVvGiV23GWt0yb/3OWy3WW4kqj62+frHyZyG+e3oaduiiz/nGj0o+bzoKe4Tiz8Uqt+3ai6UWx6mOq+6ehrGGx7IGp5DS+/Ea5/5Wo7pSsyl656kO//zrG4j/F6H2z5V27/DzG/VTB85uyw4G411HH/5a52KW5uH7A/2nN81HV/6jA0nTL/2fQ/2PU+X7P8ZjO4JTN+bzL36fQ7LjL8rDQ4MfNz9HUxNvX0sfj7tLo+N7m7+Tp7OTw5/Px9fL08dr7/vj07Pzy+fv14O73//H3+fr18+P+6P/19u387//2/Pj69/X88fD9/u3/+P/92v/6+fT++f/87f77//j9//j/7v7+9Pz/+yH+EUNyZWF0ZWQgd2l0aCBHSU1QACwAAAAAHgASAAAI/gDzpcM375+8d50GFbpD6dKmbX4MTWrDCE+uYIAA+QFEiRCzfPz87Ztnr1GRJ3WY8MDhyxARI1Kk4ACTa4oUKmdcvODD7hzIf/VouViU7NelGL0+oRCVjBidFrTaOPllbNaYNOL2/RPZz5mKQrqamTLRatOLU9KKyTFxLE+UW8qIXYnC7V7Ifeu6oYjTzBouE6lKgcA0TJooFbbm4MDUDFmdFs7a+VNXz1y5E0AghcKEIw8pHV+oVVsVQlOpF5eiUbsUopW+fPH08UOn5cUgS5CMFIE1REgoV8BmmImlow+0a51gSDo3st6+dH92iBmkKIsJVHNuLFKkCIgWWTGu/mTDtquFlnL89vXTSurEmEGHvnhQhSjEF0GQiNBANeQHp2HIZNGEOPKEhI859QizwBd0MDJGDGvAkkEdgtAxxQeVlFHDFm/Y8cMK4cDzDz3/8NOOOqx4sEUgYwBRghuasCBGF3ssUUItIkhhxxNo6NCEOfT4ww8/BrFjhQdYoPEFFiuM0sMOdnThxQ45vOIBEHiokUUISuTDXD5C+jPOESZ4oUYVMNiQyQZGvEGFGhc8kogEWXxRxRga6KHVOf/Y484+2pAAAxlfZAECFJ5Q8IQaTnCRQSSOXIBFFUt0cQEo6ezTjj377JPPMhTI8MUSQHzghioLtCCHEEJEkAgbdhegMQUQVUAwDZHp4ePPP6BIwIMQVTixQRiZaEDEFlm80EEkSnwgxBNAyFDBN/NoNY9I/CAxwQtGEIEDAnBw0MEORAghwwhKVMBCEEkAgUEK42hFDjjgePOMBQ0ckEABBOgbAAACDDAAAQ8owIABBDjQgAO8BAQAOw==" imgOutRight = "R0lGODlhHgASAOf7AAsjMAklQQYnOA8lNxAnPyAoOBosNRowPhUyRAoyfic1OgA4kRw3WCo3RABAmTA9SgNDoydAWRZBiABHnwBGsgtHjRtCkCxCYSREeQBJvgFOoAFNrRZIqQROpx5LeQ5OmgBQvSBQlwBWvRJVlQBWygRZuDBSfAVarAJX0wBbyB1YpQ5btQBd0Q1Z1SdYkwBhuQBhxwBf2xdcywBh4wJi1xhevjRcjBpexSRfnwhlxRtirgBnzB5e1DFfmx9itgBm7yhjnRFowSlmmgBr5hZl4gBs4ABr7SBpowBu1Bhn1Rhozxhn3EpkbUNjjhdsuABu6ABw4gBy0Ddolwpv3QBw8QBy3ght+FRjgCBp5gBx+Q5v5ABz7RBv7DxskgB36wB45RVz2gB64FJoqU1smAR82wB+1Rt21gB94T9wuWFqlAp69gB/6wCA5Td0vAB/+QCA80l1mRN960tytxN/3xZ98ih56DZ51TZ6zwCI5y559x2B6GF1mAaI7gWM3QCM8U55yyCF3i6D0DOA4gCP6iKH2hOI/TGD1xKJ90GCt1x8pmV8mUCB1wCR9ymH6E+Bv1d/vnB8lACV7GKBnC6I8DyH4z6H6l2CyAyX9gCb+TSO6T6N2yOU5m+Go0CQ2ACg+FOM0HeGpEuO13SHq2qLsjOY5X2Jol6Qy3mMpGePwhek4R+g8jKb7nKRrW6SsyKk7GKUz0aZ9Teg7XeU1nGYxUeh6HOax3qYx4SbuGue63ygtW6h2YOfwjOx/Xqg4W2m0ZmdrECx94qf0GKq4GCs74enw0y084Gn8GGx7Di9/4Kq5kq850W/9jzD842v5Ve/+WK891q+/4a240HJ/5a2xYu52VvG+Ke9r6y7zm3K/qW921fR/3jI/mXO/2zN+pLL95TP573J16vP2MfJxqrO69XZyNfZ1s/l7s/s6eDp8ejq59/v9uzx9Pbz+OT67P307ev4///09fb2//D69P32///2/Pb98vH+//r8+f/7+f/+4fX/+v78//j+///+7//+9f3//CH+EUNyZWF0ZWQgd2l0aCBHSU1QACwAAAAAHgASAAAI/gCjCcpESRAgQ82MUcJDiFKlQOM6acpkp9KkT/Lu7fOHb5++d4tazIhTBowRXHViaAEzxQglYzyMTKmzhUYlffs26uPn79ydLbyYIdMSyJcSPcikuYJhSliOPsykbUoyy94+fvXY7cs3LkgZaMuARfmTrAYfZdpi0QiFC4YqacUayaBWb9+/f/T+scsmI8+zaqtmWOrFglS3Z5FQoHpFAhg3Z3RKhOs3758/fpZlFebWTVWKWq9S0OKGrc6NWn+IeErFqIgPcxr9Xd0XD1EOWN22EVqhq00SXsBcUXEyKwkST57wxECjjt/Vuv/aoYkx7Ju3Lyt2HRnCB9MgGnJa/onYEumSHhKO5OHFtxMfOiFmnh1jhOSILR1GLvV5g35WhzOMHBKZKRr9I88+7phzAhKF4AEIC3KMsoEWjEQSRwa2wMFDGIMw4oUDxFylzz/4rCMFDHp4UQgSHwTzAXd8rAHDI4mcAEUcfpzRASo5jfhPPU2I8AUbeBQxQS42LPEGHl8kgQMrKjwxxxterNDFO3nhgw8/kmiwhRtrDKEBJ4ls8AUZYSwRQik97BBHHGqIAIQ6svGDjzu3mBlGFk9swIkiFGThRRhaVCCKGCKEwcYWLLgAzj7w/MPPPddYUAQUVXjBwR6QTDCEFWpMsQArY4BQRKZKVDCNbB7xQw4GaDyAocUPL3QhSQVFIBFGERCAksYHslqBhQOn6MMqP+uYsMETRgyRgwRXjFADFkbQoIEHiiSwRBFFEOEAE/f8c0+4//wSQQQPHIAAAg80MIAAAAwQAAENGEAAAwUowMAF1ohTTjnphBsQADs=" self.phInLeft = PhotoImage(data=bytes(imgInLeft, 'latin1')) self.phInRight = PhotoImage(data=bytes(imgInRight, 'latin1')) self.phOutLeft = PhotoImage(data=bytes(imgOutLeft, 'latin1')) self.phOutRight = PhotoImage(data=bytes(imgOutRight, 'latin1')) self.updateUI() # Method that updates the current status, getting info from the file # Shall be called on receivment of SIGIUSR (sent by the GPIO class) def updateUI(self): self.canvas.delete("all") c = RawConfigParser() c.read(self.WORK_FILE) x = self.START_X y = self.START_Y for i in range(0,40): state = c.getint("pin"+str(i),"state") value = c.getint("pin"+str(i),"value") ident = 2*state+value self.currState[i] = state self.currValue[i] = value e_x = x + self.PIN_SIZE e_y = y + self.PIN_SIZE self.canvas.create_oval(x, y, e_x, e_y, outline="black", fill=self.PIN_COLORS[ident], width=2, tags='pin'+str(i)) self.canvas.tag_bind('pin'+str(i),'<Button>', self.click_cb(i) ) if i%2==0: #LEFT COLUMN GPIOS self.canvas.create_window(x-70, y+10, window=Label(self.canvas, text=self.GPIO_NAMES[i], fg=self.TEXT_COLOR, bg= self.BG_COLOR)) if ident==2: #IN_LOW self.canvas.create_window(x - 20, y+8, window=Label(self.canvas, image=self.phInLeft, bd=0)) #freccia e cliccabile(?) elif ident==3: #IN_HIGH self.canvas.create_window(x - 20, y+8, window=Label(self.canvas, image=self.phInLeft, bd=0)) #freccia e cliccabile(?) elif state==self.STATE_GPIO_OUT: #OUT self.canvas.create_window(x - 20, y+8, window=Label(self.canvas, image=self.phOutLeft, bd=0)) x = e_x + self.PIN_DISTANCE else: #RIGHT COLUMN GPIOS self.canvas.create_window(e_x + 70, y+10, window=Label(self.canvas, text=self.GPIO_NAMES[i], fg=self.TEXT_COLOR, bg= self.BG_COLOR)) if ident==2: #IN_LOW self.canvas.create_window(e_x + 22, y+8, window=Label(self.canvas, image=self.phInRight, bd=0)) #freccia e cliccabile(?) elif ident==3: #IN_HIGH self.canvas.create_window(e_x + 22, y+8, window=Label(self.canvas, image=self.phInRight, bd=0)) #freccia e cliccabile(?) elif state==self.STATE_GPIO_OUT: #OUT self.canvas.create_window(e_x + 22, y+8, window=Label(self.canvas, image=self.phOutRight, bd=0)) y = e_y + self.PIN_DISTANCE x = self.START_X self.canvas.pack(fill=BOTH, expand=1) def updateFile(self): c = RawConfigParser() c.read(self.WORK_FILE) for i in range(0,40): c.set("pin"+str(i),"state",str(self.currState[i])) c.set("pin"+str(i),"value",str(self.currValue[i])) with open(self.WORK_FILE, 'w') as configfile: c.write(configfile) def simulateReboot(self, new=False): c = RawConfigParser() c.read(self.WORK_FILE) for i in range(0,40): if new: c.add_section("pin"+str(i)) c.set("pin"+str(i),"state",str(self.GPIO_STATE_DEFAULT[i])) c.set("pin"+str(i),"value", "0") with open(self.WORK_FILE, 'w') as configfile: c.write(configfile) if not new: self.updateUI() def click_cb(self,x): return lambda y: self.click(x) def click(self,pin): #pin = clicked PIN if self.currState[pin]==self.STATE_GPIO_IN: self.currValue[pin] = int ( not bool(self.currValue[pin])) self.updateFile() self.updateUI()
class GUI(): def __init__(self): self.root = ThemedTk(theme="radiance") INIT_WIDTH, INIT_HEIGHT = self.root.winfo_screenwidth( ), self.root.winfo_screenheight() boldStyle = ttk.Style() boldStyle.configure("Bold.TButton", font=('Sans', '12', 'bold')) #icon_loc = os.path.join(os.getcwd(),ICON_NAME) #img = ImageTk.PhotoImage(master = self.root, file=icon_loc) #self.root.wm_iconbitmap(img) #self.root.ttk.call('wm', 'iconphoto', self.root._w, img) self.root.title("Form Labeller") self.root.maxsize(INIT_WIDTH, INIT_HEIGHT) self.supported_formats = SUPPORTED_FORMATS self.left_frame = Frame(self.root, width=BUTTON_WIDTH) self.top_frame1 = Frame(self.left_frame, width=BUTTON_WIDTH, height=int(INIT_HEIGHT / 2)) self.top_frame = Frame(self.left_frame, width=BUTTON_WIDTH, height=INIT_HEIGHT - int(INIT_HEIGHT / 2)) self.bottom_frame = Frame(self.root, width=INIT_WIDTH - BUTTON_WIDTH, height=INIT_HEIGHT) self.load_image_directory_button = Button(self.top_frame1, text='Open Folder', command=self.load_directory, width=int(BUTTON_WIDTH), style="Bold.TButton") self.load_image_directory_button.grid(row=OPEN_FOLDER_ROW, columnspan=2, sticky=tk.W + tk.E) self.prev_img_button = Button(self.top_frame1, text='← Prev', command=self.previous_img, state=tk.DISABLED, width=int(BUTTON_WIDTH / 2), style="Bold.TButton") self.prev_img_button.grid(row=PREV_ROW, column=0, sticky=tk.W + tk.E) self.next_img_button = Button(self.top_frame1, text='Next → ', command=self.next_img, width=int(BUTTON_WIDTH / 2), style="Bold.TButton") self.next_img_button.grid(row=NEXT_COL, column=1, sticky=tk.W + tk.E) self.save_image_button = Button(self.top_frame1, text='Save ', command=self.saver, width=int(BUTTON_WIDTH), style="Bold.TButton") self.save_image_button.grid(row=SAVE_ROW, columnspan=2, sticky=tk.W + tk.E) self.delete_poly_button = Button(self.top_frame, text='Delete Selected', command=self.delete_selected, width=int(BUTTON_WIDTH), style="Bold.TButton") self.delete_poly_button.grid(row=DEL_SELECTED_ROW, columnspan=2, sticky=tk.W + tk.E) self.type_choices = TYPE_CHOICES self.variable = StringVar(self.top_frame) self.variable.set(self.type_choices[0]) self.type_options = OptionMenu(self.top_frame, self.variable, *self.type_choices, style="Bold.TButton") self.type_options.config(width=int(BUTTON_WIDTH / 2)) self.type_options.grid(row=DROP_DOWN_ROW, column=0) self.save_type_button = Button(self.top_frame, text='Save Type', command=self.save_type, width=int(BUTTON_WIDTH / 2), style="Bold.TButton") self.save_type_button.grid(row=SAVE_TYPE_ROW, column=1, sticky=tk.W + tk.E) self.deselect_all_button = Button(self.top_frame, text='Deselect All', command=self.deselect_all, width=BUTTON_WIDTH, style="Bold.TButton") self.deselect_all_button.grid(row=DESELECT_ALL_ROW, columnspan=2, sticky=tk.W + tk.E) self.select_all_button = Button(self.top_frame, text='Select All', command=self.select_all, width=BUTTON_WIDTH, style="Bold.TButton") self.select_all_button.grid(row=SELECT_ALL_ROW, columnspan=2, sticky=tk.W + tk.E) self.draw_poly_button = Button(self.top_frame, text='Draw Poly', command=self.draw_poly_func, width=BUTTON_WIDTH, style="Bold.TButton") self.draw_poly_button.grid(row=DRAW_POLY_ROW, columnspan=2, sticky=tk.W + tk.E) self.draw_rect_button = Button(self.top_frame, text='Draw Rectangle', command=self.draw_rect_func, width=BUTTON_WIDTH, style="Bold.TButton") self.draw_rect_button.grid(row=DRAW_RECT_ROW, columnspan=2, sticky=tk.W + tk.E) self.delete_all_button = Button(self.top_frame, text='Delete All', command=self.delete_all, width=BUTTON_WIDTH, style="Bold.TButton") self.save_poly_button = Button(self.top_frame, text='Save Poly', command=self.save_drawing, width=int(BUTTON_WIDTH / 2), style="Bold.TButton") self.discard_poly_button = Button(self.top_frame, text='Discard Poly', command=self.discard_drawing, width=int(BUTTON_WIDTH / 2), style="Bold.TButton") self.save_rect_button = Button(self.top_frame, text='Save Rect', command=self.save_drawing, width=int(BUTTON_WIDTH / 2), style="Bold.TButton") self.discard_rect_button = Button(self.top_frame, text='Discard Rect', command=self.discard_drawing, width=int(BUTTON_WIDTH / 2), style="Bold.TButton") self.show_type_button = Button(self.top_frame, text='Show Type', command=self.show_type, width=int(BUTTON_WIDTH / 2), style="Bold.TButton") self.show_type_button.grid(row=SHOW_TYPE_ROW, column=0, columnspan=1, sticky=tk.W + tk.E) self.hide_type_button = Button(self.top_frame, text='Hide Type', command=self.hide_type, width=int(BUTTON_WIDTH / 2), style="Bold.TButton") self.hide_type_button.grid(row=HIDE_TYPE_ROW, columnspan=1, column=1, sticky=tk.W + tk.E) self.make_tight_button = Button(self.top_frame, text='Make Tight', command=self.make_tight, width=int(BUTTON_WIDTH / 2), style="Bold.TButton") self.make_tight_button.grid(row=MAKE_TIGHT_ROW, columnspan=2, column=0, sticky=tk.W + tk.E) self.threshold_scale = Scale(self.top_frame, from_=0, to=255, orient=HORIZONTAL, width=int(BUTTON_WIDTH / 2), label="Binary Threshold") self.threshold_scale.set(128) self.threshold_scale.grid(row=THRESHOLD_ROW, columnspan=2, column=0, sticky=tk.W + tk.E) self.tight_save_button = Button(self.top_frame, text='Accept Tight', command=self.save_tight) self.tight_discard_button = Button(self.top_frame, text='Discard Tight', command=self.discard_tight) self.canvas = Canvas(self.bottom_frame, width=INIT_WIDTH - BUTTON_WIDTH, height=INIT_HEIGHT, borderwidth=1) self.image_name = None #self.image_path = os.path.join('imgs','img1.jpg') self.image_dir = None self.images_in_dir = None self.curr_idx = None self.img_cnv = None #self.img_cnv = ImageOnCanvas(self.root,self.canvas,self.image_path) self.drawing_obj = None self.tight_box_obj = None self.left_frame.pack(side=tk.LEFT) self.top_frame1.pack(side=tk.TOP) self.top_frame.pack(side=tk.BOTTOM) self.bottom_frame.pack(side=tk.LEFT) max_w, max_h = self.canvas.winfo_screenwidth( ), self.canvas.winfo_screenheight() self.hbar = Scrollbar(self.bottom_frame, orient=HORIZONTAL) self.hbar.pack(side=BOTTOM, fill=X) self.hbar.config(command=self.canvas.xview) self.vbar = Scrollbar(self.bottom_frame, orient=VERTICAL) self.vbar.pack(side=RIGHT, fill=Y) self.vbar.config(command=self.canvas.yview) max_w, max_h = self.canvas.winfo_width(), self.canvas.winfo_height() self.canvas.configure( #scrollregion=self.canvas.bbox('all'), scrollregion=(0, 0, max_w - BUTTON_WIDTH, max_h), yscrollcommand=self.vbar.set, xscrollcommand=self.hbar.set) self.canvas.pack() self.hide_buttons() self.load_image_directory_button.config(state="normal") def save_tight(self): self.tight_box_obj.save_tight_box() self.tight_save_button.grid_forget() self.tight_discard_button.grid_forget() self.make_tight_button.grid(row=MAKE_TIGHT_ROW, columnspan=2, sticky=tk.W + tk.E) self.show_buttons() self.tight_box_obj = None def discard_tight(self): self.tight_box_obj.discard_tight_box() self.tight_save_button.grid_forget() self.tight_discard_button.grid_forget() self.make_tight_button.grid(row=MAKE_TIGHT_ROW, columnspan=2, sticky=tk.W + tk.E) self.show_buttons() self.tight_box_obj = None def show_type(self): for poly in self.img_cnv.polygons: if poly.select_poly: poly.show_type() def hide_type(self): for poly in self.img_cnv.polygons: poly.unshow_type() def hide_buttons(self): self.load_image_directory_button.config(state=tk.DISABLED) self.save_image_button.config(state=tk.DISABLED) self.delete_poly_button.config(state=tk.DISABLED) self.save_type_button.config(state=tk.DISABLED) self.deselect_all_button.config(state=tk.DISABLED) self.select_all_button.config(state=tk.DISABLED) self.delete_all_button.config(state=tk.DISABLED) self.show_type_button.config(state=tk.DISABLED) self.hide_type_button.config(state=tk.DISABLED) self.make_tight_button.config(state=tk.DISABLED) def show_buttons(self): self.load_image_directory_button.config(state="normal") self.save_image_button.config(state="normal") self.delete_poly_button.config(state="normal") self.save_type_button.config(state="normal") self.deselect_all_button.config(state="normal") self.select_all_button.config(state="normal") self.delete_all_button.config(state="normal") self.show_type_button.config(state="normal") self.hide_type_button.config(state="normal") self.draw_poly_button.config(state="normal") self.draw_rect_button.config(state="normal") self.make_tight_button.config(state="normal") def select_all(self): for poly in self.img_cnv.polygons: poly.select_polygon() def deselect_all(self): self.hide_type() for poly in self.img_cnv.polygons: poly.deselect_poly() def delete_all(self): result = messagebox.askyesno("Confirm Delete All", "Delete All Annotations?") if not result: return self.select_all() self.delete_selected() #self.img_cnv.polygons_mutex.acquire() #for poly in self.img_cnv.polygons: # poly.delete_self() #self.img_cnv.polygons_mutex.release() def save_type(self): selected_option = self.variable.get() self.img_cnv.polygons_mutex.acquire() for poly in self.img_cnv.polygons: if poly.select_poly == True: if selected_option == "None": poly.poly_type = None else: poly.poly_type = selected_option #poly.unshow_type() #poly.show_type() self.img_cnv.polygons_mutex.release() self.variable.set(self.type_choices[0]) #self.deselect_all() def load_new_img(self): self.canvas.delete('all') self.img_cnv = None path = os.path.join(self.image_dir, self.image_name) self.img_cnv = ImageOnCanvas(self.root, self.bottom_frame, self.canvas, path) logger("LOADED: " + self.img_cnv.image_path) def load_directory(self): while True: selection = filedialog.askdirectory() if selection == () or selection == '': return self.root.directory = selection self.image_dir = self.root.directory file_names = os.listdir(self.image_dir) self.images_in_dir = [] self.curr_idx = None self.image_name = None for name in file_names: if name.split('.')[-1] in self.supported_formats: self.images_in_dir.append(name) if len(self.images_in_dir) == 0: self.pop_up("No supported images in the selected directory") else: break self.show_buttons() self.next_img() def pop_up(self, text): top = Toplevel() top.title("ERROR") msg = Message(top, text=text) msg.pack() button = Button(top, text="Dismiss", command=top.destroy) button.pack() def next_img(self): if self.curr_idx == None: self.curr_idx = -1 self.curr_idx = self.curr_idx + 1 if self.curr_idx >= len(self.images_in_dir): self.pop_up("Done with Images in this directory") self.curr_idx = self.curr_idx - 1 return if self.curr_idx > 0: self.prev_img_button.config(state="normal") self.image_name = self.images_in_dir[self.curr_idx] self.load_new_img() self.root.title("Form Labeller - " + self.image_name + "(" + str(self.curr_idx + 1) + "/" + str(len(self.images_in_dir)) + ")") def previous_img(self): if self.curr_idx == 1: self.curr_idx = -1 self.prev_img_button.config(state=tk.DISABLED) else: self.curr_idx = self.curr_idx - 2 self.next_img() def delete_selected(self): to_be_deleted = [] for i, poly in enumerate(self.img_cnv.polygons): if poly.select_poly == True: poly.delete_self() to_be_deleted.append(i) j = 0 for idx in to_be_deleted: self.img_cnv.polygons.pop(idx - j) self.img_cnv.bbs.pop(idx - j) self.img_cnv.poly_type.pop(idx - j) j = j + 1 def start_gui(self): self.root.mainloop() def saver(self): logger("Saving: " + self.img_cnv.image_path) self.save_image_button.config(state=tk.DISABLED) self.img_cnv.save_json(self.root.directory) self.save_image_button.config(state="normal") def draw_poly_func(self): self.deselect_all() self.img_cnv.drawing_polygon = True self.draw_poly_button.grid_forget() self.save_poly_button.grid(row=DRAW_POLY_ROW, column=0, sticky=tk.W + tk.E) self.discard_poly_button.grid(row=DRAW_POLY_ROW, column=1, sticky=tk.W + tk.E) self.hide_buttons() self.draw_rect_button.config(state=tk.DISABLED) self.drawing_obj = DrawPoly(self.bottom_frame, self.canvas, self.img_cnv, RADIUS) def draw_rect_func(self): self.deselect_all() self.img_cnv.drawing_polygon = True self.draw_rect_button.grid_forget() self.save_rect_button.grid(row=DRAW_RECT_ROW, column=0, sticky=tk.W + tk.E) self.discard_rect_button.grid(row=DRAW_RECT_ROW, column=1, sticky=tk.W + tk.E) self.hide_buttons() self.draw_poly_button.config(state=tk.DISABLED) self.drawing_obj = DrawRect(self.bottom_frame, self.canvas, self.img_cnv, RADIUS) def save_drawing(self): self.show_buttons() self.img_cnv.drawing_polygon = False new_poly_pts = self.drawing_obj.pt_coords print("Trying to save polygon with pts:", str(new_poly_pts)) for pt in self.drawing_obj.points: self.canvas.delete(pt) if self.img_cnv.scale_factor != None: for i in range(len(new_poly_pts)): for j in range(2): new_poly_pts[i][ j] = new_poly_pts[i][j] / self.img_cnv.scale_factor self.img_cnv.add_poly(new_poly_pts) #self.img_cnv.bbs.append(new_poly_pts) #self.img_cnv.draw_bbs([self.img_cnv.bbs[-1]]) #debug (1, str(type(self.drawing_obj))) if isinstance(self.drawing_obj, DrawRect): self.save_rect_button.grid_forget() self.discard_rect_button.grid_forget() self.draw_rect_button.grid(row=DRAW_RECT_ROW, columnspan=2, sticky=tk.W + tk.E) elif isinstance(self.drawing_obj, DrawPoly): self.save_poly_button.grid_forget() self.discard_poly_button.grid_forget() self.draw_poly_button.grid(row=DRAW_POLY_ROW, columnspan=2, sticky=tk.W + tk.E) self.drawing_obj.delete_self() self.drawing_obj = None def discard_drawing(self): self.show_buttons() self.img_cnv.drawing_polygon = False #for pt in self.drawing_obj.points: # self.canvas.delete(pt) self.drawing_obj.delete_self() if isinstance(self.drawing_obj, DrawRect): self.save_rect_button.grid_forget() self.discard_rect_button.grid_forget() self.draw_rect_button.grid(row=DRAW_RECT_ROW, columnspan=2, sticky=tk.W + tk.E) elif isinstance(self.drawing_obj, DrawPoly): self.save_poly_button.grid_forget() self.discard_poly_button.grid_forget() self.draw_poly_button.grid(row=DRAW_POLY_ROW, columnspan=2, sticky=tk.W + tk.E) self.drawing_obj = None def make_tight(self): self.hide_buttons() self.tight_box_obj = TightBox(self.root, self.img_cnv, self.threshold_scale.get()) self.tight_box_obj.tight_box() self.make_tight_button.grid_forget() self.tight_save_button.grid(row=MAKE_TIGHT_ROW, column=0, columnspan=1, sticky=tk.W + tk.E) self.tight_discard_button.grid(row=MAKE_TIGHT_ROW, column=1, columnspan=1, sticky=tk.W + tk.E)
class text_canvas(Frame): def __init__(self, parent, font_size, input_handler, filename): Frame.__init__(self, parent) self.parent = parent self.text_font = tkFont.Font( family='Monaco', size=font_size, weight='bold' ) self.filename = filename self.cheight, self.cwidth = font_size, self.text_font.measure('c') self.line_num_spacing = 50 self.line_height = ( (self.winfo_screenheight() - self.cheight)//(self.cheight + 2) - 4 ) self.init_UI(input_handler) def init_UI(self, input_handler): self.parent.title('') self.pack(fill=BOTH, expand=1) self.init_canvas(input_handler) def get_dimensions(self): """ Getting the dimensions might be helpful for plugin writers """ return { 'cheight': self.cheight, 'cwidth': self.cwidth, 'line_num_spacing': self.line_num_spacing, 'line_height': self.line_height, 'screen_width': self.winfo_screenwidth(), 'screen_height': self.winfo_screenheight() } def init_canvas(self, input_handler): self.canvas = Canvas( self, highlightthickness=0, width=self.winfo_screenwidth(), height=self.winfo_screenheight(), bg=options['background_color'] ) self.canvas.pack() self.canvas.focus_set() self.bind_events(input_handler) def clear_all(self): self.canvas.delete('all') def get_line_height(self): """ return number of lines per page """ return self.line_height def get_grid_y(self, y): """ return character height * y in addition distane of the spaces inbetwen """ return self.cheight * y + (y * 2) def write_line_grid(self, y, line): """ Write to line of text on grid using tokens passed in """ for token in line: self.write_text_grid(token[0], y, token[1], token[2]) def write_text_grid(self, x, y, text, color=options['text_color']): """ Write text to x, y location on grid """ x_val = self.cwidth * x + self.line_num_spacing y_val = self.cheight * y + (y * 2) # 2 pixel spacing between each line self.canvas.create_text( x_val, y_val, anchor='nw', text=text, font=self.text_font, fill=color ) def write_status_line( self, text, textcolor=options['status_text_color'], backgroundcolor=options['status_background_color'] ): """ Writen a line of text to status line this function could take in different data if desired """ y = self.line_height + 1 self.canvas.create_rectangle( 0, self.cheight * y + (y * 2), self.winfo_screenwidth(), self.cheight * y + (y * 2) + self.cheight + 4, fill=backgroundcolor, outline=backgroundcolor ) self.write_text_grid(0, self.line_height + 1, text, textcolor) def draw_highlight_grid( self, y, x1, x2, highlightcolor=options['text_highlight_color'] ): """ Draw highlights onto text canvas i.e selections during visual mode """ y_val = self.cheight * y + (y * 2) x1_val = self.cwidth * x1 + self.line_num_spacing x2_val = self.cwidth * x2 + self.line_num_spacing self.canvas.create_rectangle( x1_val, y_val, x2_val, y_val + self.cheight + 4, fill=highlightcolor, outline=highlightcolor ) def draw_line_numbers( self, start, highlightcolor=options['line_num_highlight_color'], textcolor=options['line_num_text_color'] ): self.canvas.create_rectangle( 0, 0, self.line_num_spacing / 2, self.winfo_screenheight(), fill=highlightcolor, outline=highlightcolor ) for i in range(self.line_height + 1): self.canvas.create_text( 0, self.cheight * i + (i * 2), anchor='nw', text=str(start + i), font=self.text_font, fill=textcolor ) def draw_cursor( self, x, y, highlightcolor=options['cursor_highlight_color'], cursorcolor=options['cursor_color'] ): """ draw cursor as well as line and column highlights TODO: users should have the option to disable line and column highlights """ x_val = self.cwidth * x + self.line_num_spacing y_val = self.cheight * y + (y * 2) self.canvas.create_rectangle( 0, y_val, self.winfo_screenwidth(), y_val + self.cheight + 4, fill=highlightcolor, outline=highlightcolor ) self.canvas.create_rectangle( x_val, 0, x_val + self.cwidth, self.winfo_screenheight(), fill=highlightcolor, outline=highlightcolor ) self.canvas.create_rectangle( x_val, y_val, x_val + self.cwidth, y_val + self.cheight + 4, fill=cursorcolor, outline=cursorcolor ) def draw_rectangle_absolute( self, x1, y1, x2, y2, color ): """ draw rectangle onto screen TODO: flesh out what this function should actually look like """ self.canvas.create_rectangle( x1, y1, x2, y2, fill=color, outline=color ) def bind_events(self, input_handler): """ bind events for use in input_handler TODO: this should be cleaned up ideally into a separate handler list """ input_handler.set_GUI_reference(self) self.canvas.bind('<Key>', input_handler.key) self.canvas.bind_all('<Escape>', input_handler.escape) self.canvas.bind_all('<Control-a>', input_handler.control_a) self.canvas.bind_all('<Control-b>', input_handler.control_b) self.canvas.bind_all('<Control-c>', input_handler.control_c) self.canvas.bind_all('<Control-d>', input_handler.control_d) self.canvas.bind_all('<Control-e>', input_handler.control_e) self.canvas.bind_all('<Control-f>', input_handler.control_f) self.canvas.bind_all('<Control-g>', input_handler.control_g) self.canvas.bind_all('<Control-h>', input_handler.control_h) self.canvas.bind_all('<Control-i>', input_handler.control_i) self.canvas.bind_all('<Control-j>', input_handler.control_j) self.canvas.bind_all('<Control-k>', input_handler.control_k) self.canvas.bind_all('<Control-l>', input_handler.control_l) self.canvas.bind_all('<Control-m>', input_handler.control_m) self.canvas.bind_all('<Control-n>', input_handler.control_n) self.canvas.bind_all('<Control-o>', input_handler.control_o) self.canvas.bind_all('<Control-p>', input_handler.control_p) self.canvas.bind_all('<Control-q>', input_handler.control_q) self.canvas.bind_all('<Control-r>', input_handler.control_r) self.canvas.bind_all('<Control-s>', input_handler.control_s) self.canvas.bind_all('<Control-t>', input_handler.control_t) self.canvas.bind_all('<Control-u>', input_handler.control_u) self.canvas.bind_all('<Control-v>', input_handler.control_v) self.canvas.bind_all('<Control-w>', input_handler.control_w) self.canvas.bind_all('<Control-x>', input_handler.control_x) self.canvas.bind_all('<Control-y>', input_handler.control_y) self.canvas.bind_all('<Control-z>', input_handler.control_z) self.canvas.bind_all("<MouseWheel>", input_handler.mouse_scroll) self.canvas.bind_all( '<Control-braceright>', input_handler.control_braceright ) self.canvas.bind_all( '<Control-braceleft>', input_handler.control_braceleft )
class Visual(Frame): '''Class that takes a world as argument and present it graphically on a tkinter canvas.''' def __init__(self): ''' Sets up a simulation GUI in tkinter. ''' Frame.__init__(self) self.master.title("The Schelling Segregation Model in Python") self.master.wm_resizable(0, 0) self.grid() self.movement_possible = True # --------------------------------------- # # --------- FRAMES FOR GUI -------------- # # --------------------------------------- # # The pane for user values self._entryPane = Frame(self, borderwidth=5, relief='sunken') self._entryPane.grid(row=0, column=0, sticky='n') # The buttons pane self._buttonPane = Frame(self, borderwidth=5) self._buttonPane.grid(row=1, column=0, sticky='n') # A temp pane where graph is located, just for cosmetic reasons width, height = 425, 350 self._graph = Canvas(self, width=width, height=height, background="black") self._graph.configure(relief='sunken', border=2) self._graph.grid(row=3, column=0) # The pane where the canvas is located self._animationPane = Frame(self, borderwidth=5, relief='sunken') self._animationPane.grid(row=0, column=1, rowspan=4, pady=10, sticky="n") # --------------------------------------- # # --------- FILLING THE FRAMES ---------- # # --------------------------------------- # self._canvas() # Create graphics canvas self._entry() # Create entry widgets self._buttons() # Create button widgets def _plot_setup(self, time): '''Method for crudely annotating the graph window.''' time = time # Main plot width, height = 425, 350 y0 = -time/10 self._graph = Canvas(self, width=width, height=height, background="black", borderwidth=5) self._graph.grid(row=3, column=0) self.trans = Plotcoords(width, height, y0, -0.2, time, 1.3) x, y = self.trans.screen(time // 2, 1.2) x1, y1 = self.trans.screen(time // 2, 1.13) self._graph.create_text(x, y, text="% Happy", fill="green", font="bold 12") self._graph.create_text(x1, y1, text="% Unhappy", fill="red", font="bold 12") # Line x-axis x, y = self.trans.screen((-5 * (time / 100)), -0.05) x1, y = self.trans.screen(time, -0.05) self._graph.create_line(x, y, x1, y, fill="white", width=1.5) # Text x-axis x_text, y_text = self.trans.screen(time / 2, -0.15) self._graph.create_text(x_text, y_text, text="Time", fill="white", font="bold 12") # Line y-axis x, y = self.trans.screen((-0.5 * (time / 100)), -0.05) x, y1 = self.trans.screen((-5 * (time / 100)), 1) self._graph.create_line(x, y, x, y1, fill="white", width=1.5) def _entry(self): '''Method for creating widgets for collecting user input.''' # N (no of turtles) dim = 30*30 self.fill_label = Label(self._entryPane, anchor='w', justify='left', text='Fill', relief='raised', width=12, height=1, font='italic 20') self.fill_label.grid(row=0, column=1, ipady=14) self.fill = Scale(self._entryPane, from_=0, to=1, resolution=0.01, bd=3, relief='sunken', orient='horizontal', length=235, tickinterval=20) self.fill.grid(row=0, column=2) self.fill.set(0.8) self._N_label = Label(self._entryPane, anchor='w', justify='left', text="N:", relief='raised', width=12, height=1, font="italic 20") self._N_label.grid(row=1, column=1, ipady=14) self._N = Scale(self._entryPane, from_=0, to=100, resolution=1, bd=3, relief='sunken', orient='horizontal', length=235, tickinterval=20) self._N.set(30) self._N.grid(row=1, column=2) # Ticks (length of simulation) self._Ticks_label = Label(self._entryPane, anchor='w', justify='left', text="Time:", relief='raised', width=12, height=1, font="bold 20") self._Ticks_label.grid(row=2, column=1, ipady=14) self._Ticks = Scale(self._entryPane, from_=10, to=1000, resolution=1, bd=3, relief='sunken', orient='horizontal', length=235, tickinterval=990) self._Ticks.set(500) self._Ticks.grid(row=2, column=2) # % similar wanted self._Similar_label = Label(self._entryPane, anchor='w', justify='left', text="Similar wanted:", relief='raised', width=12, height=1, font="bold 20") self._Similar_label.grid(row=3, column=1, ipady=14) self._Similar = Scale(self._entryPane, from_=0.0, to=1.0, resolution=0.01, bd=3, relief='sunken', orient='horizontal', length=235, tickinterval=0.5) self._Similar.set(0.76) self._Similar.grid(row=3, column=2) # Delay between steps self._delay_label = Label(self._entryPane, anchor='w', justify='left', text="Delay (s):", relief='raised', width=12, height=1, font="bold 20") self._delay_label.grid(row=4, column=1, ipady=14) self._delay = Scale(self._entryPane, from_=0.0, to=1.0, resolution=0.01, bd=3, relief='sunken', orient='horizontal', length=235, tickinterval=0.5) self._delay.set(0.15) self._delay.grid(row=4, column=2) def _buttons(self): '''Method for creating button widgets for setting up, running and plotting results from simulation.''' width = 7 height = 1 # The 'Setup' button self._setupButton = Button(self._buttonPane, text="Setup", command=self._setup, width=width, height=height, font="bold 30", relief='raised', borderwidth=5) self._setupButton.grid(row=0, column=0) # The 'Go' button self._goButton = Button(self._buttonPane, text="Go", command=self._go, width=width, height=height, font="bold 30", relief='raised', borderwidth=5) self._goButton.grid(row=0, column=1) # The 'Quit' button self._quitButton = Button(self._buttonPane, text="Quit", command=self._quit, width=width, height=height, font="bold 30", relief='raised', borderwidth=5) self._quitButton.grid(row=1, column=0, columnspan=2) def _canvas(self): '''Creates the canvas on which everything happens.''' # The tick counter information self._Tick_counter = Label(self._animationPane, anchor='w', justify='left', text="Time:", width=5, font="bold 20") self._Tick_counter.grid(row=0, column=0, sticky="e") self._Tick_counter1 = Label(self._animationPane, justify='center', text="", relief='raised', width=5, font="bold 20") self._Tick_counter1.grid(row=0, column=1, sticky='w') self.canvas_w, self.canvas_h = 750, 750 self.canvas = Canvas(self._animationPane, width=self.canvas_w, height=self.canvas_h, background="black") self.canvas.grid(row=1, column=0, columnspan=2) def _setup(self): '''Method for 'Setup' button.''' # Clearing the canvas and reset the go button self.canvas.delete('all') self._goButton['relief'] = 'raised' self.N = int(self._N.get()) self.Ticks = int(self._Ticks.get()) self.similar = float(self._Similar.get()) self.data = [] self.tick_counter = 0 self._Tick_counter1['text'] = str(self.tick_counter) self._plot_setup(self.Ticks) self.grid_size = self.N self.world = World(750, 750, self.grid_size) self.create_turtles() self.neighbouring_turtles() self.draw_turtles() def _go(self): '''Method for the 'Go' button, i.e. running the simulation.''' self._goButton['relief'] = 'sunken' if self.tick_counter <= self.Ticks: self._Tick_counter1['text'] = str(self.tick_counter) self.canvas.update() self._graph.update() self._graph.after(0) # Data collection turtles_unhappy = self.check_satisfaction() prop_happy, prop_unhappy = self.calc_prop_happy(self.tick_counter) self.data_collection(self.tick_counter, prop_happy, prop_unhappy) if self.tick_counter >= 1: # HAPPY values (%) x0 = self.tick_counter-1 x1 = self.tick_counter # Collecting values from stored data y0 = self.data[self.tick_counter-1][1] y1 = self.data[self.tick_counter][1] # Transforming to tkinter x1, y1 = self.trans.screen(x1, y1) x0, y0 = self.trans.screen(x0, y0) self._graph.create_line(x0, y0, x1, y1, fill="green", width=1.3, tag="happy") # Draw "happy lines # UNHAPPY values (%) x0 = self.tick_counter-1 x1 = self.tick_counter # Collecting values from stored data y0 = self.data[self.tick_counter-1][2] y1 = self.data[self.tick_counter][2] # Transforming to tkinter x1, y1 = self.trans.screen(x1, y1) x0, y0 = self.trans.screen(x0, y0) self._graph.create_line(x0, y0, x1, y1, fill="red", width=1.1, tag="unhappy") # Draw unhappy lines if prop_happy < 1: self.turtle_move(turtles_unhappy) time.sleep(self._delay.get()) self.update_neighbours() self.tick_counter += 1 self.canvas.after(0, self._go()) self._goButton['relief'] = 'raised' def _quit(self): '''Method for the 'Quit' button.''' self.master.destroy() # ------------------------------------------------------ # # ---------- FUNCTIONS CALLED AT EACH TICK ------------- # # ------------------------------------------------------ # def turtle_move(self, unhappy_turtles): '''Moves all the unhappy turtles (randomly).''' while unhappy_turtles: i = random.randint(0, len(unhappy_turtles)-1) turtle = unhappy_turtles.pop(i) turtle.move(self) def update_neighbours(self): '''Updates the turtles neigbour attributes. Called after all turtles have moved.''' for turtle in self.turtles: turtle.update_neighbours() def check_satisfaction(self): '''Checks to see if turtles are happy or not. Returns a list of unhappy turtles, i.e. turtles that should move. Called before the move method.''' for turtle in self.turtles: turtle.is_happy() unhappy_turtles = [] for element in self.turtles: if not element.happy: unhappy_turtles.append(element) return unhappy_turtles def calc_prop_happy(self, i): '''Calculates the proportion of happy turtles.''' happy = 0 unhappy = 0 for turtle in self.turtles: if turtle.happy: happy += 1 else: unhappy += 1 prop_happy = happy/len(self.turtles) prop_unhappy = unhappy/len(self.turtles) return prop_happy, prop_unhappy def data_collection(self, i, prop_happy, prop_unhappy): '''Method for collecting data at each tick.''' self.data.append((i, prop_happy, prop_unhappy)) # ------------------------------------------------------ # # ---------- INITIALISATION FUNCTIONS ------------------ # # ------------------------------------------------------ # def create_turtles(self): '''Method for creating a new list of turtles. Upon creation they are registered in the World object.''' if self.N*self.N <= self.grid_size*self.grid_size: counter = 0 self.turtles = [] while counter < self.N * self.N * self.fill.get(): s = "S"+str(counter) if counter <= int(self.N * self.N * self.fill.get() / 2): color = "green" else: color = "red" x = random.randint(0, self.grid_size-1) y = random.randint(0, self.grid_size-1) if not self.world.patch_list[x][y]: new_turtle = Schelling(world=self.world, x=x, y=y, s=s, color=color, similar_wanted=self.similar) self.world.register(new_turtle) counter += 1 self.turtles.append(new_turtle) else: print("Number of turtles exceeds world!") def draw_turtles(self): '''Method for drawing turtles on canvas. Calls each turtle's own method for drawing.''' for turtle in self.turtles: turtle.draw(self.canvas) def neighbouring_turtles(self): '''Method for updating turtles' neighbours. Calls on each turtle's own method for updating neighbours.''' for turtle in self.turtles: turtle.get_neighbouring_patches()
def Classes(sbjBook, string): from tkinter import Tk from tkinter import Canvas import os master = Tk() w=1240 h=1754 m=120 c = Canvas(master, width=1240, height=1754) c.pack() c.create_rectangle(0, 0, w, h, fill="#fff", outline="#fff") c.create_rectangle(m, 60, w-m, 180, fill="#9bbb59", outline="#cadba6") c.create_text(m+60, 90, fill="#fff", font=("Ubuntu","12", "bold") , text="SUBJECT") c.create_text(m+170, 90, fill="#fff", font=("Ubuntu","12", "bold") , text="CLASS") c.create_text(m+420, 90, fill="#fff", font=("Ubuntu","12", "bold") , text="SCHEDULE") c.create_text(m+720, 90, fill="#fff", font=("Ubuntu","12", "bold") , text="PROFESSOR") c.create_text(m+920, 90, fill="#fff", font=("Ubuntu","12", "bold") , text="OFFERED AS") for i in range(13): c.create_rectangle(m, m+120*i, w-m, m+120*i+60, fill="#ebf1de", outline="#cadba6") c.create_rectangle(m, m+120*i+60, w-m, m+120*i+120, fill="#fff", outline="#cadba6") count = -1 page = 0 for i in sbjBook: if(i == -1): pass else: classroom = -1 sameSche = [[],[],[]] scheRecord = [[],[],[]] for j in range(len(sbjBook[i])): classroom += 1 count += 1 period = sbjBook[i][j][1] hpw = sbjBook[i][j][2] professor = sbjBook[i][j][3] group = sbjBook[i][j][4] if(group==None): group = 'Elective' else: course_id = int(group/5) b26 = '' d = int(1) while(d<course_id): d = int(d*26) if(d>=26):d = int(d/26) else: pass while(d>=1): b26 = b26+chr(int(course_id/d) + ord('A')) course_id = course_id % d d = d/26 group = str(group+1)+'-Year required subject\nfor course '+b26 sche = sbjBook[i][j][5:] if(sche in scheRecord[period]): class_id = scheRecord[period].index(sche) class_idBK = scheRecord[period].index(sche) sameSche[period][class_id][0] += 1 else: scheRecord[period].append(sche) sameSche[period].append([0]) class_id = scheRecord[period].index(sche) class_idBK = scheRecord[period].index(sche) schedule = "" for k in sche: if(schedule==""):pass else: schedule = schedule + "\n" weekday = int((k+1)/2) + (k+1)%2 if(weekday==1): weekday = 'Monday ' elif(weekday==2): weekday = 'Tuesday ' elif(weekday==3): weekday = 'Wednesday ' elif(weekday==4): weekday = 'Thursday ' else: weekday = 'Friday ' if(k%2==0 and period==0): hour = "from 8:00 am to 10:00 am" elif(k%2==0 and period==1): hour = "from 2:00 pm to 4:00 pm" elif(k%2==0 and period==2): hour = "from 7:00 pm to 9:00 pm" elif(k%2==1 and period==0): hour = "from 10:00 am to 12:00 pm" elif(k%2==1 and period==1): hour = "from 4:00 pm to 6:00 pm" elif(k%2==1 and period==2): hour = "from 9:00 pm to 11:00 pm" try: schedule = schedule + weekday + hour except: print(k,period); raise b26 = '' div = int(1) while(div<class_id): div = int(div*26) if(div>=26):div = int(div/26) else: pass while(div>=1): b26 = b26+chr(int(class_id/div) + ord('A')) class_id = class_id % div div = div/26 if(period==0): periodTX = " - morning" elif(period==1): periodTX = " - afternoon" else: periodTX = " - evening" if(count<=25): pass else: c.update() c.postscript(file = "classes-"+str(page)+".ps", pageheight="29.70c",x="0",y="0",height="1754",width="1240") c.delete("lines") count = 0 page += 1 c.create_text(m+60, 150+60*count, fill="#000", font=("Ubuntu","10") , text=i, tags="lines") # Subject c.create_text(m+170, 150+60*count, fill="#000", font=("Ubuntu","10") , text=b26+str(sameSche[period][class_idBK][0]+1)+periodTX, tags="lines") # Class c.create_text(m+420, 150+60*count, fill="#000", font=("Ubuntu","10") , text=schedule, tags="lines") # Schedule c.create_text(m+720, 150+60*count, fill="#000", font=("Ubuntu","10") , text=professor, tags="lines") # Professor c.create_text(m+920, 150+60*count, fill="#000", font=("Ubuntu","10") , justify='center', text=group, tags="lines") # Group c.update() c.postscript(file = string+"-"+str(page)+".ps", pageheight="29.70c",x="0",y="0",height="1754",width="1240") #Concatenate PS files and output a single PDF, then clear PS files os.system("convert -density 300 *.ps "+string+".pdf") os.system("find . -name \*.ps -type f -delete")
class Visual(object): def __init__(self, width=800, height=600): root = Tk() self.root = root self.margin = 0.12*height self.width, self.height = width, height - self.margin self.cx, self.cy = width/2, (height - self.margin)/2 self.toolbar = \ Canvas(self.root, width=self.width, height=self.margin) self.toolbar.pack() self.canvas = Canvas(root, width=width, height=height - self.margin) self.canvas.pack() self.init_animation() root.bind("<Button-1>", lambda e: self.mouse_event(e)) root.bind("<Key>", lambda e: self.key_event(e)) root.mainloop() def draw_users(self): """Draw all users""" for user in self.users: user.draw() def draw_connections(self): """Draw all of user's connections""" for user in self.users: user.draw_students() def draw_start_screen(self): """Start screen text""" self.canvas.delete(ALL) cx, cy = self.width/2, self.height/2 font = ("Impact", "128") self.canvas.create_text(cx, 0.8*cy, text="INFECTION", font=font) font = ("Impact", 32) self.canvas.create_text(cx, 1.5*cy, text="Press s to Begin", font=font) def draw_setup_screen(self): """User setup screen""" self.canvas.delete(ALL) cx, cy = self.width/2, self.height/2 text = "Number of Users (1-{})".format(self.max_users) font = ("Impact", 24) self.canvas.create_text(cx, 0.4*cy, text=text, font=font) self.num_users_entry = Entry(self.canvas, justify=CENTER) self.canvas.create_window(cx, 0.5*cy, window=self.num_users_entry) self.num_users_entry.insert(0, str(self.default_users)) text = "Number of Coaches" self.canvas.create_text(cx, 0.6*cy, text=text, font=font) self.num_coaches_entry = Entry(self.canvas, justify=CENTER) self.canvas.create_window(cx, 0.7*cy, window=self.num_coaches_entry) self.num_coaches_entry.insert(0, str(self.default_coaches)) text = "Max Number of Students" self.canvas.create_text(cx, 0.8*cy, text=text, font=font) self.num_students_entry = Entry(self.canvas, justify=CENTER) self.canvas.create_window(cx, 0.9*cy, window=self.num_students_entry) self.num_students_entry.insert(0, str(self.default_students)) self.button = Button(cx, 1.5*cy, 0.3*cx, 0.2*cy, "Begin") self.button.draw(self.canvas) def draw_toolbar(self): """Toolbar for main animation""" self.toolbar.create_text(self.cx, 0.1*self.cy, text="INFECTION", font=("Impact", 32)) self.toolbar.create_text(self.cx*0.05, 0.1*self.cy, text="Total Infection: Click User", font=("Impact", 20), anchor="w") self.toolbar.create_text(self.cx*1.8, 0.1*self.cy, text="Limited Infection", font=("Impact", 20), anchor="e") self.limited_entry = Entry(self.toolbar, justify=CENTER, width=3) self.toolbar.create_window(self.cx*1.85, 0.1*self.cy, window=self.limited_entry) self.limited_entry.insert(0, str(self.default_users//2)) cx, cy = self.cx*1.95, self.margin*0.35 r = self.margin/5 self.limited_button = (cx, cy, r) self.toolbar.create_oval((cx-r, cy-r, cx+r, cy+r), width=2, fill="RED") self.toolbar.create_text(cx, cy, text="X", font=("Courier Bold", 30)) side = self.width/self.versions self.side = side y = 50 self.gradient = (y, y+side) for col in range(int(self.versions)): fill = self.get_fill(col) width = 2 if col == self.version else 0 self.toolbar.create_rectangle(col*side, y, (col+1)*side, y+side, fill=fill, width=width) self.select_version() def redraw_all(self): """Refresh frame for infection animation""" self.canvas.delete(ALL) # Draw connections first so circles get drawn on top of lines self.draw_connections() self.draw_users() def init_users(self): """Initializes list of VisualUser objects from users""" for user in self.raw_users: self.users.append(VisualUser(user, self)) def update_locations(self): """Update locations of all users""" for user in self.users: user.update_location() def get_fill(self, v): """ Convert version number into RGB hex value Creates gradient covering range of colors """ if v is None: return "white" b = 0 quarter = self.versions/4 if v < quarter: # Red -> Yellow r = 255 g = int(255*min((v/quarter), 1)) elif quarter <= v < 2*quarter: # Yellow -> Green r = int(255*max(0, (1-(v-quarter)/quarter))) g = 255 elif 2*quarter <= v < 3*quarter: # Green -> Blue r = 0 g = int(255*max(0, (1-(v-2*quarter)/quarter))) b = int(255*min(((v-2*quarter)/quarter), 1)) else: # Blue -> Purple g = 0 r = int(255*min(((v-3*quarter)/quarter), 1)) b = 255 return "#{:02x}{:02x}{:02x}".format(r, g, b) def draw_random_point(self): """Draw randomly colored point on screen""" fill = self.get_fill(self.start_counter % 100) self.start_counter += 1 x = random.randint(0, self.width) y = random.randint(0, self.height) self.canvas.create_rectangle(x, y, x+2, y+2, width=0, fill=fill) def timer_fired(self): """Called every frame refresh""" if self.mode == Mode.START: for _ in range(10): self.draw_random_point() if self.mode == Mode.MAIN and not self.paused: self.update_locations() self.redraw_all() def timer(self): """Setup timer loop""" self.timer_fired() self.canvas.after(self.timer_delay, self.timer) def init_animation(self): """Initialize or reset animation""" self.users = [] self.timer_delay = 100 self.start_counter = 0 self.versions = 40 self.default_users = 20 self.default_coaches = 5 self.default_students = 5 self.max_users = 100 self.version = None self.paused = False self.mode = Mode.START self.draw_start_screen() self.error_text = None self.error_font_size = 20 self.version_select = None self.timer() def start_infection(self): """Initialize users and start infections""" num_users_text = self.num_users_entry.get() num_coaches_text = self.num_coaches_entry.get() num_students_text = self.num_students_entry.get() try: error = "Invalid Number of Users" num_users = int(num_users_text) if not (1 <= num_users <= self.max_users): raise ValueError num_coaches = int(num_coaches_text) error = "Invalid Number of Coaches" if not (1 <= num_coaches <= num_users): raise ValueError error = "Invalid Number of Students" num_students = int(num_students_text) if not (1 <= num_students <= num_users): raise ValueError except ValueError: if self.error_text: self.canvas.delete(self.error_text) self.error_text = \ self.canvas.create_text(self.cx, 0.2*self.cy, text=error, font=("Impact", self.error_font_size)) self.error_font_size += 2 return self.infection = Infection(num_users=num_users, num_coaches=num_coaches, students=(1, num_students)) self.num_users = num_users self.num_coaches = num_coaches self.num_students = num_students self.raw_users = self.infection.network.users self.init_users() self.draw_toolbar() self.mode = Mode.MAIN def limited_infection(self): size_text = self.limited_entry.get() try: size = int(size_text) if not (1 <= size <= self.num_users): raise ValueError except ValueError: print("Bad input") # TODO: display to user return self.infection.limited_infection(size, self.version) print("Limited infection of size", size, self.num_users) def select_version(self): if self.version_select: # Erase old selection self.toolbar.delete(self.version_select) if self.version is None: return y0, y1 = self.gradient x0, x1 = self.version*self.side, (self.version + 1)*self.side self.version_select = \ self.toolbar.create_rectangle(x0, y0, x1, y1, width="2") def mouse_event(self, e): """Process click event""" x, y = e.x, e.y if self.mode == Mode.SETUP: if self.button.clicked(x, y): self.start_infection() if self.mode == Mode.MAIN: cx, cy, r = self.limited_button if distance(cx, cy, x, y) < r: self.limited_infection() elif self.gradient[0] <= y <= self.gradient[1]: print("gradient bar", x) self.version = int(x / self.side) print(self.versions, self.version) self.select_version() else: for user in self.users: if user.clicked(x, y): print("user clicked", user) user.infect() break def key_event(self, e): """Process keyboard event""" if e.keysym == 'r': self.init_animation() self.paused = False elif e.keysym == 'p': self.paused = not self.paused elif e.keysym == 's' and self.mode == Mode.START: self.mode = Mode.SETUP self.draw_setup_screen() elif e.keysym == 'b' and self.mode == Mode.SETUP: self.start_infection() elif e.keysym == 'q': self.root.destroy()
class CanvasRenderer(AbstractRenderer): """ The CanvasRenderer can draw figures and grids on a canvas """ def __init__(self, window): """ Constructor :param window: Reference to the main window instance """ super().__init__(window) self.canvas = Canvas(self.window) self.canvas.grid(row=0, column=0, padx=BOARD_CELL_SIZE, ipadx=10, ipady=10, sticky='nsew') self.path_sprites = set() def render_board(self, math_coords=False): """ Renders the data """ debug('CanvasRenderer.render_board() called') if not self.board: messagebox.showerror( 'No Board', 'No board has been selected, cannot render' ) self.clear() payload = self.board.grid row_range = range(0, self.board_height) # If we are drawing using mathematical coordinates (Y-axis reversed) if math_coords: row_range = range(self.board_height - 1, -1, -1) # Iterate through all nodes, create sprite coords and determine fill color for y in row_range: for x in range(len(payload[y])): draw_y = y if math_coords: draw_y = self.board_height - y coords = ( x * BOARD_CELL_SIZE + 1, draw_y * BOARD_CELL_SIZE + 1, x * BOARD_CELL_SIZE + BOARD_CELL_SIZE + 1, draw_y * BOARD_CELL_SIZE + BOARD_CELL_SIZE + 1, ) node = self.board.get_node(x, y) fill_color = '#FFFFFF' if not node.walkable: fill_color = '#000000' elif node.is_start: fill_color = '#4040FF' elif node.is_goal: fill_color = '#40FF40' self.canvas.create_rectangle( *coords, fill=fill_color ) def render_path(self, path, math_coords=False, **kwargs): """ Renders path nodes on top of the map, after clearing previously rendered path nodes :param path: A list of Node objects """ open_set = kwargs['open_set_size'] closed_set = kwargs['closed_set_size'] # Remove all previously rendered path sprites from canvas for sprite in self.path_sprites: self.canvas.delete(sprite) self.path_sprites.clear() if 'nonogram' in kwargs and kwargs['nonogram'] is not None: p = path[0].state for y in range(kwargs['nonogram'].total_rows): if len(p.nodes[y]) != 1: continue for x in range(len(p.nodes[y][0][1])): coords = ( x * BOARD_CELL_SIZE + 1, y * BOARD_CELL_SIZE + 1, x * BOARD_CELL_SIZE + BOARD_CELL_SIZE + 1, y * BOARD_CELL_SIZE + BOARD_CELL_SIZE + 1 ) fill_color = '#FFFFFF' if p.nodes[y][0][1][x]: fill_color = '#22EE22' # Create sprite and add to path sprite cache self.path_sprites.add( self.canvas.create_rectangle( *coords, fill=fill_color ) ) self.window.master.controller.references['path_length'].set( 'Path length: %d' % (len(path) - 1) ) self.window.master.controller.references['open_set_size'].set( 'OpenSet size: %d' % open_set ) self.window.master.controller.references['closed_set_size'].set( 'ClosedSet size: %d' % (closed_set - 1) ) self.window.master.controller.references['total_set_size'].set( 'Total set size: %d' % (open_set + closed_set - 1) ) else: # Add sprites for current path for node in reversed(path[:-1]): # If we are drawing using mathematical coordinates (y-reversed) y = node.y if math_coords: y = self.board_height - node.y # Create the coordinates and dimension tuple coords = ( node.x * BOARD_CELL_SIZE + 1, y * BOARD_CELL_SIZE + 1, node.x * BOARD_CELL_SIZE + BOARD_CELL_SIZE + 1, y * BOARD_CELL_SIZE + BOARD_CELL_SIZE + 1 ) fill_color = '#994499' # Create sprite and add to path sprite cache self.path_sprites.add( self.canvas.create_rectangle( *coords, fill=fill_color ) ) self.window.master.controller.references['path_length'].set( 'Path length: %d' % (len(path) - 1) ) self.window.master.controller.references['open_set_size'].set( 'OpenSet size: %d' % open_set ) self.window.master.controller.references['closed_set_size'].set( 'ClosedSet size: %d' % closed_set ) self.window.master.controller.references['total_set_size'].set( 'Total set size: %d' % (open_set + closed_set) ) def clear(self): """ Clears the content area """ self.canvas.delete('all') self.window.master.controller.clear_timers() self.window.master.controller.clear_stats() def destruct(self): """ Destroys this canvas """ self.window.master.controller.clear_timers() self.window.master.controller.clear_stats() self.canvas.destroy()
class RadiobuttonEntry(ttk.Frame): """State entry for all DMs, and controls for adding the infeasibles. Uses a set of RadioButtonSeries elements. """ def __init__(self, master, conflict): """Initialize the widget.""" ttk.Frame.__init__(self, master) self.conflict = conflict self.dmLookup = {dm.name: dm for dm in self.conflict.decisionMakers} dmNames = tuple(self.dmLookup.keys()) self.activeDMname = StringVar(value=dmNames[0]) self.activeDM = self.dmLookup[dmNames[0]] dmSelLabel = ttk.Label(self, text="Decision Maker") dmSelLabel.grid(column=0, row=0) self.dmSelector = ttk.Combobox(self, textvariable=self.activeDMname, values=dmNames, state='readonly') self.dmSelector.grid(column=1, row=0, sticky=NSEW) self.dmSelector.bind('<<ComboboxSelected>>', self.dmSel) self.rbeCanvas = Canvas(self) self.rdBtnFrame = ttk.Frame(self.rbeCanvas) self.scrollY = ttk.Scrollbar(self, orient=VERTICAL, command=self.rbeCanvas.yview) self.rbeCanvas.grid(column=0, row=1, columnspan=2, sticky=NSEW) self.scrollY.grid(column=2, row=1, sticky=NSEW) self.rbeCanvas.configure(yscrollcommand=self.scrollY.set) self.canvWindow = self.rbeCanvas.create_window( (0, 0), window=self.rdBtnFrame, anchor='nw') self.rowconfigure(1, weight=1) self.entryText = StringVar(value='') vcmd = self.register(self.onValidate) self.entryBx = ttk.Entry(self, textvariable=self.entryText, validate="key", validatecommand=(vcmd, '%S', '%P')) self.entryBx.grid(column=0, row=2, columnspan=2, sticky=NSEW) self.entryBx.bind('<Return>', self.generateAdd) self.warnText = StringVar(value='') self.addBtn = ttk.Button(self, text='Remove as Misperceived Condition', command=self.generateAdd) self.mutExBtn = ttk.Button(self, text='Perceived as Mutually Exclusive', command=self.generateMutEx) self.warnLab = ttk.Label(self, textvariable=self.warnText) self.warnLab.grid(column=0, row=3, sticky=NSEW) self.addBtn.grid(column=0, row=4, columnspan=2, sticky=NSEW) self.mutExBtn.grid(column=0, row=5, columnspan=2, sticky=NSEW) self.reloadOpts() def resize(self, event=None): """Resize the scroll region of the main canvas element.""" self.rbeCanvas.configure(scrollregion=self.rbeCanvas.bbox("all")) self.rbeCanvas["width"] = self.rbeCanvas.bbox("all")[2] def generateAdd(self, *args): """Prompt response to addition of an infeasible state.""" self.event_generate('<<addMisperceived>>') def generateMutEx(self, *args): """Prompt response to addition of a mutually exclusive set.""" self.event_generate('<<AddMutEx>>') def reloadOpts(self): """Reload all options for all DMs.""" self.rbeCanvas.delete(self.canvWindow) self.rdBtnFrame.destroy() self.rdBtnFrame = ttk.Frame(self.rbeCanvas) self.canvWindow = self.rbeCanvas.create_window( (0, 0), window=self.rdBtnFrame, anchor='nw') self.rdBtnFrame.bind('<<RdBtnChg>>', self.rdBtnChgCmd) self.rdBtnFrame.bind("<Configure>", self.resize) self.rdBtnSrs = [] self.stringVarList = [] for x, dm in enumerate(self.conflict.decisionMakers): a = RadiobuttonSeries(self.rdBtnFrame, dm) self.rdBtnSrs.append(a) a.setOpts(dm.options) a.grid(column=0, row=int(x), sticky=NSEW) self.stringVarList += a.stringVarList self.rdBtnChgCmd() def setStates(self, dashOne): """Change the condition selected on the radio buttons.""" if len(dashOne) != len(self.stringVarList): raise Exception('string length does not match number ' 'of options: {}'.format(dashOne)) for x, y in enumerate(dashOne): self.stringVarList[x].set(y) self.entryText.set(dashOne) def getStates(self): """Get the condition selected on the radio buttons.""" states = [] for srs in self.rdBtnSrs: states.extend(srs.getStates()) return states def onValidate(self, chg, res): """Validate manually entered condition characters and length.""" if chg in ['Y', 'N', 'y', 'n', '-']: if len(res) < len(self.stringVarList): self.warnText.set('Entry too short') return True if len(res) == len(self.stringVarList): self.setStates(res.upper()) self.warnText.set('') return True return False def rdBtnChgCmd(self, *args): """Set the entry box value to match the radiobuttons.""" val = ''.join([x.get() for x in self.stringVarList]) self.entryText.set(val) def dmSel(self, *args): """Prompt response to a different DM being selected.""" dmName = self.activeDMname.get() self.activeDM = self.dmLookup[dmName] self.event_generate('<<ChangeDM>>')
class prgCanvas(Frame): def __init__(self,window=None,height=500,width=500,bg="grey"): Frame.__init__(self,window,height=height,width=width,bg=bg) self.canvas = Canvas(self, bg=bg, height=height, width=width) self.flagDescription = False self.setdefault(mashtab=True,reper=True,normalization=True) self.canvas.pack(expand='y',fill="both") self.field = None #данные, блоки групп, графические примитивы, точки, #графические примитивы, надписи self.fileprogram = None #имя файла для загрузки self.filter = None #фильтр, по которому определяется выделенный фрагмент def setdefault(self,mashtab=False,reper=False,normalization=False): if mashtab: self.mashtab = 1.00 #масштаб if reper: self.reper = [10.00,10.00] #смещение if normalization: self.normalization = [0.00,0.00] #коэффициент для нормализации координат def configure(self,file=None,filter= None): if file!=None: self.fileprogram = file self.filter=filter def setMashtab(self): '''Эта функция устанавливает текущий масштаб, так чтобы вся плата была в зоне видимости''' def findcoord(field): mX,mY = field[0][0],field[0][1] # sX,sY = field[0][0],field[0][1] sX,sY = 0, 0 for c in field: if c[0]<sX: sX = c[0] elif c[0]>mX: mX = c[0] if c[1]<sY: sY = c[1] elif c[1]>mY: mY = c[1] return [sX,sY,mX,mY] sX,sY,mX,mY=findcoord(self.field) lX = int(self.canvas["width"]) lY = int(self.canvas["height"]) lengthX = abs(mX-sX) lengthY = abs(mY-sY) if lengthX>0 and lengthY>0: cX = lX/lengthX cY = lY/lengthY else: cX,cY=1.0,1.0 print("MSH",cX,cY) self.normalization = [abs(sX),abs(sY)] self.mashtab = int(min(cX,cY)*0.9) def transform(self,x,y,a,etalon): """ точка отсчета - в центре эталона """ new = list() for item in etalon: ca = cos(a) sa = sin(a) x2,y2 = item[0]-x, item[1]-y new.append([x2*ca + y2*sa+x, x2*sa - y2*ca+y]) return new def genfield(self): x,y,d=0,1,2 self.canvas.delete("all") for c in self.field: cx = (c[x]+self.normalization[x])*self.mashtab+self.reper[x] cy = (c[y]+self.normalization[y])*self.mashtab+self.reper[y] print("filter",self.filter) if self.flagDescription and self.filter==None: tag = "BLACK" _color1,_color2 = "black","black" font = "Verdana 8" self.canvas.create_text(cx,cy,anchor="nw",text=str(c[d][1]), fill=_color1,font=font,tag=("DESC",tag)) elif (not self.flagDescription) and self.filter==None: tag = "BLACK" _color1,_color2 = "black","black" elif self.flagDescription and self.filter!=None and self.filter(c[d][2]): _color1,_color2 = ["red","red"] tag = "RED" font = "Verdana 10 bold" self.canvas.create_text(cx,cy,anchor="nw",text=str(c[d][1]), fill=_color1,font=font,tag=("DESC",tag)) elif self.flagDescription: _color1,_color2 = "black","black" tag = "BLACK" # font = "Verdana 8" # self.canvas.create_text(cx,cy,anchor="nw",text=str(c[d][1]), fill=_color1,font=font,tag=("DESC",tag)) pass # здесь может быть выбор фигуры # здесь может быть угол поворота print("c",c) if c[-2][0]=="25": angle = radians(c[-1]) pattern = [[-3,-5.0],[3,-5.0],[0.0,3.0],[-3.0,-5.0]] et = [[cx+item[0],cy+item[1]] for item in pattern] new = self.transform(cx,cy,angle,et) self.canvas.create_polygon(new,activefill="white",fill=_color2,tag=("FIG",tag)) else: self.canvas.create_rectangle(cx-1,cy-1,cx+1,cy+1,outline=_color1,fill=_color2,tag=("FIG",tag)) self.canvas.tag_lower("RED") def move(self,x,y): #в группы self.reper[0]+=x self.reper[1]+=y self.canvas.move("FIG",x,y) self.canvas.move("DESC",x,y) def load(self): _p = prg(self.fileprogram) _p.download() _p.extract() #вариант кода для загрузки информации о установке self.field = [x[1:4]+[x[0]] for x in _p.progdigit if ("25" in x[3]) or ("107" in x[3])] print(_p.progdigit) #вариант кода для загрузки информации о дозировании: # self.field.group = [x[1:4] for x in _p.progdigit if "107" in x[3]] # print(self.field) def paint(self): self.load() try: self.setMashtab() self.genfield() except ZeroDivisionError: print("Zero division") except IndexError: print("Index error") #рисуем надпись self.canvas.delete("all") x,y = int(self.canvas["width"]),int(self.canvas["height"]) self.canvas.create_text(x//2,y//2,text="FILE IS CORRUPTED", font="Verdana 12 bold",fill="red",tag="del")
class TicTacToeGUI: ai = None def __init__(self, master): # Initial Frame self.frame = Frame(master) self.frame.pack(fill="both", expand=True) # Board canvas self.canvas = Canvas(self.frame, width=300, height=300) # Symbol selection buttons self.x_button = Button(self.frame, text='Play as X', height=4, command=self.set_player_x, bg='white', fg='black') self.o_button = Button(self.frame, text='Play as O', height=4, command=self.set_player_o, bg='white', fg='red') # Game start button and info box self.start_button = Button(self.frame, text="START", height=4, command=self.start, bg='white', fg='purple') self.info_box = Label(self.frame, text='Tic Tac Toe Game', height=4, bg='white', fg='blue') self.clean_game_board() def start(self): """Sets up game board, starts a tic tac toe game, and a new AI if one doesn't exist. AI makes first move if playing as X """ self.set_game_board() self.game = TicTacToe() self.game.start() if not self.ai: self.ai = TicTacToeAI() if self.ai_symbol == 'x': self.ai_action() def _board(self): """Draws tic tac toe board""" self.canvas.create_rectangle(0, 0, 300, 300, outline="black") self.canvas.create_rectangle(100, 300, 200, 0, outline="black") self.canvas.create_rectangle(0, 100, 300, 200, outline="black") def user_action(self, event): """Attempts to take action that matches user click. If the move is valid, then calls the AI to make the next move. If not, displays the error. """ move_x = event.x // 100 move_y = event.y // 100 move_result = self.game.update(self.player_symbol, (move_x, move_y)) if move_result == "Success": board_x = (200 * move_x + 100) / 2 board_y = (200 * move_y + 100) / 2 if self.player_symbol == 'x': self.draw_x(board_x, board_y) else: self.draw_o(board_x, board_y) if not self.completed(): # Wait a bit before calling the ai, for visual style self.frame.after(500, self.ai_action) else: self.info_box['text'] = move_result def ai_action(self): """Gets the next move from the AI based on current game state, and plays. """ state = self.game.get_board() move = self.ai.get_move(state) move_result = self.game.update(self.ai_symbol, move) if move_result == "Success": board_x = (200 * move[0] + 100) / 2 board_y = (200 * move[1] + 100) / 2 if self.ai_symbol == 'x': self.draw_x(board_x, board_y) else: self.draw_o(board_x, board_y) self.completed() def completed(self): """Checks the game status. If completed, displays the result, and asks whether the player would like to start another game. """ status = self.game.done() if status == 'e': return False message = "Click to start a new game." if status == 't': message = "Tie game. " + message else: message = "Player " + status.upper() + " has won. " + message self.info_box.pack_forget() self.start_button.pack(fill="both", expand=True) self.start_button["text"] = message self.start_button["command"] = self.clean_game_board def draw_x(self, x, y): self.canvas.create_line(x + 20, y + 20, x - 20, y - 20, width=4, fill="black") self.canvas.create_line(x - 20, y + 20, x + 20, y - 20, width=4, fill="black") def draw_o(self, x, y): self.canvas.create_oval(x + 25, y + 25, x - 25, y - 25, width=4, outline="red") def set_game_board(self): """Hides game start buttons, reveals the game board and info box.""" self.start_button.pack_forget() self.x_button.pack_forget() self.o_button.pack_forget() self.canvas.delete(ALL) self.canvas.pack(fill="both", expand=True) self.info_box.pack(fill="both", expand=True) self.canvas.bind("<ButtonPress-1>", self.user_action) self._board() def clean_game_board(self): """Hides game board and label, reveals game start buttons.""" self.canvas.pack_forget() self.info_box.pack_forget() self.start_button.pack_forget() self.x_button.pack(fill="both", expand=True) self.o_button.pack(fill="both", expand=True) def set_player_x(self): self.player_symbol = 'x' self.ai_symbol = 'o' self.start() def set_player_o(self): self.player_symbol = 'o' self.ai_symbol = 'x' self.start()
class Game: scale = 1 @property def margin(self): return 10 * self.scale @property def cellSize(self): return 35 * self.scale @property def pentPadding(self): return 5 * self.scale # it's better if: cellSize % (dashBlack + dashWhite) == 0 @property def dashBlack(self): return 3 * self.scale @property def dashWhite(self): return 2 * self.scale @property def canvasWidth(self): return 2 * self.margin + self.cols * self.cellSize @property def canvasHeight(self): return 2 * self.margin + self.rows * self.cellSize colors = { 'idle' : 'white', 'free' : 'yellow', 'busy' : '#F3C0BB', 'pentomino' : '#D8B042', 'pent_edit' : '#CB1222' } possibleRotations = 4 numPieces = 5 """For each rotation of the polyomino, it should be specified the "offset" from the center (0, 0) for every piece. The offset is a tuple (dx, dy). The center (0, 0) should appear somewhere in the list as well as other pieces. The order of pieces doesn't matter """ pos = ( ((2, 0), (1, 0), (0, 0), (0, 1), (0, 2)), ((-2, 0), (-1, 0), (0, 0), (0, 1), (0, 2)), ((-2, 0), (-1, 0), (0, 0), (0, -1), (0, -2)), ((2, 0), (1, 0), (0, 0), (0, -1), (0, -2)) ) """For each rotation and for each piece of the polyomino it should be specified a bitmask to instruct the program on how to draw that piece. Each piece of polyomino will be splitted in 9 subrectangles, according to the scheme: .___.___________.___. | | | | | 0 | 1 | 2 | |___|___________|___| | | | | | | | | | 3 | | 4 | | | | | |___|___________|___| | | | | | 5 | 6 | 7 | |___|___________|___| The middle rectangle will always be full. If you want the i-th rectangle to be full, then the i-th bit of the bitmask should be set. For example if you want to draw a CROSS piece then you will need to have 1-th, 3-th, 4-th and 6-th bits set: so the bitmask of the CROSS piece is (2**1)+(2**3)+(2**4)+(2**6)=90. For readability it's better to set explicitly every bit of the mask, like the pentomino's shape encoded in the "info" array, for example """ info = ( ( ((0 << 0) | (1 << 1) | (0 << 2) | (0 << 3) | (0 << 4) | (0 << 5) | (0 << 6) | (0 << 7)), ((0 << 0) | (1 << 1) | (0 << 2) | (0 << 3) | (0 << 4) | (0 << 5) | (1 << 6) | (0 << 7)), ((0 << 0) | (0 << 1) | (0 << 2) | (0 << 3) | (1 << 4) | (0 << 5) | (1 << 6) | (0 << 7)), ((0 << 0) | (0 << 1) | (0 << 2) | (1 << 3) | (1 << 4) | (0 << 5) | (0 << 6) | (0 << 7)), ((0 << 0) | (0 << 1) | (0 << 2) | (1 << 3) | (0 << 4) | (0 << 5) | (0 << 6) | (0 << 7)) ), ( ((0 << 0) | (0 << 1) | (0 << 2) | (0 << 3) | (0 << 4) | (0 << 5) | (1 << 6) | (0 << 7)), ((0 << 0) | (1 << 1) | (0 << 2) | (0 << 3) | (0 << 4) | (0 << 5) | (1 << 6) | (0 << 7)), ((0 << 0) | (1 << 1) | (0 << 2) | (0 << 3) | (1 << 4) | (0 << 5) | (0 << 6) | (0 << 7)), ((0 << 0) | (0 << 1) | (0 << 2) | (1 << 3) | (1 << 4) | (0 << 5) | (0 << 6) | (0 << 7)), ((0 << 0) | (0 << 1) | (0 << 2) | (1 << 3) | (0 << 4) | (0 << 5) | (0 << 6) | (0 << 7)) ), ( ((0 << 0) | (0 << 1) | (0 << 2) | (0 << 3) | (0 << 4) | (0 << 5) | (1 << 6) | (0 << 7)), ((0 << 0) | (1 << 1) | (0 << 2) | (0 << 3) | (0 << 4) | (0 << 5) | (1 << 6) | (0 << 7)), ((0 << 0) | (1 << 1) | (0 << 2) | (1 << 3) | (0 << 4) | (0 << 5) | (0 << 6) | (0 << 7)), ((0 << 0) | (0 << 1) | (0 << 2) | (1 << 3) | (1 << 4) | (0 << 5) | (0 << 6) | (0 << 7)), ((0 << 0) | (0 << 1) | (0 << 2) | (0 << 3) | (1 << 4) | (0 << 5) | (0 << 6) | (0 << 7)) ), ( ((0 << 0) | (1 << 1) | (0 << 2) | (0 << 3) | (0 << 4) | (0 << 5) | (0 << 6) | (0 << 7)), ((0 << 0) | (1 << 1) | (0 << 2) | (0 << 3) | (0 << 4) | (0 << 5) | (1 << 6) | (0 << 7)), ((0 << 0) | (0 << 1) | (0 << 2) | (1 << 3) | (0 << 4) | (0 << 5) | (1 << 6) | (0 << 7)), ((0 << 0) | (0 << 1) | (0 << 2) | (1 << 3) | (1 << 4) | (0 << 5) | (0 << 6) | (0 << 7)), ((0 << 0) | (0 << 1) | (0 << 2) | (0 << 3) | (1 << 4) | (0 << 5) | (0 << 6) | (0 << 7)) ) ) def __init__(self, num_rows, num_cols, best_possible): self.rows = num_rows self.cols = num_cols self.expectedBest = best_possible # create the root and the canvas root = Tk() # local function to bind/unbind events self.bind = root.bind self.unbind = root.unbind # local function to change title self.updateTitle = root.title # local function to change cursor self.updateCursor = lambda x: root.config(cursor=x) # local function to start game self.start = root.mainloop # get screen width and height ws = root.winfo_screenwidth() hs = root.winfo_screenheight() # fix scaling for higher resolutions if max(self.canvasWidth / ws, self.canvasHeight / hs) < 0.45: self.scale = 2 self.canvas = Canvas(root, width=self.canvasWidth, height=self.canvasHeight) self.canvas.pack() # calculate position x, y x = (ws - self.canvasWidth) // 2 y = (hs - self.canvasHeight) // 2 root.geometry('%dx%d+%d+%d' % (self.canvasWidth, self.canvasHeight, x, y)) root.resizable(width=0, height=0) self.init() # set up keypress events root.bind("<Key>", self.keyPressed) def gameOver(self): """Game over: clears background, unbinds events so the user can enjoy his result, updates title: "You won" """ self.over = True self.correctPending() self.updateTitle("You won !!") self.unbind("<Motion>") self.unbind("<Leave>") self.unbind("<Button-1>") self.unbind("<Button-4>") self.unbind("<Button-5>") def refreshScore(self): """Visually updates the score reached by the user: actually it just changes the window title :P """ self.updateTitle(str(self.onBoard) + " / " + str(self.expectedBest)) def checkAvailable(self, x, y): """Checks if the cell at (x, y) is on the board AND is not busy """ return 0 <= x < self.rows and 0 <= y < self.cols and not self.gridBusy[x][y] def checkFree(self, x, y): """Checks whether the position (x, y) is available or not. Returns the color to use for the background ('busy' or 'free') """ for i in range(self.numPieces): new_x = x + self.pos[self.rotation][i][0] new_y = y + self.pos[self.rotation][i][1] if not self.checkAvailable(new_x, new_y): return self.colors['busy'] return self.colors['free'] def doPaint(self, x, y, color, pattern=""): """Does the actual painting: it paints with the specified color and pattern the background at (x, y). If a pattern isn't specified it won't be used """ for i in range(self.numPieces): new_x = x + self.pos[self.rotation][i][0] new_y = y + self.pos[self.rotation][i][1] if 0 <= new_x < self.rows and 0 <= new_y < self.cols: for item in self.gridBG[new_x][new_y][0]: self.canvas.itemconfigure(item, fill=color, stipple=pattern) def correctPending(self): """Restores to the normal state the last painted background """ if self.lastPainted: self.doPaint(self.lastPainted[0], self.lastPainted[1], self.colors['idle'], "gray75") self.lastPainted = None def paintBackground(self, x, y, color): """Updates background to visually indicate whether the position (x, y) is available or not """ self.correctPending() self.lastPainted = (x, y) self.doPaint(x, y, color) def mouseOut(self, event): """Catch mouseout in order to clean the last background painted when the cursor leaves the grid """ if self.editMode and self.lastChanged: self.changeColor(self.lastChanged, self.colors['pentomino']) return self.correctPending() self.lastPosition = None def mouseOver(self, event): """Catch mouseover to paint the background accordingly to the availability of the pentomino space under the cursor """ if self.editMode: self.setEditCursor(event) return x = (event.y - self.margin) // self.cellSize y = (event.x - self.margin) // self.cellSize if self.lastPosition == (x, y): return # I've already drawn this if not (0 <= x < self.rows and 0 <= y < self.cols): return # not on the grid self.lastPosition = (x, y) self.paintBackground(x, y, self.checkFree(x, y)) def mouseClick(self, event): """Catch mouse click to confirm the insertion or removal (if in Edit mode) of a pentomino on the cell under the mouse pointer """ if self.editMode: self.applyEditing(event) self.clearEditCursor(event) return x = (event.y - self.margin) // self.cellSize y = (event.x - self.margin) // self.cellSize if self.checkFree(x, y) == self.colors['busy']: return # clicked busy position self.onBoard += 1 self.refreshScore() self.history.append(( self.setBusy(x, y), self.addPentomino(x, y) )) if self.onBoard == self.expectedBest: self.gameOver() def goBackInTime(self): """Removes the most recently inserted pentomino """ if (len(self.history) == 0): return notBusy, notVisible = self.history.pop() for cell in notVisible: for item in cell[0] + cell[1]: self.canvas.delete(item) for x, y in notBusy: self.gridBusy[x][y] = 0 self.onBoard -= 1 self.refreshScore() def setBusy(self, x, y): """Sets as "busy" the cells occupied by a pentomino centered at (x, y) rotated as the current rotation stored in self.rotation """ changes = [] for i in range(self.numPieces): new_x = x + self.pos[self.rotation][i][0] new_y = y + self.pos[self.rotation][i][1] changes.append((new_x, new_y)) self.gridBusy[new_x][new_y] = self.onBoard self.correctPending() return changes def addPentomino(self, x, y): """Adds a new pentomino with its center in the position (x, y) of the grid and returns the list of changes done. Each element of the list returned is a cell (that is the list of IDs of the new drawn items) """ changes = [] for i in range(self.numPieces): new_x = x + self.pos[self.rotation][i][0] new_y = y + self.pos[self.rotation][i][1] changes.append(self.drawCell( new_x, new_y, self.colors['pentomino'], self.info[self.rotation][i] )) return changes def doRotation(self, delta): """Sets the current rotation value to be rotated delta times by 90 degrees CW. If delta is negative the rotation is CCW """ self.correctPending() self.rotation = (self.rotation + delta) % self.possibleRotations def rollWheel(self, event): """Catch mousewheel scrolling to change the rotation """ if event.num == 4: self.doRotation(-1) # CCW rotation elif event.num == 5: self.doRotation(+1) # CW rotation else: return x = (event.y - self.margin) // self.cellSize y = (event.x - self.margin) // self.cellSize self.paintBackground(x, y, self.checkFree(x, y)) def rollWheelDelta(self, event): """Catch mousewheel scrolling to change the rotation: this is a version for newer mice (I think) because I had to add it to make the rotation work properly with a newer mouse. It would be nice to merge this routine with self.rollWheel() """ if event.delta < 0: self.doRotation(-1) # CCW rotation elif event.delta > 0: self.doRotation(+1) # CW rotation else: return x = (event.y - self.margin) // self.cellSize y = (event.x - self.margin) // self.cellSize self.paintBackground(x, y, self.checkFree(x, y)) def applyEditing(self, event): """Only called if in Edit mode: removes the pentomino that is currently under the mouse pointer. The pentomino is popped from history and every other (more recent) pentomino is updated with a new pentNumber (decreased by 1) to mantain the consistence of history ordering """ self.lastChanged = None x = (event.y - self.margin) // self.cellSize y = (event.x - self.margin) // self.cellSize if not (0 <= x < self.rows and 0 <= y < self.cols): return if not self.gridBusy[x][y]: return assert len(self.history) >= self.gridBusy[x][y] for busy, items in self.history[self.gridBusy[x][y] : ]: for i, j in busy: self.gridBusy[i][j] -= 1 notBusy, notVisible = self.history.pop(self.gridBusy[x][y] - 1) for cell in notVisible: for item in cell[0] + cell[1]: self.canvas.delete(item) for i, j in notBusy: self.gridBusy[i][j] = 0 self.onBoard -= 1 self.refreshScore() def setEditCursor(self, event): """Enters edit mode and sets the "X" cursor """ self.editMode = True self.updateCursor("X_cursor") self.changeColor(self.lastChanged, self.colors['pentomino']) x = (event.y - self.margin) // self.cellSize y = (event.x - self.margin) // self.cellSize if not (0 <= x < self.rows and 0 <= y < self.cols): return if not self.gridBusy[x][y]: return assert len(self.history) >= self.gridBusy[x][y] self.lastChanged = self.gridBusy[x][y] self.changeColor(self.lastChanged, self.colors['pent_edit']) def clearEditCursor(self, event): """Exits from edit mode and restores the classic arrow cursor """ self.editMode = False self.updateCursor("arrow") x = (event.y - self.margin) // self.cellSize y = (event.x - self.margin) // self.cellSize self.paintBackground(x, y, self.checkFree(x, y)) def changeColor(self, pentNumber, color): """Updates the internal color of the pentNumber-th pentomino in the insertion history """ if not pentNumber: return assert(len(self.history) >= pentNumber) for cell in self.history[pentNumber - 1][1]: for item in cell[0]: self.canvas.itemconfigure(item, fill=color) def keyPressed(self, event): """Catches when a key is pressed """ if event.char == "r": self.init() return elif self.over: return elif event.char == ' ': if self.editMode: self.changeColor(self.lastChanged, self.colors['pentomino']) self.clearEditCursor(event) return self.correctPending() self.setEditCursor(event) return elif event.keysym == "BackSpace": self.goBackInTime() elif event.keysym == "Right": self.doRotation(+1) # CW rotation elif event.keysym == "Left": self.doRotation(-1) # CCW rotation else: return x = (event.y - self.margin) // self.cellSize y = (event.x - self.margin) // self.cellSize self.paintBackground(x, y, self.checkFree(x, y)) def redrawAll(self): """Cleans the canvas and draws a new grid """ self.canvas.delete(ALL) self.gridBG = [] self.gridBusy = [] for row in range(self.rows): self.gridBG.append([]) self.gridBusy.append([]) for col in range(self.cols): self.gridBG[row].append(self.drawCell(row, col, self.colors['idle'], bgPattern="gray75")) self.gridBusy[row].append(0) for row in range(self.rows + 1): self.canvas.create_line( self.margin, self.margin + row * self.cellSize, self.margin + self.cols * self.cellSize, self.margin + row * self.cellSize, dash=(self.dashBlack, self.dashWhite) ) for col in range(self.cols + 1): self.canvas.create_line( self.margin + col * self.cellSize, self.margin, self.margin + col * self.cellSize, self.margin + self.rows * self.cellSize, dash=(self.dashBlack, self.dashWhite) ) def drawCell(self, x, y, bgColor, closedSection=255, borderColor="", bgPattern=""): """Draws a new cell at position (x, y) of the grid. Returns a 2-tuple of lists: the first list contains the rectangles (at most 9) and the second list contains the lines (at most 8). These rectangles and lines represent the cell's shape for this pentomino piece (as defined in "info" array) """ left = self.margin + y * self.cellSize right = left + self.cellSize top = self.margin + x * self.cellSize bottom = top + self.cellSize adjustValue = self.cellSize - self.pentPadding # sections tuple = ([rectangles], [lines]) sections = ([], []) # main section sections[0].append(self.canvas.create_rectangle( left + self.pentPadding, top + self.pentPadding, 1 + right - self.pentPadding, 1 + bottom - self.pentPadding, fill=bgColor, outline=borderColor, stipple=bgPattern )) # border sections if closedSection & (1 << 0): sections[0].append(self.canvas.create_rectangle( left, top, 1 + right - adjustValue, 1 + bottom - adjustValue, fill=bgColor, outline=borderColor, stipple=bgPattern )) if closedSection & (1 << 1): sections[0].append(self.canvas.create_rectangle( left + self.pentPadding, top, 1 + right - self.pentPadding, 1 + bottom - adjustValue, fill=bgColor, outline=borderColor, stipple=bgPattern )) if closedSection & (1 << 2): sections[0].append(self.canvas.create_rectangle( left + adjustValue, top, 1 + right, 1 + bottom - adjustValue, fill=bgColor, outline=borderColor, stipple=bgPattern )) if closedSection & (1 << 3): sections[0].append(self.canvas.create_rectangle( left, top + self.pentPadding, 1 + right - adjustValue, 1 + bottom - self.pentPadding, fill=bgColor, outline=borderColor, stipple=bgPattern )) if closedSection & (1 << 4): sections[0].append(self.canvas.create_rectangle( left + adjustValue, top + self.pentPadding, 1 + right, 1 + bottom - self.pentPadding, fill=bgColor, outline=borderColor, stipple=bgPattern )) if closedSection & (1 << 5): sections[0].append(self.canvas.create_rectangle( left, top + adjustValue, 1 + right - adjustValue, 1 + bottom, fill=bgColor, outline=borderColor, stipple=bgPattern )) if closedSection & (1 << 6): sections[0].append(self.canvas.create_rectangle( left + self.pentPadding, top + adjustValue, 1 + right - self.pentPadding, 1 + bottom, fill=bgColor, outline=borderColor, stipple=bgPattern )) if closedSection & (1 << 7): sections[0].append(self.canvas.create_rectangle( left + adjustValue, top + adjustValue, 1 + right, 1 + bottom, fill=bgColor, outline=borderColor, stipple=bgPattern )) # main section's borders if not closedSection & (1 << 1): sections[1].append(self.canvas.create_line( left + self.pentPadding, top + self.pentPadding, 1 + right - self.pentPadding, bottom - adjustValue )) if not closedSection & (1 << 3): sections[1].append(self.canvas.create_line( left + self.pentPadding, top + self.pentPadding, right - adjustValue, 1 + bottom - self.pentPadding )) if not closedSection & (1 << 4): sections[1].append(self.canvas.create_line( left + adjustValue, top + self.pentPadding, right - self.pentPadding, 1 + bottom - self.pentPadding )) if not closedSection & (1 << 6): sections[1].append(self.canvas.create_line( left + self.pentPadding, top + adjustValue, 1 + right - self.pentPadding, bottom - self.pentPadding )) # border sections' borders if (closedSection & (1 << 1)) and not (closedSection & (1 << 0)): sections[1].append(self.canvas.create_line( left + self.pentPadding, top, right - adjustValue, 1 + bottom - adjustValue )) if (closedSection & (1 << 1)) and not (closedSection & (1 << 2)): sections[1].append(self.canvas.create_line( left + adjustValue, top, right - self.pentPadding, 1 + bottom - adjustValue )) if (closedSection & (1 << 4)) and not (closedSection & (1 << 2)): sections[1].append(self.canvas.create_line( left + adjustValue, top + self.pentPadding, 1 + right, bottom - adjustValue )) if (closedSection & (1 << 4)) and not (closedSection & (1 << 7)): sections[1].append(self.canvas.create_line( left + adjustValue, top + adjustValue, 1 + right, bottom - self.pentPadding )) if (closedSection & (1 << 6)) and not (closedSection & (1 << 7)): sections[1].append(self.canvas.create_line( left + adjustValue, top + adjustValue, right - self.pentPadding, 1 + bottom )) if (closedSection & (1 << 6)) and not (closedSection & (1 << 5)): sections[1].append(self.canvas.create_line( left + self.pentPadding, top + adjustValue, right - adjustValue, 1 + bottom )) if (closedSection & (1 << 3)) and not (closedSection & (1 << 5)): sections[1].append(self.canvas.create_line( left, top + adjustValue, 1 + right - adjustValue, bottom - self.pentPadding )) if (closedSection & (1 << 3)) and not (closedSection & (1 << 0)): sections[1].append(self.canvas.create_line( left, top + self.pentPadding, 1 + right - adjustValue, bottom - adjustValue )) return sections def init(self): self.over = False self.onBoard = 0 self.rotation = 0 self.lastPosition = None self.lastPainted = None self.lastChanged = None self.editMode = False self.history = [] self.redrawAll() self.refreshScore() # set up events self.bind("<Motion>", self.mouseOver) self.bind("<Leave>", self.mouseOut) self.bind("<Button-1>", self.mouseClick) self.bind("<Button-4>", self.rollWheel) self.bind("<Button-5>", self.rollWheel) self.bind("<MouseWheel>", self.rollWheelDelta)
class rmap(): _var = [1] _nc = 0 _nr = 0 _r = 0 _c = 0 _size = 0 _w = 0 _d = 0 _NoneUpdate = False _Nonelabel = False _Nonegettext = False _field = [] _endPoint = (0,0) _robot = '' # рисунок Робота (синее кольцо) _park = '' _canvas = '' sleep = 0.5 _task = '' _solve = '' _test = '' _res = '' _bum = 0 m = [] m.append('task1') m.append('task2') m.append('task3') m.append('task4') m.append('task5') m.append('task6') m.append('task7') m.append('task8') m.append('task9') m.append('task10') m.append('task11') m.append('task12') m.append('task13') class _v: # будет содержать изображение текста и квадратиков закраски и меток. Чтобы можно было "поднимать изображение" text = '' label = '' color = '' class _Tcell(): color = '' text = '' label = '' # color wUp = False wLeft = False v = '' def help(self): """ Вывести список команд Робота Примеры использования по команде r.help_full() """ print(""" Пояснение по каждой команде: print команда.__doc__ Например: print r.color.__doc__ ---=: Команды перемещения :=--- r.rt() # Вправо r.lt() # Влево r.dn() # Вниз r.up() # Вверх r.jumpTo(r,c) # Прыжок в точку. Без особых указаний в задачах не использовать -=-=-=-=-=-=-=-=-=-=-=-=-=-==-= ---=: Команды изменения среды :=--- r.pt([цвет]) # Закрасить указанным цветом. По умолчанию зеленым r.sw(направление) # Установить стену с указанной стороны r.settext(тест) # Вписать в клетку текст -=-=-=-=-=-=-=-=-=-=-=-=-=-==-= ---=: Команды обратной связи :=--- r.cl() # Каким цветом закрашена клетка? r.color() r.label() # Какого цвета метка в клетке? r.gettext() # Какой текст в клетке? r.getCoords() # Где Робот? r.getCoordR() # В какой строке Робот? r.getCoordС() # В каком столбце Робот? r.fu() # Сверху свободно? r.fd() # Снизу свободно? r.fr() # Справа свободно? r.fl() # Слева свободно? r.wu() # Сверху стена? r.wd() # Снизу стена? r.wr() # Справа стена? r.wl() # Слева стена? r.isPark # Робот на парковке? -=-=-=-=-=-=-=-=-=-=-=-=-=-==-= ---=: Дополнительно :=--- r.sleep = 0.4 # Установить размер задержки после каждого хода. Меньше значение - быстрее Робот. r._NoneUpdate = False # Отключить прорисовку поля r._NoneUpdate = True # Включить прорисовку поля r.demo() # Показать, что нужно сделать в текущей задаче r.demoAll() # Показать все задачи (с решениями, по очереди) r.randcolor() # Генерировать случайный цвет -=-=-=-=-=-=-=-=-=-=-=-=-=-==-= """) def help_full(self): """ Примеры. Для получения списка команд r.help() Примеры использования по команде r.help_full() Больше информации по каждой команде: print команда.__doc__ Например: print r.color.__doc__ """ print(""" Не реализовано в данной версии. Если нужно - пишите на [email protected] или на сайте progras.ru """) def demo(self): """Показать выполнение задачи Пример использования: #------------------- r.demo() #------------------- Для уcкорения использовать r.sleep = 0.01 В задании 10-3(4/5) можно отключить обновление экрана #------------------- r._NoneUpdate = True r.demo() r._NoneUpdate = False #------------------- """ global r r = self exec(self._solve) def demoAll(self): """Показать выполнение всех заданий в автоматическом режиме Пример использования: #------------------- r.demoAll() #------------------- Для того, чтобы Робот двигался быстрее, используйте #------------------- r.sleep = 0 r.demoAll() #------------------- """ global r r = self for x in r.m: r.lm(x) print(x) r.demo() r.pause() def __init__(self): self._w = 4 # толщина стен self._d = 4 # на столько меньше клетки закраска (с каждой стороны) self.sleep = 0.5 # замедление self._font_size = self._size // 2 self._tk = Tk() self._tk.geometry('+0+0') x = (self._tk.winfo_screenwidth() - self._tk.winfo_reqwidth()) / 3 y = (self._tk.winfo_screenheight() - self._tk.winfo_reqheight()) / 4 self._tk.wm_geometry("+%d+%d" % (x, y)) self._tk.title('Robot-hobot') self._canvas = Canvas(self._tk, width=(self._size*(self._nc+1)), height=(self._size*(self._nr+1)), bg="gray") buttons = Frame(self._tk) self.task = Label (self._tk, justify = 'left') self.res = Label (self._tk, justify = 'left') self._but_start = Button(buttons,text = 'start',width=10,height=1) self._but_start.bind('<ButtonRelease-1>',self.but1) self._but_demo = Button(buttons,text = 'demo',width=10,height=1) self._but_demo.bind('<ButtonRelease-1>',self.but_demo) self._but_reload = Button(buttons,text = 'reload',width=10,height=1) self._but_reload.bind('<ButtonRelease-1>',self.but_reload) self._but_load_next = Button(buttons,text = 'load next',width=10,height=1) self._but_load_next.bind('<ButtonRelease-1>',self.but_load_next) buttons.grid(row=0, column=0, sticky = "w") self._canvas.grid(row=1, column=0, sticky = "e") self._but_start.pack(side = "left") self._but_demo.pack(side = "left") self._but_reload.pack(side = "left") self._but_load_next.pack(side = "left") self.task.grid(row=3, column=0, sticky = "w") self.res.grid(row=4, column=0, sticky = "w") ## self.loadmap() def but_load_next(self,event): print ("load next") index = self.m.index(self._cur_map) if index < len(self.m)-1: self.lm(self.m[index+1]) else: self.lm(self.m[0]) def but_demo(self,event): print ("demo") self.demo() def but1(self,event): print ('start') #self.lm(self._cur_map) self.solve_task() def but_reload(self,event): print ("reload") self.lm(self._cur_map) def clear (self): "Очистка данных (без перерисовки)" self._canvas.delete('all') self._field = [] self._park = [] self._Nonelabel = False self._NoneisPark = False self._Nonesettext = False self._test = '' self._res = '' self._bum = 0 for r in range(1,self._nr+2): row = [] for c in range(1,self._nc+2): row.append (self._Tcell()) self._field.append(row) for r in range (1,self._nr): for c in range(1,self._nc): self._field[r][c].text = '' self._field[r][c].color = '' self._field[r][c].label = '' self._field[r][c].wUp = False self._field[r][c].wLeft = False self._field[r][c].v = self._v() for c in range (1,self._nc): self._field[1][c].wUp = True self._field[self._nr][c].wUp = True for r in range (1,self._nr): self._field[r][1].wLeft = True self._field[r][self._nc].wLeft = True self._solve = '' self._r = 1 self._c = 1 def _paintMap(self): "Перерисовка по имеющимся данным" remc = self._c remr = self._r size = self._size sleep = self.sleep self.sleep = 0 self._bg = [self._canvas.create_rectangle(1,1,(size*(self._nc+1)), (size*(self._nr+1)), fill="gray")] # создать поле for r in range (1, self._nr+1): self._bg.append(self._canvas.create_line(size,r*size,self._nc*size,r*size)) if r < self._nr: self._canvas.create_text(size/2,r*size+size/2,text=r) for c in range (1, self._nc+1): self._bg.append(self._canvas.create_line(c*size,size,c*size,self._nr*size)) if c < self._nc: self._bg.append(self._canvas.create_text(c*size+size/2,size/2,text=c)) # клетки и номера столбцов и строк for r in range (1,self._nr): for c in range(1,self._nc): self._r = r self._c = c if self._field[r][c].wUp: # стена сверху self.setWall('up') if self._field[r][c].wLeft: # стена слева self.setWall('left') if self._field[r][c].color != '' : # закраска self.paint(self._field[r][c].color) if self._field[r][c].label != '' : # метка0000 d = self._d x1 = self._size*(c) x2 = self._size*(c+1) y1 = self._size*(r) y2 = self._size*(r+1) self._canvas.delete(self._field[r][c].v.label) self._field[r][c].v.label = self._canvas.create_rectangle(x1+d,y1+d,x2-d,y2-d, width = d-1, outline = self._field[r][c].label) self._canvas.lift(self._robot) self.settext(self._field[r][c].text) # текст for self._c in range (1,self._nc): if self._field[self._nr][self._c].wUp: # стена сверху self.setWall('down') for self._r in range (1,self._nr): if self._field[self._r][self._nc].wLeft: # стена слева self.setWall('right') r = self._endPoint[0] c = self._endPoint[1] self._canvas.delete(self._park) if r > 0 and c > 0: self._park = self._canvas.create_oval (c*size+6,r*size+6, c*size+size-6,r*size+size-6, width = 3, outline = 'yellow') # конечная точка self.jumpTo((remr,remc)) self._task = '\n'+self._task self.task.config(text = self._task) self.res.config() self._update() self.sleep = sleep #self.pause() def _update(self): "Обновить canvas" if not self._NoneUpdate: self._canvas.update() time.sleep(self.sleep) def start(self,fun): self.solve_task = fun self._tk.mainloop() ##Робот def pause(self,t=1): """Приостановка выполнения программы. Пауза в секундах. #------------------- r.pause() # пауза в одну секунду #------------------- r.pause(2) # пауза две секунды #------------------- """ time.sleep(t) def left(self, a = 1): """Шаг влево #------------------- r.left() #------------------- r.lt() #------------------- r.lt(3) #------------------- """ if a == 1: if self.freeLeft(): self._c -= 1 self._canvas.move(self._robot,-self._size*a,0) self._update() else: self._stop() else : for z in range(0,a): self.left() def right(self, a = 1): """ Шаг вправо #------------------- r.right() #------------------- r.rt() #------------------- r.rt(5) #------------------- """ if a == 1: if self.freeRight(): self._c += 1 self._canvas.move(self._robot,self._size*a,0) self._update() else: self._stop() else : for z in range(0,a): self.right() def up(self, a = 1): """Шаг вверх #------------------- r.up() #------------------- r.up(3) #------------------- """ if a == 1: if self.freeUp(): self._r -= 1 self._canvas.move(self._robot,0,-self._size*a) self._update() else: self._stop() else : for z in range(0,a): self.up() def down(self, a = 1): """ Шаг вниз #------------------- r.down() #------------------- r.dn() #------------------- r.dn(4) #------------------- """ if a == 1: if self.freeDown(): self._r += 1 self._canvas.move(self._robot,0,self._size*a) self._update() else: self._stop() else : for z in range(0,a): self.down() def jumpTo(self,coord=(1,1)): """Прыжок в клетку с указанными координами. Через стены. #------------------- r.jumpTo((2,3)) # Робот окажется в третьем столбце второй строки #------------------- """ r = coord[0] c = coord[1] if ( 0 < r < self._nc) and (0 < c < self._nc): self._r = r self._c = c size = self._size self._canvas.coords(self._robot, c*size+4,r*size+4, c*size+size-4,r*size+size-4) self._canvas.lift(self._robot) self._update() else: print("Попытка переместиться за пределы поля. Отказано.") def paint (self, color = 'green'): """ Закрасить текущую клетку выбранным цветом. Если цвет не указан, то зеленым #------------------- r.paint() # Закрасит текущую клетку зеленым цветом #------------------- r.pt() # Закрасит текущую клетку зеленым цветом #------------------- r.pt('red') # Закрасит текущую клетку красным цветом #------------------- r.pt(r.randcolor()) # Закрасит текущую клетку случайным цветом #------------------- r.pt(r.label()) # Закрасит текущую клетку цветом метки в этой клетке #------------------- """ d = self._d+1 self._field[self._r][self._c].color = color x1 = self._size*(self._c) x2 = self._size*(self._c+1) y1 = self._size*(self._r) y2 = self._size*(self._r+1) self._canvas.delete(self._field[self._r][self._c].v.color) self._field[self._r][self._c].v.color = self._canvas.create_rectangle(x1+d,y1+d,x2-d,y2-d, width = 0, fill = color) self._canvas.lift(self._field[self._r][self._c].v.text) self._canvas.lift(self._robot) self._canvas.lift(self._park) self._update() def setWall (self, target): """ Установить стену с указанной стороны #------------------- r.sw('up') # Установить стену сверху #------------------- r.sw('left') # Установить стену слева #------------------- r.sw('down') # Установить стену снизу #------------------- r.sw('right') # Установить стену справа #------------------- """ size = self._size w = self._w if target == 'up': r = self._r c = self._c x1 = size*(c)-1 x2 = size*(c+1)+1 y1 = size*(r) y2 = size*(r+1) self._field[r][c].wUp = True self._canvas.create_line(x1,y1,x2,y1, width = w) elif target == 'left': r = self._r c = self._c x1 = size*(c) x2 = size*(c+1) y1 = size*(r)-1 y2 = size*(r+1)+1 self._field[r][c].wLeft = True self._canvas.create_line(x1,y1,x1,y2, width = w) elif target == 'down': r = self._r+1 c = self._c x1 = size*(c)-1 x2 = size*(c+1)+1 y1 = size*(r) y2 = size*(r+1) self._field[r][c].wDown = True self._canvas.create_line(x1,y1,x2,y1, width = w) elif target == 'right': r = self._r c = self._c+1 x1 = size*(c) x2 = size*(c+1) y1 = size*(r)-1 y2 = size*(r+1)+1 self._field[r][c].wRight = True self._canvas.create_line(x1,y1,x1,y2, width = 4) self._update() def wallUp (self): """ Возвращает истину, если сверху есть стена #------------------- if r.wallUp(): r.pt() # Закрасить, если сверху стена #------------------- if r.wu(): r.pt() # Закрасить, если сверху стена #------------------- if r.wu(): r.pt() # Закрасить, если сверху стена r.rt() # Перейти вправо #------------------- while r.wu(): # Идти вправо, пока сверху есть стена r.rt() """ return self._field[self._r][self._c].wUp def wallDown (self): """ Возвращает истину, если снизу есть стена #------------------- if r.wallDown(): r.pt() # Закрасить, если снизу стена #------------------- if r.wd(): r.pt() # Закрасить, если снизу стена #------------------- if r.wd(): r.pt() # Закрасить, если снизу стена r.rt() # Перейти вправо #------------------- while r.wd(): # Идти вправо, пока снизу есть стена r.rt() """ return self._field[self._r+1][self._c].wUp def wallLeft (self): """ Возвращает истину, если слева есть стена #------------------- if r.wallLeft(): r.pt() # Закрасить, если слева стена #------------------- if r.wl(): r.pt() # Закрасить, если слева стена #------------------- if r.wl(): r.pt() # Закрасить, если слева стена r.dn() # Перейти вниз #------------------- while r.wl(): # Идти вниз, пока слева есть стена r.dn() """ return self._field[self._r][self._c].wLeft def wallRight (self): """ Возвращает истину, если справа есть стена #------------------- if r.wallRight(): r.pt() # Закрасить, если справа стена #------------------- if r.wr(): r.pt() # Закрасить, если справа стена #------------------- if r.wr(): r.pt() # Закрасить, если справа стена r.dn() # Перейти вниз #------------------- while r.wr(): # Идти вниз, пока справа есть стена r.dn() """ return self._field[self._r][self._c+1].wLeft def freeUp (self): """ Возвращает истину, если сверху свободно (нет стены) #------------------- if r.freeUp(): r.pt() # Закрасить, если сверху свободно #------------------- if r.fu(): r.up() # Шагнуть вверх, если сверху свободно #------------------- if r.fu(): r.up() # Шагнуть вверх r.pt() # Закрасить r.dn() # Перейти вниз #------------------- while r.fu(): # Идти вверх, пока сверху свободно r.up() """ return not self._field[self._r][self._c].wUp def freeDown (self): """ Возвращает истину, если снизу свободно (нет стены) #------------------- if r.freeDown(): r.pt() # Закрасить, если снизу свободно #------------------- if r.fd(): r.dn() # Шагнуть вверх, если снизу свободно #------------------- if r.fd(): r.dn() # Шагнуть снизу r.pt() # Закрасить r.up() # Перейти вверх #------------------- while r.fd(): # Идти вниз, пока снизу свободно r.dn() """ return not self._field[self._r+1][self._c].wUp def freeLeft (self): """ Возвращает истину, если слева свободно (нет стены) #------------------- if r.freeLeft(): r.pt() # Закрасить, если слева свободно #------------------- if r.fl(): r.lt() # Шагнуть влево, если слева свободно #------------------- if r.fl(): r.lt() # Шагнуть влево r.pt() # Закрасить r.rt() # Перейти вправо #------------------- while r.fl(): # Идти влево, пока слева свободно r.lt() """ return not self._field[self._r][self._c].wLeft def freeRight (self): """ Возвращает истину, если снизу свободно (нет стены) #------------------- if r.freeDown(): r.pt() # Закрасить, если снизу свободно #------------------- if r.fd(): r.dn() # Шагнуть вверх, если снизу свободно #------------------- if r.fd(): r.dn() # Шагнуть снизу r.pt() # Закрасить r.up() # Перейти вверх #------------------- while r.fd(): # Идти вниз, пока снизу свободно r.dn() """ return not self._field[self._r][self._c+1].wLeft def getCoords(self): " Возвращает координаты в виде (row,column)" return (self._r,self._c) def getCoordR(self): " Возвращает номер строки, в которой находиться Робот" return self._r def getCoordC(self): " Возвращает номер столбца, в которой находиться Робот" return self._c def isPark (self): " Возвращает истину, если Робот находиться на парковке" if self._NoneisPark: self.null() else: return self._endPoint == self.getCoords() def color (self): """ Возвращает цвет, которым закрашена клетка Можно использовать для проверки, закрашена ли клетка: #------------------- # Закрасить, если сверху закрашено r.up() if r.color(): r.dn() r.pt() else: r.dn() #------------------- if r.color() == 'red': r.rt() # Вправо, если закрашено красным #------------------- """ return self._field[self._r][self._c].color def randcolor (self): """ Возвращает случайный цвет #------------------- r.pt(r.randcolor()) # Закрасить случайным цветом #------------------- # Закрасить соседнюю клетку тем же цветом, что и текущая x = r.color() r.rt() r.pt(x) #------------------- """ cr = rnd(1,255,10) cg = rnd(1,255,10) cb = rnd(1,255,10) color = "#%02X%02X%02X" %(cr,cg,cb) return str(color) def label (self): """ Возвращает цвет метки текущей клетки #------------------- if r.label() == 'red': r.pt('red') # Закрасить клетку красным, если метка красная #------------------- """ if self._Nonelabel: self.null() else: return self._field[self._r][self._c].label def gettext(self): """ Возвращает текст, записанный в ячейке. #------------------- if r.gettext() != '': r.rt() # Перейти вправо, если в ячейке есть какой-нибудь текст #------------------- if r.gettext() == '3': r.rt() # Перейти вправо, если в ячейке записано 3 #------------------- n = r.gettext() if n: r.rt(n) # Перейти вправо на количество шагов, указанное в клетке #------------------- """ if self._Nonegettext: self.null() else: return self._field[self._r][self._c].text def settext(self,text): """ Записать текст в клетку #------------------- r.settext(3) #------------------- """ self._field[self._r][self._c].text = text d = 1 x1 = self._size*(self._c) x2 = self._size*(self._c+1) y1 = self._size*(self._r) y2 = self._size*(self._r+1) self._canvas.delete(self._field[self._r][self._c].v.text) self._field[self._r][self._c].v.text = self._canvas.create_text(self._c*self._size+self._size/2,self._r*self._size+self._size/2,text = self._field[self._r][self._c].text, font = ('Helvetica', self._font_size,'bold')) self._update() def _stop (self): print ("Bum!") self._bum = 1 self._canvas.delete(self._robot) x = self._c y = self._r self._robot = self._canvas.create_oval( x*self._size+2*self._d,y*self._size+2*self._d, x*self._size+self._size-2*self._d,y*self._size+self._size-2*self._d, fill = '#FF0000') def null (self, *args): print('Эта команда запрещена к использованию в данной задаче. Ищите другой способ') return '' def loadmap(self,mn=m[0],variant=0): """ Загрузить карту (задачу) #------------------- r.loadmap('task10-5') #------------------- r.lm('task10-5') # Загрузить задачу по названию #------------------- r.lm(r.m[5]) # Загрузить задачу по номеру #------------------- # Вывести полный список названий и номеров заданий for x in r.m: print r.m.index(x),x #------------------- """ self._tk.title(mn) self._cur_map = mn self._NoneUpdate = False self._endPoint = (0, 0) # self._NoneUpdate = True if mn == 'task1': self._nc = 7 self._nr = 5 self._size = 30 self.clear() self._r = 3 self._c = 2 self._solve = '' self._endPoint = (3,5) self._task = 'Необходимо перевести Робота по лабиринту\n' \ ' из начального положения в конечное.\n' self._field[2][2].wUp = True self._field[2][3].wUp = True self._field[2][4].wUp = True self._field[2][5].wUp = True self._field[4][2].wUp = True self._field[4][3].wUp = True self._field[4][4].wUp = True self._field[4][5].wUp = True self._field[2][4].wLeft = True self._field[3][3].wLeft = True self._field[3][5].wLeft = True ##-------------------------------------------------------------------------------------------- elif mn == 'task2': self._nc = 16 self._nr = 4 self._size = 30 self.clear() self._r = 3 self._c = 1 self._solve = '' self._task = 'Составьте программу рисования узора.\n' ##-------------------------------------------------------------------------------------------- elif mn == 'task3': self._nc = 10 self._nr = 5 self._size = 30 self.clear() self._r = 2 self._c = 1 self._endPoint = (2,9) self._solve = '' self._task = 'Необходимо провести Робота вдоль коридора\n' \ ' из начального положения в конечное,\n' \ ' заглядывая в каждый боковой коридор.' for i in range(2, 9): self._field[2][i].wUp = True if i%2 == 0: self._field[3][i].wUp = True else: self._field[4][i].wUp = True if i < 8: self._field[3][i+1].wLeft = True ##-------------------------------------------------------------------------------------------- elif mn == 'task4': self._nc = 8 self._nr = 12 self._size = 30 self.clear() self._r = rnd(1, self._nr) self._c = rnd(1, self._nc) for i in range(0, 5): for j in range(0, 3): self._field[6+2*j-i][2+i].label = 'red' self._solve = '' self._task = 'Составьте программу закрашивания\n' \ ' клеток поля, отмеченных звездочкой.\n' ##-------------------------------------------------------------------------------------------- elif mn == 'task5': self._nc = 11 self._nr = 10 self._r = 1 self._c = 1 self._size = 30 self.clear() self._solve = '' self._task = 'Составьте программу рисования узора.' ##-------------------------------------------------------------------------------------------- ##-------------------------------------------------------------------------------------------- elif mn == 'task6': self._nc = 25 self._nr = 25 self._r = 1 self._c = 1 self._size = 20 self.clear() self._solve = '' self._task = 'Составьте программу рисования фигуры в виде буквы "Т".\n' \ ' Вертикальные и горизонтальные размеры пользователь вводит\n' \ ' с клавиатуры. Ввод данных можно осуществлять любым способом.\n' ##------------------------------------------------------------------------------------------------------- elif mn == 'task7': self._nc = 16 self._nr = 11 self._size = 25 self.clear() self._r = rnd(1, self._nr) self._c = rnd(1, self._nc) self._field[3][2].wUp = True self._field[2][9].wUp = True self._field[3][12].wUp = True self._field[6][12].wUp = True self._field[7][3].wUp = True self._field[7][9].wUp = True self._field[8][6].wUp = True self._field[9][2].wUp = True self._field[9][11].wUp = True for i in range(0, 4): self._field[4][5+i].wUp = True self._field[5][5+i].wUp = True self._solve = '' self._task = 'Где-то в поле Робота находится горизонтальный коридор шириной в одну клетку\n' \ ' неизвестной длины. Робот из верхнего левого угла поля должен дойти до\n' \ ' коридора и закрасить клетки внутри него, как указано в задании. По полю\n' \ ' Робота в произвольном порядке располагаются стены, но расстояние \n' \ 'между ними больше одной клетки.\n' ##-------------------------------------------------------------------------------------------- elif mn == 'task8': self._nc = 16 self._nr = 11 self._size = 25 self.clear() self._r = rnd(1, self._nr) self._c = rnd(1, self._nc) self._field[2][6].wLeft = True self._field[3][6].wLeft = True self._field[5][6].wLeft = True self._field[6][6].wLeft = True self._field[7][6].wLeft = True self._field[8][6].wLeft = True self._solve = '' self._task = 'Где-то в поле Робота находится вертикальная стена с отверстием в одну клетку,\n' \ ' размеры которой неизвестны. Робот из произвольной клетки должен дойти до\n' \ ' стены и закрасить клетки как показано в задании.\n' ##-------------------------------------------------------------------------------------------- elif mn == 'task9': self._nc = 20 self._nr = 20 self._size = 25 self.clear() self._r = rnd(1, self._nr) self._c = rnd(1, self._nc) c = rnd(2,16) r = rnd(2,16) w = rnd(3,8) h = rnd(3,8) if c + w >= self._nc: w = self._nc-c if r + h >= self._nc: h = self._nr-r for rcount in range(0,h): for ccount in range(0,w): self._field[r + rcount][c+ccount].label = 'green' self._solve = '' self._task = 'На поле находится квадрат из закрашенных клеток. Вычислить и вывести на экран площадь квадрата.\n' ##-------------------------------------------------------------------------------------------- elif mn == 'task10': self._nc = 15 self._nr = 11 self._size = 30 self.clear() self._r = 2 self._c = 1 self._field[2][1].wUp = True self._field[2][2].wUp = True self._field[2][4].wUp = True self._field[2][5].wUp = True self._field[2][6].wUp = True self._field[2][8].wUp = True self._field[2][9].wUp = True self._field[2][11].wUp = True self._field[2][12].wUp = True self._field[2][13].wLeft = True self._field[3][1].wUp = True self._field[3][2].wUp = True self._field[3][3].wUp = True self._field[3][4].wUp = True self._field[3][6].wUp = True self._field[3][7].wUp = True self._field[3][8].wUp = True self._field[3][10].wUp = True self._field[3][11].wUp = True self._field[3][12].wLeft = True self._field[4][3].wLeft = True self._field[4][3].wUp = True self._field[4][4].wUp = True self._field[4][5].wUp = True self._field[4][6].wUp = True self._field[4][8].wUp = True self._field[4][9].wUp = True self._field[4][10].wUp = True self._field[4][11].wUp = True self._field[4][13].wLeft = True self._field[5][3].wLeft = True self._field[5][4].wLeft = True self._field[5][4].wUp = True self._field[5][6].wUp = True self._field[5][7].wUp = True self._field[5][8].wUp = True self._field[5][10].wUp = True self._field[5][11].wUp = True self._field[5][12].wUp = True self._field[6][3].wLeft = True self._field[6][4].wUp = True self._field[6][5].wLeft = True self._field[7][3].wUp = True self._field[7][4].wLeft = True self._field[7][6].wUp = True self._field[7][7].wLeft = True self._field[8][4].wUp = True self._field[8][5].wUp = True self._field[8][6].wLeft = True self._field[8][7].wUp = True self._field[8][8].wLeft = True self._field[9][6].wUp = True self._field[9][7].wLeft = True self._field[9][8].wUp = True self._field[9][9].wUp = True self._field[9][10].wLeft = True self._field[10][7].wUp = True self._field[10][9].wLeft = True self._field[10][10].wLeft = True self._endPoint = (10,1) self._solve = """ """ self._task = 'Необходимо провести Робота по коридору шириной в одну клетку из начального положения до конца коридора, \n' \ 'закрашивая при этом все клетки коридора, которые имеют выход. Выходы размером в одну клетку располагаются \n' \ 'произвольно по всей длине коридора. Коридор заканчивается тупиком. Коридор имеет два горизонтальных и \n' \ 'диагональный участки. Пример коридора показан на рисунке.\n' elif mn == 'task11': self._nc = 15 self._nr = 11 self._size = 30 self.clear() self._r = rnd(1, self._nr) self._c = rnd(1, self._nc) for i in range(1,self._nr): for j in range(1,self._nc): self._field[i][j].text = str(rnd(0, 10)) self._task = 'На поле 10х15 каждой в каждой клетке записана цифра (от 0 до 9).\n Закрасить квадрат 2х2 с наименьшей суммой значений клеток.' elif mn == 'task12': self._nc = 15 self._nr = 6 self._size = 30 self.clear() self._r = 2 self._c = 13 self._field[2][2].wUp = True self._field[2][3].wLeft = True self._field[3][3].wLeft = True self._field[4][3].wLeft = True self._field[5][3].wUp = True self._field[5][4].wUp = True self._field[4][5].wLeft = True self._field[3][5].wLeft = True self._field[2][5].wLeft = True self._field[2][5].wUp = True self._field[2][6].wLeft = True self._field[3][6].wLeft = True self._field[4][6].wLeft = True self._field[5][6].wUp = True self._field[5][7].wUp = True self._field[5][8].wUp = True self._field[4][9].wLeft = True self._field[3][9].wLeft = True self._field[2][9].wLeft = True self._field[2][9].wUp = True self._field[2][10].wUp = True self._field[2][11].wLeft = True self._field[3][11].wLeft = True self._field[4][11].wLeft = True self._field[5][11].wUp = True self._field[4][12].wLeft = True self._field[3][12].wLeft = True self._field[2][12].wLeft = True self._field[2][12].wUp = True self._field[2][13].wUp = True self._task = 'Робот движется вдоль стены, профиль которой показан на рисунке,\n' \ ' от начального положения до конца стены. Необходимо закрасить\n' \ ' все внутренние углы стены, как показано на примере. Размеры стены\n могут быть произвольны.' elif mn == 'task13': self._nc = 20 self._nr = 20 self._size = 25 self.clear() self._r = rnd(self._nr/2, self._nr) self._c = rnd(self._nc/2, self._nc) col = rnd(2, self._nc/2) row = rnd(4, self._nr/2) height = rnd(4, self._nr-4) if row + height >= self._nr: height = self._nr - row-1 for i in range(row, row+height): self._field[i][col].wLeft = True ##-------------------------------------------------------------------------------------------- ##-------------------------------------------------------------------------------------------- # сделать прямое управление с демонстрацией датчиков и возможностей # при запуске робота создавать task.py и справочник :) # сделать робота без клеток !!! ##-------------------------------------------------------------------------------------------- ##-------------------------------------------------------------------------------------------- else: print(mn) self._task = "Нет задачи с таким номером" self._test = '-' self._canvas.config( width=(self._size*(self._nc+1)), height=(self._size*(self._nr+1))) x = y = 1 d = self._d d = 6 self._robot = self._canvas.create_oval( x*self._size+d,y*self._size+d, x*self._size+self._size-d,y*self._size+self._size-d, outline = '#4400FF', width = 3) self._paintMap() lm = loadmap lt = left rt = right dn = down pt = paint sw = setWall wu = wallUp wd = wallDown wl = wallLeft wr = wallRight fu = freeUp fd = freeDown fl = freeLeft fr = freeRight cl = color
class SkylineUI(Frame): """ GUI for the skyline game """ def __init__(self, parent, game): self.game = game self.parent = parent Frame.__init__(self, parent) self.row, self.col = 0, 0 self.__initUI() def __initUI(self): self.parent.title("Skyline") self.pack(fill=BOTH, expand=1) self.canvas = Canvas(self, width=WIDTH, height=HEIGHT) self.canvas.pack(fill=BOTH, side=TOP) clear_button = Button(self, text="Reset", command=self.__clear_answers) clear_button.pack(fill=BOTH, side=BOTTOM) self.__draw_grid() self.__draw_game() self.canvas.bind("<Button-1>", self.__cell_clicked) self.canvas.bind("<Key>", self.__key_pressed) def __draw_grid(self): """ Draws grid divided with blue lines into 3x3 squares """ for i in range(self.game.size + 3): color = "blue" if i % 6 == 0 else "gray" if i == 1 or i == self.game.size + 1: color = "red" x0 = MARGIN + i * SIDE y0 = MARGIN x1 = MARGIN + i * SIDE y1 = HEIGHT - MARGIN self.canvas.create_line(x0, y0, x1, y1, fill=color) x0 = MARGIN y0 = MARGIN + i * SIDE x1 = WIDTH - MARGIN y1 = MARGIN + i * SIDE self.canvas.create_line(x0, y0, x1, y1, fill=color) def __draw_game(self): self.canvas.delete("numbers") for i in range(0, self.game.size): for j in range(0, self.game.size): answer = self.game.board[i][j] #if answer != 0: x = MARGIN + (j+1) * SIDE + SIDE / 2 y = MARGIN + (i+1) * SIDE + SIDE / 2 original = self.game.board_object.empty_board[i][j] color = "black" if answer == 0 else "sea green" self.canvas.create_text( x, y, text=answer, tags="numbers", fill=color ) self.__draw_hints() def __clear_answers(self): self.game.start() self.canvas.delete("victory") self.__draw_game() def __draw_cursor(self): self.canvas.delete("cursor") if self.row >= 0 and self.col >= 0: x0 = MARGIN + self.col * SIDE + 1 y0 = MARGIN + self.row * SIDE + 1 x1 = MARGIN + (self.col + 1) * SIDE - 1 y1 = MARGIN + (self.row + 1) * SIDE - 1 self.canvas.create_rectangle( x0, y0, x1, y1, outline="red", tags="cursor" ) def __cell_clicked(self, event): if self.game.hasWon: return x, y = event.x, event.y if (MARGIN < x < WIDTH - MARGIN and MARGIN < y < HEIGHT - MARGIN): self.canvas.focus_set() # get row and col numbers from x,y coordinates row, col = (y - MARGIN) / SIDE, (x - MARGIN) / SIDE # if cell was selected already - deselect it if (row, col) == (self.row, self.col): self.row, self.col = -1, -1 else: self.row, self.col = int(row), int(col) else: self.row, self.col = -1, -1 self.__draw_cursor() def __key_pressed(self, event): if self.game.hasWon: return if self.row >= 0 and self.col >= 0 and event.char in "1234": self.game.board[self.row-1][self.col-1] = int(event.char) self.col, self.row = -1, -1 self.__draw_game() self.__draw_cursor() if self.game.check_game(): self.__draw_victory() def __draw_victory(self): # create text x = y = MARGIN + 3 * SIDE + SIDE / 2 self.canvas.create_text( x, y, text="You win!", tags="victory", fill="orange", font=("Arial", 32) ) def __draw_hints(self): #draw top hints: for i in range(0, self.game.size): color = "red" hint = self.game.hints_top[i] if hint == 0: color="white" x = SIDE + MARGIN + i * SIDE + SIDE / 2 y = MARGIN + 0 * SIDE + SIDE / 2 self.canvas.create_text( x, y, text=hint, tags="numbers", fill=color ) #draw bottom hints: for i in range(0, self.game.size): color = "red" hint = self.game.hints_bottom[i] if hint == 0: color="white" x = SIDE + MARGIN + i * SIDE + SIDE / 2 y = MARGIN + (self.game.size+1) * SIDE + SIDE / 2 self.canvas.create_text( x, y, text=hint, tags="numbers", fill=color ) #draw left hints: for i in range(0, self.game.size): color = "red" hint = self.game.hints_left[i] if hint == 0: color="white" x = MARGIN + 0 * SIDE + SIDE / 2 y = MARGIN + (i+1) * SIDE + SIDE / 2 self.canvas.create_text( x, y, text=hint, tags="numbers", fill=color ) #draw right hints: for i in range(0, self.game.size): color = "red" hint = self.game.hints_right[i] if hint == 0: color="white" x = MARGIN + (self.game.size+1) * SIDE + SIDE / 2 y = MARGIN + (i+1) * SIDE + SIDE / 2 self.canvas.create_text( x, y, text=hint, tags="numbers", fill=color )
class TKinterDisplay(Display): ''' classdocs ''' ''' Constructor ''' def __init__(self, lineThickness=3, maxH=1920, maxW=1080): master = Tk() master.maxsize(maxH, maxW) self.localCanvas = Canvas(master, width=400, height=400) self.currentlyRenderedWindow = None self.lineThickness = lineThickness self.vsb = Scrollbar(master, orient="vertical", command=self.localCanvas.yview) self.hsb = Scrollbar(master, orient="horizontal", command=self.localCanvas.xview) self.localCanvas.configure(yscrollcommand=self.vsb.set) self.localCanvas.configure(xscrollcommand=self.hsb.set) master.bind("<Configure>", self.__eventOnFrameConfigure) self.hsb.pack(side="bottom", fill="x") self.vsb.pack(side="right", fill="y") self.localCanvas.pack() self.__sampleDraw() '''''' @abstractmethod def drawSquare(self, xywhTuple, tags=None, colour=None, content=None): x2 = xywhTuple[0] + xywhTuple[2] y2 = xywhTuple[1] + xywhTuple[3] square = self.localCanvas.create_rectangle(xywhTuple[0], xywhTuple[1], x2, y2, width=self.lineThickness, tags=tags, fill=colour, activeoutline="white") def handler(event, self=self, content=content): return self.__eventOnClick(event, content) self.localCanvas.tag_bind(square, "<ButtonRelease-1>", handler) return square @abstractmethod def drawCircle(self, xywhTuple, tags=None , colour=None, content=None): x2 = xywhTuple[0] + xywhTuple[2] y2 = xywhTuple[1] + xywhTuple[3] circle = self.localCanvas.create_oval(xywhTuple[0], xywhTuple[1], x2, y2, width=self.lineThickness, tags=tags, fill=colour, activeoutline="white") def handler(event, self=self, content=content): return self.__eventOnClick(event, content) self.localCanvas.tag_bind(circle, "<ButtonRelease-1>", handler) return circle @abstractmethod def connectIdWithLine(self, id1, id2, tags=None, colour=None): # Gets the coordinates of id1 and then calulates centre point id1tuple = self.__getCoords(id1) x1 = id1tuple[0] + ((id1tuple[2] - id1tuple[0]) / 2) y1 = id1tuple[1] + ((id1tuple[3] - id1tuple[1]) / 2) # Gets the coordinates of id2 and then calulates centre point id2tuple = self.__getCoords(id2) x2 = id2tuple[0] + ((id2tuple[2] - id2tuple[0]) / 2) y2 = id2tuple[1] + ((id2tuple[3] - id2tuple[1]) / 2) # Calculates, using trig, the angle of the line at shape id1. This gives the radius of the ellipse opposite = y1 - y2 adjacent = x1 - x2 x1angle = 0 x2angle = 0 hyp = 0 if adjacent != 0 and opposite != 0: hyp = math.sqrt(math.pow(opposite, 2) + math.pow(adjacent, 2)) x1angle = math.tan(opposite / adjacent) x2angle = math.tan(adjacent / opposite) else: if opposite == 0: hyp = adjacent else: hyp = opposite x1angle = math.radians(90) x2angle = math.radians(270) a1 = (id1tuple[2] - id1tuple[0]) / 2 b1 = (id1tuple[3] - id1tuple[1]) / 2 a2 = (id2tuple[2] - id2tuple[0]) / 2 b2 = (id2tuple[3] - id2tuple[1]) / 2 r1 = a1 * b1 / (math.sqrt(((a1 * a1) * (math.pow(math.sin(x1angle), 2))) + ((b1 * b1) * math.pow(math.cos(x1angle), 2)))) r2 = a2 * b2 / (math.sqrt(((a2 * a2) * (math.pow(math.sin(x2angle), 2))) + ((b2 * b2) * math.pow(math.cos(x2angle), 2)))) x1 = x1 + ((r1 / hyp) * (x2 - x1)) y1 = y1 + ((r1 / hyp) * (y2 - y1)) #x2 = x2 + ((r2 / hyp) * (x1 - x2)) #y2 = y2 - ((r2 / hyp) * (y1 - y2)) return self.__drawLine(x1, y1, x2, y2, tags, colour) @abstractmethod def renderTextInId(self, tagTocentreOn, tagsToAddTo, content, funcContent): id1tuple = self.__getCoords(tagTocentreOn) x1 = id1tuple[0] + ((id1tuple[2] - id1tuple[0]) / 2) y1 = id1tuple[1] + ((id1tuple[3] - id1tuple[1]) / 2) txt = self.__renderText(x1, y1, (id1tuple[2] - id1tuple[0]), content, tagsToAddTo) def handler(event, self=self, content=funcContent): return self.__eventOnClick(event, content) self.localCanvas.tag_bind(txt, "<ButtonRelease-1>", handler) return txt @abstractmethod def move(self, tag, xamount, yamount): self.localCanvas.move(tag, xamount, yamount) @abstractmethod def runDisplay(self): self.localCanvas.mainloop() def __hideId(self, objectId): self.localCanvas.itemconfigure(objectId, state="hidden") pass def __showId(self, objectId): self.localCanvas.itemconfigure(objectId, state="normal") pass def __sampleDraw(self): self.localCanvas.create_oval(0, 0, 0, 0, width=0) def __renderText(self, x, y, width, content, tag): val = self.localCanvas.create_text(x, y, width=width, text=content, tags=tag, justify="center", font="Helvetica 8 bold", anchor="center") self.localCanvas.tag_raise(val) return val def __drawLine(self, x1, y1, x2, y2, tags=None, colour="black"): line = self.localCanvas.create_line(x1, y1, x2, y2, tags=tags, width=self.lineThickness, arrow="first", arrowshape=(16,20,6),fill=colour, smooth=True) self.localCanvas.tag_lower(line) return # line def __remove(self, num): self.localCanvas.delete(num) def __getCoords(self, ident): return self.localCanvas.coords(ident) def __eventOnFrameConfigure(self, event): '''Reset the scroll region to encompass the inner frame''' assert self.localCanvas coord_tuple = self.localCanvas.bbox("all") if not coord_tuple: logging.error("Frame reconfigure error on coordinate acquire.") else: reconWidth = coord_tuple[2] - coord_tuple[0] reconHeight = coord_tuple[3] - coord_tuple[1] self.localCanvas.configure(width=reconWidth) self.localCanvas.configure(height=reconHeight) self.localCanvas.configure(scrollregion=self.localCanvas.bbox("all")) self.localCanvas.update_idletasks() def __eventOnClick(self, event, content): self.__createWindowOnId(self.localCanvas.find_withtag(CURRENT), content) def __createWindowOnId(self, itemId, content): if self.currentlyRenderedWindow != None: self.currentlyRenderedWindow() # self.__remove(self.currentlyRenderedWindow) idtuple = self.localCanvas.coords(itemId) if idtuple: x = idtuple[0] y = idtuple[1] frm = Frame(self.localCanvas) frm.grid(row=0, column=0) canv = Canvas(frm) vscroll = Scrollbar(frm, orient="vertical", command=canv.yview) vscroll.grid(row=0, column=1, sticky=N + S) canv.grid(row=0, column=0) canv["yscrollcommand"] = vscroll.set aframe = Frame(canv) aframe.grid(row=0, column=0) Label(aframe, text=content, anchor="center", background="#CCFFCC", borderwidth=6, relief="ridge", justify="left").grid(row=1, column=0) canvWindow = canv.create_window(x, y, window=aframe) canv.coords(canvWindow, x, y) self.localCanvas.update_idletasks() canv["scrollregion"] = canv.bbox("all") def destroyAll(): self.__remove(canvWindow) canv.destroy() aframe.destroy() vscroll.destroy() frm.destroy() self.currentlyRenderedWindow = destroyAll Button(frm, text="Close", command=lambda : destroyAll()).grid(row=2, column=0)
class IsometricViewer: def __init__(self, width, height): self.width = width self.height = height self.wireframe = True self.drawables = [] self.items = {} self.text = "" self.theta = 0 self.phi = 0 self.scale = 0 self.x_offset = 0 self.y_offset = 0 self.canvas = Canvas(Tk(), width=self.width, height=self.height) self.reset_viewport() self.init_gui() @property def camera_coords(self): return Point3(math.cos(self.theta) * math.cos(self.phi), -math.sin(self.theta) * math.cos(self.phi), math.sin(self.phi)) def reset_viewport(self): self.theta = math.pi / 8 self.phi = math.pi / 16 self.scale = 1 self.x_offset = self.width / 2 self.y_offset = self.height / 2 def init_gui(self): self.canvas.pack() self.canvas.focus_set() self.canvas.bind("<Up>", self._callback_commandline_up) self.canvas.bind("<Down>", self._callback_commandline_down) self.canvas.bind("<Left>", self._callback_commandline_left) self.canvas.bind("<Right>", self._callback_commandline_right) self.canvas.bind("=", self._callback_commandline_equal) self.canvas.bind("-", self._callback_commandline_minus) self.canvas.bind("<Shift-Up>", self._callback_commandline_shift_up) self.canvas.bind("<Shift-Down>", self._callback_commandline_shift_down) self.canvas.bind("<Shift-Left>", self._callback_commandline_shift_left) self.canvas.bind("<Shift-Right>", self._callback_commandline_shift_right) self.canvas.bind("<Shift-Return>", self._callback_commandline_shift_return) self.canvas.bind("<Button-1>", self._callback_button_1) self.canvas.bind("<B1-Motion>", self._callback_button_1_motion) def add_drawable(self, drawable): assert isinstance(drawable, Drawable) self.drawables.append(drawable) def project(self, point): projected = point.rotate(self.theta, self.phi) return Point2(projected.y * self.scale + self.x_offset, -projected.z * self.scale + self.y_offset) def unproject(self, point): return point.rotate(0, -self.phi).rotate(-self.theta, 0) def move_camera(self, theta, phi): self.theta += theta if self.theta > 2 * math.pi: self.theta -= 2 * math.pi elif self.theta < 0: self.theta += 2 * math.pi if -math.pi / 2 <= self.phi + phi <= math.pi / 2: self.phi += phi def clear(self): for item in self.items: self.canvas.delete(item) def draw_line(self, owner, p1, p2, **kargs): assert isinstance(p1, Point3) assert isinstance(p2, Point3) p1 = self.project(p1) p2 = self.project(p2) item = self.canvas.create_line(p1.x, p1.y, p2.x, p2.y, **kargs) self.items[item] = owner return item def draw_ellipse(self, owner, corners, **kargs): assert all(isinstance(p, Point3) for p in corners) item = self.draw_polygon(owner, corners, outline="#000000", smooth=1, **kargs) self.items[item] = owner return item def draw_polygon(self, owner, pts, **kargs): assert all(isinstance(p, Point3) for p in pts) args = [] for p in pts: p = self.project(p) args.extend((p.x, p.y)) item = self.canvas.create_polygon(*args, **kargs) self.items[item] = owner return item def draw_wireframe(self): for drawable in self.drawables: drawable.draw_wireframe(self) def draw(self): for drawable in self.drawables: drawable.draw(self) def update(self): self.clear() header = [ "(theta, phi): ({:.3f}, {:.3f})".format(self.theta, self.phi), "(x, y, z): {}".format(self.camera_coords), ] text = "\n".join(header) + "\n\n" + self.text item = self.canvas.create_text((10, 10), anchor="nw", text=text) self.items[item] = None if self.wireframe: self.draw_wireframe() else: self.draw() def display(self): self.update() mainloop() def _callback_commandline_up(self, event): self.move_camera(0, math.pi / 16) self.update() def _callback_commandline_down(self, event): self.move_camera(0, -math.pi / 16) self.update() def _callback_commandline_left(self, event): self.move_camera(math.pi / 16, 0) self.update() def _callback_commandline_right(self, event): self.move_camera(-math.pi / 16, 0) self.update() def _callback_commandline_equal(self, event): self.scale *= 1.2 self.update() def _callback_commandline_minus(self, event): self.scale /= 1.2 self.update() def _callback_commandline_shift_up(self, event): self.y_offset -= 10 self.update() def _callback_commandline_shift_down(self, event): self.y_offset += 10 self.update() def _callback_commandline_shift_left(self, event): self.x_offset -= 10 self.update() def _callback_commandline_shift_right(self, event): self.x_offset += 10 self.update() def _callback_commandline_shift_return(self, event): self.reset_viewport() self.update() def _callback_button_1(self, event): text = [] closest = self.canvas.find_closest(event.x, event.y)[0] overlapping = self.canvas.find_overlapping(event.x, event.y, event.x+1, event.y+1) if closest in overlapping and closest in self.items and self.items[closest] is not None: text.append(self.items[closest].clicked(self, event, closest)) self.text = "\n".join(text) self.update() def _callback_button_1_motion(self, event): pass