How to show alert in the next event loop? - javascript

I am learning VueJS and created this little practice game to enhance my knowledge on Vue.
http://jsfiddle.net/mzref4o0/1/
this attack method will also determine the winner:
attack: function(isSpecialAttack) {
let youHurt = Math.floor(Math.random() * 10);
let monsterHurt = Math.floor(Math.random() * 10);
if (isSpecialAttack) {
youHurt = Math.floor(Math.random() * (20 - 10 + 1)) + 10;
monsterHurt = Math.floor(Math.random() * (20 - 10 + 1)) + 10;
}
this.you.bloodLevel -= youHurt;
this.monster.bloodLevel -= monsterHurt;
this.messages.push([
{id: this.getRandomId, turn: 'you', msg: 'PLAYER HTIS MONSTER FOR ' + monsterHurt},
{id: this.getRandomId, turn: 'monster', msg: 'MONSTER HTIS PLAYER FOR ' + youHurt}
])
if (this.you.bloodLevel <= 0 || this.monster.bloodLevel <= 0) {
if (this.you.bloodLevel <= 0) {
alert('you lost');
} else {
alert('you won');
}
}
},
The problem is that the alert message shows up before the "attack" happens, meaning the blood bar drops & the message is added after the alert message is shown. How do I make the alert shows up only after those two things happened?
I think this problem is due to event loop... but that's all I know.

What you are trying to achieve can't really work with alert.
alert method is blocking the execution of code, therefore the browser does not start to deal with the re-painting until the block is released.
A solution was suggested in other stackoverflow post.
I highly recommend to use more modern techniques, like vue-js modals.
anyway, this block of code should work :
if (this.you.bloodLevel <= 0 || this.monster.bloodLevel <= 0) {
if (this.you.bloodLevel <= 0) {
setTimeout("alert('you lost');", 1);
} else {
setTimeout("alert('you won');", 1);
}
}

Related

Having a hard time getting the right probability outcome (js beginner)

I'm trying to make a simple rolling the dice mechanic with probabilities, if pass the level increase, if fail it decrease and if destroyed usually it resets to a certain level, but I'm having a hard time getting the right results, I am not sure if the outcome is supposed to be like this and just my intuition is wrong or something is actually messing it up.
Basically I am making a while loop that while below certain level it will roll the dice and given the results it will do something accordingly to the rates I input (40% for pass, 59.4% for fail and 0.6% to destroy). But when I do a test with 1000 tries, it always return me an average of destroyed way higher than 0.6%. I don't know if my test function is wrong, if the way I'm testing is wrong, if something on my loop is messing up the probabilities outcome.
function checkPass(successRate, failRate, destroyRate) {
let number = Math.random();
if (number < successRate) {
return 1;
} else if (number < failRate) {
return 0;
} else {
return 2;
}
}
function starforceSim(itemLevel) {
let newObj = {"level": 10, "totalMeso": 0, "destroyed": 0};
while (newObj.level < 11) {
if (newObj.level == 10) {
let passOutcome = checkPass(0.4, 0.994, 1)
if (passOutcome == 1) {
//newObj.totalMeso = newObj.totalMeso + (Math.round(1000 + (Math.pow(itemLevel, 3)) * (Math.pow(newObj.starlevel + 1, 2.7)) / 400));
newObj.level = newObj.level + 1;
} else if (passOutcome == 0) {
//newObj.totalMeso = newObj.totalMeso + (Math.round(1000 + (Math.pow(itemLevel, 3)) * (Math.pow(newObj.starlevel + 1, 2.7)) / 400));
//newObj.level = newObj.level - 1;
} else {
//newObj.totalMeso = newObj.totalMeso + (Math.round(1000 + (Math.pow(itemLevel, 3)) * (Math.pow(newObj.starlevel + 1, 2.7)) / 400));
newObj.destroyed = newObj.destroyed + 1
}
}
}
return newObj;
}
let counter = 0;
for (i=0; i<1000; i++) {
let n = starforceSim(140);
if (n.destroyed > 0) {
counter++
}
}
console.log(counter);
I disabled the decrease level when it fails just to focus on the destroy rates.
Is there a better way to code probabilities or to test them? Is there something wrong with my code?
Math.random is only pseudo-random1
1Source
This means you may not get a perfectly uniform distribution. In my own fiddling, it seems like randomness might get worse if you generate many values in rapid succession [citation needed].
If you want a better source of randomness, check out Crypto.getRandomValues.
I don't see anything wrong with your code. I think your expectations are just off. To verify that this is caused by lame randomness, take David Tansey's advice and study just the randomness output.
You may also notice different randomness quality in different browsers (or, different Javascript engines).

