我想在React.js中创建一个刽子手游戏,当用户点击一个字母时,这个代码会搜索单词中的字母并显示她。当单词只包含一个相同的字母时,它可以正常工作。 我希望这段代码可以像“' PROGRAMMING'与2' M'。
handleChooseLetter = (index) => {
const usedWord = [...this.state.usedWord];
const chosenLetter = this.state.letters[index].letter;
var letterPosition = usedWord.indexOf(chosenLetter);
if (letterPosition >= 0) {
hiddenWord.splice(letterPosition, 1, chosenLetter);
this.setState({hiddenWord: hiddenWord});
}
}
我已经尝试了一个while循环,但它在我的情况下不起作用:
var indices = [];
while(letterPosition >= 0) {
const hiddenWord = [...this.state.hiddenWord];
indices.push(letterPosition);
letterPosition = usedWord.indexOf(chosenLetter, letterPosition + 1);
hiddenWord.splice(letterPosition, 1, chosenLetter);
this.setState({hiddenWord: hiddenWord});
}
对我来说,结果就是找到这个字母,并在字母的最后一个字母处显示它们。
我认为我的问题在于拼接错误的letterPosition
拼接方法这是我的chooseWord功能:
state = {
wordList: [
{ id: 1, word: 'PROGRAMMING'},
],
usedWord: [],
hiddenWord: [],
}
chooseWord() {
const wordList = [...this.state.wordList];
const listLength = wordList.length;
const randomWord = this.state.wordList[Math.floor(Math.random() * listLength)].word;
const splittedWord = randomWord.split("");
const arr = new Array(randomWord.length + 1).join("_").split("");
this.setState({
usedWord: splittedWord,
hiddenWord: arr
});
}
答案 0 :(得分:4)
最简单的方法是replace
,不使用数组:
const usedWord = "programming";
const chosenLetter = "m";
const hiddenWord = usedWord.replace(new RegExp("[^" + chosenLetter + "]", "g"), "_");
console.log(hiddenWord);
当用户添加更多字母时,您可以将它们添加到字符类:
const usedWord = "programming";
const chosenLetters = "mp";
const hiddenWord = usedWord.replace(new RegExp("[^" + chosenLetters + "]", "g"), "_");
console.log(hiddenWord);
反应示例:
class Hangman extends React.Component {
constructor(...args) {
super(...args);
this.state = {
availableLetters: "abcdefghijklmnopqrstuvwxyz",
chosenLetters: "",
word: this.props.word
};
this.chooseLetter = this.chooseLetter.bind(this);
}
chooseLetter({target: {tagName, type, value}}) {
if (tagName === "INPUT" && type === "button") {
this.setState(prevState => ({chosenLetters: prevState.chosenLetters + value}));
}
}
render() {
const {word, chosenLetters} = this.state;
const hiddenWord = word.replace(new RegExp("[^" + chosenLetters + "]", "g"), "_");
return <div>
<div>Word: <span className="hiddenWord">{hiddenWord}</span></div>
<div onClick={this.chooseLetter} style={{marginTop: "8px"}}>
{[...this.state.availableLetters].map(
letter => <input type="button" value={letter} disabled={chosenLetters.includes(letter)} />
)}
</div>
</div>;
}
}
ReactDOM.render(
<Hangman word="programming" />,
document.getElementById("root")
);
.hiddenWord {
font-family: monospace;
letter-spacing: 1em;
font-size: 18px;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
对于单个英文字母,您不必担心使用new RegExp(chosenLetter, "g")
,因为没有一个英文字母在正则表达式中具有特殊含义。如果您确实拥有具有特殊含义的字符(.
,$
等),则在将字符传递给RegExp
构造函数之前,您将转义该字符; see this question's answers了解如何做到这一点。
答案 1 :(得分:2)
我添加了字母输入<input onChange={this.handleChooseLetter} value={letter} />
并更改了你的handleChooseLetter函数,如果找到至少1个字母,则迭代使用过的单词的字母(因为你的usedWord.indexOf(chosenLetter)
总是只返回1个索引),所以我决定迭代整个单词并检查所选字母,如果该索引上的字母存在,我只是将该字母插入同一索引上的隐藏单词 - 因为隐藏和使用的单词具有相同的长度:
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
hiddenWord: "___________",
usedWord: "PROGRAMMING",
letter: ""
};
}
handleChooseLetter = e => {
const usedWord = [...this.state.usedWord];
const chosenLetter = e.target.value.toLocaleUpperCase();
let letterPosition = usedWord.indexOf(chosenLetter);
if (letterPosition > -1) {
this.setState(prevState => {
const hiddenWord = [...prevState.hiddenWord];
for (let i = 0; i < usedWord.length; i++) {
if (usedWord[i] === chosenLetter) {
hiddenWord[i] = chosenLetter;
}
}
return { hiddenWord, letter: "" };
});
return;
}
this.setState({ letter: "" });
};
render() {
const { hiddenWord, letter } = this.state;
return (
<div className="App">
{[...hiddenWord].map((letter, index) => (
<span key={index}>{letter} </span>
))}
<input onChange={this.handleChooseLetter} value={letter} />
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.4.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>
答案 2 :(得分:-1)
啊哈!我曾经为我的班级做过类似的项目。下面是github回购供您参考: https://github.com/LordKriegan/WraithFood
基本上,我所做的是创建了一个包含多个字符串和一些函数的对象。当游戏加载时,它从我的列表中选择一个随机单词并设置2个字符串。一个是完整的单词(让我们称这个属性为fullWord),另一个基本上是一个长度相同的字符串,所有字母都转换为下划线(让我们称之为guessedWord,也可以在game.js中看到setWord()文件)。
但你有兴趣检查这些信件!多么容易。 Javascript字符串有一个名为.includes()的内置方法,它将一个字符串作为参数。因为我在对象中保存了我的单词,所以我只是用我要检查的字母在该单词上运行.includes(),然后如果它通过我的所有验证(已经猜到的字母,无论是否在字中,等),我用另一个名为.charAt(i)的String方法在guessedWord上运行了一个for循环。此方法只返回其调用的字符串中位置i的字符。由于我必须在我的对象中使用字符串,我知道它的长度相同,我可以在fullWord上执行for循环,检查位置i处的每个字母,然后使用.substr()重置guessedWord属性。此方法根据您传递的参数返回部分字符串。基本上我将guessedWord设置为+ +。这是游戏对象中的checkLet()函数。
上的字符串方法