1
0

Новый вижинер с анимацией.py 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. import sqlite3
  2. import tkinter as tk
  3. from tkinter import ttk
  4. import time
  5. # Создание таблицы для заполнения
  6. conn = sqlite3.connect("vigenere.db")
  7. cursor = conn.cursor()
  8. cursor.execute("""
  9. CREATE TABLE IF NOT EXISTS alphabets (
  10. id INTEGER PRIMARY KEY AUTOINCREMENT,
  11. name TEXT UNIQUE,
  12. alphabet TEXT
  13. )
  14. """)
  15. conn.commit()
  16. # Запись алфавита
  17. cursor.execute("SELECT COUNT(*) FROM alphabets")
  18. if cursor.fetchone()[0] == 0:
  19. cursor.execute("INSERT INTO alphabets (name, alphabet) VALUES (?, ?)",
  20. ("Русский (с Ё)", "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ"))
  21. cursor.execute("INSERT INTO alphabets (name, alphabet) VALUES (?, ?)",
  22. ("Русский (без Ё)", "АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ"))
  23. cursor.execute("INSERT INTO alphabets (name, alphabet) VALUES (?, ?)",
  24. ("Русский (с подчеркиванием)", "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ"))
  25. conn.commit()
  26. # Глобальная переменная для заполения алфавита выбранного
  27. alphabet = ""
  28. # Цветовая функция
  29. def get_color_for_key(letter):
  30. colors = ["red", "blue", "green", "orange", "purple", "magenta", "cyan", "brown"]
  31. return colors[ord(letter) % len(colors)]
  32. def build_table_lines():
  33. cell_width = 3
  34. # Выравнивание по првому краю
  35. header = " " * cell_width + "".join([letter.rjust(cell_width) for letter in alphabet])
  36. raw_key = key_entry.get().upper()
  37. unique_key = ""
  38. for ch in raw_key:
  39. if ch in alphabet and ch not in unique_key:
  40. unique_key += ch
  41. rows = []
  42. for letter in unique_key:
  43. shift = alphabet.index(letter) + 1
  44. rotated = alphabet[shift:] + alphabet[:shift]
  45. row = letter.rjust(cell_width) + "".join([r.rjust(cell_width) for r in rotated])
  46. rows.append(row)
  47. return [header] + rows, unique_key
  48. def update_table():
  49. lines, _ = build_table_lines()
  50. full_text = "\n".join(lines)
  51. table_display.config(state="normal")
  52. table_display.delete("1.0", "end")
  53. table_display.insert("1.0", full_text)
  54. table_display.config(state="disabled")
  55. def update_table_in_text(content):
  56. table_display.config(state="normal")
  57. table_display.delete("1.0", "end")
  58. table_display.insert("1.0", content)
  59. table_display.config(state="disabled")
  60. def animate_intersection(key_letter, plaintext_letter, ciphertext_letter):
  61. # Анимация сканирования и движения для выбранной буквы ключа
  62. cell_width = 3
  63. lines, unique_key = build_table_lines()
  64. if key_letter not in unique_key:
  65. return
  66. row_index = unique_key.index(key_letter) + 1
  67. shift = alphabet.index(key_letter) + 1
  68. rotated = alphabet[shift:] + alphabet[:shift]
  69. try:
  70. target_col = rotated.index(ciphertext_letter)
  71. except ValueError:
  72. target_col = 0
  73. # Пробег по таблице
  74. for j in range(len(alphabet)):
  75. new_lines = list(lines)
  76. row = new_lines[row_index]
  77. cells = [row[i:i+cell_width] for i in range(0, len(row), cell_width)]
  78. if j < len(cells) - 1:
  79. cells[j+1] = "(" + rotated[j].strip() + ")"
  80. new_lines[row_index] = key_letter.rjust(cell_width) + "".join(cells[1:])
  81. update_table_in_text("\n".join(new_lines))
  82. table_display.update()
  83. time.sleep(0.2)
  84. if j == target_col:
  85. perform_upward_animation(key_letter, target_col, rotated,
  86. row_index, cell_width, lines)
  87. break
  88. def perform_upward_animation(key_letter, target_col, rotated, row_index, cell_width, base_lines):
  89. #Анимация подъёма найденной ячейки.
  90. floating_frames = 4
  91. for frame in range(floating_frames):
  92. new_lines = list(base_lines)
  93. new_row_index = row_index - (frame + 1)
  94. if new_row_index < 1:
  95. new_row_index = 1
  96. # Обновляем строку с буквой ключа
  97. orig_line = new_lines[row_index]
  98. cells = [orig_line[i:i+cell_width] for i in range(0, len(orig_line), cell_width)]
  99. cells[target_col+1] = rotated[target_col].rjust(cell_width)
  100. new_lines[row_index] = key_letter.rjust(cell_width) + "".join(cells[1:])
  101. # Обновляем строку куда перемещаеться
  102. float_line = new_lines[new_row_index]
  103. float_cells = [float_line[i:i+cell_width] for i in range(0, len(float_line), cell_width)]
  104. if target_col+1 < len(float_cells):
  105. float_cells[target_col+1] = rotated[target_col].center(cell_width)
  106. else:
  107. float_cells.append(rotated[target_col].center(cell_width))
  108. new_lines[new_row_index] = "".join(float_cells)
  109. update_table_in_text("\n".join(new_lines))
  110. table_display.config(state="normal")
  111. line_num = new_row_index + 1
  112. start_col = (target_col+1) * cell_width
  113. end_col = start_col + cell_width
  114. table_display.tag_remove("highlight", "1.0", "end")
  115. table_display.tag_add("highlight", f"{line_num}.{start_col}", f"{line_num}.{end_col}")
  116. # Выбор цвета
  117. table_display.tag_config("highlight", foreground=get_color_for_key(key_letter))
  118. table_display.config(state="disabled")
  119. table_display.update()
  120. time.sleep(0.3)
  121. time.sleep(0.5)
  122. update_table()
  123. def vigenere_cipher(text, decrypt=False):
  124. text = text.upper()
  125. key = key_entry.get().upper()
  126. if not key:
  127. return text
  128. result = ""
  129. for i, char in enumerate(text):
  130. if char in alphabet:
  131. current_key = key[i % len(key)]
  132. shift = alphabet.index(current_key)
  133. if decrypt:
  134. new_index = (alphabet.index(char) - shift) % len(alphabet)
  135. else:
  136. new_index = (alphabet.index(char) + shift) % len(alphabet)
  137. output_letter = alphabet[new_index]
  138. if decrypt:
  139. animate_intersection(current_key, output_letter, char)
  140. else:
  141. animate_intersection(current_key, char, output_letter)
  142. result += output_letter
  143. else:
  144. result += char
  145. return result
  146. def encrypt():
  147. update_table()
  148. encrypted_text = vigenere_cipher(input_text.get(), decrypt=False)
  149. output_text.config(text=encrypted_text)
  150. def decrypt():
  151. update_table()
  152. decrypted_text = vigenere_cipher(input_text.get(), decrypt=True)
  153. output_text.config(text=decrypted_text)
  154. def load_alphabet(event=None):
  155. global alphabet
  156. selected = alphabet_var.get()
  157. cursor.execute("SELECT alphabet FROM alphabets WHERE name = ?", (selected,))
  158. result = cursor.fetchone()
  159. if result:
  160. alphabet = result[0]
  161. # Вариант с подчеркиванием
  162. if selected == "Русский (с подчеркиванием)" and not alphabet.endswith("_"):
  163. alphabet += "_"
  164. update_table()
  165. # Интерфейс
  166. root = tk.Tk()
  167. root.title("Шифр Виженера")
  168. root.geometry("800x600")
  169. alphabet_var = tk.StringVar()
  170. ttk.Label(root, text="Выберите алфавит").pack()
  171. cursor.execute("SELECT name FROM alphabets")
  172. alphabet_options = [row[0] for row in cursor.fetchall()]
  173. alphabet_menu = ttk.Combobox(root, textvariable=alphabet_var, values=alphabet_options, state="readonly")
  174. alphabet_menu.pack()
  175. alphabet_menu.bind("<<ComboboxSelected>>", load_alphabet)
  176. ttk.Label(root, text="Введите ключ").pack()
  177. key_entry = tk.Entry(root)
  178. key_entry.pack()
  179. key_entry.bind("<KeyRelease>", lambda event: update_table())
  180. table_display = tk.Text(root, font=("Courier", 14), bd=0, highlightthickness=0, wrap="none")
  181. table_display.pack(pady=10, fill="x")
  182. table_display.tag_config("highlight", foreground="red")
  183. table_display.config(state="disabled")
  184. ttk.Label(root, text="Введите текст").pack()
  185. input_text = tk.Entry(root)
  186. input_text.pack(pady=5)
  187. buttons_frame = tk.Frame(root)
  188. buttons_frame.pack(pady=10)
  189. encrypt_button = tk.Button(buttons_frame, text="Зашифровать", command=encrypt)
  190. encrypt_button.pack(side=tk.LEFT, padx=10)
  191. decrypt_button = tk.Button(buttons_frame, text="Дешифровать", command=decrypt)
  192. decrypt_button.pack(side=tk.RIGHT, padx=10)
  193. ttk.Label(root, text="Результат:").pack()
  194. output_text = tk.Label(root, text="", fg="red", font=("Courier", 14))
  195. output_text.pack(pady=10)
  196. root.mainloop()
  197. conn.close()