Simple number guessing game using Javascript

I'm trying to make a number guessing game on JS for a web dev training I'm on. The problem is that it always prints the keyInYNStrict without giving an another chance for the user. Ignore the fact that the strings and variables are not in English. Basically I want the keyInYNStrict to only come after the arvaus == arvattava is true and the game has ended.
const minLuku = 1;
const maxLuku = 30;
const readlineSync = require('readline-sync');
let arvaus, arvattava, arvaustenLkm
do {
arvaus = readlineSync.question('Ajattelen numeroa 1 ja 30 välillä. Arvaapa vaan');
arvaustenLkm = 1;
arvattava = Math.floor(Math.random() * (maxLuku + 1 - minLuku)) + minLuku
kelvollinen = !isNaN(arvaus) && arvaus > 0 && arvaus < 31;
if (!kelvollinen) {
console.log('Elä viitsi! Laita nyt jokin oikea numero.');
}
else if (arvaus < arvattava){
arvaustenLkm++;
console.log('Kokeile suurempaa lukua.');
} else if (arvaus > arvattava){
arvaustenLkm++;
console.log('Kokeile pienempää lukua.');
} else if (arvaus == arvattava){
console.log('Hienoa. arvasit oikein ' + arvaustenLkm + ' arvauksella.')
}
} while (readlineSync.keyInYNStrict('Haluatko arvata uudestaan?'))
You'll need two while loops nested. The first is to repeat the guessing until the number has been found, the second to ask if the user wished to play again. This becomes clearer if you break a single game into a function, and then wrap "Play again?" around that function.
The following is untested. Notice I also pulled out the "Invalid guess" check to separate it from the game logic. I think that also improves readability, and allows for the option of checking for some other exit condition should the user wish to end early.
EDIT: As I'm thinking about it, there's another problem: Do you want to reset the hidden number each guess? That's probably not consistent with expectations. I've modified the code to reflect.
const minLuku = 1; // Lower bound
const maxLuku = 30; // Upper bound
const readlineSync = require('readline-sync');
let arvaus, arvattava, arvaustenLkm
do {
// Number of guesses
arvaustenLkm = 1;
//Target number
arvattava = Math.floor(Math.random() * (maxLuku + 1 - minLuku)) + minLuku
do {
// User's guess
arvaus = readlineSync.question('Ajattelen numeroa 1 ja 30 välillä. Arvaapa vaan');
// Bad guess test
if (isNaN(arvaus) || arvaus < minLuku || arvaus > maxLuku) {
console.log('Elä viitsi! Laita nyt jokin oikea numero.');
continue;
}
if (arvaus < arvattava){
arvaustenLkm++;
console.log('Kokeile suurempaa lukua.');
} else if (arvaus > arvattava){
arvaustenLkm++;
console.log('Kokeile pienempää lukua.');
} else if (arvaus == arvattava){
console.log('Hienoa. arvasit oikein ' + arvaustenLkm + ' arvauksella.')
}
} while (arvaus != arvattava)
} while (readlineSync.keyInYNStrict('Play again?'))

How loop 2 setIntervals without creating multiple requests?

function Test(time) {
i = 1;
fun1 = setInterval(function () {
if (i >= 1 && i <= 10) {
$('.class.' + i).children('.BUTTON').click();
}
}, time * i);
fun2 = setInterval(function () {
if (result > 0 && i < 10) {
console.log('The number is ' + i);
i++;
}
else if (result < 0) {
console.log('Sorry at ' + i + ' point you fell in the hole');
clearInterval(fun2);
stats.loss++;
$('.loss').text(stats.loss);
console.log('Number of fell are ' + stats.loss);
} else {
console.log('Exited from maze');
clearInterval(fun);
clearInterval(fun2);
stats.wins++;
$('.wins').text(stats.wins);
console.log('Number of wins are ' + stats.wins);
$('#START').click();
}
}, time * 1.3);
}
Last time I asked about making the if's in a for holding the i, loved it, then, I had the idea of checking the result of the path, showed in this case as points. And this way works great, problem is, what if I want to create an "infinite loop" to check if in the long run my character would be a winner or loser?
Solutions I tried: for,while,do while, they ends up requestin thousands of requests to the server.
tried with A main set interval, but somehow it just creates parallel requests and even If I do clearInterval(masterloop); it just activate the test again and again, speeding up and clicks only the start/reset level button.

