My number of guesses wont stop at correct level - javascript

I am currently making a minefield game using JavaScript only. I have a problem at the end of the game. I have three difficulty levels so easy gives the user 45 guesses, intermediate 40 guesses and advanced is 35 guesses. However, for some reason when I have it set on intermediate/advanced it keeps going to 45 guesses instead of where it should stop.
After ive spent ages looking at it and changing different things such as the names of the variables and editing code. The guesses were working correctly so each guess actually counted as 1 guess now they are counting as 3. The code is now stopping at 35.
var number_of_guesses = 0;
var maximum_guesses = 45;
var intermediate_guesses = 40;
var advanced_guesses = 35;
var number_of_hits = 0;
var number_of_misses = 0;
var element = opener.document.getElementById("easy");
if (element.checked === true)
{
maximum_guesses = 45;
}
var intermediate = opener.document.getElementById("intermediate");
if (element.checked === true)
{
intermediate_guesses = 40;
}
var advanced = opener.document.getElementById("advanced");
if (element.checked === true)
{
advanced_guesses = 35;
}
number_of_guesses++;
if (number_of_guesses > maximum_guesses)
{
window.alert("Sorry, you have run out of guesses!");
return;
}
number_of_guesses++;
if (number_of_guesses > intermediate_guesses)
{
window.alert("Sorry, you have run out of guesses!");
return;
}
number_of_guesses++;
if (number_of_guesses > intermediate_guesses)
{
window.alert("Sorry, you have run out of guesses!");
return;
}
Can someone please tell me:
a) How to make each guess count as 1 instead of 3?
b) How to set each difficulty correctly?

Try having all three options set the maximum_guesses variable, rather than having three different variables for the different difficulties. Then just check that one variable.
var number_of_guesses = 0;
var maximum_guesses = 45;
var number_of_hits = 0;
var number_of_misses = 0;
// notice the missing intermediate_guesses and advanced_guesses vars
var element = opener.document.getElementById("easy");
if (element.checked)
{
maximum_guesses = 45;
}
var intermediate = opener.document.getElementById("intermediate");
if (intermediate.checked)
{
maximum_guesses = 40; // changed this to maximum_guesses
}
var advanced = opener.document.getElementById("advanced");
if (advanced.checked)
{
maximum_guesses = 35; // changed this to maximum_guesses
}
number_of_guesses++; // you only need this once
if (number_of_guesses > maximum_guesses)
{
window.alert("Sorry, you have run out of guesses!");
return;
}
EDIT: You also had a typo in that when you were checking wether or not the intermediate and advanced checkboxes were checked, you were still checking the easy element.
EDIT 2: Also, in your code, you were calling number_of_guesses++; three times, which was why each guess was counting 3 times. For them to only count as one, you only needed the first one. Each time you check, the number will stay the same, so you don't need to increment it three times.
EDIT 3: In my code, notice how I removed the === false parts in your if statements where you checked wether or not the checkboxes were checked.

Related

How to get randomly generated array to reset in simple memory game with jQuery

