Как я могу заменить элемент массива несколько раз? - PullRequest
0 голосов
/ 18 ноября 2018
console.log("Start file 1 =========================================");
function Letter (letter) {

    this.letter = letter;
    this.guess = false;
    this.answer = function () {
        if (!this.guess) {
            return "_";
        }
        else if (this.guess === true) {
            return this.letter;
        }
    }
    this.letterTest = function (guessed) {
        if (guessed === this.letter) {
            this.guess = true;
            // this.letter = guessed;
        } else {
            this.letter = "_";
        }
    }
};

module.exports = Letter;
console.log("End file 1 =========================================");


console.log("Start file 2 =========================================");
var Letter = require("./letter.js");

function Word (word) { 

    this.splitWord = [];
    for (var i = 0; i < word.length; i++) { 
        var eachLetter = new Letter (word[i]);
        this.splitWord.push(eachLetter);
    }

    this.stringRep = function () {
        var testedWord = [];
        for (var i = 0; i < this.splitWord.length; i++) {
            testedWord.push(eachLetter.answer());
        }

        testedWord = testedWord.join(" ");

        // console.log(testedWord);
        return testedWord;

};

    this.eachGuess = function (input) {
        for (var i = 0; i < this.splitWord.length; i++) {

            this.splitWord[i].letterTest(input);
        }
        }    
}

module.exports = Word;
console.log("End file 2 =========================================");


console.log("Start file 3 =========================================");
var Word = require("./word.js");
var inquirer = require('inquirer');

var remainingGuesses = 10;
var mainGame;
var currentWord;
var liveWord = [];
completeWord = null;
let countryPicker;
let testedWord;

var europe = ["Albania", "Austria", "Belgium", "Bulgaria", "Croatia", "Cyprus", "Denmark", "England", "France", "Greece", "Germany",
"Hungary", "Iceland", "Italy", "Lithuania", "Monaco", "Norway", "Poland", "Portugal", "Romania", "Serbia", "Slovakia", "Spain", "Sweden",
"Switzerland", "Ukraine"];

// Function that picks a random country
function pickCountry () {
    countryPicker = europe[Math.floor((Math.random() * europe.length) + 1)];
    var mainGame2 = new Word (countryPicker);
    mainGame = mainGame2;
    // Display word

    currentWord = mainGame.stringRep();
    currentWord = JSON.stringify(currentWord);
    console.log("Word: " + currentWord);
};

pickCountry();
// Delete this after
console.log("1: " + countryPicker);
console.log("2: " + currentWord);

inquirer.prompt([
    {
        type: "input",
        name: "game",
        message: "Guess a letter!"
    }
]).then(function(inquirerResponse) {
        liveWord = mainGame.splitWord;
        mainGame.eachGuess(inquirerResponse.game);

    for (let i = 0; i < liveWord.length; i++) {

        console.log(mainGame.splitWord[i].letter);

    }
});

Я создал игру палача, используя функции конструктора. Я настроил его так, что при выборе случайного слова каждая буква будет отображаться в виде подчеркивания.
Я использовал пакет Inquirer, чтобы попросить письмо. Когда первая буква угадана правильно, она успешно заменяет подчеркивание буквой в массиве liveWord. Проблема в том, что это работает только для одной буквы. Я должен заставить это работать, пока полное слово не будет угадано. К сведению, файлы 1 и 2 предназначены только для справки, моя проблема только в файле 3. Не нужно смотреть на первые 2. Любые советы?

Ответы [ 2 ]

0 голосов
/ 19 ноября 2018

В вашем коде есть несколько проблем:

  1. В методе letterTest вы устанавливаете свойство letter, чтобы подчеркнуть, когда предположение отличается от буквы. Это неправильно, потому что тогда вы никогда не узнаете, что такое правильное письмо. Удали это. Достаточно иметь правильное значение для свойства guess

  2. В методе stringRep вы ссылаетесь на переменную eachLetter в цикле, которая не имеет к этому никакого отношения. Вместо этого вы должны использовать this.splitWord[i].

  3. Нет цикла, позволяющего пользователю сделать второе предположение, поэтому нормально, что он работает только один раз. Должен быть цикл, который уменьшает значение вашей переменной remainingGuesses, которое вы до сих пор не использовали.

  4. Вы не должны отображать splitWord. Это относится к пункту 1. Вместо этого вы должны отобразить stringRep(), который учитывает, была ли буква уже угадана на основе свойства guessed. И это именно то, что вам нужно вывести.

  5. Отсутствует логика, которая определяет, было ли слово найдено полностью. В этом случае сообщение будет уместным, и цикл угадывания (который не был реализован) должен быть прерван.

Чтобы упростить зацикливание, я бы предложил использовать синтаксис async/await для работы с обещанием, возвращаемым inquirer.

Вот ваш код с исправленными выше перечисленными пунктами. Чтобы сделать его работоспособным в этом виджете сниппета, я не разбил его на модули, как вы, и не включил inquirer (я добавил упрощенную замену для него встроенным).

