I'm working on a JS-based game where I'm tracking the scores of several users. At the end of the game, I need to declare a winner. There may be ties.
So, two examples:
player1 = 3
player2 = 5
player3 = 4
(Player 2 is the winner)
player1 = 4
player2 = 2
player3 = 4
(player 1 and 3 tie)
With only 3 players, I could probably just do this with a bunch of nested if/elses comparing each value to each other, but was wondering if there is a more elegant way to go about this...especially in situations where you may have 10 players as an example, where if/else comparisons would get unwieldy pretty fast.
One option seems to be to stick the values in an array, then sort it, but that doesn't give you the variable name--just the values. I could then do a multi-dimensional array, but then things seem to be getting messy again at that point.
There is no easy way to iterate through variable names like player1, player2, etc... without using eval() or requiring those variables to be global variables which is generally a bad way to go.
If they were global variables, you could use this hack, but I would suggest my second method below which stores player info as an array of objects. Here's a hack using global variables (not recommended, but a more direct answer to your question):
// these must be global variables
var score1 = 100;
var score2= 99;
var score3= 80;
function findHighScore() {
var highestScore = score1;
var highestScorePlayerNum = 1;
var tempScore;
for var (i = 2; i <= 3; i++) {
// this works only because the score variables are global variables which
// can be accessed as properties off the window object
tempScore = window["score" + i];
if (tempScore > highestScore) {
highestScore = tempScore;
highestScorePlayerNum = i;
}
}
return {score: highestScore, playerNum: highestScorePlayerNum};
}
A much better way would involve not keeping each player's score in its own javascript variable, but rather putting it into an array of objects like this:
var playerData = [
{name: "John", highScore: 145, lastPlayed: 23089234},
[name: "Bill", highScore: 99, lastPlayed: 59383945}
];
Then, you can loop through the player data, find the highest score and have the name of that player too.
function findHighScore() {
var highScoreSoFar = 0;
var result;
for (var i = 0; i < playerData.length; i++) {
if (playerData[i].highScore > highScoreSoFar) {
result = playerDatra[i];
highScoreSoFar = playerData[i].highScore;
}
}
return result;
}
var highPlayer = findHighScore();
alert("Highest scoring player is " + highPlayer.name + " with a score of " + highPlayer.highScore);
If you want to return all players tied for the highest score, you can return an array of players that had the highest score:
function findHighScore() {
var highScoreSoFar = 0;
var result = [];
for (var i = 0; i < playerData.length; i++) {
if (playerData[i].highScore > highScoreSoFar) {
// new high score so start a new array with this player in it
result = [playerData[i]];
highScoreSoFar = playerData[i].highScore;
} else if (playerData[i].highScore === highScoreSoFar) {
// more than one player with this highScore so add this one to the array
result.push(playerData[i]);
}
}
return result;
}
var players = {
player1: 3,
player2: 5,
player3: 4
};
var sorted = Object.keys(players)
.sort(function(keya, keyb) {
return players[keyb] - players[keya];
})
.forEach(function(key) {
console.log(key, players[key]);
})
DEMO: http://jsfiddle.net/WUAhS/
player2 5
player3 4
player1 3
Or use .reduce() if all you want is the high score.
var high_key = Object.keys(players)
.reduce(function(keya, keyb) {
return players[keya] > players[keyb] ? keya : keyb;
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With