2 Stimmen

Verwenden von Zufall, um einen Wert festzulegen und zu verhindern, dass der Wert erneut angegeben wird?

Ich erstelle ein kleines Skript, das Rollen wie in einer App zuweist. Es fragt nach der Anzahl der Personen und führt dann eine Zufallsauswahl durch, um die Rolle jeder Person festzulegen. So etwas wie:

:mrole
set/a player1=%random% * 4 / 32768 + 1
if %player1%==1 set 1role=Mörder

Aber was ist, wenn ich nur ein bestimmtes Verhältnis von Personen eine bestimmte Rolle bekommen möchte? Zum Beispiel sind 1:4 Mörder. Was ist, wenn ich bis zu 8 Spieler habe und 6 von ihnen Mörder sind? Was ist, wenn ich nochmal durchgehen möchte, um eine Detektivrolle zu erhalten, wenn es 8 Personen gibt? Das aktuelle, das ich für mrole habe, umfasst 29 Zeilen! Gibt es einen schnelleren Weg, als jedes Mal zu überprüfen, ob es zu viele gibt? Und die Detektivprüfung wird auch sehr lang sein!

Was ich bisher habe, ist unten und hier ist ein Link: http://pastebin.com/g2GfN7v9

@echo off

:new
set test=2

:main
cls
echo Ärger in Mordstadt
echo --------------------------
echo.
echo 1. Start
echo 2. Tester-Optionen
echo 3. Beenden
echo.
set/p m=
if %m%==1 goto start
if %m%==2 goto testrat
if %m%==3 exit
goto main

:testrat
cls
echo Chance, einen Tester zu haben
echo -----------------------
echo Derzeit eine 1 zu %test% Chance, einen Tester in einem Spiel zu haben
echo.
echo 1. Immer
echo 2. Nie
echo 3. 1/2 (Standard)
echo 4. 1/3
echo 5. 1/4
echo 6. 1/5
echo 7. Zurück
echo.
set/p t=
if %t%==1 set test=1
if %t%==2 set test=0
if %t%==3 set test=2
if %t%==4 set test=3
if %t%==5 set test=4
if %t%==6 set test=5
if %t%==7 goto options
goto testrat

:start
cls
echo Wie viele Spieler gibt es, ohne den am Computer mitzurechnen?
echo.
echo 1. 3
echo 2. 4
echo 3. 5
echo 4. 6
echo 5. 7
echo 6. 8
echo 7. Quit
echo.
set/p t=
if %t%==1 set players=3
if %t%==2 set players=4
if %t%==3 set players=5
if %t%==4 set players=6
if %t%==5 set players=7
if %t%==6 set players=8
if %t%==1 goto names
if %t%==2 goto names
if %t%==3 goto names
if %t%==4 goto names
if %t%==5 goto names
if %t%==6 goto names
if %t%==7 goto main
goto start

:names
cls
echo Bitte geben Sie ihre Namen ein.
echo.
set/p player1=Spieler 1: 
echo.
set/p player2=Spieler 2: 
echo.
set/p player3=Spieler 3: 
echo.
if %players%==8 (
    set/p player4=Spieler 4: 
    echo.
    set/p player5=Spieler 5: 
    echo.
    set/p player6=Spieler 6: 
    echo.
    set/p player7=Spieler 7: 
    echo.
    set/p player8=Spieler 8: 
    goto role
) else if %players%==7 (
    set/p player4=Spieler 4: 
    echo.
    set/p player5=Spieler 5: 
    echo.
    set/p player6=Spieler 6: 
    echo.
    set/p player7=Spieler 7: 
    goto role
) else if %players%==6 (
    set/p player4=Spieler 4: 
    echo.
    set/p player5=Spieler 5: 
    echo.
    set/p player6=Spieler 6: 
    goto role
) else if %players%==5 (
    set/p player4=Spieler 4: 
    echo.
    set/p player5=Spieler 5: 
    goto role
) else if %players%==4 (
    set/p player4=Spieler 4: 
    goto role
) else goto role

:role
set 1role=0
set 2role=0
set 3role=0
set 4role=0
set 5role=0
set 6role=0
set 7role=0
set 8role=0
set murderers=0
set detectives=0
goto mrole