Я также не пытался сделать много других улучшений, чтобы вы все еще могли распознать свою собственную работу. Все изменения прокомментированы:

function Letter (letter) {
    this.letter = letter;
    this.guess = false;
    this.answer = function () {
        if (!this.guess) {
            return "_";
        }
        else { // No need to check whether this.guess is true here. It is the logical consequence...
            return this.letter;
        }
    }
    this.letterTest = function (guessed) {
        if (guessed === this.letter) {
            this.guess = true;
        }
        // Don't change this.letter, as you will forever forget what the correct letter is!
        // (code was deleted from here)
    }
}

function Word (word) { 
    this.splitWord = [];
    for (var i = 0; i < word.length; i++) { 
        var eachLetter = new Letter (word[i]);
        this.splitWord.push(eachLetter);
    }
    this.stringRep = function () {
        var testedWord = [];
        for (var i = 0; i < this.splitWord.length; i++) {
            // Don't push eachLetter, but use the i-variable as index! 
            testedWord.push(this.splitWord[i].answer());
        }
        testedWord = testedWord.join(" ");
        return testedWord;
    }

    this.eachGuess = function (input) {
        for (var i = 0; i < this.splitWord.length; i++) {
            this.splitWord[i].letterTest(input);
        }
    }    
}

// Simplified implementation of inquirer for this snippet only:
var inquirer = {
    prompt([{type, name, message}]) {
        return new Promise((resolve) => {
            const input = document.querySelector(`[name=${name}]`);
            input.value = "";
            input.placeholder = message;
            input.onchange = e => resolve({ [name]: input.value });
        });
    }
}

var remainingGuesses = 10;
var mainGame;
var currentWord;
var liveWord = [];
completeWord = null;
let countryPicker;
let testedWord;

var europe = ["Albania", "Austria", "Belgium", "Bulgaria", "Croatia", "Cyprus", "Denmark", "England", "France", "Greece", "Germany",
"Hungary", "Iceland", "Italy", "Lithuania", "Monaco", "Norway", "Poland", "Portugal", "Romania", "Serbia", "Slovakia", "Spain", "Sweden",
"Switzerland", "Ukraine"];

function pickCountry () {
    countryPicker = europe[Math.floor((Math.random() * europe.length) + 1)];
    var mainGame2 = new Word (countryPicker);
    mainGame = mainGame2;
    currentWord = mainGame.stringRep();
    currentWord = JSON.stringify(currentWord);
    console.log("Word: " + currentWord);
}

pickCountry();
// Delete this after
console.log("1: " + countryPicker);
console.log("2: " + currentWord);

(async function () { // Use an async function to allow the use of AWAIT
    while (remainingGuesses--) { // You need a loop to repeat guess/response cycle
        // Use AWAIT -- simpler to use than THEN
        const inquirerResponse = await inquirer.prompt([{
            type: "input",
            name: "game",
            message: "Guess a letter!"
        }]);
        const liveWord = mainGame.splitWord;
        mainGame.eachGuess(inquirerResponse.game);
        // Don't display splitWord here, but stringRep:
        const output = mainGame.stringRep();
        console.log(output);
        // Detect that the word has been found, and exit if so
        if (!output.includes("_")) {
            console.log("You found it!");
            return;
        }
    }
    // The maximum number of guesses was not enough to find the word
    console.log('What a pity. You ran out of guesses.');
})();
Letter: 
<input name="game">
<button>Guess</button>
0 голосов
/ 19 ноября 2018

Я не помогу вам с кодом в вашем вопросе, это раздражает отладку, перепишите чей-то код (особенно если он длинный).

Но я приведу вам пример:

const words = [
  'Azerbaijan', 'America', 'blablabla', 'Argentina', 'lambada', 'Australia', 'schmetterling', 'krankenwagen', 'kugelschreiber'
];

let word, result, charIndexes;

const start = () => {
  word = words[parseInt(Math.random()*words.length)];
  charIndexes = {};
  result = new Array(word.length+1).join('_');

  word.split('').forEach((char, i) => {
    char = char.toLowerCase();
    if (!charIndexes[char]) charIndexes[char] = []
    charIndexes[char].push(i);
  });
  
  info.innerHTML = '';
  output.innerHTML = result;
  input.focus();
};

const checkChar = (char) => {
  result = result.split('');
  if (charIndexes[char]) {
    const indexes = charIndexes[char];
    indexes.forEach(i => {
      result[i] = word.charAt(i);
    });
    delete charIndexes[char];
  }
  result = result.join('');
  output.innerHTML = result;
  if (Object.keys(charIndexes).length === 0) {
    info.innerHTML = 'Congratulations!';
  }
};

const input = document.getElementById('letter');
const output = document.getElementById('word');
const info = document.getElementById('info');

input.onkeyup = (e) => {
  const char = e.key.toLowerCase();
  input.value = '';
  checkChar(char);
};

start();
<input type="text" id="letter" value=""> 
<button onclick="start()">reset</button>
<br/><br/>
<div id="word"></div>
<div id="info"></div>
...