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

Kivy多屏幕猜单词游戏中单词显示字段失效问题求助

Kivy猜单词游戏单词显示字段异常问题解决求助

本人使用Kivy框架开发Python猜单词游戏,遇到以下问题:单独显示游戏屏幕时功能完全正常,但整合包含其他屏幕的完整游戏后,选中的字母可以正常显示,但单词字段(下划线占位的区域)无内容显示。本人学习Python不足半年,代码可能存在疏漏,望得到解决方案。

相关代码

Python代码

from kivymd.app import MDApp
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
from kivy.core.audio import SoundLoader
from kivy.core.window import Window
from kivy.properties import StringProperty
from kivy.uix.widget import Widget
from random import *

Window.size = (400,600)

class Meneger(ScreenManager):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

class Menu(Screen):
    def click(self):
        click = SoundLoader.load('click.wav')
        click.play()

class Play(Screen):
    def click(self):
        click = SoundLoader.load('click.wav')
        click.play()

class Mod(Screen):
    def click(self):
        click = SoundLoader.load('click.wav')
        click.play()

class HangmanGame(Screen, Widget):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
    display_word = StringProperty()
    wrong_guess = 0
    correct_guess = 0

    def playsound(self):
        self.sound = SoundLoader.load('button.wav')
        self.sound.volume = 0.5
        self.sound.play()

    def FindHangmanWord(self):
        word_list = ['arrow', 'arson', 'artery', 'artful', 'artier', 'artist', 'arts', 'artsy', 'arty', 
                     'ascend', 'ascent', 'ascot', 'ashcan', 'ashed', 'ashen', 'ashes', 'ashier', 'ashing', 'ashore', 'ashram', 'ashy', 'aside', 'askew', 'asking', 'asks']
        word = choice(word_list)
        return word.upper()

    def check_in_word(self, btn):
        count = 0
        for i, letter in enumerate(wow):
            if btn.text == letter.upper():
                self.display_word = self.display_word[:i * 2] + btn.text + self.display_word[i * 2 + 1:]
                self.correct_guess += 1
                count += 1

                if self.correct_guess >= len(wow):
                    print('GAME OVER, YOU WIN')

            btn.disabled = True

        if count == 0:
            self.wrong_guess += 1
            if self.wrong_guess >= 6:
                print('GAME OVER, YOU LOSE!')

    def init_display_word(self, word):
        tmp_display_word = ''
        for letter in word:
            tmp_display_word += '_ '
        self.display_word = tmp_display_word[:len(tmp_display_word) - 1]

class Info(Screen):
    def click(self):
        click = SoundLoader.load('click.wav')
        click.play()

presentation = Builder.load_file('my.kv')

class MyApp(MDApp):
    def build(self):
        game = HangmanGame()
        game.init_display_word(wow)
        self.playsound()
        sm = ScreenManager()
        sm.add_widget(Menu(name='menu'))
        sm.add_widget(Play(name='play'))
        sm.add_widget(Info(name='info'))
        sm.add_widget(Mod(name='mod'))
        sm.add_widget(HangmanGame(name='hangmangame'))
        return sm

    def playsound(self):
        self.sound = SoundLoader.load('glav.wav')
        self.sound.volume = 0.5
        self.sound.play()

if __name__ == '__main__':
    wow = HangmanGame().FindHangmanWord()
    MyApp().run()

KV代码片段

Label:
    id: display_word_id
    text: root.display_word
    font_size: 40
    color: (1, 1, 1, 1)
    pos_hint: {'center_x': 0.5}

截图情况

  • 单屏幕效果:单词字段正常显示下划线占位符,字母交互正常
  • 多屏幕整合后:单词字段无内容,选中字母可显示但下划线区域不出现

已尝试的无效方案

  • 将代码拆分到第二个文件后导入,无效果
  • 在init_display_word方法中用HangmanGame类名替代self,单词字段显示但选中字母失效;反之则字母生效但字段消失
  • 尝试在build方法中加入check_in_word,但因需要第二个参数无法自动传入

解决方案

核心问题分析

  1. 重复创建HangmanGame实例:build方法中先创建了一个game实例并初始化了display_word,但实际添加到屏幕管理器的是另一个全新的HangmanGame实例,导致屏幕上的实例未被初始化
  2. 全局变量wow的冲突:全局变量存储目标单词,导致实例间状态混乱

修复步骤

  1. 重构HangmanGame类,移除全局变量依赖
class HangmanGame(Screen):  # 无需继承Widget,Screen本身是Widget子类
    display_word = StringProperty()
    wrong_guess = 0
    correct_guess = 0

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.target_word = self.FindHangmanWord()  # 实例内部存储目标单词
        self.init_display_word(self.target_word)   # 初始化显示字段

    # 其余方法不变,仅将check_in_word中的wow替换为self.target_word
    def check_in_word(self, btn):
        count = 0
        for i, letter in enumerate(self.target_word):
            if btn.text == letter.upper():
                self.display_word = self.display_word[:i * 2] + btn.text + self.display_word[i * 2 + 1:]
                self.correct_guess += 1
                count += 1

                if self.correct_guess >= len(self.target_word):
                    print('GAME OVER, YOU WIN')

        btn.disabled = True

        if count == 0:
            self.wrong_guess += 1
            if self.wrong_guess >= 6:
                print('GAME OVER, YOU LOSE!')
  1. 修正MyApp.build方法,避免重复创建实例
class MyApp(MDApp):
    def build(self):
        self.playsound()
        sm = ScreenManager()
        sm.add_widget(Menu(name='menu'))
        sm.add_widget(Play(name='play'))
        sm.add_widget(Info(name='info'))
        sm.add_widget(Mod(name='mod'))
        # 仅创建一次HangmanGame实例并添加到屏幕管理器
        hangman_game = HangmanGame(name='hangmangame')
        sm.add_widget(hangman_game)
        return sm
  1. 移除全局变量定义
if __name__ == '__main__':
    MyApp().run()

额外优化建议

  • 将Meneger类名改为Manager(修正拼写错误)
  • 音效加载可做缓存处理,避免每次点击重复读取文件
  • 将单词列表移至类内部或单独配置文件,便于后续维护

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 02:24:54