import json from igraph import Graph, plot with open('data.json', 'r', encoding='utf-8') as file: data_raw = json.load(file) data = json.loads(json.dumps(data_raw)) #数据补充 for node_name in data_raw: node_info_raw = data_raw[node_name] node_info = data[node_name] for path_to in node_info_raw['path_to']: is_key_need = 'key_need' in path_to key_need = path_to['key_need'] if is_key_need else '' is_one_way_door = key_need == '单向门' is_one_way = not is_one_way_door and 'is_one_way' in path_to if is_one_way_door: if not 'key_get' in node_info: node_info['key_get'] = [] is_key_need = True key_need = f'单向门-{node_name}-{path_to['name']}' node_info['key_get'].append(key_need) node_info['path_to'] if not is_one_way: target_node_info = data[path_to['name']] append_path = {'name':node_name} if is_key_need: append_path['key_need'] = key_need target_node_info['path_to'].append(append_path) #多余数据删除 for node_name in data: node_info = data[node_name] for path_to in node_info['path_to']: is_key_need = 'key_need' in path_to key_need = path_to['key_need'] if is_key_need else '' is_one_way_door = key_need == '单向门' is_one_way = not is_one_way_door and 'is_one_way' in path_to if is_one_way_door: key_need = f'单向门-{node_name}-{path_to['name']}' path_to['key_need'] = key_need path_to.pop('is_one_way', None) #BFS start_node_name = '破碎遗迹' end_node_name = '战斗-魂魄妖忌' start_node = (start_node_name,set(),set(),[start_node_name],'') #name,key_get, key_use,path,portal stack = [start_node] close_set = set() useless_node_list = [] useless_key_list = [] while True: if len(stack)==0: break current = stack.pop(0) current_name = current[0] current_key_get = current[1] current_key_use = current[2] current_path = current[3] current_portal = current[4] if current_name == '白玉楼' and current_portal == '': current_portal = current_name if current_name == end_node_name: useless_node = [] useless_key = [] for node_name in data: if not node_name in current_path: useless_node.append(node_name) if 'key_get' in data[node_name]: for key_get in data[node_name]['key_get']: if not key_get in current_key_use: useless_key.append(key_get) useless_node_list.append(useless_node) useless_key_list.append(useless_key) continue if 'key_get' in data[current_name]: for key_get in data[current_name]['key_get']: if not key_get in current_key_get: current_key_get.add(key_get) current_path.append(f'获取({key_get})') for path_to in data[current_name]['path_to']: is_key_need = 'key_need' in path_to if is_key_need and not path_to['key_need'] in current_key_get: continue next_name = path_to['name'] current_key_list = list(current_key_get) current_key_list.sort() next_name_with_key = next_name + ':' + ','.join(current_key_list) if next_name_with_key in close_set: continue close_set.add(next_name_with_key) next_path = current_path.copy() next_path.append(next_name) next_key_use = current_key_use.copy() if is_key_need and path_to['key_need'] in current_key_get: next_key_use.add(path_to['key_need']) next_node = (next_name, current_key_get.copy(), next_key_use, next_path, current_portal) stack.insert(-1,next_node) #传送 if current_name == '白玉楼' and not current_portal == '': next_name = current_portal current_key_list = list(current_key_get) current_key_list.sort() next_name_with_key = next_name + ':' + ','.join(current_key_list) if next_name_with_key in close_set: continue close_set.add(next_name_with_key) next_path = current_path.copy() next_path.append(f'传送({next_name})') next_node = (next_name, current_key_get.copy(), current_key_use.copy(), next_path, current_portal) stack.insert(-1,next_node) if not current_name == '白玉楼' and not current_portal == '': next_name = '白玉楼' current_key_list = list(current_key_get) current_key_list.sort() next_name_with_key = next_name + ':' + ','.join(current_key_list) if next_name_with_key in close_set: continue close_set.add(next_name_with_key) next_path = current_path.copy() next_path.append(f'传送({next_name})') next_node = (next_name, current_key_get.copy(), current_key_use.copy(), next_path, current_name) stack.insert(-1,next_node) success_count = len(useless_node_list) key_set = set() useless_node_dict = {} useless_key_dict = {} for node_name in data: useless_node_dict[node_name] = 0 if 'key_get' in data[node_name]: for key_get in data[node_name]['key_get']: if not key_get in key_set: key_set.add(key_get) useless_key_dict[key_get] = 0 node_max = len(data) key_max = len(key_set) for useless_node in useless_node_list: for key in useless_node: useless_node_dict[key] += 1 for useless_key in useless_key_list: for key in useless_key: useless_key_dict[key] += 1 useless_node_count_sum = sum(map(lambda x: len(x), useless_node_list)) print('success_count:', success_count) print('useless_node_avg:', "{:.2f}%".format(useless_node_count_sum / success_count / node_max * 100)) for useless_node in useless_node_dict: print("{} {:.2f}%".format(useless_node,useless_node_dict[useless_node] / success_count * 100)) print("-"*20) for useless_key in useless_key_dict: print("{} {:.2f}%".format(useless_key,useless_key_dict[useless_key] / success_count * 100))