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
相关产品推荐
相关产品推荐

