1

Итак, я создаю математическую игру в серии для школы (потому что я думал, что это будет проще). Я столкнулся со странной проблемой при использовании операторов if. Таким образом, в основном, когда я вписываю 2 в командную строку, он переходит в строку в MIDDLE оператора if внутри другого оператора if, в который он даже не должен был входить.

@echo off
setlocal enabledelayedexpansion

:Start
@echo start game(1) or join game(2) note:game must be started for P2 to join
set /p YN=

IF %YN%==1 (
@echo creating files...
if not exist quizFiles (
    md "quizFiles"
)
@echo P1> quizFiles/gameState.txt
@echo 48> quizFiles/cards.txt
@echo.0> quizFiles/P1Score.txt
@echo.0> quizFiles/P2Score.txt
@echo false> quizFiles/P2Joined.txt
set /a gameMode=%RANDOM% %%4
@echo.!gameMode!> quizFiles/gameMode.txt
IF "!gameMode!"=="0" (
    set gameMode=LCM
) ELSE IF "!gameMode!"=="1" (
set gameMode=GCF
) ELSE IF "!gameMode!"=="2" (
    set gameMode=Muliplication of fractions
) ELSE IF "!gameMode!"=="3" (
    set gameMode=Division of fractions
)
@echo.!gameMode!
timeout /t 1 /nobreak > NUL
@echo waiting for other player to join...
set dot="2"
:WP2
set /p P2Joined=<quizFiles/P2Joined.txt
IF NOT "!P2Joined!"=="true" (
    timeout /t 2 /nobreak > NUL
    @echo waiting...
    GOTO WP2
)
@echo joined
:P1G
    set /p cardsRemaining=<quizFiles/cards.txt
    @echo cards left: !cardsRemaining!
    set /p P1Score=<quizFiles/P1Score.txt
    @echo P1 has: !P1Score! cards
    set /p P2Score=<quizFiles/P2Score.txt
    @echo P2 has: !P2Score! cards
    set /p currentPlayer=<quizFiles/gameState.txt
    @echo It is now !currentPlayer!'s turn
    @echo 4 cards chosen
    set /p gameMode=<quizFiles/gameMode.txt
    IF "!gameMode!"=="0" (
        set /a card1=%RANDOM% %%96
        set /a card2=%RANDOM% %%96
        set /a card3=%RANDOM% %%96
        set /a card4=%RANDOM% %%96
    )
    @echo card1: !card1!
    @echo card2: !card2!
    @echo card3: !card3!
    @echo card4: !card4!
    IF "!gameMode!"=="0" (
        @echo choose your first card(1-4)
        set /p chosenCard1=
        @echo choose your second card(1-4)
        set /p chosenCard2= <<<< leaks here
        @echo what is the LCM of these two cards
        set /p userAnswer=
    )
GOTO P1G
) ELSE IF %YN%==2 (
    @echo joining game...
    @echo true> quizFiles/P2Joined.txt
    timeout /t 1 /nobreak > NUL
    @echo joined
)
PAUSE

1 ответ1

2

Например, в вашем скрипте есть некоторые ошибки (возможно, неполные):

