首页 > 解决方案 > setSolved() 的刽子手游戏效果延迟

问题描述

我有一个几乎可以工作的刽子手游戏。问题是当我得到所有字母正确时,直到我再次单击一个字母时才会显示 YOU WIN 消息。

我将仅列出我认为相关的部分。

Game.js 是一个容器。

游戏包含状态:

state = {
        lives: 12,
        solution: 'my name is logan',
        correctUsedLetters: [],
        availableLetters: ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'],
        usedLetters: [],
        solved: false
};

还有许多处理程序,包括 setSolvedHandler:

setSolvedHandler = () => {
        const solution = this.state.solution.replace(/\s/g, '').replace(/-/g, '').split('');
        const compare = [ ...this.state.correctUsedLetters].sort();
        const unique = solution.filter(
            (elem,index,self) => (index===self.indexOf(elem))
        ).sort();

        const solved = JSON.stringify(unique) === JSON.stringify(compare);

        this.setState({
            solved: solved
        });
};

如果correctUsedLetters 匹配解决方案,则此处理程序将solved 设置为true,如果玩家解决了难题,则有效。

同样在 Game.js 中渲染了 Letters:

<div className={classes.LettersAndHangman}>
                    <Hangman lives={this.state.lives} />
                    <Letters setSolved={this.setSolvedHandler} solution={this.state.solution} correct={this.guessedCorrectHandler} incorrect={this.guessedIncorrectHandler} 
                    feed={this.state.availableLetters}
                    />
</div>

Game.js 调用 Letters,让我们来看看。

Letters.js 具有称为 lettersMap 的状态,其中包含字母表中的每个字母,并带有一个布尔值,指示该字母是否已被单击。

const [lettersMap, setLettersMap]=useState(
        {
            "a":false,"b":false,"c":false,"d":false,"e":false,"f":false,"g":false,"h":false,"i":false,"j":false,"k":false,"l":false,"m":false,"n":false,"o":false,"p":false,"q":false,"r":false,"s":false,"t":false,"u":false,"v":false,"w":false,"x":false,"y":false,"z":false
        }
);

它包含 playHandler 测试点击的字母是否正确。但是我们暂时跳过这个。

更重要的是,它包含 updateClickedHandler 它将布尔值设置为 true 用于单击的字母。这会更新 letterMap。

const updateClickedHandler = (letter) => {
        setLettersMap(
            {
                ...lettersMap,[letter]:true
            }
        );
};

然后从 Letters.js 渲染了两件事。AvailableLetter 和 DisabledLetter。AvailableLetter 表示没有被点击的字母。DisabledLetter 表示已单击的字母,现在禁止再次单击。

 const renderedLetters = Object.keys(lettersMap).map(
        (letter,i)=>{
          if (!lettersMap[letter])     //letter is not yet clicked
          {
            return (
                <AvailableLetter updateClicked={updateClickedHandler} setSolved={props.setSolved} play={()=>playHandler(letter)} correct={()=>props.correct(letter)} incorrect={()=>props.incorrect(letter)} solution={props.solution} key={i} alphabet={letter} />
            )
          }
          else                         //letter is clicked
          { 
            return (
                <DisabledLetter alphabet={letter} key={i} />
            )
          }
        }
);

以下是 AvailableLetter 和 DisabledLetter 的代码:

const AvailableLetter = (props) => {

    const setStuff = () => {
      if (props.play()) {
        props.correct();
      }
      else {
        props.incorrect();
      }

      props.setSolved();
      props.updateClicked(props.alphabet);
    };

    return (
        <Ax>
          <span className={classes.AvailableLetter} onClick={setStuff}>{props.alphabet}</span>
        </Ax>
    );
}
const DisabledLetter = (props) => {
    return (
    <span className={classes.DisabledLetter} >{props.alphabet}</span>
    );
};

现在我将介绍 Model.js,它会显示您获胜或游戏结束的消息。

const modal = (props) => {
    let show = props.gameOver() || props.solved ? true : false;

    const attachedClasses = [ classes.Message ];
    if (!show) {
        attachedClasses.push(classes.Hide);
    }

    return (
        <div>
            <Backdrop show={show} />
            <div className={attachedClasses.join(' ')} >
                {props.gameOver()?<p>GAME OVER</p>:null}
                {props.solved?<p>YOU WIN!</p>:null}
            </div>
        </div>
    );
};

调查代码,如果游戏结束或解决,则显示为真。此值用于显示/隐藏背景。它还用于显示/隐藏消息。

然后根据游戏结束或解决,您会收到相应的消息:游戏结束或您获胜。

我还不确定问题的根源是什么,但问题是即使解决了难题,您也不会显示 YOU WIN,直到您再单击一个字母(除了触发消息之外没有任何作用) .

目前,当单击 span 时,在 AvailableLetter.js 中调用 setSolved()。似乎在单击字母时调用 setSolved 的效果会有所延迟。

我会尽量简洁地构建问题。感谢您的耐心等待。

你可以在这里获得完整的源代码: https ://github.com/guntinug/hangmanclicked/tree/master/src

标签: reactjs

解决方案


我用 hack 修复了它:

在 Game.js 中,我编写了函数 checkSolvedWithoutStateChange:

// A hack for Modal.js
    checkSolvedWithoutStateChange = () => {
        const solution = this.state.solution.replace(/\s/g, '').replace(/-/g, '').split('');
        const compare = [ ...this.state.correctUsedLetters].sort();
        const unique = solution.filter(
            (elem,index,self) => (index===self.indexOf(elem))
        ).sort();

        const solved = JSON.stringify(unique) === JSON.stringify(compare);
        return solved;
    };

然后,我将它传递给 Game.js 中的渲染:

<Modal checkSolved={this.checkSolvedWithoutStateChange} gameOver={this.gameOverHandler} />

这是 Modal.js:

import React from 'react';
import Backdrop from './Backdrop/Backdrop';
import classes from './Modal.module.css';

const modal = (props) => {
    let show = props.gameOver() || props.checkSolved() ? true : false;

    const attachedClasses = [ classes.Message ];
    if (!show) {
        attachedClasses.push(classes.Hide);
    }

    return (
        <div>
            <Backdrop show={show} />
            <div className={attachedClasses.join(' ')} >
                {props.gameOver()?<p>GAME OVER</p>:null}
                {props.checkSolved()?<p>YOU WIN!</p>:null}
            </div>
        </div>
    );
};

export default modal;

现在它已修复,但我想知道一种更好的方法来避免这种“黑客”。:D


推荐阅读