Разработка программного продукта для решения прикладных задач. Тема курсовой работы Разработка программного продукта для решения прикладных задач
Скачать 1.19 Mb.
|
Задание №4 import copy from tkinter import * ''' Данная программа реализует метод решения модифицированной задачи о Ханойских башняхю Для визуализации используется библиотека tkinter. Автор: Брянцев Вячеслав Павлович Дата написания программы: 19.05.2021 ''' global iterXY win = Tk() figure = Canvas(win, width=1400, height=900) figure.pack() win.title("Ханойские башни. Модифицированный алгоритм") win.geometry("1400x900") # Определяем переменные wd = '' mem = [] cont = 0 disks = [2, 0, 3, 0, 5, 1, 0, 7] iterXY = 204967 max_iterXY = 409934 # цвет для дисков colors = {1: 'yellow', 2: 'white', 3: 'orange', 4: 'green', 5: 'blue', 6: 'purple', 7: 'pink', 8: 'red', 9: 'yellow', 10: 'white', 11: 'orange', 12: 'green', 13: 'blue', 14: 'purple', 15: 'pink', 16: 'red', 17: 'yellow', 18: 'white', 19: 'orange', 20: 'green', 21: 'blue', 22: 'purple', 23: 'pink', 24: 'red', 25: 'yellow', 26: 'white', 27: 'orange', 28: 'green', 29: 'blue', 30: 'purple', 31: 'pink', 32: 'red', 33: 'yellow', 34: 'white', 35: 'orange', 36: 'green', 37: 'blue', 38: 'purple', 39: 'pink', 40: 'red', 41: 'yellow', 42: 'white', 43: 'orange', 44: 'green', 45: 'blue', 46: 'purple', 47: 'pink', 48: 'red', 49: 'yellow', 50: 'white', 51: 'orange', 52: 'green', 53: 'blue', 54: 'purple', 55: 'pink', 56: 'red', 57: 'yellow', 58: 'white', 59: 'orange', 60: 'green', 61: 'blue', 62: 'purple', 63: 'pink', 64: 'red', 65: 'yellow', 66: 'white', 67: 'orange', 68: 'green', 69: 'blue', 70: 'purple', 71: 'pink', 72: 'red', 73: 'yellow', 74: 'white', 75: 'orange', 76: 'green', 77: 'blue', 78: 'purple', 79: 'pink', 80: 'red', 81: 'yellow', 82: 'white', 83: 'orange', 84: 'green', 85: 'blue', 86: 'purple', 87: 'pink', 88: 'red', 89: 'yellow'} # задаем размеры дисков for i in range(len(disks)): mem.append(mem[:0]) if disks[len(disks) - (i + 1)] != 0: for j in range(int(disks[-1 - i])): mem[i].append(((len(disks) - (i + 1)) * 10 + 10) + (int((disks[-1 - i])) - j)) else: mem[i].clear() def move(b1, b2): global cont cont += 1 b2.append(b1.pop()) # функции для осуществления переноса дисков по шпинделям def m_even(b1, b2, b3, cont_disk): while len(b1) + len(b3) < cont_disk or \ (''.join(str(b3)).find(''.join(str(wd)[1:-1]))) == -1: if cont < iterXY: if len(b1) + len(b3) == cont_disk and \ (''.join(str(b3)).find(''.join(str(wd)[1:-1]))) >= 0: break else: if (len(b1) != 0 and len(b2) == 0) or \ (len(b1) != 0 and b2[-1] > b1[-1]): move(b1, b2) else: move(b2, b1) else: break if cont < iterXY: if len(b1) + len(b3) == cont_disk and \ (''.join(str(b3)).find(''.join(str(wd)[1:-1]))) >= 0: break else: if (len(b1) != 0 and len(b3) == 0) or \ (len(b1) != 0 and b3[-1] > b1[-1]): move(b1, b3) else: move(b3, b1) else: break if cont < iterXY: if len(b1) + len(b3) == cont_disk and \ (''.join(str(b3)).find(''.join(str(wd)[1:-1]))) >= 0: break else: if (len(b2) != 0 and len(b3) == 0) or \ (len(b2) != 0 and b3[-1] > b2[-1]): move(b2, b3) else: move(b3, b2) else: break def m_odd(b1, b2, b3, cont_disk): while cont < iterXY or len(b1) + len(b3) < cont_disk or \ (''.join(str(b3)).find(''.join(str(wd)[1:-1]))) == -1: if cont < iterXY: if len(b1) + len(b3) == cont_disk and \ (''.join(str(b3)).find(''.join(str(wd)[1:-1]))) >= 0: break else: if (len(b1) != 0 and len(b3) == 0) or \ (len(b1) != 0 and b3[-1] > b1[-1]): move(b1, b3) else: move(b3, b1) else: break if cont < iterXY: if len(b1) + len(b3) == cont_disk and \ (''.join(str(b3)).find(''.join(str(wd)[1:-1]))) >= 0: break else: if (len(b1) != 0 and len(b2) == 0) or \ (len(b1) != 0 and b2[-1] > b1[-1]): move(b1, b2) else: move(b2, b1) else: break if cont < iterXY: if len(b1) + len(b3) == cont_disk and \ (''.join(str(b3)).find(''.join(str(wd)[1:-1]))) >= 0: break else: if (len(b2) != 0 and len(b3) == 0) or \ (len(b2) != 0 and b3[-1] > b2[-1]): move(b2, b3) else: move(b3, b2) else: break def move_disks(b1, b2, b3, cont_disk): if len(b1) != 0: if len(b1) % 2 != 0: m_odd(b1, b2, b3, cont_disk) else: m_even(b1, b2, b3, cont_disk) # Отрисовка шпинделей def draw_beams(): xt = 115 for k in range(8): figure.create_rectangle(xt, 120, xt + 5, 500, fill='grey', width=1) label1 = Label(text=str(8 - k), font="Arial 14") label1.place(x=xt, y=530) xt += 170 # Отрисовка перемещения дисков def draw_disks(): x_0 = -50 figure.delete("all") draw_beams() for n in range(len(disks)): x_0 = x_0 + 170 y_0 = 500 for m in range(len(mem[n])): figure.create_rectangle(x_0, y_0, x_0 + mem[n][0 + m], y_0 - 10, fill=colors[mem[n][m]], width=0) figure.create_rectangle(x_0, y_0, x_0 - mem[n][0 + m], y_0 - 10, fill=colors[mem[n][m]], width=0) y_0 = y_0 - 10 figure.create_text(x_0, y_0 + 4, text=str(mem[n][m])) label_cont = Label(text="Количество итераций: " + str(cont), font="Times 12") label_cont.place(x=600, y=40) # Функция, осуществляющая передвижение дисков. def init_move(): global wd, mem, i for i in range(len(disks) - 2): if i == len(disks) - 3: wd = mem[i + 2][:] move_disks(mem[i + 2], mem[i], mem[i + 1], (len(mem[i + 1]) + len(mem[i + 2]))) wd = mem[i + 1][:] move_disks(mem[i + 1], mem[i + 2], mem[i], (len(mem[i]) + len(mem[i + 1]))) wd = mem[i][:] move_disks(mem[i], mem[i + 1], mem[i + 2], (len(mem[i]) + len(mem[i + 2]))) else: wd = mem[i + 2][:] move_disks(mem[i + 2], mem[i], mem[i + 1], (len(mem[i + 1]) + len(mem[i + 2]))) wd = mem[i + 1][:] move_disks(mem[i + 1], mem[i + 2], mem[i], (len(mem[i]) + len(mem[i + 1]))) wd = mem[i][:] move_disks(mem[i], mem[i + 2], mem[i + 1], (len(mem[i]) + len(mem[i + 1]))) draw_disks() def start_m(): global mem mem = [[87, 86, 85, 84, 83, 82, 81], [], [61], [55, 54, 53, 52, 51], [], [33, 32, 31], [], [12, 11]] x_0 = -50 figure.delete("all") draw_beams() for v in range(len(disks)): x_0 = x_0 + 170 y_0 = 500 for w in range(len(mem[v])): figure.create_rectangle(x_0, y_0, x_0 + mem[v][0 + w], y_0 - 10, fill=colors[mem[v][w]], width=0) figure.create_rectangle(x_0, y_0, x_0 - mem[v][0 + w], y_0 - 10, fill=colors[mem[v][w]], width=0) y_0 = y_0 - 10 figure.create_text(x_0, y_0 + 4, text=str(mem[v][w])) label1 = Label(text="Количество итераций: 0", font="Arial 14") label1.place(x=600, y=40) start_m() def end_move(): last_p = [[], [], [], [], [], [], [], []] mem = [[87, 86, 85, 84, 83, 82, 81], [], [61], [55, 54, 53, 52, 51], [], [33, 32, 31], [], [12, 11]] for g in mem: last_p[7].extend(g) x_0 = -50 figure.delete("all") draw_beams() for s in range(len(disks)): x_0 = x_0 + 170 y_0 = 500 for q in range(len(last_p[s])): figure.create_rectangle(x_0, y_0, x_0 + last_p[s][0 + q], y_0 - 10, fill=colors[last_p[s][q]], width=0) figure.create_rectangle(x_0, y_0, x_0 - last_p[s][0 + q], y_0 - 10, fill=colors[last_p[s][q]], width=0) y_0 = y_0 - 10 figure.create_text(x_0, y_0 + 4, text=str(last_p[s][q])) label_cont = Label(text="Количество итераций: 409934", font="Arial 12") label_cont.place(x=600, y=40) # Функция, осуществляющая перенос дисков исходя из номера итерации. def av_move(p): global max_iterXY, iterXY global cont, mem disk_fly = 0 spindles_fly_one = 0 mem = [[87, 86, 85, 84, 83, 82, 81], [], [61], [55, 54, 53, 52, 51], [], [33, 32, 31], [], [12, 11]] cont = 0 iterXY = 0 iterXY = float(eval("entry{}".format(p)).get()) * max_iterXY / 100 # Получение номера итерации. if iterXY > 409934: iterXY = max_iterXY if iterXY % 1 == 0.0: # Если итерация цельная, то запускает функцию init_move без изменений init_move() else: # Запускает функцию init_move(), копирует расположение дисков и снова её запускает на +1 итерацию. init_move() old_mem = copy.deepcopy(mem) iterXY += 1 init_move() # Если элемент старого списка совпадает с элементом нового, то пропуск. # Иначе - найти, какой именно элемент отделился, убрать его из нового списка и произвести отрисовку # уже без него. for d in range(len(mem)): if old_mem[j] == mem[j]: pass else: if len(old_mem[j]) < len(mem[j]): # Слева направо disk_fly = copy.deepcopy(mem[j].pop()) spindles_fly_one = copy.deepcopy(j) init_move() elif len(old_mem[j]) > len(mem[j]): # Справа налево spindles_fly_two = copy.deepcopy(j) old_mem[j].pop() mem = old_mem init_move() draw_disk(disk_fly, spindles_fly_one, spindles_fly_two) # Запуск отрисовки диска в воздухе # Функция, осуществляющая отрисовку диска в воздухе. def draw_disk(disk, spindle1, spindle2): figure.delete("all") draw_beams() draw_disks() y0 = 100 y1 = y0 - 10 list_sizes = [] xt = 115 for d in range(8): list_sizes.append(xt) xt += 170 between = (list_sizes[spindle1] + list_sizes[spindle2]) / 2 x0 = between - disk x1 = between + disk figure.create_rectangle(x0, y0, x1, y1, fill=colors[disk], width=0) figure.create_text(x0 + disk, y0 - 6, text=str(disk)) # Интерфейс окна draw_beams() stButton = Button(win, text="Начало", command=start_m, font="Arial 14") stButton.place(x=250, y=630, width=150) eButton = Button(win, text="Окончание", command=end_move, font="Arial 14") eButton.place(x=950, y=630, width=150) iterationLabel = Label(text="Количество итераций: " + str(0), font="Arial 14") iterationLabel.place(x=600, y=40) onButton = Button(text=" П.1 ", command=lambda: av_move(1)) onButton.place(x=500, y=680, width=50) twButton = Button(text=" П.2 ", command=lambda: av_move(2)) twButton.place(x=600, y=680, width=50) thButton = Button(text=" П.3 ", command=lambda: av_move(3)) thButton.place(x=700, y=680, width=50) fButton = Button(text=" П.4 ", command=lambda: av_move(4)) fButton.place(x=800, y=680, width=50) entry1 = Entry(font="Arial 14") entry1.place(x=500, y=630, width=50) entry2 = Entry(font="Arial 14") entry2.place(x=600, y=630, width=50) entry3 = Entry(font="Arial 14") entry3.place(x=700, y=630, width=50) entry4 = Entry(font="Arial 14") entry4.place(x=800, y=630, width=50) win.mainloop() Приложение Б: Листинг GUI заданий Задание №2 Задание №3 Задание №4 |