• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Losowanie wygranego gracza

Object Storage Arubacloud
+1 głos
85 wizyt
pytanie zadane 20 grudnia 2022 w JavaScript przez Whereismycode Obywatel (1,710 p.)

Nie mam pomysłu jak w optymalny sposób zrobić losowanie wygranego gracza, którego szanse wygranej zależą od ilości losów, które posiada:

let _ALLTICKETS = 100;
let _PARTICIPANTS = [
		{
			ID: 1,
			USER_NAME: "Wilczur",
			TICKETS: 1
		},
		{
			ID: 2,
			USER_NAME: "Kotołak",
			TICKETS: 33
		},
		{
			ID: 3,
			USER_NAME: "Kukumba",
			TICKETS: 55
		},
		{
			ID: 4,
			USER_NAME: "Makarov",
			TICKETS: 11
		}
	];
  
  
  
  for(let i = 0; i< _PARTICIPANTS.length; i++){
   		console.log(_CHECKCHANCE(_PARTICIPANTS[i].TICKETS, _ALLTICKETS)) 
  }
  
	function _CHECKCHANCE(a, b){
  		return ((a/b)*100).toFixed(2);
  }

Podpowiecie jak wykonać losowanie skupiając się na właśnie szansy wygranej.

PS: Znając życie odpowiedź pewnie jest banalna, ale totalnie nie mam pomysłu

1 odpowiedź

+1 głos
odpowiedź 21 grudnia 2022 przez VBService Ekspert (253,340 p.)
edycja 21 grudnia 2022 przez VBService
 
Najlepsza

Proponuję utworzyć dla każdego uczestnika tablicę zawierająca jego ID tyle razy ile ma szans (TICKETS)

for (PARTICIPANT of _PARTICIPANTS)
  const tickets_per_participant = new Array(PARTICIPANT.TICKETS).fill(PARTICIPANT.ID);

 

w kolejnym kroku dodawać tę tablicę szans dla każdego użytkownika do tablicy losowań

let draw_pool = [];
for (PARTICIPANT of _PARTICIPANTS) {
  const tickets_per_participant = new Array(PARTICIPANT.TICKETS).fill(PARTICIPANT.ID);
  draw_pool = [...draw_pool, ...tickets_per_participant];
}

 

na podstawie danych z Twojego przykładu tablica losowań będzie wyglądać tak

[
  1, // TICKETS: 1
  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // TICKETS: 33
  3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 55
  4,4,4,4,4,4,4,4,4,4,4 // TICKETS: 11
]

 

teraz tę tablicę mieszamy (shuffle) i losujemy szczęśliwca, statystycznie najwięcej razy powinno ukazać
- USER_NAME: "Kukumba" (TICKETS: 55) i
USER_NAME: "Kotołak" (TICKETS: 33)

 

[ on-line ]

  drawn_ID = Math.floor(Math.random() * draw_pool.length);
  const lucky_user = _PARTICIPANTS.find(p => p.ID === draw_pool[drawn_ID]);

 

1
komentarz 21 grudnia 2022 przez Whereismycode Obywatel (1,710 p.)
Wygląda na to, że działa. Dzięki!
1
komentarz 21 grudnia 2022 przez VBService Ekspert (253,340 p.)

Można ewentualnie spróbować zaimplementować sposób opisany przez @Great; tutaj o nazwie Fisher–Yates, dla otrzymania "lepszej" losowości.

1
komentarz 21 grudnia 2022 przez Whereismycode Obywatel (1,710 p.)

Brzmi cudowanie i wygląda też całkiem nieźle. Znalazłem funkcję, która działa na zasadzie Fisher-Yates. 

function fyShuffle(arr) {
  let i = arr.length;
  while (--i > 0) {
    let randIndex = Math.floor(Math.random() * (i + 1));
    [arr[randIndex], arr[i]] = [arr[i], arr[randIndex]];
  }
  return arr;
}

Teraz pytanie. Powyższą funkcję użyję zamiast tego? :

drawn_ID = Math.floor(Math.random() * draw_pool.length);

 

1
komentarz 21 grudnia 2022 przez VBService Ekspert (253,340 p.)
edycja 21 grudnia 2022 przez VBService

Do mieszania tablicy losowań

draw_pool = fyShuffle(draw_pool);

zamiast

draw_pool.sort(() => Math.random() - 0.5);

 

do wylosowania "szczęśliwca" wystarczy już

drawn_ID = Math.floor(Math.random() * draw_pool.length);

 

1
komentarz 21 grudnia 2022 przez VBService Ekspert (253,340 p.)

Wprowadziłem Ciebie w błąd, powyżej poprawiona odpowiedz. angel

1
komentarz 21 grudnia 2022 przez Whereismycode Obywatel (1,710 p.)
edycja 21 grudnia 2022 przez Whereismycode

Właśnie coś mi tu nie pasowało laugh

Tak się zastanawiam czy teraz gdy mam tą funkcję Fisher-Yates to czy mogę zrezygnować z tej pętli:

for (let i=0; i<10; i++) {
  drawn_ID = Math.floor(Math.random() * draw_pool.length);
  const lucky_user = _PARTICIPANTS.find(p => p.ID === draw_pool[drawn_ID]);
  //console.log(drawn_ID, draw_pool[drawn_ID]); // dla demonstracji
  console.log('ID: '+lucky_user.ID+'  USER_NAME: '+lucky_user.USER_NAME);
}

na rzecz tego:

draw_pool = _FY_SHUFFLE(_DRAW_POOL);
drawn_ID = Math.floor(Math.random() * draw_pool.length);
const lucky_user = _PARTICIPANTS.find(p => p.ID === draw_pool[drawn_ID]);
    
console.log('ID: '+_LUCKY_USER.ID+'  USER_NAME: '+_LUCKY_USER.USER_NAME + ' TICKETS: '+_LUCKY_USER.TICKETS);

 

komentarz 21 grudnia 2022 przez VBService Ekspert (253,340 p.)

Tak, ta pętla jest dla demonstracji, że najczęściej wylosowany jest user o największej wartości TICKETS

Podobne pytania

0 głosów
2 odpowiedzi 121 wizyt
pytanie zadane 15 marca 2018 w Algorytmy przez revizor451 Obywatel (1,930 p.)
0 głosów
0 odpowiedzi 364 wizyt
+1 głos
3 odpowiedzi 924 wizyt
pytanie zadane 17 lipca 2021 w JavaScript przez MSB Nowicjusz (190 p.)

92,576 zapytań

141,426 odpowiedzi

319,651 komentarzy

61,961 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...