I'm trying to learn coding by building a simple text game. The end game is going to have 4 rooms. You'll start in room 1, exit west to room 2, exit south to room 3, and finally exit east in room 4. (clockwise).
Anyway, my starting code is from a YouTube tutorial I found that consists of all if / else if statements. I already see that's terribly inefficient. My question is how do I improve this code?
I'm guessing I should make each room and it's contents an object (ie. Room 1 has a sword in it, so the object would contain the location of the room and the sword). I'm also guessing if I have a monster in a room, he'd be his own object.
My problem is if the above is correct (object) - I don't understand how to use the object once I create it. ie. if the user types "take sword" how do I call the object to do that?
If I'm on the complete wrong track, please point me back in the right direction.
Here's the current code for the first room:
$("form").submit(function() {
var input = $("#commandLine").val();
function check() {
check = true;
}
if (input == "help") {
$("#messageHelp").clone().insertBefore("#placeholder").fadeIn(1000);
check();
}
if (input == "take sword" && currentRoom == "nCorridor") {
$("<p>You picked up a sword.</p>").hide().insertBefore("#placeholder").fadeIn(1000);
check();
}
else if (input == "take sword" && currentRoom != "nCorridor") {
$("<p>The sword is not here.</p>").hide().insertBefore("#placeholder").fadeIn(1000);
check();
}
else if (input != "take sword" && input != "help") {
$("<p>I don't understand " + input + ".</p>").hide().insertBefore("#placeholder").fadeIn(1000);
}
$("#commandLine").val("");
});
Ideally, I'd like to eliminate or greatly reduce my need to use if and else if statements for something more efficient.
First let's improve the logic in the if statements to reduce the duplicate conditions, to see how far that gets you:
if (input == "help") {
$("#messageHelp").clone().insertBefore("#placeholder").fadeIn(1000);
check();
} else if (input == "take sword") {
if (currentRoom == "nCorridor") {
$("<p>You picked up a sword.</p>").hide().insertBefore("#placeholder").fadeIn(1000);
check();
} else {
$("<p>The sword is not here.</p>").hide().insertBefore("#placeholder").fadeIn(1000);
check();
}
} else {
$("<p>I don't understand " + input + ".</p>").hide().insertBefore("#placeholder").fadeIn(1000);
}
Another way to determine the action depending on input is using a switch, which may be more useful when you get more options:
switch (input) {
case "help":
$("#messageHelp").clone().insertBefore("#placeholder").fadeIn(1000);
check();
break;
case "take sword":
if (currentRoom == "nCorridor") {
$("<p>You picked up a sword.</p>").hide().insertBefore("#placeholder").fadeIn(1000);
check();
} else {
$("<p>The sword is not here.</p>").hide().insertBefore("#placeholder").fadeIn(1000);
check();
}
break;
default:
$("<p>I don't understand " + input + ".</p>").hide().insertBefore("#placeholder").fadeIn(1000);
}
To go on and using objects for keeping track of items, you could create an object for the sword (with just the location for now):
var sword = {
room: "nCorridor"
};
In the code you could use the object like this:
if (currentRoom == sword.room) {
$("<p>You picked up a sword.</p>").hide().insertBefore("#placeholder").fadeIn(1000);
check();
} else {
$("<p>The sword is not here.</p>").hide().insertBefore("#placeholder").fadeIn(1000);
check();
}
From there you can add more properties and methods to items. The objects might for example have methods that you can use to determine what you can do with them, like that the item apple can be eaten, but the item sword can not.
Related
I have this little Pacman game made in JavaScript
Whats is happening is when i call a random item from the array this is what the game return:
Video here
The game show all the items from the array, before display only one of then...
A part of the code
if (gameOver || gameWin) {
//display this array if game win
text = textOptionsWin[Math.floor(Math.random() * textOptionsWin.length)];;
if (gameOver) {
//display this array if game over
text = textOptions[Math.floor(Math.random() * textOptions.length)];;
//go back to the first level if lost
setTimeout(function () {
if (tileMap.fase == 1) {
location.href = "/?fase=1";
// text = "O COVID-19 TE PEGOU! 😷";
} else if (tileMap.fase == 2) {
location.href = "/?fase=1";
} else if (tileMap.fase == 3) {
location.href = "/?fase=1";
}
}, 2500);
//Delay to change the level
}
}
I'm missing something to this happen? any tip can be useful
I don't fully understand, but I think this is the answer:
var a = ["end1", "end2", "end3"]
console.log(a[Math.floor(Math.random() * 3)])
This prints a random item in the array 'a' to console.
I am programing a simple blackjack game but my function to "stand" will only print "you win" for all conditions met.
function stand(){
if(gethandvalue(playerhand) < dealerhand ){
document.getElementById("game-status").innerHTML = "you lose";
}
if(gethandvalue(playerhand) === dealerhand){
document.getElementById("game-status").innerHTML =" its a tie";
}
else(gethandvalue(playerhand) > dealerhand)
document.getElementById("game-status").innerHTML ="you win!";
youwinsound.play();
}
When the dealer's hand gets higher than the player's hand the code still prints out "you win".
It looks like the ifs are a bit muddled. If the first two cases have been eliminated, then the third case is what is left, so you don't need to actually test for it.
If you put the message into a variable, it keeps things tidy for when you set the text: e.g. if you changed the id of the element showing the message, you'd only have to change it in one place.
I assume that playerhand and dealerhand are two instances of some hand entity, so to get the value you just need to call the same function for each.
Variable names can be used to help show what is being done, something like this:
function stand() {
var gameStatusMessage;
var playerHandValue = gethandvalue(playerhand);
var dealerHandValue = gethandvalue(dealerhand);
if (playerHandValue < dealerHandValue) {
gameStatusMessage = "you lose";
}
else if (playerHandValue === dealerHandValue) {
gameStatusMessage = "it's a tie";
}
else { /* last case: playerHandValue > dealerHandValue) */
gameStatusMessage = "you win!";
youwinsound.play();
}
document.getElementById("game-status").innerHTML = gameStatusMessage;
}
I am trying to create a JavaScript Quiz.
The function will check the user's input value.
If it is correct; it will change the question.
Exact Code See JSFiddle
There are probably many more efficient and conventional ways to achieve what I am trying to do. Current issue is the function runs from the top every time it runs(obviously)
function checkAnswer() {
var question = document.getElementById("ques").innerHTML;
var userAnswer = document.getElementById("answer").value;
if (userAnswer === "New York City") {
alert("correct!");
question = "What is the best college football team?";
if (userAnswer === "Alabama") {
alert("Correct!");
question = "Next question will go here and so on..."
}
}
}
In no way would I suggest doing things this way, but here's how to get your jsfiddle to work:
function check() {
var question = document.getElementById('question').innerHTML
var userAnswer = document.getElementById("answer").value;
//Makes answer lowercase
userAnswer = userAnswer.toLowerCase();
//question one
if (question === "Write One, Two, Three..") {
if (userAnswer === "one two three") {
alert('correct');
}
else {
alert('Sorry Wrong!');
}
//question two
document.getElementById('question').innerHTML = "Write 4, 5, 6";
}
else {
if (userAnswer === "4 5 6") {
alert("correct!");
}
else {
alert('Sorry Wrong!');
}
}
}
One simple way to do what you want is to put your questions in an array:
var QandA = [
["question1...", "answer1...."],
["question2...", "answer2...."],
["question3...", "answer3...."],
["question4...", "answer4...."]
];
function check()
{
// No more questions?
if (0 === QandA.length) return;
// Check answer
var userAnswer = document.getElementById("answer").value.toLowerCase();
if (userAnswer === QandA[0][1]) {
alert("Correct");
}
else {
alert("Incorrect");
}
// Delete that question
QandA.shift();
// And move to next
if (0 != QandA.length) {
document.getElementById('question').innerHTML = QandA[0][0];
}
}
If you have a number of questions that you need validating I would take the following approach. It allows you as many questions as you like without repeating code.
First, store your questions in an array:
var arr = ["one two three", "4 5 6"];
Set a counter to zero, and a total (to measure the user performance):
var count = 0;
var total = 0;
Cache the elements:
var questionEl = document.getElementById('question');
var userAnswerEl = document.getElementById("answer");
Separate out the code that writes the question into a new function. It writes the question based on the counter:
function writeQuestion() {
if (count < arr.length) {
questionEl.innerHTML = "Write " + arr[count];
} else {
alert('No more questions. You have scored ' + total);
}
}
function check() {
userAnswer = userAnswerEl.value.toLowerCase();
if (userAnswer === arr[count]) {
alert('correct');
count++;
total++;
writeQuestion();
} else {
alert('Sorry Wrong!');
count++;
writeQuestion();
}
}
DEMO
if (userAnswer === "New York City") {
alert("correct!");
question = "What is the best college football team?";
if (userAnswer === "Alabama") {
alert("Correct!");
question = "Next question will go here and so on..."
}
}
This block only runs if userAnswer is "New York City", but inside it, you test whether userAnswer is "Alabama" - that will never be true. You probably want to move the second if outside of the first if block.
You seem to be assigning to question but not using the value. If you think you are updating the question text by assigning a value to question that isn't going to work. I think you are trying to do this:
question = document.getElementById("ques");
// later on...
question.innerHTML = "this is another question";
// even later...
question.innerHTML = "and here is a new question";
That would update the page for you because question would point to a DOM node and you can set .innerHTML on that, but the way you wrote it, you're setting question to a string value initially, and then other string values later, but not using any of them in anyway.
i'd like to use the return value of a specific function as the condition of an if statement. Is that possible ?
I'm basically building a string inside a function that takes an array (the conditionArray) and concatenates it to a statement.
Then it returns this condition as a string.
After that, i wanted to use this string as the condition of my if-statement.
My current problem looks something like that.
var answer = prompt("Tell me the name of a typical domestic animal");
var conditionArray = new Array("Dog", "Turtle", "Cat", "Mouse")
function getCondition(conditionArray) {
for (i = 0; i < conditionArray.length; i++) {
if (i != conditionArray.length) {
condition += 'answer === ' + conditionArray[i] + ' || ';
} else {
condition += 'answer === ' + conditionArray[i];
}
return condition;
}
}
if (getCondition(conditionArray)) {
alert("That is correct !");
} else {
alert("That is not a domestic animal !");
}
For this type of test use Array.prototype.indexOf, x = arr.indexOf(item)
x === -1 means item is not in arr
Otherwise x is the index of arr that the first occurrence of item is located
var options = ["Dog", "Turtle", "Cat", "Mouse"],
answer = prompt("Tell me the name of a typical domestic animal");
// some transformation of `answer` here, i.e. casing etc
if (options.indexOf(answer) !== -1) {
alert("That is correct !");
} else {
alert("That is not a domestic animal !");
}
The best way to do this kind of test is to use Array.prototype.indexOf. See Paul's answer for more details on how to use it.
--
If you really really want to return a condition, you can use eval() to evaluate the condition string. Keep in mind that eval() is dangerous though. It's usage isn't recommended. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval#Don%27t_use_eval_needlessly!
if (eval(getCondition(conditionArray))) {
alert("That is correct !");
} else {
alert("That is not a domestic animal !");
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I have question about else if
in my case last else not working
var pakeEach = $(".Thide").each(function () {
var cat = $(this).val();
if (cat.indexOf(PCatId) == -1) {
console.log("Pilih tidak ada di your aksess")
} else {
if (cat.indexOf(PCatId) != -1) {
console.log("Show only " + cat);
} else {
console.log("Remove");//why not working last else
}
}
});
Starting with your logic:
if (value == -1) {
...
} else {
if (value != -1) {
...
} else {
...
}
}
you can simplify it to:
if (value == -1) {
...
} else if (value != -1) {
...
} else {
...
}
As you can see, you're saying "if value is -1 then ..., otherwise if value is not -1..." That covers both possible circumstances: value cannot be anything but -1 or not -1 (as discussed by A. Wolff in the comments).
The else can never be hit, since all possible branches have already been covered.
If you want to include the remove logic in one of the other branches (probably the branch where the item was found), you should use something like:
if (value === -1) {
console.log("Pilih tidak ada di your aksess")
} else {
console.log("Show only " + cat);
console.log("Remove!");
}
This is a much more concise way of writing the same thing. Note that the === operator is generally preferred over ==, especially when you know you'll be comparing objects of the same type.
Because you are calling indexOf, the only possible result is the item is in the collection (indexOf(foo) > -1) or not in the collection (indexOf(foo) === -1). There is no third option here, unless you care about where in the collection it is.
For example, to remove the item if it is not the first item present in the collection, you would use:
if (value === -1) {
console.log("Pilih tidak ada di your aksess")
} else if (value === 0) {
console.log("Show only " + cat);
} else {
console.log("Remove!");
}
Because the if conditions only match a small subset of the possible values, the else can actually be hit in this case.
Algorithmically you are saying
if cat.indexOf(PCatId) is equal to -1 then execute the first if block
else execute the second block which is logically treating the case where cat.indexOf(PCatId) is different then -1.
I mean in the first else you can never ever get cat.indexOf(PCatId) == -1 because you are catching it in the first if
here is your answer with some modifications and comments :
var pakeEach = $(".Thide").each(function () {
var cat = $(this).val();
if (cat.indexOf(PCatId) == -1) {
// this part of code is executed if cat.indexOf(PCatId) == -1
console.log("Pilih tidak ada di your aksess")
} else {
// here at this level we can never get cat.indexOf(PCatId) == 1
if (cat.indexOf(PCatId) != -1) {
console.log("Show only " + cat);
}
// this else should be removed !!!! because it is useless
else {
console.log("Remove");//why not working last else
}
}
});
Try this:
var pakeEach = $(".Thide").each(function () {
var cat = $(this).val();
if (cat.indexOf(PCatId) == -1)
{
console.log("Pilih tidak ada di your aksess");
console.log("Remove");
}
else
{
console.log("Show only " + cat);
}
});
What you are trying to do is this:
var pakeEach = $(".Thide").each(function () {
var cat = $(this).val();
if (!cat) {
console.log("Pilih tidak ada di your aksess")
} else if (cat === PCatID) {
console.log("Show only " + cat);
} else {
console.log("Remove");
}
});
First check if cat is empty, then branch according to its value.