123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230 |
- import sqlite3
- import tkinter as tk
- from tkinter import ttk
- import time
- # Создание таблицы для заполнения
- conn = sqlite3.connect("vigenere.db")
- cursor = conn.cursor()
- cursor.execute("""
- CREATE TABLE IF NOT EXISTS alphabets (
- id INTEGER PRIMARY KEY AUTOINCREMENT,
- name TEXT UNIQUE,
- alphabet TEXT
- )
- """)
- conn.commit()
- # Запись алфавита
- cursor.execute("SELECT COUNT(*) FROM alphabets")
- if cursor.fetchone()[0] == 0:
- cursor.execute("INSERT INTO alphabets (name, alphabet) VALUES (?, ?)",
- ("Русский (с Ё)", "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ"))
- cursor.execute("INSERT INTO alphabets (name, alphabet) VALUES (?, ?)",
- ("Русский (без Ё)", "АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ"))
- cursor.execute("INSERT INTO alphabets (name, alphabet) VALUES (?, ?)",
- ("Русский (с подчеркиванием)", "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ"))
- conn.commit()
- # Глобальная переменная для заполения алфавита выбранного
- alphabet = ""
- # Цветовая функция
- def get_color_for_key(letter):
- colors = ["red", "blue", "green", "orange", "purple", "magenta", "cyan", "brown"]
- return colors[ord(letter) % len(colors)]
- def build_table_lines():
- cell_width = 3
- # Выравнивание по првому краю
- header = " " * cell_width + "".join([letter.rjust(cell_width) for letter in alphabet])
-
- raw_key = key_entry.get().upper()
- unique_key = ""
- for ch in raw_key:
- if ch in alphabet and ch not in unique_key:
- unique_key += ch
- rows = []
- for letter in unique_key:
- shift = alphabet.index(letter) + 1
- rotated = alphabet[shift:] + alphabet[:shift]
- row = letter.rjust(cell_width) + "".join([r.rjust(cell_width) for r in rotated])
- rows.append(row)
-
- return [header] + rows, unique_key
- def update_table():
- lines, _ = build_table_lines()
- full_text = "\n".join(lines)
- table_display.config(state="normal")
- table_display.delete("1.0", "end")
- table_display.insert("1.0", full_text)
- table_display.config(state="disabled")
- def update_table_in_text(content):
- table_display.config(state="normal")
- table_display.delete("1.0", "end")
- table_display.insert("1.0", content)
- table_display.config(state="disabled")
- def animate_intersection(key_letter, plaintext_letter, ciphertext_letter):
-
- # Анимация сканирования и движения для выбранной буквы ключа
-
- cell_width = 3
- lines, unique_key = build_table_lines()
- if key_letter not in unique_key:
- return
- row_index = unique_key.index(key_letter) + 1
-
- shift = alphabet.index(key_letter) + 1
- rotated = alphabet[shift:] + alphabet[:shift]
- try:
- target_col = rotated.index(ciphertext_letter)
- except ValueError:
- target_col = 0
- # Пробег по таблице
- for j in range(len(alphabet)):
- new_lines = list(lines)
- row = new_lines[row_index]
- cells = [row[i:i+cell_width] for i in range(0, len(row), cell_width)]
- if j < len(cells) - 1:
- cells[j+1] = "(" + rotated[j].strip() + ")"
- new_lines[row_index] = key_letter.rjust(cell_width) + "".join(cells[1:])
- update_table_in_text("\n".join(new_lines))
- table_display.update()
- time.sleep(0.2)
- if j == target_col:
- perform_upward_animation(key_letter, target_col, rotated,
- row_index, cell_width, lines)
- break
- def perform_upward_animation(key_letter, target_col, rotated, row_index, cell_width, base_lines):
-
- #Анимация подъёма найденной ячейки.
-
- floating_frames = 4
- for frame in range(floating_frames):
- new_lines = list(base_lines)
- new_row_index = row_index - (frame + 1)
- if new_row_index < 1:
- new_row_index = 1
- # Обновляем строку с буквой ключа
- orig_line = new_lines[row_index]
- cells = [orig_line[i:i+cell_width] for i in range(0, len(orig_line), cell_width)]
- cells[target_col+1] = rotated[target_col].rjust(cell_width)
- new_lines[row_index] = key_letter.rjust(cell_width) + "".join(cells[1:])
-
- # Обновляем строку куда перемещаеться
- float_line = new_lines[new_row_index]
- float_cells = [float_line[i:i+cell_width] for i in range(0, len(float_line), cell_width)]
- if target_col+1 < len(float_cells):
- float_cells[target_col+1] = rotated[target_col].center(cell_width)
- else:
- float_cells.append(rotated[target_col].center(cell_width))
- new_lines[new_row_index] = "".join(float_cells)
-
- update_table_in_text("\n".join(new_lines))
- table_display.config(state="normal")
- line_num = new_row_index + 1
- start_col = (target_col+1) * cell_width
- end_col = start_col + cell_width
- table_display.tag_remove("highlight", "1.0", "end")
- table_display.tag_add("highlight", f"{line_num}.{start_col}", f"{line_num}.{end_col}")
- # Выбор цвета
- table_display.tag_config("highlight", foreground=get_color_for_key(key_letter))
- table_display.config(state="disabled")
- table_display.update()
- time.sleep(0.3)
- time.sleep(0.5)
- update_table()
- def vigenere_cipher(text, decrypt=False):
-
- text = text.upper()
- key = key_entry.get().upper()
- if not key:
- return text
- result = ""
- for i, char in enumerate(text):
- if char in alphabet:
- current_key = key[i % len(key)]
- shift = alphabet.index(current_key)
- if decrypt:
- new_index = (alphabet.index(char) - shift) % len(alphabet)
- else:
- new_index = (alphabet.index(char) + shift) % len(alphabet)
- output_letter = alphabet[new_index]
- if decrypt:
- animate_intersection(current_key, output_letter, char)
- else:
- animate_intersection(current_key, char, output_letter)
- result += output_letter
- else:
- result += char
- return result
- def encrypt():
- update_table()
- encrypted_text = vigenere_cipher(input_text.get(), decrypt=False)
- output_text.config(text=encrypted_text)
- def decrypt():
- update_table()
- decrypted_text = vigenere_cipher(input_text.get(), decrypt=True)
- output_text.config(text=decrypted_text)
- def load_alphabet(event=None):
- global alphabet
- selected = alphabet_var.get()
- cursor.execute("SELECT alphabet FROM alphabets WHERE name = ?", (selected,))
- result = cursor.fetchone()
- if result:
- alphabet = result[0]
- # Вариант с подчеркиванием
- if selected == "Русский (с подчеркиванием)" and not alphabet.endswith("_"):
- alphabet += "_"
- update_table()
- # Интерфейс
- root = tk.Tk()
- root.title("Шифр Виженера")
- root.geometry("800x600")
- alphabet_var = tk.StringVar()
- ttk.Label(root, text="Выберите алфавит").pack()
- cursor.execute("SELECT name FROM alphabets")
- alphabet_options = [row[0] for row in cursor.fetchall()]
- alphabet_menu = ttk.Combobox(root, textvariable=alphabet_var, values=alphabet_options, state="readonly")
- alphabet_menu.pack()
- alphabet_menu.bind("<<ComboboxSelected>>", load_alphabet)
- ttk.Label(root, text="Введите ключ").pack()
- key_entry = tk.Entry(root)
- key_entry.pack()
- key_entry.bind("<KeyRelease>", lambda event: update_table())
- table_display = tk.Text(root, font=("Courier", 14), bd=0, highlightthickness=0, wrap="none")
- table_display.pack(pady=10, fill="x")
- table_display.tag_config("highlight", foreground="red")
- table_display.config(state="disabled")
- ttk.Label(root, text="Введите текст").pack()
- input_text = tk.Entry(root)
- input_text.pack(pady=5)
- buttons_frame = tk.Frame(root)
- buttons_frame.pack(pady=10)
- encrypt_button = tk.Button(buttons_frame, text="Зашифровать", command=encrypt)
- encrypt_button.pack(side=tk.LEFT, padx=10)
- decrypt_button = tk.Button(buttons_frame, text="Дешифровать", command=decrypt)
- decrypt_button.pack(side=tk.RIGHT, padx=10)
- ttk.Label(root, text="Результат:").pack()
- output_text = tk.Label(root, text="", fg="red", font=("Courier", 14))
- output_text.pack(pady=10)
- root.mainloop()
- conn.close()
|