简体   繁体   中英

Can't figure out this behavior: 2 while loops inside a while loop

I'm doing a kata for Codewars that puts two arrays of numbers up against each other. The "opponent" array always has on average larger numbers than the "codewarrior" array, and both arrays are always the same length. What I need to do is find the most efficient way to get victories (codewarrior[x] > opponent[y]), stalemates (codewarrior[x] == opponent[y]) if a victory isn't possible, or defeats (codewarrior[x] < opponent[y]) if neither a victory or stalemate is possible. Before anyone asks, I don't want the solution to the kata, only how to get my program to work.

function codewarResult(codewarrior, opponent) {
    codewarrior = codewarrior.sort(function(a, b){return a - b});
    opponent = opponent.sort(function(a, b){return a - b});

    console.log("Ordered codewarrior array: ", codewarrior);
    console.log("Ordered opponent array:", opponent);

    let victories = 0;
    let stalemates = 0;
    let defeats = 0;
    
    let x = 0;
    while(x < codewarrior.length) {
        let y = 0;
        while(codewarrior[x] > opponent[y]) { // Victory loop (most preferable)
            if(codewarrior[x] <= opponent[y + 1]) {
                victories++;
                codewarrior.splice(codewarrior.indexOf(x), 1, null); // I replace the value to null so the array retains it's length
                opponent.splice(opponent.indexOf(y), 1);
                console.log(`Codewarrior array after victory: `, codewarrior);
                console.log(`Opponent array after defeat: `, opponent);
            }
            y++;
        }
        if(codewarrior[x] == opponent[y]) { // Stalemate checker (second most preferable)
            stalemates++;
            codewarrior.splice(codewarrior.indexOf(x), 1, null);
            opponent.splice(opponent.indexOf(y), 1);
            console.log(`Codewarrior array after stalemate: `, codewarrior);
            console.log(`Opponent array after stalemate: `, opponent);
        }
        while(codewarrior[x] < opponent[y]) { // Defeat loop (least preferable)
            if(codewarrior[x] >= opponent[y + 1]) {
                defeats++;
                codewarrior.splice(codewarrior.indexOf(x), 1, null);
                opponent.splice(opponent.indexOf(y), 1);
                console.log(`Codewarrior array after defeat: `, codewarrior);
                console.log(`Opponent array after victory: `, opponent);
            }
            y++;
        }
        x++;
    }
    
    console.log(`victories: ${victories}, stalemates: ${stalemates}, defeats ${defeats}.`);
    
    if(victories > defeats) {
      return "Victory";
    } else if(victories === defeats) {
      return "Stalemate";
    } else {
      return "Defeat";
    }
}

Above I order the two arrays ordered from smallest to largest. I then have one large while loop that iterates the "codewarrior" array, and two while loops and an if statement inside iterating the "opponent" array each time that checks for a possible victory first, a stalemate second, and a defeat last. It checks for the most efficient way to get a victory (the values of codewarrior[x] > opponent[y] as close as possible) a stalemate, or a defeat (the values of codewarrior[x] < opponent[y] as far apart as possible).

When I try

codewarResult([4,3,2,1], [5,4,3,2]);

I expect the two arrays to have 4 "battles" against each other, with the values of "codewarrior" slowly becoming null as the large while loop iterates through it. Instead I get this behavior in the console:

Ordered codewarrior array:  [ 1, 2, 3, 4 ]
Ordered opponent array: [ 2, 3, 4, 5 ]
Codewarrior array after stalemate:  [ null, 2, 3, 4 ]
Opponent array after stalemate:  [ 2, 3, 4 ]
Codewarrior array after victory:  [ null, null, 3, 4 ]
Opponent array after defeat:  [ 2, 3 ]
Codewarrior array after stalemate:  [ null, null, 3, null ]
Opponent array after stalemate:  [ 2 ]
victories: 1, stalemates: 2, defeats 0.

Why is there only 3 battles being recorded and the 3 in the "codewarriors" array being skipped? Why does the first battle result in a stalemate when it should be a defeat (1 vs 5)?

Couple of things...

Your outer loop goes through all of your codeWarrior numbers... That makes sense...

Your inner loops for victory and defeat though are odd... it looks like if codeWarrior[0] is greater than opponent[0] then it should be a victory right? But your victories counter only gets incremented if codeWarrior[0] will lose/stalemate against opponent[1]. Same deal for defeat... if codeWarrior[0] loses to opponent[0], it only counts a defeat if codeWarrior[0] would win/stalemate with opponent[1].

As for not having the number of battles you think you should... look here:

if(codewarrior[x] == opponent[y]) { // Stalemate checker (second most preferable)
stalemates++;
codewarrior.splice(codewarrior.indexOf(x), 1, null);
opponent.splice(opponent.indexOf(y), 1);

You are probably meaning to remove a single number from codeWarrior at index x and single number from opponent at index y. By using indexOf() however, you are saying find the index in codeWarrior where the warrior's number == x and remove that element. If the value of X isnt found as a number in the codeWarrior at all,then nothing happens. Same for opponent and indexOf(y). As a result, you are having most likely the wrong items being removed from the arrays or not removed if they are supposed to.

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