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

时间:2014-08-29 14:46:33

标签: batch-file

我正在编写一个小脚本,将角色分配为应用程序。它要求人数,然后随机运行以查看您的角色。 像这样:

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

但是,如果我只想让一定比例的人获得某种角色呢?说1:4是杀人犯。如果我为多达8名球员做这样的事情,如果他们中的6人是凶手呢?如果有8个人,我想再次参加侦探角色怎么办?我目前的mrole是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

2 个答案:

答案 0 :(得分:1)

您正在寻找的算法是随机播放。把你的角色想象成一个套牌 卡,每张卡一个角色。如果你和人一起玩游戏,你就是这样 洗牌角色,并将一张牌交给每个人。

研究以下代码,声明一副4张牌,然后将它们洗牌。 我用更传统的编程命名了阵列风格的套牌 语言,但它只是一个惯例。我本来可以把它命名为 形式DECK.1, DECK.2, ...或其他什么。

我还将程序的一部分分离为子程序。这是一个子程序 生成随机数,打印"数组",随机播放数组,然后交换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.

答案 1 :(得分:0)

@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

这是一个可能实现目标的片段。

但首先,有一点商业广告 - 你的帖子中有一条线:

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

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

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

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

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

确定游戏的角色集后,您可以将字符串中的每个角色分配给玩家,并在分配角色时删除该角色。

我使用标准的clear out all variables with names starting "$"'例程;然后分配所需的角色,(根据需要附加任何额外的东西)然后循环很简单 - 选择一个随机播放器;如果该玩家已经分配了角色,请再次选择。如果没有,只需在列表中分配最后一个角色并删除最后一个角色条目。继续,直到roles列表为空,并且全部完成...