:mrole
set/a player1=%random% * 4 / 32768 + 1
if %player1%==1 set 1role=Mörder
if %player1%==1 set/a murderers=%murderers% + 1
if %player1%==1 set mcheck=y
if %player1% neq 1 set mcheck=n
if %mcheck%==y if %players% lss 8 goto drole
set/a player2=%random% * 4 / 32768 + 1
if %murderers%==1 if %players%==8 if %player2%==1 set 2role=Mörder
if %mcheck%==y if %players% lss 8 goto drole
set/a player3=%random% * 4 / 32768 + 1
if %murderers%==1 if %players%==8 if %player3%==1 set 3role=Mörder
if %mcheck%==y if %players% lss 8 goto drole
set/a player4=%random% * 4 / 32768 + 1
if %mcheck%==y if %players% lss 8 goto drole
if %murderers%==1 if %players%==8 if %player4%==1 set 4role=Mörder
set/a player5=%random% * 4 / 32768 + 1
if %mcheck%==y if %players% lss 8 goto drole
if %murderers%==1 if %players%==8 if %player5%==1 set 5role=Mörder
set/a player6=%random% * 4 / 32768 + 1
if %mcheck%==y if %players% lss 8 goto drole
if %murderers%==1 if %players%==8 if %player6%==1 set 6role=Mörder
set/a player7=%random% * 4 / 32768 + 1
if %mcheck%==y if %players% lss 8 goto drole
if %murderers%==1 if %players%==8 if %player7%==1 set 7role=Mörder
set/a player8=%random% * 4 / 32768 + 1
if %mcheck%==y if %players% lss 8 goto drole
if %murderers%==1 if %players%==8 if %player8%==1 set 8role=Mörder
if %murderers% lss 1 goto mrole
if %players%==8 if %murderers% lss 2 goto mrole

:drole
if %players%==8 (

) else if %players lss 8 goto irole

:irole
if 1role==0 set 1role=Unschuldig
if 2role==0 set 2role=Unschuldig
if 3role==0 set 3role=Unschuldig
if 4role==0 set 4role=Unschuldig
if 5role==0 set 5role=Unschuldig
if 6role==0 set 6role=Unschuldig
if 7role==0 set 7role=Unschuldig
if 8role==0 set 8role=Unschuldig

1voto

indiv Punkte 16498

Der Algorithmus, den Sie suchen, ist ein Shuffle. Denken Sie an Ihre Rollen wie ein Kartenspiel, mit einer Rolle pro Karte. Wenn Sie ein Spiel mit Menschen spielen würden, würden Sie das Deck mit Rollen mischen und jeder Person eine Karte aushändigen.

Studieren Sie den folgenden Code, der ein Deck mit 4 Karten deklariert und sie dann mischt. Ich habe das Deck im Stil eines Arrays aus traditionelleren Programmiersprachen benannt, aber es ist wirklich nur eine Konvention. Ich hätte es auch im Format DECK.1, DECK.2, ... oder ähnlich nennen können.

Ich habe auch Teile des Programms in Unterprogramme isoliert. Es gibt ein Unterprogramm, um eine Zufallszahl zu generieren, ein "Array" zu drucken, ein Array zu mischen und 2 Elemente in einem Array auszutauschen. Wenn Sie mit arrayähnlicher Indirektion in Stapelverarbeitung arbeiten, werden Sie an Ihre Grenzen stoßen, wenn Sie die Dinge nicht in Unterprogramme aufteilen.

@echo off
setlocal EnableDelayedExpansion

set "DECK[0]=1H"
set "DECK[1]=2S"
set "DECK[2]=3C"
set "DECK[3]=4D"
set "DECK_SIZE=4"

call :print_array "DECK" %DECK_SIZE%
call :shuffle "DECK" %DECK_SIZE%
echo -----
call :print_array "DECK" %DECK_SIZE%

goto :eof

REM Generiere eine Zufallszahl von %1 min bis %2 max.
:rand
set /a RAND_NUM=%RANDOM% * (%~2 - %~1 + 1) / 32768 + %~1
goto :eof

REM %1 Name des Arrays, das gedruckt werden soll
REM %2 Größe des Arrays
:print_array
set /a LAST_INDEX=%~2-1
for /L %%a in (0, 1, %LAST_INDEX%) do (
    echo %~1[%%a]: !%~1[%%a]!
)
goto :eof

rem Um ein Array a von n Elementen (Indizes 0..n-1) zu mischen:
rem   für i von n 1 abwärts bis 1 machen
rem        wähle j zufällige ganze Zahl mit 0 j i
rem        tausche a[j] und a[i] aus

