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

Tkinter网格墙生成函数While循环崩溃问题排查求助

墙体生成函数循环崩溃问题排查

问题描述

我需要实现一个函数,根据传入的wall_type(例如1-line horizontal)在网格指定范围内随机放置墙体。函数wall_gen接收两个参数:

  • wall_type:决定网格上生成的墙体类型
  • amount:决定该类型墙体的生成次数

函数会创建存储墙体类型的数组wt_list和存储墙体实例的数组w_list,用变量存储tkinter canvas绘制的线条信息(格式如w1=canvas.create_line(0,0,50,0)),方便后续删除。

当前问题:不使用while循环时代码正常运行,添加循环生成多个墙体时程序崩溃。碰撞检测逻辑用于判断生成的墙体是否与玩家位置重叠,若重叠则重新循环,否则生成墙体后继续循环,对应代码:

if (player_trail.count(wt_x1+z)>0 or player_trail.count(wt_y1+t)>0 or player_trail.count(wt_x2+z)>0 or player_trail.count(wt_y2+t)>0)

原代码片段:

# @@@@@@ WALL TYPES @@@@@@@@@
wt1=(0,0,  50,0) # 1-line h.
wt2=(0,0,  100,0) # 2-line h.
wt3=(0,0,  150,0) # 3-line h.

wt4=(0,0,  0,50) # 1-line v.
wt5=(0,0,  0,100) # 2-line v.
wt6=(0,0,  0,150) # 3-line v.

wt7=(0,0,  50,50) # 1-1-line d.
wt8=(0,0,  100,100) # 2-2-line d.

wt9=(0,50,  50,0) # fliped 1-1-line d.
wt10=(0,100,  100,0) # fliped 2-2-line d.

wt11=(0,0,  100,50) # 2-1-line hd. 
wt12=(0,0,  50,100) # 2-1-line vd.

wt13=(0,50,  100,0) # fliped 2-1-line hd.
wt14=(0,100,  50,0) # fliped 2-1-line vd.


#@@@@@@ WALL GEN @@@@@@@@@@@@@@@
def wall_gen(wall_type,amount):

    global w1,w2,w3,w4,w5,w6,w7,w8,w9,w10,w11,w12,w13,w14,w15,w16,w17,w18,w19,w20,w21,w22,w23,w24
    global wt1,wt2,wt3,wt4,wt5,wt6,wt7,wt8,wt9,wt10,wt11,wt12,wt13,wt14

    w_list =[0,w1,w2,w3,w4,w5,w6,w7,w8,w9,w10,w11,w12,w13,w14,w15,w16,w17,w18,w19,w20,w21,w22,w23,w24]
    wt_list=[0,wt1,wt2,wt3,wt4,wt5,wt6,wt7,wt8,wt9,wt10,wt11,wt12,wt13,wt14]


    # seperates the wall_type into its x1,x2,y1,y2 cordinates 
    wt_x1,wt_y1,wt_x2,wt_y2=(wt_list[wall_type])


    
    plusx_list=[200,250,300]
    plusy_list=[200,250,300]

   
    
    wall_number=1
    while wall_number<=amount:
        
        # gets a random value from a 'plusx_list' and 'plusy_list' lists to be added to wall_type x1,x2,y1,y2 cordinates 
        z=random.choice(plusx_list)
        t=random.choice(plusy_list)
        if (player_trail.count(wt_x1+z)>0 or player_trail.count(wt_y1+t)>0 or player_trail.count(wt_x2+z)>0 or player_trail.count(wt_y2+t)>0) : 
            continue
            
        if (player_trail.count(wt_x1+z)<1 and player_trail.count(wt_y1+t)<1 and player_trail.count(wt_x2+z)<1 and player_trail.count(wt_y2+t)<1): 
            (w_list[wall_number])=canvas.create_line(wt_x1+z, wt_y1+t, wt_x2+z, wt_y2+t)
            wall_number+1
            print(wall_number)

错误分析与修复方案

1. 核心死循环问题

代码中wall_number+1仅执行加法运算,没有将结果赋值回wall_number,导致wall_number永远不会递增,循环无法终止,最终程序卡死。必须改为wall_number += 1。

2. 冗余条件判断

第一个if已经判断了墙体是否与玩家轨迹重叠,第二个if是完全相反的条件,属于冗余判断,可以直接合并逻辑,减少代码复杂度。

3. 全局变量管理问题

原代码中w_list初始化时直接引用全局变量w1-w24,但修改w_list的元素并不会同步更新全局变量,因为列表存储的是变量的当前值而非引用。建议改用单个全局列表存储所有墙体实例,替代大量单独的变量,更便于管理。

4. 碰撞检测逻辑漏洞

当前仅检测墙体四个端点是否在玩家轨迹中,但墙体是一条线段,中间部分与玩家重叠的情况未被覆盖。如果玩家轨迹是坐标点集合,可补充线段上所有网格点的检测(或根据网格对齐特性简化为边界盒检测)。

修正后的代码

# @@@@@@ WALL TYPES @@@@@@@@@
wt1=(0,0,  50,0) # 1-line h.
wt2=(0,0,  100,0) # 2-line h.
wt3=(0,0,  150,0) # 3-line h.

wt4=(0,0,  0,50) # 1-line v.
wt5=(0,0,  0,100) # 2-line v.
wt6=(0,0,  0,150) # 3-line v.

wt7=(0,0,  50,50) # 1-1-line d.
wt8=(0,0,  100,100) # 2-2-line d.

wt9=(0,50,  50,0) # fliped 1-1-line d.
wt10=(0,100,  100,0) # fliped 2-2-line d.

wt11=(0,0,  100,50) # 2-1-line hd. 
wt12=(0,0,  50,100) # 2-1-line vd.

wt13=(0,50,  100,0) # fliped 2-1-line hd.
wt14=(0,100,  50,0) # fliped 2-1-line vd.

# 用全局列表统一存储所有墙体实例,替代单独的w1-w24变量
wall_instances = []

#@@@@@@ WALL GEN @@@@@@@@@@@@@@@
def wall_gen(wall_type, amount):
    global wall_instances
    wt_list = [0, wt1, wt2, wt3, wt4, wt5, wt6, wt7, wt8, wt9, wt10, wt11, wt12, wt13, wt14]
    
    # 分解墙体类型的坐标
    wt_x1, wt_y1, wt_x2, wt_y2 = wt_list[wall_type]
    
    plusx_list = [200, 250, 300]
    plusy_list = [200, 250, 300]
    
    wall_number = 0
    while wall_number < amount:
        # 随机获取偏移量
        z = random.choice(plusx_list)
        t = random.choice(plusy_list)
        
        # 计算墙体的实际坐标
        x1, y1 = wt_x1 + z, wt_y1 + t
        x2, y2 = wt_x2 + z, wt_y2 + t
        
        # 检测墙体端点是否与玩家轨迹重叠
        if x1 in player_trail or y1 in player_trail or x2 in player_trail or y2 in player_trail:
            continue
        
        # 生成墙体并添加到实例列表
        wall = canvas.create_line(x1, y1, x2, y2)
        wall_instances.append(wall)
        wall_number += 1
        print(wall_number)

额外说明

  • 若需要更精准的碰撞检测,可实现线段与玩家轨迹点的交集判断(例如遍历线段上的所有网格点,检查是否存在于player_trail中)。
  • 全局列表wall_instances可方便后续批量删除墙体,例如通过for wall in wall_instances: canvas.delete(wall)实现。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 22:06:27