简体   繁体   English

查找数组(单词)中的所有出现(字母)

[英]Find all occurrences (letters) in array (word)

I want to create a hangman game in React.js, with this code when the user click on a letter, it will search the letter in the word and display her. 我想在React.js中创建一个子手游戏,使用此代码,当用户单击字母时,它将在单词中搜索字母并显示她。 It work correctly when the word contain only one same letter. 当单词只包含一个相同的字母时,它可以正常工作。 I would like this code work with word like 'PROGRAMMING' with 2 'M'. 我希望这段代码可以使用带有2个“ M”的单词“ PROGRAMMING”。

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});
}

} }

I already try a while loop but it not work in my case: 我已经尝试了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});
}

For me, the result is that find the letter and display them always for the last letter of the word. 对我来说,结果是找到字母并始终显示单词的最后一个字母。

I think my problem is with the splice method who splice the wrong letterPosition 我认为我的问题是使用拼接方法拼接了错误的字母

Here my chooseWord function: 这里我的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
});

} }

The simplest way is replace , not using an array: 最简单的方法是replace ,而不使用数组:

 const usedWord = "programming"; const chosenLetter = "m"; const hiddenWord = usedWord.replace(new RegExp("[^" + chosenLetter + "]", "g"), "_"); console.log(hiddenWord); 

As the user adds more letters, you can add them to the character class: 随着用户添加更多字母,您可以将它们添加到字符类中:

 const usedWord = "programming"; const chosenLetters = "mp"; const hiddenWord = usedWord.replace(new RegExp("[^" + chosenLetters + "]", "g"), "_"); console.log(hiddenWord); 

React Example: React示例:

 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:&nbsp;&nbsp;&nbsp;<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> 


For single English alphabet letters, you don't have to worry about using new RegExp(chosenLetter, "g") because none of the English alphabetic letters has special meaning in a regular expression. 对于单个英文字母,您不必担心使用new RegExp(chosenLetter, "g")因为没有英文字母在正则表达式中具有特殊含义。 If you did have characters with special meaning ( . , $ , etc.), you'd escape the character before passing it to the RegExp constructor; 如果确实有特殊含义的字符( .$等),则在将字符传递给RegExp构造函数之前会对其进行转义。 see this question's answers for ways to do that. 请参阅此问题的答案以了解解决方法。

I've added letter input <input onChange={this.handleChooseLetter} value={letter} /> and changed your handleChooseLetter function to iterate through letters of used word if at least 1 letter is found (because your usedWord.indexOf(chosenLetter) always returns 1 index only), so I decided to iterate entire word and check for chosen letter, if letter on that index exists, I just insert that letter to the hidden word on the same index - because hidden and used words have the same length: 我添加了字母输入<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}&nbsp;</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> 

Aha! 啊哈! I had to do a similar project for my class once. 我上课不得不做一次类似的项目。 Heres the github repo for your reference: https://github.com/LordKriegan/WraithFood 继承人的github仓库供您参考: https : //github.com/LordKriegan/WraithFood

Essentially, what I did was I created an object with several strings and a few functions. 本质上,我所做的就是创建了一个包含多个字符串和几个函数的对象。 When the game loads, it picks a random word from my list and sets 2 of the strings. 游戏加载后,它将从我的列表中选择一个随机单词并设置2个字符串。 One is the full word (lets call this property fullWord), the other is basically a string of the same length with all letters converted to underscores (let's call this one guessedWord, also see setWord() in the game.js file). 一个是完整的单词(让我们将此属性称为fullWord),另一个基本上是一个长度相同的字符串,所有字母都转换为下划线(我们将其称为一个guessedWord,也请参阅game.js文件中的setWord())。

But you are interested in checking the letters! 但是您有兴趣检查字母! Thats easy enough. 那很容易。 Javascript strings have a built-in method called .includes(), which takes a string as a parameter. Javascript字符串具有一个称为.includes()的内置方法,该方法将字符串作为参数。 Since I had my word saved in the object, I simply ran a .includes() on that word with the letter I wanted to check, then if it passed all my validation (letter already guessed, whether it is or isnt in the word, etc), I ran a for loop on guessedWord with another String method called .charAt(i). 由于我已将单词保存在对象中,因此我只需在该单词上运行一个.includes()并添加要检查的字母,然后它是否通过了我的所有验证(字母已经猜出,单词中是否存在,等等),我使用另一个名为.charAt(i)的String方法在guessedWord上运行了一个for循环。 This method simply returns the character at position i in the string its called on. 此方法仅返回其调用的字符串中位置i处的字符。 Since I have to strings in my object, which I KNOW to be the same length, I can execute a for loop on fullWord, check every letter at position i, and then reset the guessedWord property with .substr(). 由于我必须在对象中输入字符串,我知道它的长度是相同的,因此可以在fullWord上执行for循环,检查位置i处的每个字母,然后使用.substr()重置guessedWord属性。 This method returns partial strings based on what parameters you pass it. 此方法根据传递的参数返回部分字符串。 Essentially I set guessedWord to + + . 基本上,我将guessword设置为++。 This was the checkLet() function in the game object. 这是游戏对象中的checkLet()函数。

I would reccomend reading up on string methods at https://www.w3schools.com/js/js_string_methods.asp 我建议阅读https://www.w3schools.com/js/js_string_methods.asp上的字符串方法

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM