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("<>", load_alphabet) ttk.Label(root, text="Введите ключ").pack() key_entry = tk.Entry(root) key_entry.pack() key_entry.bind("", 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()