I'm sorry if this has been asked before,
I've searched through Stackoverflow but couldn't find anything that answered my problem.
I'm building a simple memory game, an online version of Simon, when you click the "Start" button it runs the code below to create a random array (of length 4) out of the four colour buttons.
But when you click "Start" again for the next round it doesn't clear the array, and instead creates a second one, and then checks your input against both telling you you're both right and wrong, or right and right (depending on the random array created out of the buttons).
I've tried buttonsToClick = [] in the else section, but it doesn't reset.
I don't know what I'm missing, I've only been learning JavaScript/jQuery for about a month but I wanted to test my knowledge.
The code snipped:
var score = 0;
$("#score").html(`${score}`);
$("#button5").on("click", function() {
var buttons = document.getElementsByClassName("js-button");
var buttonsToClick = chooseRandomButtons(buttons);
currentButtons = buttonsToClick;
flashButtons(buttonsToClick, 0);
var currentOrder = 0;
$(".js-button").on("click", function() {
var selectedButton = $(this)[0];
var button = currentButtons[0];
if (selectedButton === button) {
currentButtons.splice(button,1);
/*alert("Correct");*/
score += 1;
$("#score").html(`${score}`);
} else {
currentButtons = buttonsToClick;
alert("Wrong. Click 'Start' to try again");
score = 0;
$("#score").html(`${score}`);
}
});
})
function chooseRandomButtons(buttons) {
var buttonsToClick = [];
var maxRandomNumber = buttons.length - 1;
for (var i = 0; i < 4; i++) {
buttonsToClick.push(buttons[randomIntFromInterval(0, maxRandomNumber)]);
}
return buttonsToClick;
}
function randomIntFromInterval(min, max) { // min and max included
return Math.floor(Math.random() * (max - min + 1) + min);
}
function flashButtons(buttonsToClick, index) {
setTimeout(function() {
$(buttonsToClick[index]).fadeOut(500).fadeIn(500);
if (index === buttonsToClick.length - 1) {
return;
}
flashButtons(buttonsToClick, index = index + 1);
}, 1000);
}
welcome to SO.
In general you're doing anything correct with your arrays.
The issue is your event handler.
Every time you click the #button5, which I guess is the start button, you register on all your .js-button a new listener. Since you're not unbinding the old event listeners they're still active.
Since the old event listeners have a reference to your old array, you're basically checking the button against the old game and the new game.
Your solution would be to unregister the old one before registering the new one.
This could be done for example by the .off method.
Your code should then look like this:
var currentOrder = 0;
$(".js-button").off("click").on("click", function() {
var selectedButton = $(this)[0];
var button = currentButtons[0];
if (selectedButton === button) {
currentButtons.splice(button,1);
/*alert("Correct");*/
score += 1;
$("#score").html(`${score}`);
} else {
currentButtons = buttonsToClick;
alert("Wrong. Click 'Start' to try again");
score = 0;
$("#score").html(`${score}`);
}
});
Notice the .off() there.
The documentation about the method could be found here: https://api.jquery.com/off/

faild to move the element in between?

i have been try to solve the sudoku with Blacktracking algo, everything is good, canvar is called and i able to see the number but the things is number are not moving i.e the logic is not exectuing
current.i === 0; is where i'm get the error! even i have declared a sperate variable for the num also the problem is not sloved. only if i remove the .num current == 0 than its not showing any error but still the number is not moving
enter image description here
var cell = [];
var stack = [];
var sudoku = [2,3,0,9,4,0,6,7,0,
8,0,0,3,2,5,9,1,4,
9,0,0,7,6,0,3,2,0,
1,0,0,0,0,0,7,9,2,
5,0,3,2,1,0,4,8,6,
4,0,0,6,8,0,5,3,1,
7,0,0,1,0,0,0,0,9,
6,5,9,8,7,2,1,4,3,
3,0,0,0,9,0,0,0,7];
var current;
var number = 1;
function setup(){
createCanvas(450,450);
var a=0;
var b=0;
for(var i=0;i<81;i++){
if(a%9==0 && i!=0){
b = b+50;
a = 0;
}
each[i] = new each(a,b,i,sudoku[i]);
a = a+50;
}
current = cell[0];
}
function draw(){
background(10);
for(var i=0;i<81;i++){
each[i].show();
}
if(current.num === 0){ //the error is typeerror can't read the property of num
if(! sameColumn(current.i,number) && ! sameRow(current.i,number) && ! sameSquare(current.i,number) && number<(10)){
current.num = number;
stack.push(current);
number = 0;
current.each[current.i+1];
}
else {
if(number > 8){
current.num = 0;
current = stack.pop();
number = current.num;
current.num = 0;
}
}
}
else{
current = each[current+1];
number = 0;
}
number++;
}
function each(a,b,i,num){
this.a = a;
this.b = b;
this.i = i;
this.num = num;
this.show = function(){
noFill();
stroke(255);
rect(this.a,this.b,50,50);
textSize(32);
text(this.num,a+12,b+40);
}
}
The error is pretty much straight forward. current = cell[0]; becomes undefined since you defined cell as an empty array and didn't manipulated it after that.
From what I have observed so far, many parts of your code logically does not work, for example,
same Column(current.i,number) && ! sameRow(current.i,number) && ! sameSquare(current.i,number)
will definitely throw you an error is it is executed (it is not since the execution does not reach to that line), unless you have a separate js file that contains these functions.
Another one is
current = cell[current+1];
if the current variable is to store the cell object, it does not make sense to add 1 to it, and vice versa.
Now I believe this is how setup function was meant to look like:
function setup(){
createCanvas(450,450);
var a=0;
var b=0;
for(var i=0;i<81;i++){
if(a%9==0 && i!=0){
b = b+50;
a = 0;
}
cell[i] = new Cell(a,b,i,sudoku[i]); //changed each[i] to cell[i], also renamed the 'each' class
a = a+50;
}
current = cell[0];
}
If possible, please edit in a little more information about what exactly does your code do. Cheers :)