Why is my Javascript not adding data on submit?

I am building a hot and Cold App in JS and jQuery.
My issue is on form submit that user input inserts a number and the game tells them if its hold or cold or hotter or holder based on how close or far from the number.
Issue is that It only works the first time. After that it does nothing.
How do I made it so that when the user input on submit it generates a new secretNumber and based on the checker I have setup outputs either hot or cold or hotter or colder.
Seems its not generating a new secret number or it is just not inputing it.
Code here http://codepen.io/mackenzieabby/pen/qOXNLg
JS
$(document).ready(function(){
// Global Variables.
var theSecret = Math.floor((Math.random() * 100) + 0); // Creates Secret Number
var userGuess = $('#userGuess').val(); // User Inut Guess
var count = 0;
var addList = document.createElement("li")
// Display information modal box
$(".what").click(function(){
$(".overlay").fadeIn(1000);
});
// Hide information modal box
$("a.close").click(function(){
$(".overlay").fadeOut(1000);
});
// Functions
// New Game
function newGame() {
// new gama data here
}
// Add To List
function addtoList() {
}
function preventRefresh() {
$("form").submit(function(event) {
event.preventDefault();
theSecret();
veryHotGuess();
hotGuess();
veryColdGuess();
coldGuess()
correctAnswer();
});
}
preventRefresh();
function addGuess() {
$("ul#guessList").append("<li>" + userGuess + "</li>");
}
// Checks if hot or cold or correct
function veryHotGuess() {
if (userGuess < 25 && theSecret < 25) {
document.getElementById('feedback').innerHTML = "Very Hot";
}
}
function hotGuess() {
if (userGuess < 50 && theSecret < 50) {
document.getElementById('feedback').innerHTML = "Hot";
}
}
function veryColdGuess() {
if (userGuess < 100 && theSecret < 100) {
document.getElementById('feedback').innerHTML = "Very Cold";
}
}
function coldGuess() {
if (userGuess < 75 && theSecret < 75) {
document.getElementById('feedback').innerHTML = "Cold";
}
}
function correctAnswer() {
if (userGuess == theSecret) {
document.getElementById('feedback').innerHTML = "You Got It";
}
}
});
Calling theSecret(); causes a JavaScript error. You are calling the variable as a function, which it isn’t obviously.
BTW, I think your calculation of guess "temperature" might be quite wrong.
You have to redefine your definition of Global variable in javascript:
$(document).ready(function(){
// Global Variables.
var theSecret = Math.floor((Math.random() * 100) + 0); // Creates Secret Number
var userGuess = $('#userGuess').val(); // User Inut Guess
var count = 0;
var addList = document.createElement("li")
...
those ARE NOT global variables, because you made then in a scope, the document.ready scope... a Global Variable must be defined outside any scope, so it's available in all scopes, including inside the document.ready as well inside any function method you wrote.
Secondly, you need to rethink what you are doing, as a rule, you are repeating yourself over and over with
document.getElementById('feedback').innerHTML = xxxx;
one day you need to change the feedback to something else, or also write something else, can you see in how many places you need to change your code? When you see several lines of almost the same code: You're doing it wrong...
And you need to simplify your calculations, you make it hard to code and see what's going on...
Third, as Alexander pointed out, you need to re-think how you're calculating, what you want to calculate if not the userGuess or the theSecret, but give an answer based on how close/far the user guess is from the correct value ... that I would call it the difference between 2 numbers.
something like: Math.abs(theSecret - userGuess)
Here's my approach:
http://codepen.io/anon/pen/wKqzvg?editors=001
(irrelevant code removed)
var theSecret = 0,
guesses = [];
$(document).ready(function() {
// Creates Secret Number
theSecret = Math.floor((Math.random() * 100) + 0);
$("form").submit(function(evt) {
evt.preventDefault();
checkTemperature();
});
});
// Functions
// Add To List
function addToList(txt) {
guesses.push(txt);
$("#count").text(guesses.length);
$("ul#guessList").append("<li>" + txt + "</li>");
}
function write(txt) {
document.getElementById('feedback').innerHTML = txt;
}
function checkTemperature() {
var userGuess = parseInt($('#userGuess').val()),
dif = Math.abs(theSecret - userGuess);
// for debug only
console.log("theSecret:" + theSecret);
console.log("userGuess:" + userGuess);
console.log("dif:" + dif);
addToList(userGuess);
if (dif < 5)
write("Vulcan Hot");
else if (dif < 25)
write("Very Hot");
else if (dif < 50)
write("Hot");
else if (dif < 75)
write("Cold");
else if (dif < 100)
write("Very Cold");
else if (dif === 0)
write("You Got It");
}
The problem isn't with theSecret but with userGuess. You were not grabbing the value on submit so it was empty. I suggest to always console.log or inspect variables to make sure they are getting populated correctly. In your submit I added this: userGuess = $('#userGuess').val(); and it will now check correctly.
However, as Alexander mentioned the math is wrong. The value will always be under 100 and so it will always be Very Cold. You have to get the absolute difference of both numbers and then do your guess check:
var difference = Math.abs(theSecret - userGuess);
if (difference < 100) {
document.getElementById('feedback').innerHTML = "Very Cold";
}
if (difference < 75) {
document.getElementById('feedback').innerHTML = "Cold";
}
if (difference < 50) {
document.getElementById('feedback').innerHTML = "Hot";
}
if (difference < 25) {
document.getElementById('feedback').innerHTML = "Very Hot";
}
if (difference == 0) {
document.getElementById('feedback').innerHTML = "You Got It";
}
I forked your project here: http://codepen.io/paulmg/pen/xwLExM

JavaScript function crashes every time it's run

I'm writing this really fantastic game in JavaScript but a part of the function I just wrote crashes every time it's run.
So I'm wondering, is it just to much to run in a for loop or have I made a syntax error somewhere?
Here's the code; it's taken from a function but this is the part that makes it crash.
for (zloop=min_houses_per_block; zloop<(house_number+1); zloop++)
{
if (zloop>0)
{
city_block_array[first][second].house_array[zloop].width =
(min_house_width+(((max_house_width-min_house_width)/house_width_slots)*(Math.floor(Math.random()*house_width_slots))));
city_block_array[first][second].house_array[zloop].height =
(min_house_height+(((max_house_height-min_house_height)/house_height_slots)*(Math.floor(Math.random()*house_height_slots))));
if (zloop=1)
{
x_number=(block_width-(house_threshold*2))-city_block_array[first][second].house_array[zloop].width;
min_house_x=house_threshold
city_block_array[first][second].house_array[zloop].x =
(min_house_x+(((x_number)/house_x_slots)*(Math.floor(Math.random()*house_x_slots))));
}
city_block_array[first][second].house_array[zloop].x=6000;
city_block_array[0][0].house_array[1].x=6000;
}
}
Without the if (zloop=1) part it runs fine.
Do you mean to say if (zloop==1)
Your error is most likely this line:
if (zloop = 1) {
This sets zloop to 1. You want to compare zloop to 1, so use zloop == 1.
Also, try to trim down on the line length. You can use some more descriptive variables:
for (var zloop = min_houses_per_block; zloop < (house_number + 1); zloop++) {
var house = city_block_array[first][second].house_array[zloop];
if (zloop > 0) {
house.width = (min_house_width + (((max_house_width - min_house_width) / house_width_slots) * (Math.floor(Math.random() * house_width_slots))));
house.height = (min_house_height + (((max_house_height - min_house_height) / house_height_slots) * (Math.floor(Math.random() * house_height_slots))));
if (zloop == 1) {
x_number = (block_width - (house_threshold * 2)) - house.width;
house.x = (house_threshold + (((x_number) / house_x_slots) * (Math.floor(Math.random() * house_x_slots))));
} else {
city_block_array[0][0].house_array[1].x = 6000;
house.x = 6000;
}
}
}
if (zloop=1)
Did you mean
if (zloop == 1)
= is an assignment
== is a comparison

Categories

Resources