console.info("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.info("End file 1 ======================================== = ");
console.info("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.info(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.info("End file 2 ======================================== = ");
console.info("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.info("Word: " + currentWord);
};
pickCountry();
// Delete this after
console.info("1: " + countryPicker);
console.info("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.info(mainGame.splitWord[i].letter);
}
});
Я построил игру с палачом, используя функции-конструкторы. Я настроил его так, чтобы при выборе случайного слова каждая буква отображалась как подчеркивание. Я воспользовался пакетом Inquirer, чтобы попросить письмо. Когда первая буква угадана правильно, она успешно заменяет подчеркивание буквой в массиве liveWord. Проблема в том, что работает только для одной буквы. Мне нужно заставить его работать, пока не будет угадано полное слово. К вашему сведению, файлы 1 и 2 приведены только для справки, моя проблема только в файле 3. Не нужно смотреть на первый 2. Есть какие-нибудь советы?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Я не буду помогать Вам с кодом в Вашем вопросе, раздражает отлаживать, переписывать чей-то код (особенно длинный).
Но приведу пример:
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>В вашем коде есть несколько проблем:
В методе letterTest вы устанавливаете свойство letter на подчеркивание, когда предположение отличается от буквы. Это неправильно, потому что тогда вы больше никогда не узнаете, какая буква правильная. Удали это. Достаточно иметь правильное значение для свойства guess.
В методе stringRep вы ссылаетесь на переменную eachLetter в цикле, которая не имеет там никакого отношения. Вместо этого вы должны использовать this.splitWord[i].
Нет цикла, который позволяет пользователю сделать второе предположение, поэтому это нормально, он работает только один раз. Должен быть цикл, который уменьшает значение вашей переменной remainingGuesses, которую вы до сих пор не использовали.
Вы не должны отображать splitWord. Это связано с пунктом 1. Вместо этого вы должны отобразить stringRep(), который учитывает, угадывалась ли уже буква на основе свойства guessed. И это именно то, что вам нужно вывести.
Отсутствует логика, определяющая, было ли слово найдено полностью. В этом случае сообщение будет уместным, и цикл угадывания (который не был реализован) должен быть прерван.
Чтобы облегчить зацикливание, я бы предложил использовать синтаксис 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.info("Word: " + currentWord);
}
pickCountry();
// Delete this after
console.info("1: " + countryPicker);
console.info("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.info(output);
// Detect that the word has been found, and exit if so
if (!output.includes("_")) {
console.info("You found it!");
return;
}
}
// The maximum number of guesses was not enough to find the word
console.info('What a pity. You ran out of guesses.');
})();Letter:
<input name = "game">
<button>Guess</button>Спасибо за помощь!
Я написал функции конструктора, следуя инструкциям для HW. Единственная проблема, с которой я столкнулся, - это последний фрагмент кода в файле 3.prompt, поэтому изменение первых двух не было вариантом.
Ваше решение выглядит красиво :)