(1) Что, если пользователь просто нажимает только ENTER в ответ на set /p YN=? Используйте двойные кавычки, как указано ниже, IF "%YN%"=="1" ( или рассмотрите возможность переключения на команду CHOICE которая позволяет вводить нажатие одной клавиши с клавиатуры.

(2) Почему вы используете одну и ту же переменную gameMode для хранения разных вещей?

(3 - важно) Закрывающая скобка в echo choose your second card(1-4) используется в блоке кода в скобках, чтобы закрыть его. Либо избегайте его как echo … card(1-4^) либо используйте скобки другой формы, например квадратные скобки, как в echo … card [1-4] .

(4 - наиболее важно) Никогда не используйте :label or :: label-like comment внутри командного блока, заключенного в скобки () . Вместо этого создайте и вызовите подпрограмму . Вы можете goto свободном доступе внутри такой процедуры тела.

(5) %RANDOM% внутри командного блока, заключенного в скобки () соответствует одному и тому же номеру. Следовательно, все card1 card2 card3 и card4 в следующем фрагменте кода одинаковы:

IF "!gameMode!"=="0" (
    set /a card1=%RANDOM% %%96
    set /a card2=%RANDOM% %%96
    set /a card3=%RANDOM% %%96
    set /a card4=%RANDOM% %%96
)

Более того, даже не используя !RANDOM! вместо %RANDOM% может гарантировать разные значения. Сравните : перетащите процедуру :dragNthCard .

Полезный комментарий Дбенхэма вдохновил меня немного поиграть с вашим кодом. Вот черновик (работающий в некотором смысле, который не может полностью соответствовать вашей цели). Реализовал LCM и GCF как односторонний тест для инициатора P1 и присоединенного P2: одна и та же задача, разные наборы карт.

@ECHO OFF
SETLOCAL EnableExtensions EnableDelayedExpansion

:Start
@echo note:game must be started for P2 to join
CHOICE /C 12Q /M "start game (1) or join game (2) or quit game (Q)"
set "YN=%errorlevel%"
IF errorlevel 3 goto :eof
IF errorlevel 2 (
    @echo joining game...
    @echo true> quizFiles/P2Joined.txt
    timeout /t 1 /nobreak > NUL
    @echo joined
) ELSE (
    @echo creating files...
    if not exist quizFiles md "quizFiles"
    @echo P1> quizFiles/gameState.txt
    @echo 48> quizFiles/cards.txt
    @echo.0> quizFiles/P1Score.txt
    @echo.0> quizFiles/P2Score.txt
    @echo false> quizFiles/P2Joined.txt
    set /a gameMode=%RANDOM% %%4
    echo gameMode !gameMode!
    @echo.!gameMode!> quizFiles/gameMode.txt
    timeout /t 1 /nobreak > NUL
    @echo waiting for other player to join...
    call :waitToJoin
)
rem commont part for both initiator P1 and joined P2

call :dragCards
REM currently implemented only one round game 
REM 
REM set /p cardsRemaining=<quizFiles/cards.txt
REM @echo cards left: !cardsRemaining!
REM set /p P1Score=<quizFiles/P1Score.txt
REM @echo P1 has: !P1Score! cards
REM set /p P2Score=<quizFiles/P2Score.txt
REM @echo P2 has: !P2Score! cards
REM set /p currentPlayer=<quizFiles/gameState.txt
REM @echo It is now !currentPlayer!'s turn
REM 
@echo 4 cards chosen
set /p gameMode=<quizFiles/gameMode.txt
IF "!gameMode!"=="0" (
    set gameModeText=LCM
) ELSE IF "!gameMode!"=="1" (
set gameModeText=GCF
) ELSE IF "!gameMode!"=="2" (
    set gameModeText=Multiplication of fractions
) ELSE IF "!gameMode!"=="3" (
    set gameModeText=Division of fractions
)
echo gameMode !gameMode! !gameModeText!
set "rightAnswer=nonsens"
IF "!gameMode!"=="0" (
    call :Choose2Cards
    call :%gameModeText% !chosenCard1! !chosenCard2!
)
IF "!gameMode!"=="1" (
    call :Choose2Cards
    call :%gameModeText% !chosenCard1! !chosenCard2!
)
IF "!gameMode!"=="3" call :Choose2Cards & rem not implemented yet
IF "!gameMode!"=="4" call :Choose2Cards & rem not implemented yet
IF "%rightAnswer%"=="nonsens" (
    echo not implemented yet: %gameModeText%
) else (
    If "%userAnswer%"=="%rightAnswer%" (
      echo %userAnswer% is right 
    ) ELSE (
      echo %userAnswer% is wrong; right answer = %rightAnswer%
    )
)

rem PAUSE

:::::::::::::::::::::::::::::::
:::
:::  Your script continues here: save score, loop next round etc.
:::
:::::::::::::::::::::::::::::::

ENDLOCAL
goto :eof

:LCM
rem Least common multiple usage: call :lcm <input1> <input2>
rem by https://rosettacode.org/wiki/Least_common_multiple#Batch_File
set "_aux1=%1"
set "_aux2=%2"
:lcmSub
if %2 equ 0 (
    set /a rightAnswer = %_aux1%*%_aux2%/%1
    rem echo rightAnswer = !rightAnswer!
    goto :EOF
)
set /a res = %1 %% %2
call :lcmSub %2 %res%
goto :eof

:GCF
rem Greatest common factor / divisor
rem by https://rosettacode.org/wiki/Greatest_common_divisor#Batch_File
if %2 equ 0 (
    set rightAnswer=%1
    rem echo rightAnswer = !rightAnswer!
    goto :eof
)
set /a res = %1 %% %2
call :gcf %2 %res%
goto :eof

:Muliplication
goto :eof
:Division
goto :eof

:waitToJoin
  set dot="2"
  :WP2
  set /p P2Joined=<quizFiles/P2Joined.txt
  IF NOT "!P2Joined!"=="true" (
      timeout /t 2 /nobreak > NUL
      @echo waiting...
      GOTO WP2
  )
  @echo joined
goto :eof

:dragCards
:P1G
  for /L %%N in (1,1,4) do (
      call :dragNthCard %%N 
      echo card%%N: !card%%~N!
  )
goto :eof 

:Choose2Cards
    CHOICE /C 1234 /M "choose your first  card "
    set "chosenCard1=!card%errorlevel%!"
    :Choose2CardsDifferent
    CHOICE /C 1234 /M "choose your second card "
    set "chosenCard2=!card%errorlevel%!"
    If %chosenCard1% EQU %chosenCard2% goto :Choose2CardsDifferent
    echo what is the %gameModeText% of these two cards: %chosenCard1% and %chosenCard2%
    set /p "userAnswer=%gameModeText%( %chosenCard1%, %chosenCard2%) = "
goto :eof 

:dragNthCard
  set "_cardNo=%~1"
  set /A _cardMax=%_cardNo% - 1
  :dragNthAgain
  set /a card%_cardNo%=%RANDOM% %%96
  for /L %%G in (1,1,%_cardMax%) do (
    if !card%_cardNo%! EQU !card%%G! (
      timeout /t 1 /nobreak > NUL
      goto :dragNthAgain
    )
  )
  rem echo CARD%_cardNo%: !card%_cardNo%!
goto :eof 

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .