reactjs - 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
解决方案
我用 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
推荐阅读
- reactjs - 打字稿错误“typeof DefaultTheme”类型上不存在属性“div”
- java - 为什么 Jenkins 管道抛出 java.lang.ClassNotFoundException: com.mysql.jdbc.Driver?
- javascript - 无法读取地图未定义反应的属性
- firebase - 颤振火力,列表
不是列表类型 - codeigniter - 如何使用不同的数据库表制作注册表单codeigniter
- amazon-web-services - AWS API 网关测试
- django - 在 UpdateView 中更改 django 绑定数据
- qt - 如果单击 QTableView 的单元格,则发出信号
- oracle - 如何修复使用 oracle 数据库在 utl_http 响应中获取不可读字符的问题?
- c - 如何在 MinGW gcc 中捕获断言失败?