REM %1 Name des Arrays, das gemischt werden soll
REM %2 Größe des Arrays
:shuffle
set /a LAST_INDEX=%~2-1
for /L %%a in (0, 1, %LAST_INDEX%) do (
    call :rand %%a %LAST_INDEX%
    call :swap "%~1[%%a]" "%~1[!RAND_NUM!]"
)
goto :eof

REM %1 Eine der Variablen, die vertauscht werden sollen.
REM %2 Die andere Variable, die vertauscht werden soll.
:swap
set "__tmp=!%~1!"
set "%~1=!%~2!"
set "%~2=!__tmp!"
goto :eof

Um diesen Code für Ihr Programm anzupassen, möchten Sie ein Array von Spielern und ein Array von Rollen haben. Das Spieler-Array bleibt fest, und Sie mischen das Rollen-Array.

Zum Beispiel,

set "PLAYER[0]=Howard"
set "PLAYER[1]=Fred"
set "PLAYER[2]=Robin"
set "PLAYER[3]=Gary"
set PLAYER_SIZE=4

set "ROLE[0]=Mörder"
set "ROLE[1]=Unschuldiger"
set "ROLE[2]=Unschuldiger"
set "ROLE[3]=Detektiv"
set "ROLE_SIZE=4"

call :shuffle "ROLE" %ROLE_SIZE%
set /a ROLE_LAST_INDEX=%ROLE_SIZE%-1
for /L %%a in (0, 1, %ROLE_LAST_INDEX%) do (
    echo Spieler !PLAYER[%%a]! ist !ROLE[%%a]!.
)

Ein Beispieloutput dieses Codes würde Ihnen geben:

Spieler Howard ist Detektiv.
Spieler Fred ist unschuldig.
Spieler Robin ist Mörder.
Spieler Gary ist unschuldig.

0voto

Magoo Punkte 76050
@ECHO AUS
SETLOCAL
:: Variablen entfernen, die mit $ beginnen
FOR  /F "delims==" %%a In ('set $ 2^>Nul') DO SET "%%a="

SET "rollen=1234"
SET spieler=4
:setzspielrolle
SET /a spieler=1+(%ZUFÄLLIG% %% %spieler%)
IF DEFINIERT $%spieler% GOTO setzspielrolle
SET $%spieler%=%rollen:~-1%&SET "rollen=%rollen:~0,-1%"
IF DEFINIERT rollen GOTO setzspielrolle

SET $

GOTO :EOF

Hier ist ein Ausschnitt, der Ihr Ziel erreichen könnte.

Zuerst jedoch eine kleine Anmerkung - Sie haben diese Zeile in Ihrem Posting:

if %player1%==1 set 1role=Murderer

Es ist möglich, dies zu tun, aber eine wirklich, wirklich schlechte Idee aufgrund der Syntax von Batch. Beginnen Sie niemals einen Variablennamen mit einer Zahl. Das hat enorme Konsequenzen, und keine davon ist gut.

--- zurück zu unserem - äh, Programm...

Es ist nicht klar, ob Ihr Problem darin besteht, die Verhältnisse der Rollen auf die Spieler zu verteilen, aber es scheint, dass Sie eine Proportion in jeder Rolle wünschen; garantiert, dass niemand diese Rolle nicht spielt.

Für mich wäre das, was Sie tun würden, eine Menge von Rollen zuweisen - ich habe einfach 1..4 mit einer gleichmäßigen Verteilung verwendet. Möglicherweise möchten Sie 10 Spieler haben, einer in jeder Rolle 1..4 und die anderen zufällig, wobei Sie den Rollen-String aufbauen könnten, indem Sie die zufälligen Rollen an einen Samen von erforderlichen Rollen anhängen.

Nachdem die Rollen für das Spiel festgelegt wurden, weisen Sie dann jeder Rolle im String einen Spieler zu und entfernen Sie die Rolle, sobald sie zugewiesen wurde.

Ich verwende eine Standardroutine zum Entfernen aller Variablen mit Namen, die mit "$" beginnen; weisen Sie dann die erforderlichen Rollen zu (hängen Sie beliebige Extras an, wie Sie möchten) - dann ist die Schleife einfach: Wählen Sie einen zufälligen Spieler; wenn dieser Spieler bereits eine zugewiesene Rolle hat, wählen Sie erneut. Wenn nicht, weisen Sie einfach die letzte Rolle in der Liste zu und entfernen Sie den letzten Rolle-Eintrag. Fahren Sie fort, bis die Rollen-Liste leer ist, und alles ist erledigt...

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X