You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于节点与边的带权重随机文本类游戏地图生成与打印咨询

文本类游戏地图生成实现方案

核心设计

解决同层节点唯一标识、边绑定、打印三个核心问题:

  • 每个节点使用层号_同层序号格式的唯一ID作为标识,不会出现重复
  • 用字典存储全量节点(key为节点ID),同时用嵌套列表存储每层的节点ID,兼顾快速查询和按层遍历需求
  • 每个节点存储关联的上层节点ID列表,满足最少1个、最多3个上层连接的规则
  • 打印时从最高层往最低层输出,每层占2行:第一行打印节点,第二行打印连接边

完整实现代码

import random
from typing import Dict, List, Tuple

# 配置项
# 节点类型与生成权重,可按需调整
NODE_WEIGHT: Dict[str, int] = {
    "R": 25,
    "?": 20,
    "M": 30,
    "$": 10,
    "E": 15,
    "T": 10
}
# 总层数,固定0为起点层,16为终点层
TOTAL_LAYERS = 17
# 每层节点数量区间
LAYER_NODE_RANGE: Dict[int, Tuple[int, int]] = {
    0: (1, 1), 1: (3, 3), 2: (3, 4), 3: (4, 5), 4: (4, 5),
    5: (4, 5), 6: (4, 5), 7: (4, 5), 8: (4, 5), 9: (4, 5),
    10: (4, 5), 11: (4, 5), 12: (4, 5), 13: (4, 5), 14: (3, 4),
    15: (3, 4), 16: (1, 1)
}
# 打印时的节点水平间距
COL_SPACING = 6

def generate_map() -> Tuple[Dict, List[List[str]]]:
    """生成地图节点与边关系"""
    all_nodes = {}
    layers = []
    # 第一步:生成所有节点
    for layer_idx in range(TOTAL_LAYERS):
        min_cnt, max_cnt = LAYER_NODE_RANGE[layer_idx]
        node_cnt = random.randint(min_cnt, max_cnt)
        current_layer = []
        for node_idx in range(node_cnt):
            node_id = f"{layer_idx}_{node_idx}"
            # 特殊处理起点、终点
            if layer_idx == 0:
                node_type = "S"
            elif layer_idx == TOTAL_LAYERS - 1:
                node_type = "B"
            else:
                # 加权随机生成节点类型
                types, weights = zip(*NODE_WEIGHT.items())
                node_type = random.choices(types, weights=weights, k=1)[0]
            all_nodes[node_id] = {
                "id": node_id, "type": node_type,
                "layer": layer_idx, "idx": node_idx,
                "upper_nodes": []  # 存储上层连接的节点ID
            }
            current_layer.append(node_id)
        layers.append(current_layer)
    # 第二步:绑定上下层边关系
    for layer_idx in range(TOTAL_LAYERS - 1):
        current_layer = layers[layer_idx]
        upper_layer = layers[layer_idx + 1]
        for node_id in current_layer:
            node = all_nodes[node_id]
            current_pos = node["idx"]
            # 限制只能连接上层相邻位置的节点,保证边的形状合理
            optional_upper_idx = []
            for offset in (-1, 0, 1):
                upper_pos = current_pos + offset
                if 0 <= upper_pos < len(upper_layer):
                    optional_upper_idx.append(upper_pos)
            # 随机选择1~3个上层节点连接
            connect_cnt = random.randint(1, min(3, len(optional_upper_idx)))
            selected_idx = random.sample(optional_upper_idx, connect_cnt)
            node["upper_nodes"] = [upper_layer[i] for i in selected_idx]
    return all_nodes, layers

def print_map(all_nodes: Dict, layers: List[List[str]]):
    """控制台打印地图"""
    max_node_cnt = max(len(l) for l in layers)
    # 从最高层往最低层打印,和示例展示逻辑一致
    for layer_idx in reversed(range(TOTAL_LAYERS)):
        current_layer = layers[layer_idx]
        # 计算当前层每个节点的打印位置
        node_pos = {}
        offset = (max_node_cnt - len(current_layer)) * COL_SPACING // 2
        for node_id in current_layer:
            pos = offset + all_nodes[node_id]["idx"] * COL_SPACING
            node_pos[node_id] = pos
        # 打印节点行
        node_line = f"#{layer_idx:<2d}"
        for node_id in current_layer:
            node_type = all_nodes[node_id]["type"]
            node_line += " " * (node_pos[node_id] - len(node_line) + 4)
            node_line += node_type
        print(node_line)
        # 最低层不需要打印下方的边
        if layer_idx == 0:
            break
        # 打印边行
        edge_line = "#   "
        lower_layer = layers[layer_idx - 1]
        # 计算下层节点的打印位置
        lower_offset = (max_node_cnt - len(lower_layer)) * COL_SPACING // 2
        lower_node_pos = {
            node_id: lower_offset + all_nodes[node_id]["idx"] * COL_SPACING
            for node_id in lower_layer
        }
        # 遍历当前层节点,生成连接下层的边
        for lower_node_id in lower_layer:
            lower_x = lower_node_pos[lower_node_id]
            for upper_node_id in all_nodes[lower_node_id]["upper_nodes"]:
                if upper_node_id not in node_pos:
                    continue
                upper_x = node_pos[upper_node_id]
                min_x = min(lower_x, upper_x)
                max_x = max(lower_x, upper_x)
                # 补空格到边的起始位置
                while len(edge_line) < min_x + 4:
                    edge_line += " "
                if lower_x == upper_x:
                    # 垂直边
                    edge_line = edge_line[:lower_x + 4] + "|" + edge_line[lower_x + 5:]
                elif lower_x > upper_x:
                    # 左斜杠
                    edge_line = edge_line[:upper_x + 4] + "\\" + edge_line[upper_x + 5:]
                else:
                    # 右斜杠
                    edge_line = edge_line[:max_x + 4] + "/" + edge_line[max_x + 5:]
        print(edge_line)

if __name__ == "__main__":
    all_nodes, layers = generate_map()
    print_map(all_nodes, layers)

内容的提问来源于stack exchange,提问作者Difio

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 07:42:01