如何检查一个单词是否由不同数组中的字母组成

3
我正在使用Vue编写一个单词游戏。
游戏从一串随机字符开始,用户需要输入可以由这些字符组成的单词。例如,对于“ABEOHSTD”,用户可以输入“BASE”,得到4分。
我有一个外部的单词列表,保存在一个.txt文件中(但我也无法让它正常工作,这是另一个问题),我需要根据这个列表来验证单词是否正确,但我遇到了验证单词是否由给定的随机字符串组成的困难。
我不知道如何确保每个字母只能使用与其在数组中出现次数相同的次数,甚至不知道如何存储分数,但我只想先让这个第一部分能够正常工作。
我已经尝试将输入的单词和随机字符串都分割为各个字符的数组,然后循环遍历数组,检查用户输入的字符串中的每个字符是否包含在随机字符串的数组中。
      splitUserCurrentWord = this.userAttemptedWord.split("");
      for (var i = 0; i <= splitUserCurrentWord.length; i++) {
        if (this.randomStringForGame.split("").includes(splitUserCurrentWord[i])) {
          return true;
          //i++
        }
        else {
          return false;
        }
      }
    }

当前我希望如果用户输入的单词中所有字母都出现在随机字符串数组中,结果应该为true。但是实际上它似乎仅根据数组的第一个字母来判断是否为true或false,这并不好,因为只要随机字符串数组中的第一个字母存在,它就会被认为是true/correct。

到目前为止的整个jsfiddle代码如下: https://jsfiddle.net/sk4f9d8w/


return语句将在第一次运行时退出for循环。return true需要放在它的外面。您可以尽快返回false,并假设整个过程都是true。 - Flink
3个回答

1

你的return语句在第一次迭代后退出了循环。

一种方法是使用Array.every验证所有字母,并使用String.includes检查字母是否是接受的字符串的一部分。

const randomString = "ABEOHSTD";

console.log(isWordValid(randomString, "BASE"));
console.log(isWordValid(randomString, "BASEU"));

function isWordValid(validLetters, attemtedWord) {
  const attemptedWordSplitted = attemtedWord.split("");
  return attemptedWordSplitted.every(attemptedLetter => validLetters.includes(attemptedLetter));
}

如果您不允许多次重复使用同一个字母,您需要采用另一种方法,即从可接受字母列表中删除已使用的字母。

const randomString = "ABEOHSTD";

console.log(isWordValid(randomString, "BASE"));
console.log(isWordValid(randomString, "BAASE"));
console.log(isWordValid(randomString, "BASEU"));

function isWordValid(validLetters, attemptedWord) {
  const validLettersSplitted = validLetters.split("");
  const attemptedWordSplitted = attemptedWord.split("");
  return attemptedWordSplitted.every(attemptedLetter => {
    const letterIndex = validLettersSplitted.indexOf(attemptedLetter);
    if(letterIndex > -1){
      validLettersSplitted.splice(letterIndex, 1);
      return true;
    } else {
      return false
    }
  });
}


1
你走在正确的道路上,需要检查用户输入的每个字母并检查它们是否在随机生成的单词中。如果一个字母在随机单词中,你需要从随机单词中删除它,这样它就不能再次使用。

let randomWord = "ABEOHSTD";
let userWordThatFail = "BAASE";
let userWord = "BASE";

// optionnaly, uppercase both words.

// we split into letters to make it easiers to process
let randomLetters = randomWord.split('');
let userLetters = userWord.split('');

let score = 0;

//we parse each letter of the user input
userLetters.forEach((letter) => {
  // the letter exists in the random word.
  let indexOfTheCurrentLetter = randomLetters.indexOf(letter);
  // the letter exists, we remove it and increment the score.
  if(indexOfTheCurrentLetter !== -1) {
    randomLetters.splice(indexOfTheCurrentLetter, 1);
    score++;
  }
});

// the user input contains letters that are not in the random input.
if(score < userLetters.length) {
  console.log('fail');
} else {
  console.log('win : ' + score);
}


这对我有用,但是我遇到了一个问题,就是无法在控制台记录函数的布尔返回值。更新后的jsfiddle:https://jsfiddle.net/ztxgu9Lj/1/第40和61行没有记录任何内容,所以我无法看到为什么第16行的条件语句没有执行。 - DipoOgunmodede
1
在这两种情况下,console.log 被执行之前就已经返回了。 - Nicolas
啊,好的,听起来我可能并没有根本理解return和/或console.log()的工作原理,我需要更深入地了解它。 - DipoOgunmodede
1
基本上,return指令是您的函数将要执行的最后一条指令。在此之后您不能再有任何内容。请注意,同一个函数中可以有多个返回值。 - Nicolas
我现在已经将它更改为:https://jsfiddle.net/ea5jx9g1/我注意到我无法控制台输出 wordHasValidCharacters(),但我可以 console.log 返回 true 或 false 的实际函数,即第 48 行的 isWordValid。 - DipoOgunmodede

1
一个简单的方法是对于测试字符串中遇到的每个字符,迭代有效字符列表。使用 string.includes 会落入这个范畴。问题在于每次比较的时间复杂度为 O(n_validchars * n_testchars)。对于更长的字符串可能不理想。
JavaScript 的 Set 对象可以在这里提供帮助。
利用这个高阶函数(它严重依赖于字符串的 iterable 特性),你可以为一组有效字符生成可重用的函数:

function testFor(validChars) {
  const charSet = new Set(validChars);
  return testString =>
    Array.prototype.every.call(testString, c => charSet.has(c));
}

// And to use it:

const testForABC = testFor("ABC"); //returns a function

console.log(testForABC("AABBCC")); //true
console.log(testForABC("abc")); //false

现在,由于Set的查找是O(1)的,我们只需要考虑长度为n的字符串,时间复杂度为O(n)。这要好得多。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接