简体   繁体   中英

My script crashes the browser

My script runs but when it gets to the setTimeout part it just doesn't like it :( The browser crashes and I have to exit. Is the browser wrong or have I dun goofed?

var health=100;
var ehealth=100;
var atk;
var eatk;

function attack(x){
x=Math.floor(Math.random()*11);
atk=x;
ehealth=ehealth-atk
document.write('Enemy Health:' + '   ' + ehealth + '   ')
}

function eattack(x){
x=Math.floor(Math.random()*11);
eatk=x;
health=health-eatk
document.write('Health:' + '   ' + health )
}

function dead(){
if(health<=0){
    document.write('You Lose');
}else{
    if(ehealth<=0){
  document.write('You Win');
}
}
}

function battle(){
document.write('Enemy Health:' + '&nbsp; &nbsp;' + ehealth + '&nbsp; &nbsp; Health: &nbsp; &nbsp;' + health + '<br/>\n')
while(health>=0&&ehealth>=0){
setTimeout(function(){
    attack(0)
},400)
setTimeout(function(){
eattack(0)
},400)
document.write("<br/>\n");
dead();
}
}

What am I to do :(

the problem is your while loop:

while(health>=0&&ehealth>=0){
setTimeout(function(){
    attack(0)
},400)

your are setting attack function to execute an "infinite" number of time.

Your while loop doesn't terminate. You trigger an endless stream of setTimeout() callbacks, but due to JS being executed in just one thread, none of these callbacks gets executed ever.

Let's see what happens in more detail:

in the event loop (the queue for JS code to be executed) at first there is just you battle function.

After the first iteration of the while loop, the event loop still looks like this:

battle | attack | eattack

The functions using setTimeout() get queued behind your battle() function. After the next iteration, it looks like this

battle | attack | eattack | attack | eattack

But still no (e)attack() function has been executed and hence the health and ehealth variables remain unchanged. This goes on and on forever until your browser has eaten all the memory and breaks down.

As a solution I suggest introducing something like this:

function battleRound() {
  attack(0);
  eattack(0);

  dead();

  if( health>=0&&ehealth>=0 ) {
    // still a round to go
    setTimeout( battleRound, 400 );
  }
}

Instead of queuing a multitude of functions, just enqueue one round of fighting after another until the battle is over.

Generally your code tries to set up infinite number of timeout handlers.

setTimeout sets some function to be run in future but it ends running immediately, doesn't wait until function is ran. So while loop runs infinitely as there is nothing inside that changes health.

Other better solution is to use intervals - something like:

var game_interval;

function turn () {
  attack(0);
  eattack(0);
  if (health<=0 || ehealth<=0) {
    clearInterval(game_interval);
    dead();
  }
}

game_interval = setInterval(400,turn);
turn(); // first turn immediately

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM