返回列表 发帖

[游戏娱乐] 一个用以抽奖的批处理

思路:
以csv格式存储两个文档:成员名单及其愿望(中特等奖后使用),奖项设置
成员名单按“编号,姓名,愿望”的格式存储文本,奖项设置按“中奖等级,名额,等级名称”的格式存储文本
将成员名单的内容读入内存,然后分别按奖项设置中的等级与名额来进行名单的随机滚动,人为按下任意键后停止滚动并显示中奖人序号名及字,如为特等奖,显示其愿望,并将显示内容语音播报。代码及附件如下:
@echo off
if not %1#==# goto %1
setlocal enabledelayedexpansion
prompt $
chcp 437>nul&graftabl 936>nul
color 0f
title 抽奖程序.::by 呼吸新世界::.
set /a nMemCount=0
set /a nChoiseCount=0
set /a gDegree=0
set "clr=123456789abcdef"
set /p= <nul>%tmp%\$$
:_Main
(
    call :_LoadList
   
    for /f "tokens=1,2,3 delims=, skip=1" %%i in (奖项设置.csv) do (
        call :_MakeList %%i %%j %%k
    )
   
    call :_ShowChoiseList
   
    goto :EOF
)
REM =============================================分割线======================================================
REM 取得列表
:_LoadList
(
    for /f "tokens=1,2,* delims=, skip=1" %%i in (名单.csv) do (
        if not %%k#==# (
            set /a nMemCount+=1
            call :_AddMemList !nMemCount! %%i "%%j" %%k  
        )
    )
    pause
    goto :EOF
)
REM 抽奖主函数(%1 抽奖等级0为特等奖,%2 抽奖名额)
:_MakeList
(
    echo.&echo.&echo.
    if not %3#==# (
        set "strShow=下面抽取%3..."
    ) else (
        set "strShow=下面抽取%1等奖..."
    )
    ECHO !strShow!
    call :_SpeakContent "!strShow:.=!"
    echo =========================================
    for /l %%i in (1 1 %2) do (
        call :_GetChoise %1
    )
    echo =========================================
    if not %3#==# (
        set "strShow=%3抽取完毕..."
    ) else (
        set "strShow=%1等奖抽取完毕..."
    )
    ECHO !strShow!
    call :_SpeakContent "!strShow:.=!"
    pause
    goto :EOF
)
REM 添加参与人员名单(%1 载入队列序号,%2 抽奖编号,%3 人员名字,%4 愿望)
:_AddMemList
(
    set /a nNum%1=%2
    set strName%1=%3
    set strName%1=!strName%1:"=!
    set "strWish%1=%4"
    set "strWish%1=!strWish%1:"=!"
    set "strShowNum=  !nNum%1!"
    set "strShowNum=!strShowNum:~-2!"
    echo 编号:!strShowNum!    人名:!strName%1!    愿望:!strWish%1!
    goto :EOF
)
REM 添加已抽中人员名单(%1 抽中队列序号,%2 抽奖编号,%3 人员名字)
:_AddChoiseList
(
    set /a nChoiseNum%1=%2
    set "strChoiseName%1=%3"
    set "strChoiseName%1=!strChoiseName%1:"=!"
    set "strNull=!strNull:"=!"
    goto :EOF
)
REM 得到抽奖号码的名字,如为特殊奖项,报出其愿望(%1 载入队列序号,%2 抽奖等级)
:_GetMem
(
    if not !nNum%1!#==# (
        call :_ChkMem %1 %2
        if !nContinue!#==1# (
            set /a nChoiseCount+=1
            call :_AddChoiseList !nChoiseCount! !nNum%1! "!strName%1!"
            set "strNum=     !nNum%1!"
            set "strNum=!strNum:~-3!"
            echo.
            echo 请编号为 !strNum! 的 【!strName%1!】 上台领奖...
            call :_SpeakContent "请编号为 !strNum!!strName%1! 上台领奖"
            REM if %2#==1# (
            REM     rem pause
            REM     echo 恭喜 【!strName%1!】 抽中一等奖,其愿望为 【!strWish%1!】
            REM     call :_SpeakContent "恭喜 !strName%1! 抽中一等奖,其愿望为 !strWish%1!"
            REM )
            if %2#==0# (
                REM pause
                echo 恭喜 【!strName%1!】 抽中特等奖,其愿望为 【!strWish%1!
                call :_SpeakContent "恭喜 !strName%1! 抽中特等奖,其愿望为 !strWish%1!"
            )
        ) else (
            echo 重复号码!nNum%1!, 重新抽取...
            call :_SpeakContent "重复号码!nNum%1!, 重新抽取"
            call :_GetChoise %2
            GOTO :EOF
        )  
    ) else (
        echo 对不起,当前列表中无此抽奖号码...
        call :_SpeakContent "对不起,当前列表中无此抽奖号码"
    )
    goto :EOF
)
REM 得到并检测当前产生的抽奖号码(%1 抽奖等级)
:_GetChoise
(
    REM set /a nTmp=!random!%%!nMemCount!+1
    REM echo 当前产生随机号为:!nTmp!
    REM call :_GetMem !nTmp! %1
   
    set /a gDegree=%1
    call :_StartScroll
    REM pause>nul
    goto :EOF
)
set /a nHaveMem=0
set /a nContinue=0
REM 检测是否有重复被抽取的情况(%1 载入队列序号,%2 抽奖等级)
:_ChkMem
(
    for /l %%i in (1 1 !nChoiseCount!) do (
        call :_ChkList %1 %%i
        if !nHaveMem!#==1# (
            set /a nContinue=0
            goto :EOF
        )
    )
    set /a nContinue=1
    goto :EOF
)
REM 检测已存储抽奖队列中是否有当前编号(%1 载入队列序号,%2 已抽中队列中的序号)
:_ChkList
(
    if !nNum%1!#==!nChoiseNum%2!# (
        set /a nHaveMem=1
    ) else (
        set /a nHaveMem=0
    )
    goto :EOF
)
REM 显示已抽中人员名单(%1 已抽中队列序号)
:_ShowChoiseNum
(
    set "nTmp=   %1"
    set "nTmp=!nTmp:~-3!"
    set "nTmpNum=   !nChoiseNum%1!"
    set "nTmpNum=!nTmpNum:~-3!"
    set "strShow2=第 !nTmp! 个抽中人员编号为 !nTmpNum!     姓名为【!strChoiseName%1!】"
    call :_ShowColorLine "!strShow2!"
    echo.
    goto :EOF
)
REM 语音播报内容(%1 播报文本内容)
:_SpeakContent
(
    set "strTmp=%1"
    set "strTmp=!strTmp: =!"
    mshta "javascript:new ActiveXObject("sapi.spvoice").speak(!strTmp!);window.close();"
    goto :EOF
)
REM 显示抽奖列表
:_ShowChoiseList
(
    echo.&echo.&echo.
    for /l %%i in (1 1 !nChoiseCount!) do (
        call :_ShowChoiseNum %%i
    )
    pause
    goto :EOF
)
REM 显示滚动名单(%1 序号)
:_ShowScrollList
(   
    set "strTmp=   !nNum%1!"
    set "strTmp=!strTmp:~-3!"
   
    if not !nNewLine!#==1# (
        set /p=<nul
    )
    set "strShow=★编号『!strTmp!』            姓名『!strName%1!』★"
    call :_ShowColorLine "!strShow!"
   
    set /a nNewLine=0
    goto :EOF
)
REM 随机显示
:_ShowRnd
(
    REM color 9e
    set /a nTmp=!random!%%!nMemCount!+1
    REM echo 当前产生随机号为:!nTmp!
    call :_ShowScrollList !nTmp!
    REM pause>nul
    if exist $ (
        REM pause>nul
        del $
        REM color
        set /a nNewLine=0
        call :_GetMem !nTmp! !gDegree!
        goto :EOF
    )
   
    goto :_ShowRnd
    goto :EOF
)
REM 开始滚动
:_StartScroll
(
    del $ 2>nul
    start /b %~fs0 :_Thread
   
    call :_ShowRnd
   
    goto :EOF
)
set /a nNewLine=0
REM 另开线程用以监听按键
:_Thread
(
    set /a nNewLine=1
    pause>nul
    >$ echo.
    exit
)
REM 彩色字体显示(%1 显示的语句)
:_ShowColorLine
(
    set /a nRndB=!random!%%15
:_ReTry
    set /a nRndF=!random!%%15
    if !nRndB!#==!nRndF!# goto :_ReTry
    call set tmpClr=%%clr:~!nRndB!,1%%%%clr:~!nRndF!,1%%
    REM echo !tmpClr!
    set "strShow1=%1"
    set "strShow1=!strShow1:"=!"
    set "strNull=!strNull:"=!"
    pushd %tmp%
    (
        set /p=<nul
        ren $$ "!strShow1!" >nul 2>nul
        findstr /a:!tmpClr! . "!strShow1!*"
        ren "!strShow1!" $$ >nul 2>nul
    )
    popd
   
    goto :EOF
)
REM =============================================分割线======================================================COPY
链接: https://pan.baidu.com/s/1Mmii3SeZR-QuN5PV7nUz8Q?pwd=u7as

两点建议:
1、重复中奖号码在后台处理掉就行了,没有必要显示出来,对于观众来说它没有什么意义。
2、需要考虑中奖人没到现场,需要补抽的问题,年会上经常有这事。比如10个五等奖,其中3个人没来,就要再抽3个五等奖。

TOP

回复 2# DAIC

  好提议,重复抽奖当初在使用的时候也发现这个问题了,特别是随着中奖人员的增加,后期会有很多重复的情况出现,后台处理也会相对较慢,当时想了另一个方法,就是将未抽中的人员另存一个队列,后面的抽奖直接在这个队列里面进行挑选,这样就快得多了。至于说的未到人员,因为领取编号是到年会之后再领取的号牌,名字与愿望是事先输入的,在处理时,对于未编号的人员是直接跳过的,所以这个问题当时也就没有过多处理。

TOP

返回列表