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

Python地图生成函数优化咨询:循环、Append与Tkinter性能问题

地图文明填充代码优化方案

一、GenerateWorld函数核心性能优化

1. 替换低效的文明存在性检查

原代码通过str(basemap.getcolors())判断文明是否已放置,这会遍历全地图并生成字符串,效率极低。改为直接在文明字典中维护标记:

# 初始化时为每个文明添加放置标记
for civ_id in civilisationdictionary:
    civilisationdictionary[civ_id]['placed'] = False

# GenerateWorld函数内判断逻辑
if not civilisationdictionary[i]['placed']:
    # 执行初始像素放置逻辑
    # 放置成功后更新标记
    civilisationdictionary[i]['placed'] = True

2. 预生成陆地候选点,避免随机循环

原代码随机选点后反复判断是否为水域,可提前为每个文明的区域预存所有陆地坐标:

# 预生成各文明区域内的陆地坐标(全局执行一次)
world_land_coords = {}
allpixels = basemap.load()
for civ_id in worldmapdictionary:
    civ_lands = []
    regions = zip(
        worldmapdictionary[civ_id]['minx'],
        worldmapdictionary[civ_id]['maxx'],
        worldmapdictionary[civ_id]['miny'],
        worldmapdictionary[civ_id]['maxy']
    )
    for minx, maxx, miny, maxy in regions:
        for x in range(minx, maxx+1):
            for y in range(miny, maxy+1):
                if allpixels[x,y] != (255,255,255,255):
                    civ_lands.append((x,y))
    world_land_coords[civ_id] = civ_lands

# GenerateWorld内直接从预存列表选点
x, y = random.choice(world_land_coords[i])

3. 用Numpy矢量化替代像素遍历

原双重循环遍历全地图找文明像素,改用Numpy数组实现批量操作:

import numpy as np

def GenerateWorldNumpy(img_array, civilisationdictionary):
    water_color = np.array([255,255,255,255])
    for i in civilisationdictionary.keys():
        colour = np.array(list(civilisationdictionary[i]['colour1']) + [255])
        
        if not civilisationdictionary[i]['placed']:
            x, y = random.choice(world_land_coords[i])
            img_array[y, x] = colour
            civilisationdictionary[i]['placed'] = True
        else:
            # 批量找出文明所有像素
            mask = np.all(img_array == colour, axis=-1)
            own_pixels = np.argwhere(mask)
            
            # 生成8邻接坐标并过滤边界
            offsets = [(-1,-1), (-1,0), (-1,1),
                       (0,-1),          (0,1),
                       (1,-1),  (1,0), (1,1)]
            neighbor_coords = []
            for dx, dy in offsets:
                neighbors = own_pixels + [dx, dy]
                valid = (neighbors[:,0] >=0) & (neighbors[:,0] < img_array.shape[0]) & \
                        (neighbors[:,1] >=0) & (neighbors[:,1] < img_array.shape[1])
                neighbor_coords.append(neighbors[valid])
            neighbor_coords = np.vstack(neighbor_coords)
            
            # 排除文明自身像素
            own_set = set(tuple(p) for p in own_pixels)
            new_pixels = [p for p in neighbor_coords if tuple(p) not in own_set]
            
            if not new_pixels:
                continue
            
            # 随机选非水域像素
            whilecounter = 0
            while whilecounter < 1000:
                y, x = random.choice(new_pixels)
                if not np.all(img_array[y, x] == water_color):
                    img_array[y, x] = colour
                    break
                whilecounter +=1
    return img_array

4. 优化邻接像素筛选逻辑

原代码用列表判断j not in ownpixels(时间复杂度O(n)),改为集合查找(O(1)):

own_set = set(tuple(p) for p in ownpixels)
newpixels = [j for j in allnewpixels if tuple(j) not in own_set]

二、Tkinter地图更新环节优化

1. 减少UI更新频率

不必每回合都更新界面,可间隔N回合更新一次,避免阻塞主循环:

def GenerateWorldMapMain():
    global tkbasemap
    basemap = Image.open('basemap.png')
    img_array = np.array(basemap)
    
    # 预生成陆地坐标、初始化文明标记(省略重复代码)
    
    for i in range(1000):
        print('Turn:',i)
        img_array = GenerateWorldNumpy(img_array, d1.civilisationdictionary)
        
        # 每10回合更新一次UI
        if i % 10 == 0:
            basemap = Image.fromarray(img_array)
            tkbasemap = ImageTk.PhotoImage(basemap)
            imagelabel.configure(image=tkbasemap)
            imagelabel.image=tkbasemap
            imagelabel.update_idletasks()  # 用非阻塞更新代替update()
    
    # 最后全量更新一次
    basemap = Image.fromarray(img_array)
    tkbasemap = ImageTk.PhotoImage(basemap)
    imagelabel.configure(image=tkbasemap)
    imagelabel.image=tkbasemap

2. 避免全局变量来回转换

直接保留Numpy数组或PIL图像对象,仅在需要更新UI时转换为PhotoImage,省去ImageTk.getimage()的反向转换开销。

三、其他辅助优化

  • 提前预处理文明颜色:一次性将所有文明的colour1转换为带alpha通道的格式,存入字典,避免循环内重复转换。
  • 使用局部变量:将全局变量(如worldmapdictionary)赋值为函数内局部变量,减少全局查找的性能损耗。
  • 过滤无效邻接像素:生成邻接坐标时直接排除图像边界外的像素,避免后续无效判断。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 04:20:31