JavaScriptsVerschiedenes

Losentscheid

Zieht aus einer Namensliste einen oder mehrere Gewinner — fair gemischt, mit kurzer Ziehungsanimation und auf Wunsch mit Zurücklegen.

Wer räumt heute die Küche auf? Wer bekommt das Freilos? Welche drei Einsendungen gewinnen? Für all das braucht man einen Losentscheid — und der Zettel im Hut ist zwar romantisch, aber unpraktisch, wenn dreißig Namen hineinsollen. Dieses Script übernimmt das Ziehen.

Tragt die Namen ein, eine Zeile je Name, und legt fest, wie viele gezogen werden sollen. Der Schalter „mit Zurücklegen" bestimmt, ob ein Name mehrfach gewinnen kann: Beim Ziehen ohne Zurücklegen — der Normalfall bei einer Verlosung — wird jeder höchstens einmal gezogen. Mit Zurücklegen hat bei jeder Ziehung wieder jeder dieselbe Chance, so wie beim Würfeln.

Die Ziehung läuft mit einer kurzen Animation ab, bei der die Namen durchlaufen, bevor das Ergebnis stehenbleibt. Das ist reine Zierde und ändert nichts am Ergebnis — dieses steht bereits fest, bevor die Animation beginnt. Wir sagen das ausdrücklich dazu, weil manche Verlosungsseiten den Eindruck erwecken, während der Animation würde noch etwas entschieden.

Zur Fairness: Gemischt wird mit dem Fisher-Yates-Verfahren, dem einzigen einfachen Verfahren, das nachweislich jede Reihenfolge gleich wahrscheinlich macht. Der Zufall stammt aus Math.random — gut genug für Küchendienst und Tombola, aber nicht fälschungssicher. Wer eine rechtlich belastbare Verlosung braucht, sollte notariell ziehen lassen oder wenigstens vor Zeugen.

Verwandtes im Archiv: Gruppen einteilen verteilt dieselbe Liste auf mehrere Mannschaften, Lottozahlen zieht Zahlen statt Namen, und Zeilen sortieren mischt eine Liste ohne Gewinnerauswahl.

Verschiedenes Baujahr 2026 läuft in deinem Browser
Script von kostenlose-javascripts.de

So funktioniert das Script

Das Script zeigt zwei Dinge, die man leicht falsch macht: wie man wirklich fair mischt und wie man verhindert, dass ein zweiter Klick während der Animation alles durcheinanderbringt.

for (let i = liste.length - 1; i > 0; i--) {
  const j = Math.floor(Math.random() * (i + 1));
  const merker = liste[i];
  liste[i] = liste[j];
  liste[j] = merker;
}

Das ist das Fisher-Yates-Verfahren. Es läuft von hinten nach vorn und tauscht jedes Element mit einem zufällig gewählten aus dem noch nicht bearbeiteten vorderen Teil — inklusive sich selbst, deshalb i + 1. Jede der möglichen Reihenfolgen kommt damit exakt gleich häufig heraus.

Der oft gesehene Einzeiler liste.sort(() => Math.random() - 0.5) tut das nicht. Sortierverfahren setzen voraus, dass die Vergleichsfunktion sich widerspruchsfrei verhält — wenn A vor B kommt und B vor C, dann auch A vor C. Eine zufällige Antwort verletzt das, und je nach Sortierverfahren des Browsers bleiben manche Elemente überdurchschnittlich oft an ihrem Platz. Bei einer Verlosung wäre das ein handfestes Problem.

return mischen(namen.slice()).slice(0, anzahl);

Ziehen ohne Zurücklegen ist nach dem Mischen trivial: Man nimmt einfach die ersten Elemente. Das slice() ohne Argumente ist dabei wichtig — es legt eine Kopie der Liste an. Ohne die Kopie würde die Originalliste mitgemischt, und das fiele spätestens dann auf, wenn man die Namen noch einmal in der eingegebenen Reihenfolge bräuchte. Funktionen, die ihre Eingaben heimlich verändern, sind eine ergiebige Fehlerquelle.

const gewinner = ziehen(namen, anzahl, mitZuruecklegen);
laeuft = true;
let schritte = 0;
const uhr = setInterval(function () { … }, 70);

Die Reihenfolge ist Absicht: Erst wird gezogen, dann läuft die Animation. Sie zeigt zufällige Namen, hat aber keinerlei Einfluss auf das Ergebnis — das steht schon fest. So kann die Animation auch nicht durch einen langsamen Rechner oder einen Reiterwechsel verfälscht werden.

if (laeuft) return;

Diese eine Zeile am Anfang des Knopf-Empfängers ist eine sogenannte Sperre. Ohne sie startete jeder weitere Klick während der Animation eine zweite Wecker-Kette; zwei Ketten schrieben abwechselnd in dieselbe Fläche, und am Ende erschienen zwei verschiedene Gewinner. Solche Sperren braucht man überall dort, wo eine Aktion Zeit braucht — beim Absenden eines Formulars genauso wie hier.

.map(function (zeile) { return zeile.trim(); })
.filter(function (zeile) { return zeile !== ""; });

Die Namensliste wird beim Einlesen gleich aufgeräumt: map schneidet bei jeder Zeile den Leerraum ab, filter wirft leere Zeilen weg. Ohne diesen Schritt könnte eine versehentliche Leerzeile den Losentscheid gewinnen — ein Fehler, der beim eigenen Testen nie auftritt und beim ersten echten Einsatz sofort.

Zum Anpassen: Für Gewichtungen — etwa doppelte Chance für Vereinsmitglieder — tragt ihr den Namen einfach mehrfach in die Liste ein; das Verfahren bleibt dasselbe. Soll die Ziehung nachvollziehbar sein, könnt ihr die gemischte Liste vollständig ausgeben statt nur die vordersten Plätze.

Script für die eigene Homepage

Kopiert euch den kompletten Code und fügt ihn an der Stelle eurer Seite ein, an der das Script erscheinen soll. Er läuft ohne weitere Dateien und ohne fremde Server.

Mehr aus der Kategorie Verschiedenes