I have a mathematical problem in my JavaScript code. I need to divide a given number of players into 2 teams randomly so that each time – if players want to play again – the
For the even cases, just pick numbers you haven't used randomly and make teams.
For the odd cases, pick a number randomly to sit out. Then the remaining numbers are like an even case.
Using values is a good idea, but if you make them bit masks it's easier to check which players s have been matched. e.g.
player1.value = 1
player2.value = 2
player3.value = 4
//(dynamically player n would have value 1 << (n-1) )
By checking the mask with another player, it can be checked if they have been coupled already, since they already have their own mask value, they can never match themselves. As for the random factor, I think the easiest way is to create all combinations first, as you did in your example, and use an array of those combinations as the base of picking a random match. If you feel this approach is a good way to go, but have trouble implementing, I can try and cook up some example code.
Edit here's the example code, hope the comments help sort out their meaning Edit2 changed team combinations
var playercount = 5;
//add players
var players = new Array();
for (var i = 0; i < playercount; i++) {
players[i] = { Index: i, Mask: 1 << i, Name: "Player" + (i + 1), toString: function () { return this.Name; } };
//about the 1 << i: "<<" is a so called bit wise shift to the left.
//1 << i has the same outcome as 2 to the power of i
}
//the line below would print all players
//for (var pi in players) { var p = players[pi]; document.write(p + " (Mask:" + p.Mask + ")<br>"); } document.writeln("<br>");
//create all possible team combinations
var teams = new Array();
var playersPerTeam = Math.floor(playercount / 2);
function Team(){
this.list = new Array();
this.mask = 0;
this.count = 0;
this.full =false;
this.Add = function (i) {
this.list.push(players[i]);
this.mask |= players[i].Mask;
this.full = ++this.count === playersPerTeam;
}
this.toString = function () {
var res = "", cnt = this.list.length;
for (var i = 0; i < cnt; i++) {
if (i > 0)
res += i == cnt - 1 ? " and " : ",";
res += this.list[i].Name;
}
return res;
}
}
function addplayers() {
var indices = new Array(playersPerTeam);
for (var p = 0; p < playersPerTeam; p++) indices[p] = p;
var l = playersPerTeam - 1;
function addteam() {
var team = new Team();
for (var p = 0; p < playersPerTeam; p++) team.Add(indices[p]);
teams.push(team);
}
function addplayer(start, depth) {
var target = players.length - playersPerTeam + depth + 1;
var team;
for (var i = start; i < target; i++) {
indices[depth] = i;
if (depth == l)
addteam();
else
addplayer(i + 1, depth + 1);
}
}
addplayer(0, 0);
}
addplayers();
//the line below would print the team combinations
//for (var te in teams) { var t = teams[te]; document.write(t + " (mask:" + t.mask + ")<br>"); } document.writeln("<br>");
//create matches
var matches = new Array();
//the matches can be created in the same way as the teams, only the first team cannot have players of the second team
for (var i = 0; i < teams.length; i++) {
for (var j = i + 1; j < teams.length; j++) {
var t1 = teams[i], t2 = teams[j];
if ((t1.mask & t2.mask) === 0) //this is where the masks come in,
matches.push({ Team1: t1, Team2: t2, toString: function () { return this.Team1 + " versus " + this.Team2 } });
}
}
//randomize matches. Instead of picking a random match per turn, we can randomize at the
//start, so we know all the matches in advance.
//this can be done by using a sort on the array with a random index
//NB, this isn't the most random randomness (or whatever you call it LOL). For better shuffling
//there are several alternatives, but perhaps this one is enough
matches.sort(function() { return (parseInt(Math.random() * 100) % 2);});
//the line below prints the matches
for (var mi in matches) { document.write(matches[mi] + "<br>"); } document.writeln("<br>");