From eb9cae6ec296d332fe4240ec4f3bafee4af7ac08 Mon Sep 17 00:00:00 2001 From: Gary Gan Date: Mon, 30 Jun 2025 21:05:34 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9C=BA=E5=85=B3UI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Lock.py | 42 +++++ SourceCollector.py | 2 +- assets/lock.png | Bin 0 -> 29782 bytes codeforces_c3.py | 129 ++++++++++++++ codeforces_c3_final.py | 97 ++++++++++ codeforces_c3_v2.py | 110 ++++++++++++ config.py | 1 + debug_maze.py | 43 +++++ main.py | 38 +++- maze.py | 51 +++++- maze_generator.py | 97 ++++++++-- mechanism_ui.py | 146 +++++++++++++++ mylock.py | 381 ++++++++++++++++++++++------------------ pwd/pwd_000.json | 13 ++ pwd/pwd_001.json | 14 ++ pwd/pwd_002.json | 14 ++ pwd/pwd_003.json | 12 ++ pwd/pwd_004.json | 12 ++ pwd/pwd_005.json | 14 ++ pwd/pwd_006.json | 14 ++ pwd/pwd_007.json | 14 ++ pwd/pwd_008.json | 12 ++ pwd/pwd_009.json | 12 ++ pwd/pwd_010.json | 14 ++ pwd/pwd_011.json | 13 ++ pwd/pwd_012.json | 12 ++ pwd/pwd_013.json | 14 ++ pwd/pwd_014.json | 12 ++ pwd/pwd_015.json | 14 ++ pwd/pwd_016.json | 13 ++ pwd/pwd_017.json | 14 ++ pwd/pwd_018.json | 13 ++ pwd/pwd_019.json | 12 ++ pwd/pwd_020.json | 14 ++ pwd/pwd_021.json | 14 ++ pwd/pwd_022.json | 14 ++ pwd/pwd_023.json | 12 ++ pwd/pwd_024.json | 13 ++ pwd/pwd_025.json | 14 ++ pwd/pwd_026.json | 13 ++ pwd/pwd_027.json | 12 ++ pwd/pwd_028.json | 14 ++ pwd/pwd_029.json | 13 ++ pwd_output/pwd_000.json | 14 ++ pwd_output/pwd_001.json | 14 ++ pwd_output/pwd_002.json | 14 ++ pwd_output/pwd_003.json | 12 ++ pwd_output/pwd_004.json | 12 ++ pwd_output/pwd_005.json | 14 ++ pwd_output/pwd_006.json | 14 ++ pwd_output/pwd_007.json | 14 ++ pwd_output/pwd_008.json | 12 ++ pwd_output/pwd_009.json | 12 ++ pwd_output/pwd_010.json | 14 ++ pwd_output/pwd_011.json | 13 ++ pwd_output/pwd_012.json | 12 ++ pwd_output/pwd_013.json | 14 ++ pwd_output/pwd_014.json | 12 ++ pwd_output/pwd_015.json | 14 ++ pwd_output/pwd_016.json | 13 ++ pwd_output/pwd_017.json | 14 ++ pwd_output/pwd_018.json | 13 ++ pwd_output/pwd_019.json | 12 ++ pwd_output/pwd_020.json | 14 ++ pwd_output/pwd_021.json | 14 ++ pwd_output/pwd_022.json | 14 ++ pwd_output/pwd_023.json | 12 ++ pwd_output/pwd_024.json | 13 ++ pwd_output/pwd_025.json | 14 ++ pwd_output/pwd_026.json | 13 ++ pwd_output/pwd_027.json | 12 ++ pwd_output/pwd_028.json | 14 ++ pwd_output/pwd_029.json | 13 ++ 73 files changed, 1729 insertions(+), 199 deletions(-) create mode 100644 Lock.py create mode 100644 assets/lock.png create mode 100644 codeforces_c3.py create mode 100644 codeforces_c3_final.py create mode 100644 codeforces_c3_v2.py create mode 100644 debug_maze.py create mode 100644 mechanism_ui.py create mode 100644 pwd/pwd_000.json create mode 100644 pwd/pwd_001.json create mode 100644 pwd/pwd_002.json create mode 100644 pwd/pwd_003.json create mode 100644 pwd/pwd_004.json create mode 100644 pwd/pwd_005.json create mode 100644 pwd/pwd_006.json create mode 100644 pwd/pwd_007.json create mode 100644 pwd/pwd_008.json create mode 100644 pwd/pwd_009.json create mode 100644 pwd/pwd_010.json create mode 100644 pwd/pwd_011.json create mode 100644 pwd/pwd_012.json create mode 100644 pwd/pwd_013.json create mode 100644 pwd/pwd_014.json create mode 100644 pwd/pwd_015.json create mode 100644 pwd/pwd_016.json create mode 100644 pwd/pwd_017.json create mode 100644 pwd/pwd_018.json create mode 100644 pwd/pwd_019.json create mode 100644 pwd/pwd_020.json create mode 100644 pwd/pwd_021.json create mode 100644 pwd/pwd_022.json create mode 100644 pwd/pwd_023.json create mode 100644 pwd/pwd_024.json create mode 100644 pwd/pwd_025.json create mode 100644 pwd/pwd_026.json create mode 100644 pwd/pwd_027.json create mode 100644 pwd/pwd_028.json create mode 100644 pwd/pwd_029.json create mode 100644 pwd_output/pwd_000.json create mode 100644 pwd_output/pwd_001.json create mode 100644 pwd_output/pwd_002.json create mode 100644 pwd_output/pwd_003.json create mode 100644 pwd_output/pwd_004.json create mode 100644 pwd_output/pwd_005.json create mode 100644 pwd_output/pwd_006.json create mode 100644 pwd_output/pwd_007.json create mode 100644 pwd_output/pwd_008.json create mode 100644 pwd_output/pwd_009.json create mode 100644 pwd_output/pwd_010.json create mode 100644 pwd_output/pwd_011.json create mode 100644 pwd_output/pwd_012.json create mode 100644 pwd_output/pwd_013.json create mode 100644 pwd_output/pwd_014.json create mode 100644 pwd_output/pwd_015.json create mode 100644 pwd_output/pwd_016.json create mode 100644 pwd_output/pwd_017.json create mode 100644 pwd_output/pwd_018.json create mode 100644 pwd_output/pwd_019.json create mode 100644 pwd_output/pwd_020.json create mode 100644 pwd_output/pwd_021.json create mode 100644 pwd_output/pwd_022.json create mode 100644 pwd_output/pwd_023.json create mode 100644 pwd_output/pwd_024.json create mode 100644 pwd_output/pwd_025.json create mode 100644 pwd_output/pwd_026.json create mode 100644 pwd_output/pwd_027.json create mode 100644 pwd_output/pwd_028.json create mode 100644 pwd_output/pwd_029.json diff --git a/Lock.py b/Lock.py new file mode 100644 index 0000000..6256258 --- /dev/null +++ b/Lock.py @@ -0,0 +1,42 @@ +import hashlib +import os + +class PasswordLock: + def __init__(self): + self.salt = b'\xb2S"e}\xdf\xb0\xfe\x9c\xde\xde\xfe\xf3\x1d\xdc>' + + def hash_password(self, password): + # 将密码转换为字节流 + password_bytes = password.encode('utf-8') + + # 将盐值和密码组合并进行哈希 + hash_obj = hashlib.sha256(self.salt + password_bytes) + password_hash = hash_obj.hexdigest() + + return password_hash + + def verify_password(self, input_password, stored_hash): + # 使用相同的盐值对输入密码进行哈希 + calculated_hash = self.hash_password(input_password) + + # 比较计算出的哈希值与存储的哈希值 + return calculated_hash == stored_hash + + +# 使用示例 +if __name__ == "__main__": + lock = PasswordLock() + + # 用户设置密码 + user_password = input("请设置一个三位数密码: ") + + # 加密密码 + password_hash = lock.hash_password(user_password) + print(f"密码已加密,哈希值: {password_hash}") + + # 验证密码 + test_password = input("请输入密码进行验证: ") + if lock.verify_password(test_password, password_hash): + print("密码验证成功!") + else: + print("密码验证失败!") diff --git a/SourceCollector.py b/SourceCollector.py index 723ca6e..4f5b6d0 100644 --- a/SourceCollector.py +++ b/SourceCollector.py @@ -210,7 +210,7 @@ class SourceCollector: if item == self.path[idx-1]: del self.path[idx] - + self.path.extend(self.bfs_path(self.path[-1],self.end_pos)) diff --git a/assets/lock.png b/assets/lock.png new file mode 100644 index 0000000000000000000000000000000000000000..f99d39b17ce3bf6e15df51e36f80ebf9c0c3739d GIT binary patch literal 29782 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

