简体   繁体   中英

JavaScript if statement with some Boolean only works first time

I have these two functions, the first one (move_c(i)) runs when the user clicks on a (source) image, and the second one (move_to_c1(i)) runs when the user clicks on a (destination) div.

And there is a Boolean value (cp) which flip flops between true and false each time the second function is run.

The images are red or yellow, and the idea is that red will only move when cp == true and yellow will only move when cp == false, but it only works the very first time, after that it fails to do its job and I don't understand why.

Red must go first. The first move, the if condition works, red && true. Yellow && true does not move for the first move (which is correct). But for subsequent moves the if condition isn't working.

You can see it in action here.

And the code is here.

Oh... and I've only implemented this on the circle game not the square.

var cp = true;
function move_c(i) {
  alert(document.getElementById(i).className + " " + cp);
  this.image_c = i;
  if (((document.getElementById(i).className == 'red') && (cp == true)) || ((document.getElementById(i).className == 'yellow') && (cp == false))) {
    c1.setAttribute('onclick', 'move_to_c1(image_c)');
    c2.setAttribute('onclick', 'move_to_c2(image_c)');
    c3.setAttribute('onclick', 'move_to_c3(image_c)');
    c4.setAttribute('onclick', 'move_to_c4(image_c)');
    c5.setAttribute('onclick', 'move_to_c5(image_c)');
    c6.setAttribute('onclick', 'move_to_c6(image_c)');
    c7.setAttribute('onclick', 'move_to_c7(image_c)');
    c8.setAttribute('onclick', 'move_to_c8(image_c)');
    c9.setAttribute('onclick', 'move_to_c9(image_c)');
  }
}

function move_to_c1(i) {
  if (document.getElementById(i).name == 'c' || document.getElementById(i).name == 'c2' || document.getElementById(i).name == 'c4' || document.getElementById(i).name == 'c5') {
    document.getElementById("c1").appendChild(document.getElementById(i));
    document.getElementById(i).style.zIndex = 1;
    document.getElementById(i).setAttribute('name', 'c1');
    cp = !cp;
  }
}

I recommend opening your page in Chrome, and using the developer tools. You can open the console by pressing F12 on your keyboard.

The console will show you that exceptions are being thrown from the c3.setAttribute lines in move_c after the first smiley has been moved. This appears to be because name c3 is changed to refer to multiple elements when the smiley is moved. When it refers to multiple elements rather than the expected single element, then the setAttribute is not available on the group.

The fix is to avoid calling c3.setAttribute('onclick', 'move_to_c3(image_c)'); and similar for smileys which have been moved/renamed. The most straight forward way to do that is to check before each setAttribute :

 
 
 
  
  if (c1) { c1.setAttribute(.....); }
 
  

You can change the code to avoid giving multiple objects the same name. Instead of setting the name attribute, you can save the game state in a separate object. Add var gamestate = []; somewhere at the top, and then replace document.getElementById(i).setAttribute('name', 'c1'); with gamestate[i] = 'c1'; . Then you will be able to lookup the position of an image by accessing gamestate[i] . You can log the complete game state any time you want using console.log(gamestate); .

Note that once you have the console open, you can use console.log instead of alert to see what's going on. It is much more comfortable than confirming alert dialogs all the time. Also it allows you to inspect the inside of objects in more detail as you'll see if you try console.log(gamestate); .

Once you've got that working, then start studying arrays and for loops. It will help to simplify your code by removing all the repetitions.

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