How do I get Javascript to remember a variable that is reset in my function, yet initially defined outside of my function?

I'm creating a game where the computer tries to guess the user's number based on user feedback like too high or too low. I'm using a binary search. The functions work properly, however, every time the buttons are pressed, the code resets to make the original list from 1 to 100 making the guess 50 instead of remembering the new list and guess defined inside my functions.
var list = new Array();
for (i = 0; i <= 100; i++) {
list.push(i)
}
//console.log(list)
// List is intially an empty array (list). The
// for loop generates integers from
// 0 to 100 and pushes them into the array.
var guess = list[Math.floor((list.length / 2))];
console.log(guess);
var toolow = function(guess) {
while (list.includes(guess) == true) {
list.shift()
};
var guess = list[Math.floor((list.length / 2) - 1)];
console.log(list);
console.log(guess)
}
// toolow(guess)
var toohigh = function(guess) {
var last = parseInt(list.length);
while (list.includes(guess) == true) {
list.pop()
};
var guess = list[Math.round(list.length / 2)];
console.log(list);
console.log(guess)
}
// toohigh(guess)
<h1> Guess Your Number </h1>
<button id="TooLow" onclick="toolow(guess);"> Too Low</button>
<button id="TooHigh" onclick="toohigh(guess);">Too High</button>
your over use of the variable guess is causing all sorts of issues
no need to pass guess from onclick to the function
don't declare a var guess inside the functions
et voila - your code works now
var list = new Array();
for (i = 0; i <= 100; i++) {
list.push(i)
}
//console.log(list)
// List is intially an empty array (list). The
// for loop generates integers from
// 0 to 100 and pushes them into the array.
var guess = list[Math.floor((list.length / 2))];
console.log(guess);
var toolow = function() {
while (list.includes(guess) == true) {
list.shift()
};
guess = list[Math.floor((list.length / 2) - 1)];
console.log(list);
console.log(guess)
}
// toolow(guess)
var toohigh = function() {
var last = parseInt(list.length);
while (list.includes(guess) == true) {
list.pop()
};
guess = list[Math.round(list.length / 2)];
console.log(list);
console.log(guess)
}
// toohigh(guess)
<h1> Guess Your Number </h1>
<button id="TooLow" onclick="toolow();"> Too Low</button>
<button id="TooHigh" onclick="toohigh();">Too High</button>

this.functionName is not a function error