&estmxQ2 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 KMNUMnLSTaJnDVs% literal 0 HcmV?d00001 diff --git a/codeforces_c3.py b/codeforces_c3.py new file mode 100644 index 0000000..fc5f5b6 --- /dev/null +++ b/codeforces_c3.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python3 +import sys + +def solve(): + n = int(input()) + + # 基于示例的策略分析: + # 示例1: 目标100, x未知 -> add -10(失败) -> add 1(成功) -> mul 10(成功) -> 结果100 + # 示例2: 目标5, x未知 -> digit(成功) -> div 2(成功) -> 结果5 + + # 观察:我们需要一个能处理任意初始值的通用策略 + + # 通用策略: + # 1. 先用digit将值标准化到较小范围 + # 2. 然后用算术操作构造目标 + + # 第一步:标准化 + print("digit") + sys.stdout.flush() + response = int(input()) + + if response != 1: + return + + # 现在值在某个较小的范围内(但可能不是1-9,因为digit可能需要多次) + + # 第二步:构造目标 + if n <= 9: + # 对于单位数目标,尝试多种调整策略 + success = False + + # 策略1:尝试各种可能的当前值,调整到n + for possible_current in range(1, 100): # 扩大搜索范围 + if success: + break + + # 计算需要的调整 + diff = n - possible_current + + # 尝试加法调整 + if abs(diff) <= 10**18: + print(f"add {diff}") + sys.stdout.flush() + response = int(input()) + if response == 1: + success = True + break + + # 策略2:如果加法失败,尝试除法(如示例2) + if not success and n < 10: + for divisor in range(2, 20): + print(f"div {divisor}") + sys.stdout.flush() + response = int(input()) + if response == 1: + # 除法成功,可能需要继续调整 + for adj in range(-10, 11): + if adj == 0: + continue + print(f"add {adj}") + sys.stdout.flush() + response = int(input()) + if response == 1: + success = True + break + break + + else: + # 对于大数目标,使用乘法+加法组合 + success = False + + # 策略1:找到合适的因数分解 n = a * b + for a in range(1, min(100, n+1)): + if success: + break + + if n % a == 0: + b = n // a + if b <= 10**18: + # 尝试构造 a,然后乘以 b + + # 首先尝试调整到 a + for current_guess in range(1, 100): + diff = a - current_guess + print(f"add {diff}") + sys.stdout.flush() + response = int(input()) + + if response == 1: + # 成功调整到 a,现在乘以 b + print(f"mul {b}") + sys.stdout.flush() + response = int(input()) + if response == 1: + success = True + break + else: + # 乘法失败,尝试下一个分解 + break + + # 如果这个调整失败,尝试下一个current_guess + + if success: + break + + # 策略2:如果因数分解失败,尝试直接构造 + if not success: + for current_guess in range(1, 100): + diff = n - current_guess + if abs(diff) <= 10**18: + print(f"add {diff}") + sys.stdout.flush() + response = int(input()) + if response == 1: + success = True + break + + # 输出结果 + print("!") + sys.stdout.flush() + final_response = int(input()) + +def main(): + t = int(input()) + for _ in range(t): + solve() + +if __name__ == "__main__": + main() diff --git a/codeforces_c3_final.py b/codeforces_c3_final.py new file mode 100644 index 0000000..1ade6e7 --- /dev/null +++ b/codeforces_c3_final.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python3 +import sys + +def solve(): + n = int(input()) + + # 最终策略:基于问题的深入理解 + # + # 核心思想: + # 1. 使用digit操作标准化到小范围 + # 2. 利用数学性质构造目标 + + # 对于所有情况,先用digit标准化 + print("digit") + sys.stdout.flush() + response = int(input()) + + if response != 1: + return + + # 现在当前值是原数字的数字和 + # 对于1-9的目标,我们有简单策略 + # 对于更大的目标,我们使用构造法 + + if n <= 9: + # 目标是1-9,直接尝试所有可能的调整 + # 由于我们不知道确切的当前值,枚举所有可能性 + + attempts = [ + # 假设当前是1-9,计算到n的差值 + n - 1, n - 2, n - 3, n - 4, n - 5, + n - 6, n - 7, n - 8, n - 9 + ] + + for diff in attempts: + print(f"add {diff}") + sys.stdout.flush() + response = int(input()) + if response == 1: + break + + else: + # 目标大于9,使用乘法构造 + # 策略:找到n的一个小因子d,使得n = d * q + # 然后构造d,再乘以q + + best_factor = None + best_quotient = None + + # 寻找最佳的因子分解 + for d in range(1, 10): + if n % d == 0: + q = n // d + if q <= 10**17: # 确保乘法不会溢出 + best_factor = d + best_quotient = q + break + + if best_factor is not None: + # 使用因子分解策略 + # 先构造best_factor + for current_guess in range(1, 10): + diff = best_factor - current_guess + print(f"add {diff}") + sys.stdout.flush() + response = int(input()) + + if response == 1: + # 成功构造因子,现在乘以quotient + print(f"mul {best_quotient}") + sys.stdout.flush() + response = int(input()) + break + else: + # 没有合适的因子分解,使用直接加法 + # 这种情况下,假设当前是某个小数字,直接加到n + for current_guess in range(1, 10): + diff = n - current_guess + if 0 < diff <= 10**18: + print(f"add {diff}") + sys.stdout.flush() + response = int(input()) + if response == 1: + break + + # 结束 + print("!") + sys.stdout.flush() + final_response = int(input()) + +def main(): + t = int(input()) + for _ in range(t): + solve() + +if __name__ == "__main__": + main() diff --git a/codeforces_c3_v2.py b/codeforces_c3_v2.py new file mode 100644 index 0000000..75bc01e --- /dev/null +++ b/codeforces_c3_v2.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python3 +import sys + +def solve(): + n = int(input()) + + # 基于理论分析的最优策略: + # 对任意目标n,我们可以证明存在一个通用的构造方法 + + # 关键观察: + # 1. digit操作将任何数转换为其数字和(最终会到1-9范围) + # 2. 从任何1-9的数,我们都可以用很少操作构造任意目标 + + # 最优构造策略: + if n == 1: + # 对于目标1:digit -> 然后想办法变为1 + print("digit") + sys.stdout.flush() + response = int(input()) + + # 现在尝试各种方法变为1 + # 方法1: 如果当前是偶数,除以自身 + for d in [2, 3, 4, 5, 6, 7, 8, 9]: + print(f"div {d}") + sys.stdout.flush() + response = int(input()) + if response == 1: + # 除法成功,现在可能是1或其他数 + # 继续尝试到达1 + break + + # 方法2: 用加法调整 + for adj in range(-8, 9): + if adj != 0: + print(f"add {adj}") + sys.stdout.flush() + response = int(input()) + if response == 1: + break + + elif 2 <= n <= 9: + # 对于2-9:digit -> 调整到目标 + print("digit") + sys.stdout.flush() + response = int(input()) + + # 枚举所有可能的当前值,尝试调整到n + for current in range(1, 10): + diff = n - current + print(f"add {diff}") + sys.stdout.flush() + response = int(input()) + if response == 1: + break + + else: + # 对于n > 9:使用构造策略 + # 策略:digit -> 构造一个因子 -> 乘法得到n + + print("digit") + sys.stdout.flush() + response = int(input()) + + # 寻找n的最小因子(除了1) + smallest_factor = n + for f in range(2, min(10, n + 1)): + if n % f == 0: + smallest_factor = f + break + + if smallest_factor < n: + # 找到了因子,使用分解策略 + quotient = n // smallest_factor + + # 尝试构造smallest_factor + for current in range(1, 10): + diff = smallest_factor - current + print(f"add {diff}") + sys.stdout.flush() + response = int(input()) + + if response == 1: + # 成功构造factor,现在乘以quotient + print(f"mul {quotient}") + sys.stdout.flush() + response = int(input()) + break + else: + # n是质数或没有小因子,使用直接加法 + for current in range(1, 10): + diff = n - current + if diff > 0 and diff <= 10**18: + print(f"add {diff}") + sys.stdout.flush() + response = int(input()) + if response == 1: + break + + # 输出答案 + print("!") + sys.stdout.flush() + final_response = int(input()) + +def main(): + t = int(input()) + for _ in range(t): + solve() + +if __name__ == "__main__": + main() diff --git a/config.py b/config.py index d855a2c..d9b9a88 100644 --- a/config.py +++ b/config.py @@ -29,6 +29,7 @@ WALL_IMAGE = f"{ASSETS_PATH}/wall.png" COIN_IMAGE = f"{ASSETS_PATH}/coin.png" TRAP_IMAGE = f"{ASSETS_PATH}/trap.png" BOSS_IMAGE = f"{ASSETS_PATH}/boss.jpg" +LOCK_IMAGE = f"{ASSETS_PATH}/lock.png" START_BUTTON_IMAGE = f"{ASSETS_PATH}/start_button.png" SAVE_BUTTON_IMAGE = f"{ASSETS_PATH}/save.png" LOAD_BUTTON_IMAGE = f"{ASSETS_PATH}/load.png" diff --git a/debug_maze.py b/debug_maze.py new file mode 100644 index 0000000..344488c --- /dev/null +++ b/debug_maze.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 +""" +调试迷宫生成问题 +""" + +import sys +import os +sys.path.append(os.path.dirname(os.path.abspath(__file__))) + +from maze_generator import MazeGenerator + +def debug_maze_generation(): + """调试迷宫生成""" + print("=== 调试迷宫生成 ===") + + # 创建迷宫生成器 + generator = MazeGenerator(size=15, filename="debug_test.csv") + + print(f"迷宫尺寸: {generator.size}") + + # 初始化迷宫 + generator.initialize_maze() + print(f"初始化后的迷宫大小: {len(generator.maze)} x {len(generator.maze[0]) if generator.maze else 0}") + + # 生成迷宫结构 + generator.create_maze(1, 1, generator.size - 2, generator.size - 2) + + # 检查可用单元格 + available_cells = generator.get_available_cells() + print(f"可用单元格数量: {len(available_cells)}") + + if len(available_cells) == 0: + print("❌ 没有可用单元格,检查迷宫结构...") + # 打印迷宫以便调试 + print("迷宫结构:") + for i, row in enumerate(generator.maze): + print(f"第{i}行: {row}") + else: + print(f"✅ 找到 {len(available_cells)} 个可用单元格") + print(f"前5个可用单元格: {available_cells[:5]}") + +if __name__ == "__main__": + debug_maze_generation() diff --git a/main.py b/main.py index de20aef..cdf00b9 100644 --- a/main.py +++ b/main.py @@ -6,6 +6,7 @@ from maze import Maze from draw import Button, Toast from save_ui import SaveLoadUI from boss_fight_ui import BossFightUI +from mechanism_ui import MechanismUI from config import * import sys import os @@ -81,6 +82,7 @@ if __name__ == "__main__": image_coin = pygame.image.load(COIN_IMAGE).convert_alpha() image_trap = pygame.image.load(TRAP_IMAGE).convert_alpha() image_boss = pygame.image.load(BOSS_IMAGE).convert_alpha() + image_lock = pygame.image.load(LOCK_IMAGE).convert_alpha() # 初始按钮位置和按钮 button_positions = get_button_positions() @@ -100,6 +102,9 @@ if __name__ == "__main__": # 创建Boss战斗界面 boss_fight_ui = BossFightUI() + + # 创建机关界面 + mechanism_ui = MechanismUI(textFont) # 路径控制变量 auto_play = False @@ -131,16 +136,20 @@ if __name__ == "__main__": boss_fight_ui.update() # 自动播放逻辑 - if auto_play and len(maze.full_path) > 0 and not maze.show_history and not boss_fight_ui.is_showing: + if auto_play and len(maze.full_path) > 0 and not maze.show_history and not boss_fight_ui.is_showing and not mechanism_ui.is_showing: auto_play_timer += 1 if auto_play_timer >= auto_play_interval: - has_next, boss_encountered, boss_info = maze.next_path_step() + has_next, boss_encountered, boss_info, mechanism_encountered, mechanism_info = maze.next_path_step() if not has_next: auto_play = False # 路径播放完成后停止自动播放 elif boss_encountered and boss_info: # 显示Boss战斗界面 boss_fight_ui.show_boss_fight(boss_info['boss_data'], boss_info['player_skills']) auto_play = False # 遇到boss时停止自动播放 + elif mechanism_encountered and mechanism_info: + # 显示机关界面 + mechanism_ui.show_mechanism() + auto_play = False # 遇到机关时停止自动播放 auto_play_timer = 0 # 历史迭代自动播放逻辑 @@ -152,7 +161,11 @@ if __name__ == "__main__": history_auto_timer = 0 for event in pygame.event.get(): - # 首先让Boss战斗界面处理事件 + # 首先让机关界面处理事件 + if mechanism_ui.handle_event(event): + continue + + # 然后让Boss战斗界面处理事件 if boss_fight_ui.handle_event(event): continue @@ -166,8 +179,8 @@ if __name__ == "__main__": elif save_result == "load_failed": mes5.show() - # 如果存档界面或Boss战斗界面正在显示,不处理其他按钮事件 - if not save_ui.show_save_list and not boss_fight_ui.is_showing: + # 如果存档界面、Boss战斗界面或机关界面正在显示,不处理其他按钮事件 + if not save_ui.show_save_list and not boss_fight_ui.is_showing and not mechanism_ui.is_showing: buttons['start'].handle_event(event=event) buttons['save'].handle_event(event=event) buttons['load'].handle_event(event=event) @@ -234,10 +247,13 @@ if __name__ == "__main__": # 路径控制 if buttons['next_step'].pressed == True and len(maze.full_path) > 0 and not maze.show_history: - has_next, boss_encountered, boss_info = maze.next_path_step() + has_next, boss_encountered, boss_info, mechanism_encountered, mechanism_info = maze.next_path_step() if boss_encountered and boss_info: # 显示Boss战斗界面 boss_fight_ui.show_boss_fight(boss_info['boss_data'], boss_info['player_skills']) + elif mechanism_encountered and mechanism_info: + # 显示机关界面 + mechanism_ui.show_mechanism() if buttons['reset_path'].pressed == True and len(maze.full_path) > 0 and not maze.show_history: maze.reset_path() @@ -266,10 +282,13 @@ if __name__ == "__main__": # 键盘控制 if event.type == pygame.KEYDOWN: if event.key == pygame.K_SPACE and len(maze.full_path) > 0 and not maze.show_history: - has_next, boss_encountered, boss_info = maze.next_path_step() + has_next, boss_encountered, boss_info, mechanism_encountered, mechanism_info = maze.next_path_step() if boss_encountered and boss_info: # 显示Boss战斗界面 boss_fight_ui.show_boss_fight(boss_info['boss_data'], boss_info['player_skills']) + elif mechanism_encountered and mechanism_info: + # 显示机关界面 + mechanism_ui.show_mechanism() elif event.key == pygame.K_r and len(maze.full_path) > 0 and not maze.show_history: maze.reset_path() auto_play = False @@ -312,7 +331,7 @@ if __name__ == "__main__": running = False - maze.draw(screen=screen, wall_texture=image_wall, coin_texture=image_coin, trap_texture=image_trap, boss_texture=image_boss) + maze.draw(screen=screen, wall_texture=image_wall, coin_texture=image_coin, trap_texture=image_trap, boss_texture=image_boss, lock_texture=image_lock) buttons['start'].draw(screen=screen) buttons['save'].draw(screen=screen) buttons['load'].draw(screen=screen) @@ -388,6 +407,9 @@ if __name__ == "__main__": # 绘制Boss战斗界面(必须在最上层) boss_fight_ui.draw(screen) + # 绘制机关界面(必须在最上层) + mechanism_ui.draw(screen) + pygame.display.flip() pygame.quit() diff --git a/maze.py b/maze.py index ea17d84..9dcdf2c 100644 --- a/maze.py +++ b/maze.py @@ -35,6 +35,10 @@ class Maze: # Boss战斗相关 self.boss_data = [] # Boss血量序列 self.player_skills = [] # 玩家技能序列 + + # 已遇到的Boss和机关位置记录(避免重复触发) + self.encountered_bosses = set() # 已遇到的Boss位置 (y, x) + self.encountered_mechanisms = set() # 已遇到的机关位置 (y, x) def update_display_size(self): """根据当前迷宫大小更新显示尺寸""" @@ -83,6 +87,11 @@ class Maze: self.player_skills = [(random.randint(8, 20), random.randint(2, 5)) for _ in range(random.randint(3, 6))] # 随机生成技能:(伤害, 冷却时间) print(f"Boss数据: {self.boss_data}") print(f"玩家技能: {self.player_skills}") + + # 在路径上放置机关(只放置1个) + placed_mechanisms = self.generater.place_mechanisms_on_path(self.full_path, mechanisms_count=1) + if placed_mechanisms: + print(f"已在路径上放置 {len(placed_mechanisms)} 个机关") # 设置显示状态 self.grid = self.generater.maze # 使用原始迷宫数据 @@ -98,14 +107,21 @@ class Maze: if self.path_step < len(self.full_path): # 获取当前要显示的位置 current_y, current_x = self.full_path[self.path_step] + current_position = (current_y, current_x) - # 检查当前位置是否有boss + # 检查当前位置是否有boss或机关 boss_encountered = False + mechanism_encountered = False boss_info = None + mechanism_info = None + if self.generater.maze: current_cell = str(self.generater.maze[current_y][current_x]) - if current_cell.lower().startswith('b'): + + # 检查Boss(只有在之前没有遇到过这个位置的Boss时才触发) + if current_cell.lower().startswith('b') and current_position not in self.encountered_bosses: boss_encountered = True + self.encountered_bosses.add(current_position) # 记录已遇到的Boss位置 # 如果有boss数据和玩家技能数据,创建boss信息 if self.boss_data and self.player_skills: boss_info = { @@ -116,19 +132,34 @@ class Maze: else: print(f"遇到Boss但缺少战斗数据!Boss数据: {self.boss_data}, 玩家技能: {self.player_skills}") boss_info = None + + # 检查机关(只有在之前没有遇到过这个位置的机关时才触发) + elif current_cell.lower().startswith('l') and current_position not in self.encountered_mechanisms: + mechanism_encountered = True + self.encountered_mechanisms.add(current_position) # 记录已遇到的机关位置 + mechanism_info = { + 'position': (current_y, current_x), + 'cell_value': current_cell + } + print(f"遇到机关!位置: ({current_y}, {current_x}), 机关值: {current_cell}") self.path_step += 1 self.update_grid_with_path() - # 返回是否遇到boss和boss信息 - return True, boss_encountered, boss_info - return False, False, None + # 返回是否有下一步、是否遇到boss、boss信息、是否遇到机关、机关信息 + return True, boss_encountered, boss_info, mechanism_encountered, mechanism_info + return False, False, None, False, None def reset_path(self): """重置路径显示""" self.path_step = 0 self.is_path_complete = False self.grid = self.generater.maze if self.generater.maze else [] + + # 重置已遇到的Boss和机关记录,允许重新体验 + self.encountered_bosses = set() + self.encountered_mechanisms = set() + print("路径重置,Boss和机关遭遇记录已清除") def auto_advance_path(self): """自动推进路径显示""" @@ -221,7 +252,7 @@ class Maze: - def draw(self, screen, wall_texture, coin_texture, trap_texture, boss_texture): + def draw(self, screen, wall_texture, coin_texture, trap_texture, boss_texture, lock_texture): if len(self.grid) == 0: return @@ -234,6 +265,7 @@ class Maze: coin_texture = pygame.transform.scale(coin_texture, (tile_size, tile_size)) trap_texture = pygame.transform.scale(trap_texture, (tile_size, tile_size)) boss_texture = pygame.transform.scale(boss_texture, (tile_size, tile_size)) + lock_texture = pygame.transform.scale(lock_texture, (tile_size, tile_size)) for y in range(self.size): for x in range(self.size): @@ -243,6 +275,9 @@ class Maze: if self.grid[y][x].startswith('b'): screen.blit(boss_texture, (x * tile_size, y * tile_size)) continue + if self.grid[y][x].startswith('l'): + screen.blit(lock_texture, (x * tile_size, y * tile_size)) + continue if self.grid[y][x].startswith('g'): screen.blit(coin_texture, (x * tile_size, y * tile_size)) @@ -371,6 +406,10 @@ class Maze: self.is_path_complete = False self.full_path = [] + # 重置已遇到的Boss和机关记录 + self.encountered_bosses = set() + self.encountered_mechanisms = set() + # 显示相关状态 self.grid = [] diff --git a/maze_generator.py b/maze_generator.py index 963c0ce..0e45858 100644 --- a/maze_generator.py +++ b/maze_generator.py @@ -129,17 +129,16 @@ class MazeGenerator: def place_special_elements(self, boss_count=0, traps_range=(3, 8), mechanisms_range=(2, 6), skill_traps=5,gold_range=(3,8)): - """放置特殊元素(支持技能触发陷阱)- 不包括Boss,Boss将在路径生成后放置""" + """放置特殊元素(支持技能触发陷阱)- 不包括Boss和机关,这些将在路径生成后放置""" available = self.get_available_cells() random.shuffle(available) - # 计算所需单元格数量(不包括Boss) - required = 2 + random.randint(*traps_range) + random.randint(*mechanisms_range) + skill_traps + random.randint(*gold_range) + # 计算所需单元格数量(不包括Boss和机关) + required = 2 + random.randint(*traps_range) + skill_traps + random.randint(*gold_range) if len(available) < required: raise ValueError(f"空间不足,需要{required}个单元格,实际可用{len(available)}") # 放置出入口 - start, end = available.pop(), available.pop() self.special_elements.extend([(start[0], start[1], self.START), (end[0], end[1], self.END)]) self.maze[start[0]][start[1]] = self.START @@ -161,24 +160,33 @@ class MazeGenerator: self.special_elements.append((pos[0], pos[1], f"{self.TRAP}{val}")) self.maze[pos[0]][pos[1]] = f"{self.TRAP}{val}" - # 放置机关 - mechanisms = random.randint(*mechanisms_range) - for _ in range(mechanisms): + # 技能触发陷阱 + for _ in range(skill_traps): pos = available.pop() - val = random.randint(10, 30) - self.special_elements.append((pos[0], pos[1], f"{self.MECHANISM}{val}")) - self.maze[pos[0]][pos[1]] = f"{self.MECHANISM}{val}" + val = random.randint(5, 20) + self.special_elements.append((pos[0], pos[1], f"{self.TRAP}{val}")) + self.maze[pos[0]][pos[1]] = f"{self.TRAP}{val}" + + # 注释掉机关放置,机关将在路径生成后放置 + # # 放置机关 + # mechanisms = random.randint(*mechanisms_range) + # for _ in range(mechanisms): + # pos = available.pop() + # val = random.randint(10, 30) + # self.special_elements.append((pos[0], pos[1], f"{self.MECHANISM}{val}")) + # self.maze[pos[0]][pos[1]] = f"{self.MECHANISM}{val}" + # 放置金币 - mechanisms = random.randint(*gold_range) - for _ in range(mechanisms): + gold_count = random.randint(*gold_range) + for _ in range(gold_count): pos = available.pop() val = random.randint(10, 30) self.special_elements.append((pos[0], pos[1], f"{self.GOLD}{val}")) self.maze[pos[0]][pos[1]] = f"{self.GOLD}{val}" def generate(self, seed=None, traps_range=(3, 8), - mechanisms_range=(2, 6), skill_traps=5): - """生成迷宫主方法 - Boss将在路径生成后单独放置""" + mechanisms_range=(1, 1), skill_traps=5): + """生成迷宫主方法 - Boss和机关将在路径生成后单独放置""" # 清除之前的历史记录 self.history_mazes = [] self.special_elements = [] @@ -187,8 +195,8 @@ class MazeGenerator: self.initialize_maze() self.create_maze(1, 1, self.size - 2, self.size - 2) self.patch_maze_edges() # 自动修正边界 - self.place_special_elements(0, traps_range, mechanisms_range, skill_traps) # boss_count=0 - print(f"成功生成迷宫: {self.name} (Boss将在路径生成后放置)") + self.place_special_elements(0, traps_range, mechanisms_range, skill_traps) # boss_count=0, mechanisms也不在这里放置 + print(f"成功生成迷宫: {self.name} (Boss和机关将在路径生成后放置)") def export_to_csv(self, filename): """导出迷宫到CSV文件""" @@ -399,6 +407,63 @@ class MazeGenerator: return placed_bosses + def place_mechanisms_on_path(self, path, mechanisms_count=1, mechanisms_range=(1, 1)): + """ + 在给定路径上随机放置机关 + + Args: + path: 路径列表,格式为[(y1, x1), (y2, x2), ...] + mechanisms_count: 要放置的机关数量,默认为1 + mechanisms_range: 机关数量范围,当mechanisms_count为None时使用 + + Returns: + list: 放置机关的位置列表 + """ + if not path or len(path) < 3: + print("路径太短,无法放置机关") + return [] + + # 如果没有指定机关数量,使用默认值1 + if mechanisms_count is None: + mechanisms_count = 1 + + # 排除起点和终点,只在中间路径上放置机关 + middle_path = path[1:-1] # 去掉第一个(起点)和最后一个(终点) + + # 过滤掉已经被Boss和其他特殊元素占据的位置 + available_positions = [] + for pos in middle_path: + y, x = pos + cell_str = str(self.maze[y][x]) + # 只在通路位置或路径标记位置放置机关,避免覆盖Boss和其他特殊元素 + if (self.maze[y][x] == self.ROUTE or cell_str.startswith('p')) and not cell_str.startswith('b'): + available_positions.append(pos) + + if len(available_positions) < mechanisms_count: + print(f"路径中可用位置不足,只能放置{len(available_positions)}个机关") + mechanisms_count = len(available_positions) + + if mechanisms_count <= 0: + print("无可用位置放置机关") + return [] + + # 随机选择机关放置位置,确保不重复 + mechanism_positions = random.sample(available_positions, mechanisms_count) + placed_mechanisms = [] + + for pos in mechanism_positions: + y, x = pos + # 再次检查位置是否可用(避免重复放置) + if self.maze[y][x] == self.ROUTE or str(self.maze[y][x]).startswith('p'): + val = random.randint(10, 30) + mechanism_element = f"{self.MECHANISM}{val}" + self.maze[y][x] = mechanism_element + self.special_elements.append((y, x, mechanism_element)) + placed_mechanisms.append((y, x, val)) + print(f"在路径位置 ({y}, {x}) 放置机关,奖励: {val}") + + return placed_mechanisms + def main(): # 示例1: 生成带技能陷阱的迷宫 generator = MazeGenerator( diff --git a/mechanism_ui.py b/mechanism_ui.py new file mode 100644 index 0000000..21c789b --- /dev/null +++ b/mechanism_ui.py @@ -0,0 +1,146 @@ +import pygame +import json +import random +import os +from config import * + +class MechanismUI: + def __init__(self, font): + self.font = font + self.is_showing = False + self.mechanism_data = None + self.window_rect = pygame.Rect(0, 0, 600, 400) + self.close_button_rect = pygame.Rect(0, 0, 80, 40) + self.setup_window() + + def setup_window(self): + """设置窗口位置""" + self.window_rect.center = (UI_WIDTH // 2, UI_HEIGHT // 2) + self.close_button_rect.x = self.window_rect.right - 90 + self.close_button_rect.y = self.window_rect.y + 10 + + def load_random_password_file(self): + """从pwd_output目录随机加载一个密码文件""" + pwd_dir = "pwd_output" + if not os.path.exists(pwd_dir): + print(f"目录 {pwd_dir} 不存在") + return None + + # 获取所有json文件 + json_files = [f for f in os.listdir(pwd_dir) if f.endswith('.json')] + if not json_files: + print(f"目录 {pwd_dir} 中没有找到json文件") + return None + + # 随机选择一个文件 + selected_file = random.choice(json_files) + file_path = os.path.join(pwd_dir, selected_file) + + try: + with open(file_path, 'r', encoding='utf-8') as f: + data = json.load(f) + print(f"成功加载密码文件: {selected_file}") + return data + except Exception as e: + print(f"加载密码文件失败: {str(e)}") + return None + + def show_mechanism(self): + """显示机关界面""" + self.mechanism_data = self.load_random_password_file() + if self.mechanism_data: + self.is_showing = True + print("机关界面已显示") + else: + print("无法显示机关界面:密码数据加载失败") + + def hide_mechanism(self): + """隐藏机关界面""" + self.is_showing = False + self.mechanism_data = None + print("机关界面已隐藏") + + def handle_event(self, event): + """处理事件""" + if not self.is_showing: + return False + + if event.type == pygame.MOUSEBUTTONDOWN: + if self.close_button_rect.collidepoint(event.pos): + self.hide_mechanism() + return True + elif event.type == pygame.KEYDOWN: + if event.key == pygame.K_ESCAPE: + self.hide_mechanism() + return True + + return True # 阻止其他事件处理 + + def draw(self, screen): + """绘制机关界面""" + if not self.is_showing or not self.mechanism_data: + return + + # 绘制半透明背景 + overlay = pygame.Surface((UI_WIDTH, UI_HEIGHT)) + overlay.set_alpha(128) + overlay.fill((0, 0, 0)) + screen.blit(overlay, (0, 0)) + + # 绘制主窗口 + pygame.draw.rect(screen, COLOR_WHITE, self.window_rect) + pygame.draw.rect(screen, COLOR_BLACK, self.window_rect, 3) + + # 绘制标题 + title_text = self.font.render("机关密码破解", True, COLOR_BLACK) + title_rect = title_text.get_rect(centerx=self.window_rect.centerx, y=self.window_rect.y + 20) + screen.blit(title_text, title_rect) + + # 绘制密码信息 + password = self.mechanism_data.get("password", "未知") + password_text = self.font.render(f"最终密码: {password}", True, (255, 0, 0)) + password_rect = password_text.get_rect(centerx=self.window_rect.centerx, y=self.window_rect.y + 60) + screen.blit(password_text, password_rect) + + # 绘制三种策略的信息 + results = self.mechanism_data.get("results", {}) + y_offset = 100 + + method_names = { + "method1": "策略一: 暴力破解", + "method2": "策略二: 启发式搜索", + "method3": "策略三: 智能分析" + } + + for method_key, method_info in results.items(): + if method_key in method_names: + method_name = method_names[method_key] + tries = method_info.get("tries", 0) + password_array = method_info.get("password", []) + + # 绘制策略名称 + method_text = self.font.render(method_name, True, (0, 0, 255)) + screen.blit(method_text, (self.window_rect.x + 30, self.window_rect.y + y_offset)) + + # 绘制尝试次数 + tries_text = self.font.render(f"尝试次数: {tries}", True, COLOR_BLACK) + screen.blit(tries_text, (self.window_rect.x + 50, self.window_rect.y + y_offset + 25)) + + # 绘制密码数组 + password_str = "".join(map(str, password_array)) + password_array_text = self.font.render(f"密码: {password_str}", True, COLOR_GREEN) + screen.blit(password_array_text, (self.window_rect.x + 50, self.window_rect.y + y_offset + 50)) + + y_offset += 80 + + # 绘制关闭按钮 + pygame.draw.rect(screen, COLOR_GRAY, self.close_button_rect) + pygame.draw.rect(screen, COLOR_BLACK, self.close_button_rect, 2) + close_text = self.font.render("关闭", True, COLOR_BLACK) + close_rect = close_text.get_rect(center=self.close_button_rect.center) + screen.blit(close_text, close_rect) + + # 绘制操作提示 + hint_text = self.font.render("按ESC键或点击关闭按钮退出", True, COLOR_GRAY) + hint_rect = hint_text.get_rect(centerx=self.window_rect.centerx, y=self.window_rect.bottom - 30) + screen.blit(hint_text, hint_rect) diff --git a/mylock.py b/mylock.py index 35a5126..3fd59bd 100644 --- a/mylock.py +++ b/mylock.py @@ -1,5 +1,6 @@ import os import json +import random from Lock import PasswordLock @@ -18,190 +19,204 @@ def satisfies_prime_unique_condition(digits): return all(is_prime(d) for d in digits) and len(set(digits)) == 3 -def crack_method1(conditions): +def crack_method1(conditions, stored_hash): """从高位到低位回溯(第一位→第二位→第三位)""" - possible_passwords = [] - tries = 0 + tries = 1 + found_password = None + found = False + lock = PasswordLock() + + # 根据线索生成每位的合法数字范围 + digit_options = [[] for _ in range(3)] + + for i in range(3): + for d in range(10): + valid = True + for cond in conditions: + if cond == [-1, -1]: + if not is_prime(d): + valid = False + break + elif len(cond) == 2: + a, t = cond + a = abs(a) + if a - 1 == i and ((t == 0 and d % 2 != 0) or (t == 1 and d % 2 != 1)): + valid = False + break + elif len(cond) == 3: + if cond[i] != -1 and d != cond[i]: + valid = False + break + if valid: + digit_options[i].append(d) + + for i in range(3): + random.shuffle(digit_options[i]) def backtrack(index, current_digits): - nonlocal tries - tries += 1 - if index == 3: - for condition in conditions: - if condition == [-1, -1]: - if not satisfies_prime_unique_condition(current_digits): - return - elif len(condition) == 2: - a, t = condition - a = abs(a) - if 1 <= a <= 3: - if t == 0 and current_digits[a - 1] % 2 != 0: - return - elif t == 1 and current_digits[a - 1] % 2 != 1: - return - else: - return - elif len(condition) == 3: - b1, b2, b3 = condition - if b1 != -1 and current_digits[0] != b1: - return - if b2 != -1 and current_digits[1] != b2: - return - if b3 != -1 and current_digits[2] != b3: - return - possible_passwords.append("".join(map(str, current_digits))) + nonlocal tries, found, found_password + if found: return - for digit in range(10): - if index == 0: - has_fixed_value = any(len(cond) == 3 and cond[0] != -1 for cond in conditions) - if has_fixed_value: - fixed_values = [cond[0] for cond in conditions if len(cond) == 3 and cond[0] != -1] - if digit not in fixed_values: - continue - elif index == 1: - has_fixed_value = any(len(cond) == 3 and cond[1] != -1 for cond in conditions) - if has_fixed_value: - fixed_values = [cond[1] for cond in conditions if len(cond) == 3 and cond[1] != -1] - if digit not in fixed_values: - continue - elif index == 2: - has_fixed_value = any(len(cond) == 3 and cond[2] != -1 for cond in conditions) - if has_fixed_value: - fixed_values = [cond[2] for cond in conditions if len(cond) == 3 and cond[2] != -1] - if digit not in fixed_values: - continue + if index == 3: + password = "".join(map(str, current_digits)) + calculated_hash = lock.hash_password(password) + + + if calculated_hash == stored_hash: + found_password = password + found = True + return + + tries += 1 + return + + for digit in digit_options[index]: current_digits.append(digit) backtrack(index + 1, current_digits) current_digits.pop() + if found: + return backtrack(0, []) - return possible_passwords, tries + return [found_password] if found_password else [], tries -def crack_method2(conditions): - """从第二位开始回溯(第二位→第三位→第一位)""" - possible_passwords = [] - tries = 0 +def crack_method2(conditions, stored_hash): + """按条件优先级排序的回溯方法:先处理约束最多的位置""" + tries = 1 + found_password = None + found = False + lock = PasswordLock() + + digit_options = [[] for _ in range(3)] + for i in range(3): + for d in range(10): + valid = True + for cond in conditions: + if cond == [-1, -1]: + if not is_prime(d): + valid = False + break + elif len(cond) == 2: + a, t = cond + a = abs(a) + if a - 1 == i and ((t == 0 and d % 2 != 0) or (t == 1 and d % 2 != 1)): + valid = False + break + elif len(cond) == 3: + if cond[i] != -1 and d != cond[i]: + valid = False + break + if valid: + digit_options[i].append(d) + + for i in range(3): + random.shuffle(digit_options[i]) + + sorted_indices = sorted(range(3), key=lambda x: len(digit_options[x])) def backtrack(index, current_digits): - nonlocal tries - tries += 1 - if index == 3: - reordered = [current_digits[2], current_digits[0], current_digits[1]] - for condition in conditions: - if condition == [-1, -1]: - if not satisfies_prime_unique_condition(reordered): - return - elif len(condition) == 2: - a, t = condition - a = abs(a) - if 1 <= a <= 3: - if t == 0 and reordered[a - 1] % 2 != 0: - return - elif t == 1 and reordered[a - 1] % 2 != 1: - return - else: - return - elif len(condition) == 3: - b1, b2, b3 = condition - if b1 != -1 and reordered[0] != b1: - return - if b2 != -1 and reordered[1] != b2: - return - if b3 != -1 and reordered[2] != b3: - return - possible_passwords.append("".join(map(str, reordered))) + nonlocal tries, found, found_password + if found: return - for digit in range(10): - if index == 0: # 第二位 - has_fixed_value = any(len(cond) == 3 and cond[1] != -1 for cond in conditions) - if has_fixed_value: - fixed_values = [cond[1] for cond in conditions if len(cond) == 3 and cond[1] != -1] - if digit not in fixed_values: - continue - elif index == 1: # 第三位 - has_fixed_value = any(len(cond) == 3 and cond[2] != -1 for cond in conditions) - if has_fixed_value: - fixed_values = [cond[2] for cond in conditions if len(cond) == 3 and cond[2] != -1] - if digit not in fixed_values: - continue - elif index == 2: # 第一位 - has_fixed_value = any(len(cond) == 3 and cond[0] != -1 for cond in conditions) - if has_fixed_value: - fixed_values = [cond[0] for cond in conditions if len(cond) == 3 and cond[0] != -1] - if digit not in fixed_values: - continue + if index == 3: + reordered = [0, 0, 0] + for i, pos in enumerate(sorted_indices): + reordered[pos] = current_digits[i] + password = "".join(map(str, reordered)) + calculated_hash = lock.hash_password(password) + + if calculated_hash == stored_hash: + found_password = password + found = True + return + + tries += 1 + return + + current_index = sorted_indices[index] + for digit in digit_options[current_index]: current_digits.append(digit) backtrack(index + 1, current_digits) current_digits.pop() + if found: + return backtrack(0, []) - return possible_passwords, tries + return [found_password] if found_password else [], tries -def crack_method3(conditions): - """从第三位开始回溯(第三位→第一位→第二位)""" - possible_passwords = [] - tries = 0 +def crack_method3(conditions, stored_hash): + """双向回溯:从左右两侧同时构建密码""" + tries = 1 + found_password = None + found = False + lock = PasswordLock() - def backtrack(index, current_digits): - nonlocal tries - tries += 1 - if index == 3: - reordered = [current_digits[1], current_digits[2], current_digits[0]] - for condition in conditions: - if condition == [-1, -1]: - if not satisfies_prime_unique_condition(reordered): - return - elif len(condition) == 2: - a, t = condition + digit_options = [[] for _ in range(3)] + + for i in range(3): + for d in range(10): + valid = True + for cond in conditions: + if cond == [-1, -1]: + if not is_prime(d): + valid = False + break + elif len(cond) == 2: + a, t = cond a = abs(a) - if 1 <= a <= 3: - if t == 0 and reordered[a - 1] % 2 != 0: - return - elif t == 1 and reordered[a - 1] % 2 != 1: - return - else: - return - elif len(condition) == 3: - b1, b2, b3 = condition - if b1 != -1 and reordered[0] != b1: - return - if b2 != -1 and reordered[1] != b2: - return - if b3 != -1 and reordered[2] != b3: - return - possible_passwords.append("".join(map(str, reordered))) + if a - 1 == i and ((t == 0 and d % 2 != 0) or (t == 1 and d % 2 != 1)): + valid = False + break + elif len(cond) == 3: + if cond[i] != -1 and d != cond[i]: + valid = False + break + if valid: + digit_options[i].append(d) + + for i in range(3): + random.shuffle(digit_options[i]) + + def backtrack(left_pos, right_pos, current_digits): + nonlocal tries, found, found_password + + if found: return - for digit in range(10): - if index == 0: # 第三位 - has_fixed_value = any(len(cond) == 3 and cond[2] != -1 for cond in conditions) - if has_fixed_value: - fixed_values = [cond[2] for cond in conditions if len(cond) == 3 and cond[2] != -1] - if digit not in fixed_values: - continue - elif index == 1: # 第一位 - has_fixed_value = any(len(cond) == 3 and cond[0] != -1 for cond in conditions) - if has_fixed_value: - fixed_values = [cond[0] for cond in conditions if len(cond) == 3 and cond[0] != -1] - if digit not in fixed_values: - continue - elif index == 2: # 第二位 - has_fixed_value = any(len(cond) == 3 and cond[1] != -1 for cond in conditions) - if has_fixed_value: - fixed_values = [cond[1] for cond in conditions if len(cond) == 3 and cond[1] != -1] - if digit not in fixed_values: - continue - current_digits.append(digit) - backtrack(index + 1, current_digits) - current_digits.pop() + if len(current_digits) == 3: + password = "".join(map(str, current_digits)) + calculated_hash = lock.hash_password(password) - backtrack(0, []) - return possible_passwords, tries + if calculated_hash == stored_hash: + found_password = password + found = True + return + tries += 1 + return + + # 根据当前方向选择位置 + if left_pos <= right_pos: + for digit in digit_options[left_pos]: + current_digits.append(digit) + backtrack(left_pos + 1, right_pos, current_digits) + current_digits.pop() + if found: + return + else: + for digit in digit_options[right_pos]: + current_digits.insert(0, digit) + backtrack(left_pos, right_pos - 1, current_digits) + current_digits.pop(0) + if found: + return + + backtrack(0, 2, []) + return [found_password] if found_password else [], tries def format_json(data): """自定义 JSON 格式化函数""" @@ -240,8 +255,8 @@ def format_json(data): def main(): # 输入和输出路径 - input_dir = r"" # path - output_dir = r"" # path + input_dir = r"pwd" + output_dir = r"pwd_output" # 如果输出目录不存在,则创建 os.makedirs(output_dir, exist_ok=True) @@ -254,7 +269,7 @@ def main(): with open(input_file_path, 'r', encoding='utf-8') as f: try: - # 读取原始 JSON 文本内容(保留结构) + # 读取原始 JSON 文本内容(字符串) original_content = f.read() # 解析为字典用于处理 sample_data = json.loads(original_content) @@ -262,24 +277,36 @@ def main(): print(f"跳过无效的 JSON 文件: {filename}") continue - conditions = sample_data["C"] - stored_hash = sample_data["L"] + conditions = sample_data.get("C", []) + stored_hash = sample_data.get("L", "") print(f"\n正在处理文件: {filename}") - pwd1, tries1 = crack_method1(conditions) - pwd2, tries2 = crack_method2(conditions) - pwd3, tries3 = crack_method3(conditions) + # 调用三种方法破解密码 + pwd1, tries1 = crack_method1(conditions, stored_hash) + pwd2, tries2 = crack_method2(conditions, stored_hash) + pwd3, tries3 = crack_method3(conditions, stored_hash) - lock = PasswordLock() + # 找到第一个非空结果作为最终密码 matched_passwords = [] - - for pwd in pwd1 + pwd2 + pwd3: - if pwd not in matched_passwords and lock.verify_password(pwd, stored_hash): - matched_passwords.append(pwd) + if pwd1: + matched_passwords.append(pwd1[0]) + if pwd2: + matched_passwords.append(pwd2[0]) + if pwd3: + matched_passwords.append(pwd3[0]) first_match = matched_passwords[0] if matched_passwords else "" + # 打印每个方法的尝试次数 + print(f"方法1尝试次数: {tries1}") + print(f"方法2尝试次数: {tries2}") + print(f"方法3尝试次数: {tries3}") + + # 计算并打印平均尝试次数 + avg_tries = (tries1 + tries2 + tries3) / 3 + print(f"平均尝试次数: {avg_tries:.1f}") + # 更新 JSON 内容中的结果部分 result_update = { "password": first_match, @@ -303,6 +330,24 @@ def main(): print(f"结果已保存至: {output_file_path}") + # 新增:比较写入内容是否与原始内容一致(忽略 results 字段中的 tries) + with open(output_file_path, 'r', encoding='utf-8') as f: + written_content = f.read() + + # 解析原始和写入后的内容为 dict + original_dict = json.loads(original_content) + written_dict = json.loads(written_content) + + # 删除 results 字段用于比较 + original_dict.pop("results", None) + written_dict.pop("results", None) + + # 重新序列化为字符串进行比较 + if json.dumps(original_dict, sort_keys=True) == json.dumps(written_dict, sort_keys=True): + print("输出内容(除 results 外)与原始内容一致") + else: + print("输出内容(除 results 外)与原始内容不一致") + if __name__ == "__main__": main() \ No newline at end of file diff --git a/pwd/pwd_000.json b/pwd/pwd_000.json new file mode 100644 index 0000000..5f99b57 --- /dev/null +++ b/pwd/pwd_000.json @@ -0,0 +1,13 @@ +{ + "C": [ + [2,-1,-1], + [-1,0,-1] + ], + "L": "347088a782a525d04d5db928977eed08aaf985ad80e4912446adba1d717ab682", + "password": "205", + "results": { + "method1": {"tries": 6, "password": [2, 0, 5]}, + "method2": {"tries": 7, "password": [2, 0, 5]}, + "method3": {"tries": 5, "password": [2, 0, 5]} + } +} diff --git a/pwd/pwd_001.json b/pwd/pwd_001.json new file mode 100644 index 0000000..3896ce5 --- /dev/null +++ b/pwd/pwd_001.json @@ -0,0 +1,14 @@ +{ + "C": [ + [-1,7,-1], + [1,1], + [2,1] + ], + "L": "ef489e31e9f932ff343749a1f66f5132e4392161979ab6c75f7958b2107aa3aa", + "password": "773", + "results": { + "method1": {"tries": 34, "password": [7, 7, 3]}, + "method2": {"tries": 35, "password": [7, 7, 3]}, + "method3": {"tries": 36, "password": [7, 7, 3]} + } +} diff --git a/pwd/pwd_002.json b/pwd/pwd_002.json new file mode 100644 index 0000000..605d3a9 --- /dev/null +++ b/pwd/pwd_002.json @@ -0,0 +1,14 @@ +{ + "C": [ + [3,-1,-1], + [3,1], + [2,0] + ], + "L": "38b5eddb98061eb811e4660c492769a7641d77163748915f19b56da70b2bb4cd", + "password": "365", + "results": { + "method1": {"tries": 18, "password": [3, 6, 5]}, + "method2": {"tries": 16, "password": [3, 6, 5]}, + "method3": {"tries": 12, "password": [3, 6, 5]} + } +} diff --git a/pwd/pwd_003.json b/pwd/pwd_003.json new file mode 100644 index 0000000..e360ecc --- /dev/null +++ b/pwd/pwd_003.json @@ -0,0 +1,12 @@ +{ + "C": [ + [2,0] + ], + "L": "54a76d5a60849cbe4a6e7f75d830fe73f413586f329cec620eaf69bea2ade132", + "password": "946", + "results": { + "method1": {"tries": 477, "password": [9, 4, 6]}, + "method2": {"tries": 458, "password": [9, 4, 6]}, + "method3": {"tries": 317, "password": [9, 4, 6]} + } +} diff --git a/pwd/pwd_004.json b/pwd/pwd_004.json new file mode 100644 index 0000000..d91f246 --- /dev/null +++ b/pwd/pwd_004.json @@ -0,0 +1,12 @@ +{ + "C": [ + [3,-1,-1] + ], + "L": "755ba5c1907b9df34ef9d65c9ef9d32f25614816f3f6a5a699b86540ad7f46a9", + "password": "313", + "results": { + "method1": {"tries": 14, "password": [3, 1, 3]}, + "method2": {"tries": 15, "password": [3, 1, 3]}, + "method3": {"tries": 94, "password": [3, 1, 3]} + } +} diff --git a/pwd/pwd_005.json b/pwd/pwd_005.json new file mode 100644 index 0000000..d8867c1 --- /dev/null +++ b/pwd/pwd_005.json @@ -0,0 +1,14 @@ +{ + "C": [ + [-1,9,-1], + [1,0], + [2,-1,-1] + ], + "L": "b6b6f5f531ebb073c291dd679f1b01aab1dd4b7b3f94fa08bd126805650b37d8", + "password": "295", + "results": { + "method1": {"tries": 6, "password": [2, 9, 5]}, + "method2": {"tries": 7, "password": [2, 9, 5]}, + "method3": {"tries": 7, "password": [2, 9, 5]} + } +} diff --git a/pwd/pwd_006.json b/pwd/pwd_006.json new file mode 100644 index 0000000..d445d7f --- /dev/null +++ b/pwd/pwd_006.json @@ -0,0 +1,14 @@ +{ + "C": [ + [1,0], + [-1,3,-1], + [3,0] + ], + "L": "286da4632ef25db843f432010a4ce57a9a20bbb2732743349e538387ff03fb97", + "password": "238", + "results": { + "method1": {"tries": 10, "password": [2, 3, 8]}, + "method2": {"tries": 15, "password": [2, 3, 8]}, + "method3": {"tries": 9, "password": [2, 3, 8]} + } +} diff --git a/pwd/pwd_007.json b/pwd/pwd_007.json new file mode 100644 index 0000000..5558b8e --- /dev/null +++ b/pwd/pwd_007.json @@ -0,0 +1,14 @@ +{ + "C": [ + [-1,-1,5], + [1,1], + [3,1] + ], + "L": "528e74638d1476111b128f8d94883225bf7fdd607b89bc0f6e5c9947e0372b1a", + "password": "755", + "results": { + "method1": {"tries": 36, "password": [7, 5, 5]}, + "method2": {"tries": 37, "password": [7, 5, 5]}, + "method3": {"tries": 21, "password": [7, 5, 5]} + } +} diff --git a/pwd/pwd_008.json b/pwd/pwd_008.json new file mode 100644 index 0000000..f5e76ed --- /dev/null +++ b/pwd/pwd_008.json @@ -0,0 +1,12 @@ +{ + "C": [ + [3,1] + ], + "L": "1190fb88a3821ccece881dc87af9f877e036ff0ec858ff82d7c5431246657671", + "password": "477", + "results": { + "method1": {"tries": 239, "password": [4, 7, 7]}, + "method2": {"tries": 29, "password": [4, 7, 7]}, + "method3": {"tries": 259, "password": [4, 7, 7]} + } +} diff --git a/pwd/pwd_009.json b/pwd/pwd_009.json new file mode 100644 index 0000000..bb75d02 --- /dev/null +++ b/pwd/pwd_009.json @@ -0,0 +1,12 @@ +{ + "C": [ + [-1,-1] + ], + "L": "11cfd52ee4313c86fff1cc50c3403c891c94cdd2427fc985ab1cd380654cbfe1", + "password": "732", + "results": { + "method1": {"tries": 21, "password": [7, 3, 2]}, + "method2": {"tries": 19, "password": [7, 3, 2]}, + "method3": {"tries": 14, "password": [7, 3, 2]} + } +} diff --git a/pwd/pwd_010.json b/pwd/pwd_010.json new file mode 100644 index 0000000..2011198 --- /dev/null +++ b/pwd/pwd_010.json @@ -0,0 +1,14 @@ +{ + "C": [ + [-1,-1], + [-1,2,-1], + [3,1] + ], + "L": "54668768990130bb9311a9ecc4b1540aa989ec328be5e66860a0d0d222ac4751", + "password": "725", + "results": { + "method1": {"tries": 6, "password": [7, 2, 5]}, + "method2": {"tries": 5, "password": [7, 2, 5]}, + "method3": {"tries": 6, "password": [7, 2, 5]} + } +} diff --git a/pwd/pwd_011.json b/pwd/pwd_011.json new file mode 100644 index 0000000..f5d3bd7 --- /dev/null +++ b/pwd/pwd_011.json @@ -0,0 +1,13 @@ +{ + "C": [ + [-1,-1,6], + [3,0] + ], + "L": "a92ef4ff4c91b8dc516ab99793b250136367cb726854463ec0f20ea3a4074b33", + "password": "376", + "results": { + "method1": {"tries": 38, "password": [3, 7, 6]}, + "method2": {"tries": 46, "password": [3, 7, 6]}, + "method3": {"tries": 70, "password": [3, 7, 6]} + } +} diff --git a/pwd/pwd_012.json b/pwd/pwd_012.json new file mode 100644 index 0000000..c6324cd --- /dev/null +++ b/pwd/pwd_012.json @@ -0,0 +1,12 @@ +{ + "C": [ + [5,-1,-1] + ], + "L": "1dc13577545c00c68900358e14499f863bd538529bf7fe25a1aa15538fcefd19", + "password": "533", + "results": { + "method1": {"tries": 34, "password": [5, 3, 3]}, + "method2": {"tries": 45, "password": [5, 3, 3]}, + "method3": {"tries": 74, "password": [5, 3, 3]} + } +} diff --git a/pwd/pwd_013.json b/pwd/pwd_013.json new file mode 100644 index 0000000..2097497 --- /dev/null +++ b/pwd/pwd_013.json @@ -0,0 +1,14 @@ +{ + "C": [ + [2,1], + [1,1], + [-1,-1,7] + ], + "L": "55d064bf74d7ad3f2383012ba22528483a51735c41caa315d6da4bc2932186da", + "password": "957", + "results": { + "method1": {"tries": 23, "password": [9, 5, 7]}, + "method2": {"tries": 21, "password": [9, 5, 7]}, + "method3": {"tries": 3, "password": [9, 5, 7]} + } +} diff --git a/pwd/pwd_014.json b/pwd/pwd_014.json new file mode 100644 index 0000000..5b70b46 --- /dev/null +++ b/pwd/pwd_014.json @@ -0,0 +1,12 @@ +{ + "C": [ + [2,0] + ], + "L": "72d4a72601bc0461c78b57774f04b2e331f6b54307dfd6a57da0404696405407", + "password": "322", + "results": { + "method1": {"tries": 163, "password": [3, 2, 2]}, + "method2": {"tries": 224, "password": [3, 2, 2]}, + "method3": {"tries": 233, "password": [3, 2, 2]} + } +} diff --git a/pwd/pwd_015.json b/pwd/pwd_015.json new file mode 100644 index 0000000..79e0c12 --- /dev/null +++ b/pwd/pwd_015.json @@ -0,0 +1,14 @@ +{ + "C": [ + [3,1], + [2,1], + [-1,7,-1] + ], + "L": "7a328a202c195ef362df07bb6b2440855eda415e38668231dd2520e3bb8826ef", + "password": "673", + "results": { + "method1": {"tries": 32, "password": [6, 7, 3]}, + "method2": {"tries": 38, "password": [6, 7, 3]}, + "method3": {"tries": 3, "password": [6, 7, 3]} + } +} diff --git a/pwd/pwd_016.json b/pwd/pwd_016.json new file mode 100644 index 0000000..1017a29 --- /dev/null +++ b/pwd/pwd_016.json @@ -0,0 +1,13 @@ +{ + "C": [ + [3,1], + [-1,-1,5] + ], + "L": "81d5400ab2eca801a80837500be67485d0f8b297db1fa8ecbe4a23b66b65f6b8", + "password": "825", + "results": { + "method1": {"tries": 83, "password": [8, 2, 5]}, + "method2": {"tries": 84, "password": [8, 2, 5]}, + "method3": {"tries": 57, "password": [8, 2, 5]} + } +} diff --git a/pwd/pwd_017.json b/pwd/pwd_017.json new file mode 100644 index 0000000..239b2eb --- /dev/null +++ b/pwd/pwd_017.json @@ -0,0 +1,14 @@ +{ + "C": [ + [-1,4,-1], + [2,0], + [3,0] + ], + "L": "28df3327f1bcdf12f715f4205bd5f8c99f5f44fb75453afc23e8bb0a3714241e", + "password": "342", + "results": { + "method1": {"tries": 17, "password": [3, 4, 2]}, + "method2": {"tries": 23, "password": [3, 4, 2]}, + "method3": {"tries": 47, "password": [3, 4, 2]} + } +} diff --git a/pwd/pwd_018.json b/pwd/pwd_018.json new file mode 100644 index 0000000..a2a8f26 --- /dev/null +++ b/pwd/pwd_018.json @@ -0,0 +1,13 @@ +{ + "C": [ + [-1,-1], + [-1,-1,3] + ], + "L": "21967d701a06c3e02a934e208c599183e6da36ec4e7d5f8fdcfb3209474083fa", + "password": "273", + "results": { + "method1": {"tries": 2, "password": [2, 7, 3]}, + "method2": {"tries": 2, "password": [2, 7, 3]}, + "method3": {"tries": 2, "password": [2, 7, 3]} + } +} diff --git a/pwd/pwd_019.json b/pwd/pwd_019.json new file mode 100644 index 0000000..0e51a1c --- /dev/null +++ b/pwd/pwd_019.json @@ -0,0 +1,12 @@ +{ + "C": [ + [2,0] + ], + "L": "a8b1a9f6741f4903c9f8e337849118532809ebdfb05aa9b99c3377d529c5579c", + "password": "783", + "results": { + "method1": {"tries": 394, "password": [7, 8, 3]}, + "method2": {"tries": 295, "password": [7, 8, 3]}, + "method3": {"tries": 15, "password": [7, 8, 3]} + } +} diff --git a/pwd/pwd_020.json b/pwd/pwd_020.json new file mode 100644 index 0000000..9214d87 --- /dev/null +++ b/pwd/pwd_020.json @@ -0,0 +1,14 @@ +{ + "C": [ + [1,0], + [6,-1,-1], + [3,0] + ], + "L": "5fce2d1a75f54c4dbf70ac4ad3b1d66920f7209e0aae5982f893447cddc4ce58", + "password": "652", + "results": { + "method1": {"tries": 27, "password": [6, 5, 2]}, + "method2": {"tries": 33, "password": [6, 5, 2]}, + "method3": {"tries": 18, "password": [6, 5, 2]} + } +} diff --git a/pwd/pwd_021.json b/pwd/pwd_021.json new file mode 100644 index 0000000..b657caa --- /dev/null +++ b/pwd/pwd_021.json @@ -0,0 +1,14 @@ +{ + "C": [ + [1,1], + [2,0], + [-1,-1,8] + ], + "L": "19350eedb2b07bedd0d604c04c26c7bd71f8b3dce8885a43df8085a9aa819bc0", + "password": "728", + "results": { + "method1": {"tries": 17, "password": [7, 2, 8]}, + "method2": {"tries": 18, "password": [7, 2, 8]}, + "method3": {"tries": 16, "password": [7, 2, 8]} + } +} diff --git a/pwd/pwd_022.json b/pwd/pwd_022.json new file mode 100644 index 0000000..892b329 --- /dev/null +++ b/pwd/pwd_022.json @@ -0,0 +1,14 @@ +{ + "C": [ + [-1,-1,2], + [1,1], + [-1,2,-1] + ], + "L": "35276b964e7b1f91eb9634ad24a7ef260d2cfd7d7a354209492b132ad66574a4", + "password": "722", + "results": { + "method1": {"tries": 4, "password": [7, 2, 2]}, + "method2": {"tries": 4, "password": [7, 2, 2]}, + "method3": {"tries": 3, "password": [7, 2, 2]} + } +} diff --git a/pwd/pwd_023.json b/pwd/pwd_023.json new file mode 100644 index 0000000..2b9e97d --- /dev/null +++ b/pwd/pwd_023.json @@ -0,0 +1,12 @@ +{ + "C": [ + [-1,0,-1] + ], + "L": "61399aa8f0e6d1336857bc64290db7a41af69edd7f8af6909bf981b539485ec8", + "password": "503", + "results": { + "method1": {"tries": 54, "password": [5, 0, 3]}, + "method2": {"tries": 65, "password": [5, 0, 3]}, + "method3": {"tries": 55, "password": [5, 0, 3]} + } +} diff --git a/pwd/pwd_024.json b/pwd/pwd_024.json new file mode 100644 index 0000000..e877c42 --- /dev/null +++ b/pwd/pwd_024.json @@ -0,0 +1,13 @@ +{ + "C": [ + [0,-1,-1], + [-1,5,-1] + ], + "L": "670544e235ad5f18b949f224bfdc86e9751fbfe04f9fa202144825342e6e9a1c", + "password": "051", + "results": { + "method1": {"tries": 2, "password": [0, 5, 1]}, + "method2": {"tries": 2, "password": [0, 5, 1]}, + "method3": {"tries": 2, "password": [0, 5, 1]} + } +} diff --git a/pwd/pwd_025.json b/pwd/pwd_025.json new file mode 100644 index 0000000..3e0b8d0 --- /dev/null +++ b/pwd/pwd_025.json @@ -0,0 +1,14 @@ +{ + "C": [ + [3,0], + [-1,-1,2], + [1,1] + ], + "L": "4303efd52a6c11047de02002aced680808dbdd0c2c5ed6dc06f5d24f979d701b", + "password": "542", + "results": { + "method1": {"tries": 25, "password": [5, 4, 2]}, + "method2": {"tries": 1, "password": [5, 4, 2]}, + "method3": {"tries": 33, "password": [5, 4, 2]} + } +} diff --git a/pwd/pwd_026.json b/pwd/pwd_026.json new file mode 100644 index 0000000..3ba9052 --- /dev/null +++ b/pwd/pwd_026.json @@ -0,0 +1,13 @@ +{ + "C": [ + [2,0], + [3,0] + ], + "L": "dd21cbefcda693704ad8e8d8045d4bc01a2ba4875a8cc069a8105e5362b7f3b7", + "password": "226", + "results": { + "method1": {"tries": 59, "password": [2, 2, 6]}, + "method2": {"tries": 89, "password": [2, 2, 6]}, + "method3": {"tries": 209, "password": [2, 2, 6]} + } +} diff --git a/pwd/pwd_027.json b/pwd/pwd_027.json new file mode 100644 index 0000000..654fd59 --- /dev/null +++ b/pwd/pwd_027.json @@ -0,0 +1,12 @@ +{ + "C": [ + [-1,-1] + ], + "L": "78cc114968ab659cb55dabd23e31d30186cf6529d6e7529cdfadb5940d5be8e5", + "password": "357", + "results": { + "method1": {"tries": 10, "password": [3, 5, 7]}, + "method2": {"tries": 4, "password": [3, 5, 7]}, + "method3": {"tries": 12, "password": [3, 5, 7]} + } +} diff --git a/pwd/pwd_028.json b/pwd/pwd_028.json new file mode 100644 index 0000000..60b7005 --- /dev/null +++ b/pwd/pwd_028.json @@ -0,0 +1,14 @@ +{ + "C": [ + [1,1], + [-1,1,-1], + [3,1] + ], + "L": "fd6c3f5085ea7aec0ea67683fd144303b0747091af782b246683811047e6dab8", + "password": "715", + "results": { + "method1": {"tries": 18, "password": [7, 1, 5]}, + "method2": {"tries": 16, "password": [7, 1, 5]}, + "method3": {"tries": 3, "password": [7, 1, 5]} + } +} diff --git a/pwd/pwd_029.json b/pwd/pwd_029.json new file mode 100644 index 0000000..f9362d3 --- /dev/null +++ b/pwd/pwd_029.json @@ -0,0 +1,13 @@ +{ + "C": [ + [3,0], + [-1,3,-1] + ], + "L": "5e9bf15c58b8a37d559a77155d431df6f5352071fea05a49abf84902ddc73f79", + "password": "538", + "results": { + "method1": {"tries": 30, "password": [5, 3, 8]}, + "method2": {"tries": 35, "password": [5, 3, 8]}, + "method3": {"tries": 1, "password": [5, 3, 8]} + } +} diff --git a/pwd_output/pwd_000.json b/pwd_output/pwd_000.json new file mode 100644 index 0000000..c6bc12d --- /dev/null +++ b/pwd_output/pwd_000.json @@ -0,0 +1,14 @@ +{ + "C": [ + [2, -1, -1], + [-1, 0, -1] + ], + "L": "347088a782a525d04d5db928977eed08aaf985ad80e4912446adba1d717ab682", + "password": "205", + "results": { + "method1": {"tries": 1, "password": [2, 0, 5]}, + "method2": {"tries": 6, "password": [2, 0, 5]}, + "method3": {"tries": 6, "password": [2, 0, 5]} + } + +} \ No newline at end of file diff --git a/pwd_output/pwd_001.json b/pwd_output/pwd_001.json new file mode 100644 index 0000000..a32bb2a --- /dev/null +++ b/pwd_output/pwd_001.json @@ -0,0 +1,14 @@ +{ + "C": [ + [-1, 7, -1], + [1, 1], + [2, 1] + ], + "L": "ef489e31e9f932ff343749a1f66f5132e4392161979ab6c75f7958b2107aa3aa", + "password": "773", + "results": { + "method1": {"tries": 40, "password": [7, 7, 3]}, + "method2": {"tries": 4, "password": [7, 7, 3]}, + "method3": {"tries": 20, "password": [7, 7, 3]} + } +} \ No newline at end of file diff --git a/pwd_output/pwd_002.json b/pwd_output/pwd_002.json new file mode 100644 index 0000000..e2bb463 --- /dev/null +++ b/pwd_output/pwd_002.json @@ -0,0 +1,14 @@ +{ + "C": [ + [3, -1, -1], + [3, 1], + [2, 0] + ], + "L": "38b5eddb98061eb811e4660c492769a7641d77163748915f19b56da70b2bb4cd", + "password": "365", + "results": { + "method1": {"tries": 9, "password": [3, 6, 5]}, + "method2": {"tries": 24, "password": [3, 6, 5]}, + "method3": {"tries": 18, "password": [3, 6, 5]} + } +} \ No newline at end of file diff --git a/pwd_output/pwd_003.json b/pwd_output/pwd_003.json new file mode 100644 index 0000000..0532707 --- /dev/null +++ b/pwd_output/pwd_003.json @@ -0,0 +1,12 @@ +{ + "C": [ + [2, 0] + ], + "L": "54a76d5a60849cbe4a6e7f75d830fe73f413586f329cec620eaf69bea2ade132", + "password": "946", + "results": { + "method1": {"tries": 258, "password": [9, 4, 6]}, + "method2": {"tries": 336, "password": [9, 4, 6]}, + "method3": {"tries": 140, "password": [9, 4, 6]} + } +} \ No newline at end of file diff --git a/pwd_output/pwd_004.json b/pwd_output/pwd_004.json new file mode 100644 index 0000000..4cbc809 --- /dev/null +++ b/pwd_output/pwd_004.json @@ -0,0 +1,12 @@ +{ + "C": [ + [3, -1, -1] + ], + "L": "755ba5c1907b9df34ef9d65c9ef9d32f25614816f3f6a5a699b86540ad7f46a9", + "password": "313", + "results": { + "method1": {"tries": 98, "password": [3, 1, 3]}, + "method2": {"tries": 54, "password": [3, 1, 3]}, + "method3": {"tries": 2, "password": [3, 1, 3]} + } +} \ No newline at end of file diff --git a/pwd_output/pwd_005.json b/pwd_output/pwd_005.json new file mode 100644 index 0000000..390ba73 --- /dev/null +++ b/pwd_output/pwd_005.json @@ -0,0 +1,14 @@ +{ + "C": [ + [-1, 9, -1], + [1, 0], + [2, -1, -1] + ], + "L": "b6b6f5f531ebb073c291dd679f1b01aab1dd4b7b3f94fa08bd126805650b37d8", + "password": "295", + "results": { + "method1": {"tries": 6, "password": [2, 9, 5]}, + "method2": {"tries": 6, "password": [2, 9, 5]}, + "method3": {"tries": 5, "password": [2, 9, 5]} + } +} \ No newline at end of file diff --git a/pwd_output/pwd_006.json b/pwd_output/pwd_006.json new file mode 100644 index 0000000..9552e22 --- /dev/null +++ b/pwd_output/pwd_006.json @@ -0,0 +1,14 @@ +{ + "C": [ + [1, 0], + [-1, 3, -1], + [3, 0] + ], + "L": "286da4632ef25db843f432010a4ce57a9a20bbb2732743349e538387ff03fb97", + "password": "238", + "results": { + "method1": {"tries": 19, "password": [2, 3, 8]}, + "method2": {"tries": 3, "password": [2, 3, 8]}, + "method3": {"tries": 9, "password": [2, 3, 8]} + } +} \ No newline at end of file diff --git a/pwd_output/pwd_007.json b/pwd_output/pwd_007.json new file mode 100644 index 0000000..59baf5e --- /dev/null +++ b/pwd_output/pwd_007.json @@ -0,0 +1,14 @@ +{ + "C": [ + [-1, -1, 5], + [1, 1], + [3, 1] + ], + "L": "528e74638d1476111b128f8d94883225bf7fdd607b89bc0f6e5c9947e0372b1a", + "password": "755", + "results": { + "method1": {"tries": 50, "password": [7, 5, 5]}, + "method2": {"tries": 8, "password": [7, 5, 5]}, + "method3": {"tries": 17, "password": [7, 5, 5]} + } +} \ No newline at end of file diff --git a/pwd_output/pwd_008.json b/pwd_output/pwd_008.json new file mode 100644 index 0000000..cd5e3e1 --- /dev/null +++ b/pwd_output/pwd_008.json @@ -0,0 +1,12 @@ +{ + "C": [ + [3, 1] + ], + "L": "1190fb88a3821ccece881dc87af9f877e036ff0ec858ff82d7c5431246657671", + "password": "477", + "results": { + "method1": {"tries": 97, "password": [4, 7, 7]}, + "method2": {"tries": 281, "password": [4, 7, 7]}, + "method3": {"tries": 225, "password": [4, 7, 7]} + } +} \ No newline at end of file diff --git a/pwd_output/pwd_009.json b/pwd_output/pwd_009.json new file mode 100644 index 0000000..443cb9d --- /dev/null +++ b/pwd_output/pwd_009.json @@ -0,0 +1,12 @@ +{ + "C": [ + [-1, -1] + ], + "L": "11cfd52ee4313c86fff1cc50c3403c891c94cdd2427fc985ab1cd380654cbfe1", + "password": "732", + "results": { + "method1": {"tries": 43, "password": [7, 3, 2]}, + "method2": {"tries": 34, "password": [7, 3, 2]}, + "method3": {"tries": 54, "password": [7, 3, 2]} + } +} \ No newline at end of file diff --git a/pwd_output/pwd_010.json b/pwd_output/pwd_010.json new file mode 100644 index 0000000..8b44788 --- /dev/null +++ b/pwd_output/pwd_010.json @@ -0,0 +1,14 @@ +{ + "C": [ + [-1, -1], + [-1, 2, -1], + [3, 1] + ], + "L": "54668768990130bb9311a9ecc4b1540aa989ec328be5e66860a0d0d222ac4751", + "password": "725", + "results": { + "method1": {"tries": 12, "password": [7, 2, 5]}, + "method2": {"tries": 1, "password": [7, 2, 5]}, + "method3": {"tries": 6, "password": [7, 2, 5]} + } +} \ No newline at end of file diff --git a/pwd_output/pwd_011.json b/pwd_output/pwd_011.json new file mode 100644 index 0000000..8f742e4 --- /dev/null +++ b/pwd_output/pwd_011.json @@ -0,0 +1,13 @@ +{ + "C": [ + [-1, -1, 6], + [3, 0] + ], + "L": "a92ef4ff4c91b8dc516ab99793b250136367cb726854463ec0f20ea3a4074b33", + "password": "376", + "results": { + "method1": {"tries": 97, "password": [3, 7, 6]}, + "method2": {"tries": 1, "password": [3, 7, 6]}, + "method3": {"tries": 78, "password": [3, 7, 6]} + } +} \ No newline at end of file diff --git a/pwd_output/pwd_012.json b/pwd_output/pwd_012.json new file mode 100644 index 0000000..a5b656b --- /dev/null +++ b/pwd_output/pwd_012.json @@ -0,0 +1,12 @@ +{ + "C": [ + [5, -1, -1] + ], + "L": "1dc13577545c00c68900358e14499f863bd538529bf7fe25a1aa15538fcefd19", + "password": "533", + "results": { + "method1": {"tries": 57, "password": [5, 3, 3]}, + "method2": {"tries": 75, "password": [5, 3, 3]}, + "method3": {"tries": 13, "password": [5, 3, 3]} + } +} \ No newline at end of file diff --git a/pwd_output/pwd_013.json b/pwd_output/pwd_013.json new file mode 100644 index 0000000..c857d9f --- /dev/null +++ b/pwd_output/pwd_013.json @@ -0,0 +1,14 @@ +{ + "C": [ + [2, 1], + [1, 1], + [-1, -1, 7] + ], + "L": "55d064bf74d7ad3f2383012ba22528483a51735c41caa315d6da4bc2932186da", + "password": "957", + "results": { + "method1": {"tries": 22, "password": [9, 5, 7]}, + "method2": {"tries": 7, "password": [9, 5, 7]}, + "method3": {"tries": 17, "password": [9, 5, 7]} + } +} \ No newline at end of file diff --git a/pwd_output/pwd_014.json b/pwd_output/pwd_014.json new file mode 100644 index 0000000..5bff9c8 --- /dev/null +++ b/pwd_output/pwd_014.json @@ -0,0 +1,12 @@ +{ + "C": [ + [2, 0] + ], + "L": "72d4a72601bc0461c78b57774f04b2e331f6b54307dfd6a57da0404696405407", + "password": "322", + "results": { + "method1": {"tries": 315, "password": [3, 2, 2]}, + "method2": {"tries": 114, "password": [3, 2, 2]}, + "method3": {"tries": 400, "password": [3, 2, 2]} + } +} \ No newline at end of file diff --git a/pwd_output/pwd_015.json b/pwd_output/pwd_015.json new file mode 100644 index 0000000..801f47e --- /dev/null +++ b/pwd_output/pwd_015.json @@ -0,0 +1,14 @@ +{ + "C": [ + [3, 1], + [2, 1], + [-1, 7, -1] + ], + "L": "7a328a202c195ef362df07bb6b2440855eda415e38668231dd2520e3bb8826ef", + "password": "673", + "results": { + "method1": {"tries": 13, "password": [6, 7, 3]}, + "method2": {"tries": 37, "password": [6, 7, 3]}, + "method3": {"tries": 7, "password": [6, 7, 3]} + } +} \ No newline at end of file diff --git a/pwd_output/pwd_016.json b/pwd_output/pwd_016.json new file mode 100644 index 0000000..389809f --- /dev/null +++ b/pwd_output/pwd_016.json @@ -0,0 +1,13 @@ +{ + "C": [ + [3, 1], + [-1, -1, 5] + ], + "L": "81d5400ab2eca801a80837500be67485d0f8b297db1fa8ecbe4a23b66b65f6b8", + "password": "825", + "results": { + "method1": {"tries": 96, "password": [8, 2, 5]}, + "method2": {"tries": 44, "password": [8, 2, 5]}, + "method3": {"tries": 70, "password": [8, 2, 5]} + } +} \ No newline at end of file diff --git a/pwd_output/pwd_017.json b/pwd_output/pwd_017.json new file mode 100644 index 0000000..f71e68c --- /dev/null +++ b/pwd_output/pwd_017.json @@ -0,0 +1,14 @@ +{ + "C": [ + [-1, 4, -1], + [2, 0], + [3, 0] + ], + "L": "28df3327f1bcdf12f715f4205bd5f8c99f5f44fb75453afc23e8bb0a3714241e", + "password": "342", + "results": { + "method1": {"tries": 11, "password": [3, 4, 2]}, + "method2": {"tries": 18, "password": [3, 4, 2]}, + "method3": {"tries": 43, "password": [3, 4, 2]} + } +} \ No newline at end of file diff --git a/pwd_output/pwd_018.json b/pwd_output/pwd_018.json new file mode 100644 index 0000000..0a1ab7a --- /dev/null +++ b/pwd_output/pwd_018.json @@ -0,0 +1,13 @@ +{ + "C": [ + [-1, -1], + [-1, -1, 3] + ], + "L": "21967d701a06c3e02a934e208c599183e6da36ec4e7d5f8fdcfb3209474083fa", + "password": "273", + "results": { + "method1": {"tries": 13, "password": [2, 7, 3]}, + "method2": {"tries": 12, "password": [2, 7, 3]}, + "method3": {"tries": 12, "password": [2, 7, 3]} + } +} \ No newline at end of file diff --git a/pwd_output/pwd_019.json b/pwd_output/pwd_019.json new file mode 100644 index 0000000..fd4084e --- /dev/null +++ b/pwd_output/pwd_019.json @@ -0,0 +1,12 @@ +{ + "C": [ + [2, 0] + ], + "L": "a8b1a9f6741f4903c9f8e337849118532809ebdfb05aa9b99c3377d529c5579c", + "password": "783", + "results": { + "method1": {"tries": 191, "password": [7, 8, 3]}, + "method2": {"tries": 387, "password": [7, 8, 3]}, + "method3": {"tries": 75, "password": [7, 8, 3]} + } +} \ No newline at end of file diff --git a/pwd_output/pwd_020.json b/pwd_output/pwd_020.json new file mode 100644 index 0000000..0490e51 --- /dev/null +++ b/pwd_output/pwd_020.json @@ -0,0 +1,14 @@ +{ + "C": [ + [1, 0], + [6, -1, -1], + [3, 0] + ], + "L": "5fce2d1a75f54c4dbf70ac4ad3b1d66920f7209e0aae5982f893447cddc4ce58", + "password": "652", + "results": { + "method1": {"tries": 30, "password": [6, 5, 2]}, + "method2": {"tries": 48, "password": [6, 5, 2]}, + "method3": {"tries": 22, "password": [6, 5, 2]} + } +} \ No newline at end of file diff --git a/pwd_output/pwd_021.json b/pwd_output/pwd_021.json new file mode 100644 index 0000000..3f16768 --- /dev/null +++ b/pwd_output/pwd_021.json @@ -0,0 +1,14 @@ +{ + "C": [ + [1, 1], + [2, 0], + [-1, -1, 8] + ], + "L": "19350eedb2b07bedd0d604c04c26c7bd71f8b3dce8885a43df8085a9aa819bc0", + "password": "728", + "results": { + "method1": {"tries": 6, "password": [7, 2, 8]}, + "method2": {"tries": 11, "password": [7, 2, 8]}, + "method3": {"tries": 1, "password": [7, 2, 8]} + } +} \ No newline at end of file diff --git a/pwd_output/pwd_022.json b/pwd_output/pwd_022.json new file mode 100644 index 0000000..cb9535b --- /dev/null +++ b/pwd_output/pwd_022.json @@ -0,0 +1,14 @@ +{ + "C": [ + [-1, -1, 2], + [1, 1], + [-1, 2, -1] + ], + "L": "35276b964e7b1f91eb9634ad24a7ef260d2cfd7d7a354209492b132ad66574a4", + "password": "722", + "results": { + "method1": {"tries": 1, "password": [7, 2, 2]}, + "method2": {"tries": 3, "password": [7, 2, 2]}, + "method3": {"tries": 3, "password": [7, 2, 2]} + } +} \ No newline at end of file diff --git a/pwd_output/pwd_023.json b/pwd_output/pwd_023.json new file mode 100644 index 0000000..7b54b59 --- /dev/null +++ b/pwd_output/pwd_023.json @@ -0,0 +1,12 @@ +{ + "C": [ + [-1, 0, -1] + ], + "L": "61399aa8f0e6d1336857bc64290db7a41af69edd7f8af6909bf981b539485ec8", + "password": "503", + "results": { + "method1": {"tries": 44, "password": [5, 0, 3]}, + "method2": {"tries": 99, "password": [5, 0, 3]}, + "method3": {"tries": 26, "password": [5, 0, 3]} + } +} \ No newline at end of file diff --git a/pwd_output/pwd_024.json b/pwd_output/pwd_024.json new file mode 100644 index 0000000..07d620e --- /dev/null +++ b/pwd_output/pwd_024.json @@ -0,0 +1,13 @@ +{ + "C": [ + [0, -1, -1], + [-1, 5, -1] + ], + "L": "670544e235ad5f18b949f224bfdc86e9751fbfe04f9fa202144825342e6e9a1c", + "password": "051", + "results": { + "method1": {"tries": 3, "password": [0, 5, 1]}, + "method2": {"tries": 2, "password": [0, 5, 1]}, + "method3": {"tries": 5, "password": [0, 5, 1]} + } +} \ No newline at end of file diff --git a/pwd_output/pwd_025.json b/pwd_output/pwd_025.json new file mode 100644 index 0000000..65fd23a --- /dev/null +++ b/pwd_output/pwd_025.json @@ -0,0 +1,14 @@ +{ + "C": [ + [3, 0], + [-1, -1, 2], + [1, 1] + ], + "L": "4303efd52a6c11047de02002aced680808dbdd0c2c5ed6dc06f5d24f979d701b", + "password": "542", + "results": { + "method1": {"tries": 14, "password": [5, 4, 2]}, + "method2": {"tries": 14, "password": [5, 4, 2]}, + "method3": {"tries": 27, "password": [5, 4, 2]} + } +} \ No newline at end of file diff --git a/pwd_output/pwd_026.json b/pwd_output/pwd_026.json new file mode 100644 index 0000000..9fe95d6 --- /dev/null +++ b/pwd_output/pwd_026.json @@ -0,0 +1,13 @@ +{ + "C": [ + [2, 0], + [3, 0] + ], + "L": "dd21cbefcda693704ad8e8d8045d4bc01a2ba4875a8cc069a8105e5362b7f3b7", + "password": "226", + "results": { + "method1": {"tries": 95, "password": [2, 2, 6]}, + "method2": {"tries": 32, "password": [2, 2, 6]}, + "method3": {"tries": 212, "password": [2, 2, 6]} + } +} \ No newline at end of file diff --git a/pwd_output/pwd_027.json b/pwd_output/pwd_027.json new file mode 100644 index 0000000..3eefc63 --- /dev/null +++ b/pwd_output/pwd_027.json @@ -0,0 +1,12 @@ +{ + "C": [ + [-1, -1] + ], + "L": "78cc114968ab659cb55dabd23e31d30186cf6529d6e7529cdfadb5940d5be8e5", + "password": "357", + "results": { + "method1": {"tries": 43, "password": [3, 5, 7]}, + "method2": {"tries": 36, "password": [3, 5, 7]}, + "method3": {"tries": 54, "password": [3, 5, 7]} + } +} \ No newline at end of file diff --git a/pwd_output/pwd_028.json b/pwd_output/pwd_028.json new file mode 100644 index 0000000..1ea9030 --- /dev/null +++ b/pwd_output/pwd_028.json @@ -0,0 +1,14 @@ +{ + "C": [ + [1, 1], + [-1, 1, -1], + [3, 1] + ], + "L": "fd6c3f5085ea7aec0ea67683fd144303b0747091af782b246683811047e6dab8", + "password": "715", + "results": { + "method1": {"tries": 5, "password": [7, 1, 5]}, + "method2": {"tries": 24, "password": [7, 1, 5]}, + "method3": {"tries": 5, "password": [7, 1, 5]} + } +} \ No newline at end of file diff --git a/pwd_output/pwd_029.json b/pwd_output/pwd_029.json new file mode 100644 index 0000000..c9980e3 --- /dev/null +++ b/pwd_output/pwd_029.json @@ -0,0 +1,13 @@ +{ + "C": [ + [3, 0], + [-1, 3, -1] + ], + "L": "5e9bf15c58b8a37d559a77155d431df6f5352071fea05a49abf84902ddc73f79", + "password": "538", + "results": { + "method1": {"tries": 25, "password": [5, 3, 8]}, + "method2": {"tries": 42, "password": [5, 3, 8]}, + "method3": {"tries": 21, "password": [5, 3, 8]} + } +} \ No newline at end of file