Cum de a împărți numărul de jucători x în 2 echipe în mod aleatoriu de mai multe ori, diferit de fiecare dată?

Am o problemă matematică în codul meu JavaScript. Trebuie să împart un număr dat de jucători în 2 echipe în mod aleatoriu, astfel încât de fiecare dată - dacă jucătorii vor să joace din nou - echipele se formează din nou și ar trebui să fie diferite până când se formează toate combinațiile.

Let's say I have 4 players, so all the combinations are as follows:
[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]

Cu toate acestea, deoarece partea echipei nu se ia în considerare, există doar 3 combinații diferite:

[1,2] vs [3,4]
[1,3] vs [2,4]
[1,4] vs [2,3]

Când numărul de jocuri jucate depășește numărul de combinații, ar trebui să înceapă din nou ... adică alegerea aleatorie a uneia dintre cele trei combinații, selectarea aleatorie a următorului și așa mai departe ...

Dar există o răsucire ... și abilitățile matematice ale mele se îndreaptă destul de mult spre sud atunci când numărul de jucători este ciudat și unul dintre jucători trebuie să se odihnească la un joc. Deci, cu 5 jucători, toate combinațiile de potrivire sunt (ultimul număr fiind jucătorul care se odihnește):

[1,2] vs [3,4] [5]
[1,2] vs [3,5] [4]
[1,2] vs [4,5] [3]

[1,3] vs [2,4] [5]
[1,3] vs [2,5] [4]
[1,3] vs [4,5] [2]

[1,4] vs [2,3] [5]
[1,4] vs [2,5] [3]
[1,4] vs [3,5] [2]

[1,5] vs [2,3] [4]
[1,5] vs [2,4] [3]
[1,5] vs [3,4] [2]

[2,3] vs [4,5] [1]
[2,4] vs [3,5] [1]
[2,5] vs [3,4] [1]

Cum este posibil ca în JavaScript să se formeze aceste echipe?

Un lucru care a venit în minte a fost să dea fiecărui jucător o valoare unică (10 ^ x), de exemplu:

player1.value = 10;
player2.value = 100;
player3.value = 1000;
player4.value = 10000;

... și apoi atunci când buclă pentru a forma echipe verifica dacă o valoare totală a echipei este egală cu ultimele valori.

Ar putea cineva matematic/JavaScript mai talentat te rog ajută-mă cu această problemă de codificare. Mulțumiri!

0

2 răspunsuri

Utilizarea valorilor este o idee bună, dar dacă le faci măști de biți, este mai ușor să verifici ce jucători au fost potrivite. de exemplu.

player1.value = 1 
player2.value = 2
player3.value = 4
//(dynamically player n would have value 1 << (n-1) )

Verificând masca cu un alt jucător, se poate verifica dacă au fost deja cuplate, deoarece au deja o valoare de mască proprie, nu se pot potrivi niciodată. În ceea ce privește factorul aleatoriu, cred că cea mai ușoară cale este să creezi mai întâi toate combinațiile, așa cum ai făcut în exemplul tău, și să folosești o serie de combinații ca bază pentru alegerea unui meci aleatoriu. Dacă simțiți că această abordare este o modalitate bună de a merge, dar aveți probleme cu implementarea, pot încerca să pregătesc un exemplu de cod.

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 + ")
"); } document.writeln("
"); //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 + ")
"); } document.writeln("
"); //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] + "
"); } document.writeln("
");
0
adăugat
sună bine - creând toate combinațiile și apoi selectând aleatoriu - dar nu a înțeles nimic despre "masca bit" sau "1 << (n-1)". Un exemplu de cod ar fi grozav!
adăugat autor micadelli, sursa
lucruri minunate! Încercați să rulați acest lucru și funcționează, deși încă nu am acei "mască: jucători [i] .Mask | players [j] .Mask" și "if ((t1.mask & t2.mask) === 0) "... dar voi. Cu toate acestea, nu știu dacă se datorează greșelii mele englezești, dar acest lucru împarte jucătorii într-o echipă de 2 jucători și am vrut doar să împărți toți jucătorii în 2 echipe separate. Deci, 9 jucători vor fi împărțiți 5 vs 4. Cum ar trebui schimbat codul.
adăugat autor micadelli, sursa
Bună, am creat o întrebare de urmărire aici: stackoverflow.com/questions/12046888/… dacă ați putea arunca o privire, vă mulțumesc.
adăugat autor micadelli, sursa
Ne pare rau pentru raspunsul tarziu, am fost la cafenea si cina :) Am adaugat proba la postul de mai sus
adăugat autor Me.Name, sursa
Îmi pare rău, nu am primit asta. Am schimbat crearea echipei. Este un lucru amuzant, genul de recursiune implicat cu asta este relativ mai greu decât mascarea: D Oricum, despre mascare, & returnează o valoare cu biții stabiliți pe poziția în care ambele măști au puțin. Deci, dacă e 0, nu corespund biți, ceea ce noi urmărim. Mai multe despre machetarea de biți aici: en.wikipedia.org/wiki/Mask_(computing)
adăugat autor Me.Name, sursa

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.

0
adăugat
Prin "alegeți numerele pe care nu le-ați folosit la întâmplare și le-ați făcut echipe", vrei să spui indexul de matrice al tuturor jucătorilor, nu? Cum să nu mai formăm din nou aceeași echipă? Și mai important, cum fac aceste echipe? Puteți furniza un exemplu real/pseudo-cod. Multumesc
adăugat autor micadelli, sursa
JavaScript, România - Moldova
JavaScript, România - Moldova
328 participanți

Comunitatea Română JavaScript: github.com/js-ro Pentru confort, opriți notificările. Parteneri: @node_ro, @php_ro, @python_ro, @seo_ro, @RomaniaGroup, @ai_ro, @Grupuri_IT Offtop: @holywars_ro Joburi: @js_jobs_ro Sponsored with ❤️ by ciupacabra.com