I am writing a simulation for bunny survival in a meadow and have to detect the minimal plant growth rate for the bunny to survive. I decided to go with OOP. Hence, tried to design my "classes" in js. I haven't done much OOP in JS, so I am stuck. I don't understand why I keep getting "this.checkElementExists" is not a function.
I tried to follow OOP that was shown in Mozilla MDN for JS and here I am stuck. I updated to ES6 classes.
class Meadow{
constructor(){
this.grid = this.makeGrid();
//console.log(this.grid);
}
makeGrid(){
let grid = new Array(30);
for(var i=0; i < 30; i++){
grid[i] = new Array(30).fill(null);
}
return grid;
}
checkElementExists(coordinates){
if(this.grid[coordinates[0]][coordinates[1]] != null){
return true;
}else{
return false;
}
}
growAPlant(timeRate){
if(timeRate == null){
clearInterval(this.growAPlant);
}
let plant = new Plant();
let coord = plant.generateCoordinateInMeadow();
//console.log(coord);
// add a plant to the 2d array, but check if the that spot is free
// otherwise use the generateCOordinate in the meadow function
//console.log(this.grid[coord[0]][coord[1]]);
//var that = this;
var ans = checkElementExists(coord).bind(this);
console.log(ans);
while(!checkElementExists(coord)){
coord = plant.generateCoordinateInMeadow();
}
//console.log(coord);
//console.log(this.grid[coord[0]] == undefined);
this.grid[coord[0]][coord[1]] = plant;
//console.log(this.grid);
}
}
class Simulation{
constructor(){
this.passRateArray = []; // this array will be used to plot the data
this.failureRateArray = []; // array that will hold failure growth rates
this.timeToEnergyData = []; // an example would be [{0: 1000, 1: 999, 2: 998, ....., 10000: 0}]
this.rateToEnergyTimeData = {};
this.timeCounter = 100; // 10000
this.growthTimeRate = 1000; // 1 second
this.gap = 0.05;
this.meadow = new Meadow();
this.bunny = new Bunny();
}
timeToEnergyDataPopulator(currTime, energy){
var relation = {currTime : energy};
this.timeToEnergyData.push(relation);
}
simulation(){
// HERE I MAKE A CALL TO MEADOW.GROWAPLANT
setInterval(this.meadow.growAPlant.bind(this.meadow), this.growthTimeRate);
//meadow.growAPlant(this.growthTimeRate);
let bunnyMove = this.bunny.move();
// not enough energy, bunny did not survive
if(bunnyMove == false){
this.timeToEnergyDataPopulator(this.timeCounter, bunny.getBunnyEnergy());
let rate = this.growthTimeRate / 1000;
this.rateToEnergyTimeData = {rate : this.timeToEnergyData};
// add the failure rate to the failureRateArray
this.failureRateArray.push(this.growthTimeRate);
// increase the rate of plant growth
if(this.passRateArray.length < 1){
this.growthTimeRate = this.growthTimeRate + this.growthTimeRate * 0.5;
}else{
let lastSurvivalRate = this.passRateArray[this.passRateArray.length - 1];
this.growthTimeRate = lastSurvivalRate - ((lastSurvivalRate - this.growthTimeRate)*0.5);
}
// stop the meadow from growing a plant
meadow.growAPlant(null);
// stop the simulation
clearInterval(this.simulation);
}
while(!this.meadow.checkValidBunnyMove(bunnyMove).bind(this.meadow)){
bunnyMove = bunny.move();
}
if(meadow.checkIfBunnyEats(bunnyMove)){
// since bunny made still a move, -1 energy
bunny.decreaseEnergyByOne();
// and since the meadow at that coordinate had food, we add +10 to energy via eatPlant method
bunny.eatPlant();
// track the time to energy data
this.timeToEnergyDataPopulator(this.timeCounter, bunny.getBunnyEnergy);
}else{
// no food, -1 energy
bunny.decreaseEnergyByOne();
// track the time to energy data
this.timeToEnergyDataPopulator(this.timeCounter, bunny.getBunnyEnergy);
}
// decrement the timeCounter
this.timeCounter -= 1;
if(this.timeCounter <= 0){
this.timeToEnergyDataPopulator(this.timeCounter, bunny.getBunnyEnergy());
let rate = this.growthTimeRate / 1000;
this.rateToEnergyTimeData = {rate : this.timeToEnergyData};
this.passRateArray.push(this.growthTimeRate);
// bunny survived, adjust the growth rate
if(this.failureRateArray.length < 1){
this.growthTimeRate = this.growthTimeRate - (this.growthTimeRate * 0.5);
}else{
let lastFailureRate = this.failureRateArray[this.failureRateArray.length - 1];
this.growthTimeRate = this.growthTimeRate - ((this.growthTimeRate - lastFailureRate) * 0.5);
}
clearInterval(this.simulation);
}
}
runner(){
while(this.passRateArray[this.passRateArray.length - 1] - this.failureRateArray[this.failureRateArray.length - 1] > this.gap || this.passRateArray.length == 0 || this.failureRateArray.length == 0){
setInterval(this.simulation(), 1000);
}
console.log("The minimum plant regeneration rate required to sustain the bunny for 10000 units of time is " +
this.growthTimeRate + " regenerations/unit time");
}
}
Errors that I get:
1) simulation.js:62 Uncaught TypeError: this.meadow.checkValidBunnyMove is not a function
at Simulation.simulation (simulation.js:62)
at Simulation.runner (simulation.js:101)
at (index):24
2) meadow.js:1 Uncaught SyntaxError: Identifier 'Meadow' has already been declared
at VM16689 meadow.js:1
3) VM16689 meadow.js:37 Uncaught ReferenceError: checkElementExists is not defined
at Meadow.growAPlant (VM16689 meadow.js:37)
My question is why the number 1 and 3 errors persist?
clearInterval(this.growAPlant);
This clearInterval isn’t correct, because you need pass the return value of setInterval to it, not a function. It does helpfully imply that you have a setInterval(someMeadow.growAPlant, …) somewhere, though, and that’s where the issue is. When you reference a function without calling it – like when you pass it to setInterval – the object it belonged to doesn’t come with it. Then, when the timer fires, it calls the function without a this value.
In JavaScript, the value of this inside a non-arrow function is determined entirely by how the function is called, not where it’s declared. You can read about how this works in various other questions and pieces of documentation. Fixing the problem involves giving growAPlant the correct this somehow, either by:
placing a reference to it in a containing scope (i.e. moving your var that = this out one level and using that instead of this throughout)
wrapping the function in one that’ll preserve the correct value, as in
setInterval(someMeadow.growAPlant.bind(someMeadow), …);
(Function.prototype.bind) or
setInterval(function () {
someMeadow.growAPlant();
}, …);
(the someMeadow.growAPlant reference is now part of a call, so someMeadow becomes the this value for the call)
changing it into an arrow function, which doesn’t have its own this and uses the one from the containing scope
Only (2) will work when you convert to the simplest form of an ES6 class, so it’s the approach I recommend.
Explanation
First, this always refers to the first parent function. In your case it is:
this.growAPlant = function(timeRate){
//content
var that = this; // this is growAPlant
}
And
this.checkElementExists = function(coordinates){ }
Is accessible with Meadow object. However, your var that is referring to this.growAPlant = function(timeRate) not Meadow.
Solution
Create that in the beginning
function Meadow(){
var that = this;
that.growAPlant = function(timeRate){
}
that.checkElementExists = function(coordinates){
if(this.grid[coordinates[0]][coordinates[1]] != null){
return true;
}else{
return false;
}
};
return that;
}

