使用随机设置值并防止再次给出值?

问题描述:

我正在制作一个小脚本,将角色分配为一种应用程序。它要求的人数,然后随机运行,看看你是什么角色。 像这样:使用随机设置值并防止再次给出值?

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

但如果我只希望人们一定比例获得了一定的作用是什么?说1:4是凶手。如果我为8名球员做这样的事情,如果他们中有6人是杀人犯呢?如果我想再次遇到8人的侦探角色呢?目前我所买的是29行!有没有比检查是否有太多时间更快的方法?而侦探检查也将会很长!

我有这么远低于这里是一个链接:http://pastebin.com/g2GfN7v9

@echo off 

:new 
set test=2 

:main 
cls 
echo Trouble in Murder Town 
echo -------------------------- 
echo. 
echo 1. Start 
echo 2. Tester Options 
echo 3. Quit 
echo. 
set/p m= 
if %m%==1 goto start 
if %m%==2 goto testrat 
if %m%==3 exit 
goto main 

:testrat 
cls 
echo Chance to have a tester 
echo ----------------------- 
echo Currently a 1 in %test% chance to have a tester in a game 
echo. 
echo 1. Always 
echo 2. Never 
echo 3. 1/2 (default) 
echo 4. 1/3 
echo 5. 1/4 
echo 6. 1/5 
echo 7. Back 
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 How many players not including the one at the computer? 
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 Please enter their names. 
echo. 
set/p player1=Player 1: 
echo. 
set/p player2=Player 2: 
echo. 
set/p player3=Player 3: 
echo. 
if %players%==8 (
    set/p player4=Player 4: 
    echo. 
    set/p player5=Player 5: 
    echo. 
    set/p player6=Player 6: 
    echo. 
    set/p player7=Player 7: 
    echo. 
    set/p player8=Player 8: 
    goto role 
) else if %players%==7 (
    set/p player4=Player 4: 
    echo. 
    set/p player5=Player 5: 
    echo. 
    set/p player6=Player 6: 
    echo. 
    set/p player7=Player 7: 
    goto role 
) else if %players%==6 (
    set/p player4=Player 4: 
    echo. 
    set/p player5=Player 5: 
    echo. 
    set/p player6=Player 6: 
    goto role 
) else if %players%==5 (
    set/p player4=Player 4: 
    echo. 
    set/p player5=Player 5: 
    goto role 
) else if %players%==4 (
    set/p player4=Player 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=Murderer 
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=Murderer 
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=Murderer 
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=Murderer 
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=Murderer 
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=Murderer 
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=Murderer 
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=Murderer 
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=Innocent 
if 2role==0 set 2role=Innocent 
if 3role==0 set 3role=Innocent 
if 4role==0 set 4role=Innocent 
if 5role==0 set 5role=Innocent 
if 6role==0 set 6role=Innocent 
if 7role==0 set 7role=Innocent 
if 8role==0 set 8role=Innocent 

你要找的算法是一个洗牌。把你的角色想象成一副扑克牌 ,每张牌只有一个角色。如果你正在和别人玩游戏,你可以洗牌,然后把一张牌交给每个人。

研究下面的代码,它声明4张牌的牌组然后洗牌。 我已经从更传统的编程 语言中将数组的风格命名为数组,但它实际上只是一个约定。我可以用DECK.1, DECK.2, ...的 表格或其他名称命名它。

我也将程序的部分分离成子程序。有一个子程序 生成一个随机数,打印一个“数组”,洗牌一个数组,并交换数组中的项目。当在批处理中使用数组式间接寻址时,如果不将事情分解为子例程,您将会遇到墙壁问题 。

@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 Generate random number from %1 min through %2 max. 
:rand 
set /a RAND_NUM=%RANDOM% * (%~2 - %~1 + 1)/32768 + %~1 
goto :eof 

REM %1 Name of array to print 
REM %2 Size of the array 
: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 To shuffle an array a of n elements (indices 0..n-1): 
rem for i from n − 1 downto 1 do 
rem  j ← random integer with 0 ≤ j ≤ i 
rem  exchange a[j] and a[i] 

REM %1 Name of array to shuffle 
REM %2 Size of the array 
: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 One of the variables to swap. 
REM %2 The other variable to swap. 
:swap 
set "__tmp=!%~1!" 
set "%~1=!%~2!" 
set "%~2=!__tmp!" 
goto :eof 

所以要修改这个代码,你的程序,你想要的球员阵列和阵列 角色。播放器阵列保持不变,并且您洗牌角色数组。

例如,从这个代码

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

set "ROLE[0]=murderer" 
set "ROLE[1]=innocent" 
set "ROLE[2]=innocent" 
set "ROLE[3]=detective" 
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 Player !PLAYER[%%a]! is !ROLE[%%a]!. 
) 

一个输出样本会给你:

Player Howard is detective. 
Player Fred is innocent. 
Player Robin is murderer. 
Player Gary is innocent. 

@ECHO OFF 
SETLOCAL 
:: remove variables starting $ 
FOR /F "delims==" %%a In ('set $ 2^>Nul') DO SET "%%a=" 

SET "roles=1234" 
SET players=4 
:setplayrole 
SET /a player=1+(%RANDOM% %% %players%) 
IF DEFINED $%player% GOTO setplayrole 
SET $%player%=%roles:~-1%&SET "roles=%roles:~0,-1%" 
IF DEFINED roles GOTO setplayrole 

SET $ 

GOTO :EOF 

下面是可能实现你的目标的一个片段。

但首先,有点商业 - 你必须在你的帖子TIS线:

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

庵 - 它是可能要做到这一点,但由于批量语法的一个非常,非常糟糕的主意。切勿使用数字启动变量名称。它有巨大的后果,没有一个是好的。

---回到我们的 - 呃,程序...

我不清楚你的困难是否分配角色给玩家的比例,但似乎要在每个角色的比例;保证没有'没有人扮演这个角色'。

对我来说,你要做的是分配一组roles - 我只是使用1..4的均匀分布。您可能希望有10名玩家,角色分别为1..4和其他玩家,您可以通过将random角色附加到所需角色的种子来构建roles字符串。

在建立了游戏角色集之后,您将字符串中的每个角色分配给玩家,并在角色被分配时移除角色。

我使用标准clear out all variables with names starting "$"'例程;然后分配所需的角色,(如你所愿追加任何额外的),然后循环很简单 - 选择一个随机玩家;如果该玩家已拥有指定的角色,请再次选择。如果不是,只需分配列表中的最后一个角色并删除最后一个角色条目。继续,直到roles列表为空,并且全部完成...