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

Python控制台交互式菜单选中项重复Bug排查求助

控制台菜单重复选中项Bug排查与修复

问题重现

操作步骤:

  1. 下移至第4项(counter值为3)
  2. 按Enter键切换到shop状态
  3. 在shop状态下移至第5项(counter值为4)
  4. 按Enter键切回play状态
  5. 按向下箭头

实际显示结果:

TOSHOP    
> TOSHOP <
TOSHOP    
> TOSHOP <

预期显示结果:

TOSHOP    
> TOSHOP <
TOSHOP    
TOSHOP

相关代码

main.py

import keyboard
import ui
import os

os.system("cls")
ui.play[ui.counter] = "> " + ui.play[ui.counter] + " <"
ui.navmenuprint(ui.play)

while True:
    while ui.state == "play":
        keypressed = keyboard.read_key()
        while keyboard.is_pressed("down"): pass
        while keyboard.is_pressed("up"): pass
        while keyboard.is_pressed("enter"): pass

        if keypressed == "up":
            os.system("cls")
            ui.navup(ui.play, ui.play2)
            ui.navmenuprint(ui.play)
        if keypressed == "down":
            os.system("cls")
            ui.navdown(ui.play, ui.play2)
            ui.navmenuprint(ui.play)
        if keypressed == "enter":
            if ui.counter == 0:
                ui.switchstate("shop")
            if ui.counter == 1:
                ui.switchstate("shop")
            if ui.counter == 2:
                ui.switchstate("shop")
            if ui.counter == 3:
                ui.switchstate("shop")

    while ui.state == "shop":
        keypressed = keyboard.read_key()
        while keyboard.is_pressed("down"): pass
        while keyboard.is_pressed("up"): pass
        while keyboard.is_pressed("enter"): pass
        
        if keypressed == "up":
            os.system("cls")
            ui.navup(ui.shop, ui.shop2)
            ui.navmenuprint(ui.shop)
        if keypressed == "down":
            os.system("cls")
            ui.navdown(ui.shop, ui.shop2)
            ui.navmenuprint(ui.shop)
        if keypressed == "enter":
            if ui.counter == 0:
                ui.switchstate("play")
            if ui.counter == 1:
                ui.switchstate("play")
            if ui.counter == 2:
                ui.switchstate("play")
            if ui.counter == 3:
                ui.switchstate("play")
            if ui.counter == 4:
                ui.switchstate("play")

ui.py

import os
from termcolor import cprint

state = "play"
counter = 0
play = ["TOSHOP", "TOSHOP", "TOSHOP","TOSHOP"]
play2 = ["TOSHOP", "TOSHOP", "TOSHOP","TOSHOP"]
shop = ["TOPLAY", "TOPLAY","TOPLAY","TOPLAY","TOPLAY"]
shop2 = ["TOPLAY", "TOPLAY","TOPLAY","TOPLAY","TOPLAY"]

def switchstate(fromwhere):
    global state, counter
    if fromwhere == "play":
        counter = 0
        state = fromwhere
        play = play2.copy()
        os.system("cls")
        play[counter] = "> " + play[counter] + " <"
        navmenuprint(play)
    if fromwhere == "shop":
        counter = 0
        state = fromwhere
        shop = shop2.copy()
        os.system("cls")
        shop[counter] = "> " + shop[counter] + " <"
        navmenuprint(shop)

def navup(list1, list2):
    global counter
    if counter != 0:
        list1[counter] = list2[counter]
        counter -= 1
        list1[counter] = "> " + list1[counter] + " <"
    else:
        list1[counter] = list2[counter]
        counter -= 1
        list1[counter] = "> " + list1[counter] + " <"
        counter = len(list1) - 1
    print (counter)

def navdown(list1,list2):
    global counter
    if counter != len(list1) - 1:
        list1[counter] = list2[counter]
        counter += 1
        list1[counter] = "> " + list1[counter] + " <"
    else:
        list1[counter] = list2[counter]
        counter = 0
        list1[counter] = "> " + list1[counter] + " <"
    print (counter)

def navmenuprint(list):
    global counter
    for i in list:
        print(i)

Bug原因分析

  1. 全局列表未被正确重置:switchstate函数中修改play和shop时,未将其声明为全局变量,导致函数内创建了局部变量,而非修改全局的列表实例。全局列表仍保留之前操作添加的选中标记(> TOSHOP <),切换回play状态后,新的选中标记与旧标记叠加,出现重复。
  2. 状态切换逻辑错误:switchstate函数中,state = fromwhere的赋值逻辑完全错误——比如从play切换到shop时,应该将state设为"shop"而非传入的fromwhere参数值,导致状态切换失效,进一步加剧了列表状态的混乱。
  3. navup函数存在索引逻辑错误:当counter为0时,代码先将其减至-1再赋值,虽Python允许负索引,但不符合循环到列表末尾的预期逻辑,存在潜在风险。

修复方案

1. 修正switchstate函数的全局变量声明与状态赋值

def switchstate(target_state):
    global state, counter, play, shop  # 声明要修改的全局变量
    counter = 0
    state = target_state  # 直接设置为目标状态
    if target_state == "shop":
        play = play2.copy()  # 重置play列表
        os.system("cls")
        play[counter] = "> " + play[counter] + " <"
        navmenuprint(play)
    if target_state == "play":
        shop = shop2.copy()  # 重置shop列表
        os.system("cls")
        shop[counter] = "> " + shop[counter] + " <"
        navmenuprint(shop)

2. 修正navup函数的循环逻辑

避免负索引,直接实现循环到列表末尾的逻辑:

def navup(list1, list2):
    global counter
    # 清除当前选中项
    list1[counter] = list2[counter]
    # 处理循环逻辑
    if counter > 0:
        counter -= 1
    else:
        counter = len(list1) - 1
    # 设置新选中项
    list1[counter] = "> " + list1[counter] + " <"
    print(counter)

3. 简化main.py中的Enter判断逻辑

# play状态下的Enter处理
if keypressed == "enter":
    if ui.counter in range(4):
        ui.switchstate("shop")

# shop状态下的Enter处理
if keypressed == "enter":
    if ui.counter in range(5):
        ui.switchstate("play")

修复后验证

按照原操作步骤执行,切回play状态后按向下箭头,只会显示一个选中项,符合预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 21:50:22