Bomberman Vanilla JS

I'm trying to make bomberman using vanilla JS, for my examination project.
I am a little stuck right now with how to take out the bombs in the array and push them into the array again after they explode.
They need to explode after 2 seconds.
My code for bombs:
function bombPlayerOne() {
let ss = new createjs.SpriteSheet(game.q.getResult('bomb'))
let temp = new createjs.Sprite(ss, "bombIt");
temp.x = playerOne.x;
temp.y = playerOne.y;
game.stage.addChild(temp);
powerUps.bombs.push(temp);
console.log("player one placed a bomb");
for (var i = powerUps.bombs.length - 1; i > 0; i--) {
powerUps.bombs.splice;
// TODO : tween bomber ud...
powerUps.bombs.push;
}
}
function bombPlayerTwo() {
let ss = new createjs.SpriteSheet(game.q.getResult('bomb'))
let temp = new createjs.Sprite(ss, "bombIt");
temp.x = playerTwo.x;
temp.y = playerTwo.y;
game.stage.addChild(temp);
powerUps.bombs.push(temp);
console.log("player two placed a bomb");
for (var i = powerUps.bombs.length - 1; i > 0; i--) {
powerUps.bombs.splice;
// TODO : tween bomber ud...
powerUps.bombs.push;
}
}
So you have a few options, and FYI this isn't necessarily a javascript question so much as how do you handle game logic/code design type of question.
1) A bomb when placed contains a reference back to it's owner. ie
bomb.owner = playerOne
2) You have a manager that controls the state of a level, which keeps track of bombs
LevelManager.player1Bombs = ....
3) You have an array of bombs placed belonging to each player, which you then update during your logic update calls.
function gameUpdate(long milliSecondsSinceLastFrame){
for(bomb in playerOne.placedBombs){
if(bomb.isExploded){
//do other cleanup
playerOne.availableBombs ++;
}
}
//... do same for player 2 etc
}
All of them have their own advantages/disadvantages.

Categories