I wonder if there is a simple way to branch execution in a Windows batch file depending on the value of one single expression. Something akin to switch/case blocks in C, C++, C#, Java, JavaScript, PHP, and other real programming languages.
My only workaround is a plain if/else block where the same expression is repeatedly checked for equality against different values:
IF "%ID%"=="0" (
REM do something
) ELSE IF "%ID%"=="1" (
REM do something else
) ELSE IF "%ID%"=="2" (
REM do another thing
) ELSE (
REM default case...
)
So dumb. Is there a better solution?
I ended up using label names containing the values for the case expressions as suggested by AjV Jsy. Anyway, I use CALL instead of GOTO to jump into the correct case block and GOTO :EOF to jump back. The following sample code is a complete batch script illustrating the idea.
#ECHO OFF
SET /P COLOR="Choose a background color (type red, blue or black): "
2>NUL CALL :CASE_%COLOR% # jump to :CASE_red, :CASE_blue, etc.
IF ERRORLEVEL 1 CALL :DEFAULT_CASE # If label doesn't exist
ECHO Done.
EXIT /B
:CASE_red
COLOR CF
GOTO END_CASE
:CASE_blue
COLOR 9F
GOTO END_CASE
:CASE_black
COLOR 0F
GOTO END_CASE
:DEFAULT_CASE
ECHO Unknown color "%COLOR%"
GOTO END_CASE
:END_CASE
VER > NUL # reset ERRORLEVEL
GOTO :EOF # return from CALL
This is simpler to read:
IF "%ID%"=="0" REM do something
IF "%ID%"=="1" REM do something else
IF "%ID%"=="2" REM do another thing
IF %ID% GTR 2 REM default case...
Compact form for short commands (no 'echo'):
IF "%ID%"=="0" ( ... & ... & ... ) ELSE ^
IF "%ID%"=="1" ( ... ) ELSE ^
IF "%ID%"=="2" ( ... ) ELSE ^
REM default case...
After ^ must be an immediate line end, no spaces.
I guess all other options would be more cryptic. For those who like readable and non-cryptic code:
IF "%ID%"=="0" (
REM do something
) ELSE IF "%ID%"=="1" (
REM do something else
) ELSE IF "%ID%"=="2" (
REM do another thing
) ELSE (
REM default case...
)
It's like an anecdote:
Magician: Put the egg under the hat, do the magic passes ... Remove the hat and ... get the same egg but in the side view ...
The IF ELSE solution isn't that bad. It's almost as good as python's if elif else. More cryptic 'eggs' can be found here.
I searched switch / case in batch files today and stumbled upon this. I used this solution and extended it with a goto exit.
IF "%1"=="red" echo "one selected" & goto exit
IF "%1"=="two" echo "two selected" & goto exit
...
echo "Options: [one | two | ...]
:exit
Which brings in the default state (echo line) and no extra if's when the choice is found.
Hariprasad didupe suggested a solution provided by Batchography, but it could be improved a bit. Unlike with other cases getting into default case will set ERRORLEVEL to 1 and, if that is not desired, you should manually set ERRORLEVEL to 0:
goto :switch-case-N-%N% 2>nul || (
rem Default case
rem Manually set ERRORLEVEL to 0
type nul>nul
echo Something else
)
...
The readability could be improved for the price of a call overhead:
call:Switch SwitchLabel %N% || (
:SwitchLabel-1
echo One
goto:EOF
:SwitchLabel-2
echo Two
goto:EOF
:SwitchLabel-3
echo Three
goto:EOF
:SwitchLabel-
echo Default case
)
:Switch
goto:%1-%2 2>nul || (
type nul>nul
goto:%1-
)
exit /b
Few things to note:
As stated before, this has a call overhead;
Default case is required. If no action is needed put rem inside to
avoid parenthesis error;
All cases except the default one are executed in the sub-context. If
you want to exit parent context (usually script) you may use this;
Default case is executed in a parent context, so it cannot be
combined with other cases (as reaching goto:EOF will exit parent
context). This could be circumvented by replacing goto:%1- in
subroutine with call:%1- for the price of additional call overhead;
Subroutine takes label prefix (sans hyphen) and control variable. Without label
prefix switch will look for labels with :- prefix (which are valid) and
not passing a control variable will lead to default case.
Try by this way. To perform some list of operations like
Switch case has been used.
Checking the conditional statements.
Invoking the function with more than two arguments.
#echo off
:Start2
cls
goto Start
:Start
echo --------------------------------------
echo Welcome to the Shortcut tool
echo --------------------------------------
echo Choose from the list given below:
echo [1] 2017
echo [2] 2018
echo [3] Task
set /a one=1
set /a two=2
set /a three=3
set /a four=4
set input=
set /p input= Enter your choice:
if %input% equ %one% goto Z if NOT goto Start2
if %input% equ %two% goto X if NOT goto Start2
if %input% equ %three% goto C if NOT goto Start2
if %input% geq %four% goto N
:Z
cls
echo You have selected year : 2017
set year=2017
echo %year%
call:branches year
pause
exit
:X
cls
echo You have selected year : 2018
set year=2018
echo %year%
call:branches year
pause
exit
:C
cls
echo You have selected Task
call:Task
pause
exit
:N
cls
echo Invalid Selection! Try again
pause
goto :start2
:branches
cls
echo Choose from the list of Branches given below:
echo [1] January
echo [2] Feburary
echo [3] March
SETLOCAL
set /a "Number1=%~1"
set input=
set /p input= Enter your choice:
set /a b=0
set /a bd=3
set /a bdd=4
if %input% equ %b% goto N
if %input% leq %bd% call:Z1 Number1,input if NOT goto Start2
if %input% geq %bdd% goto N
:Z1
cls
SETLOCAL
set /a "Number1=%~1"
echo year = %Number1%
set /a "Number2=%~2"
echo branch = %Number2%
call:operation Number1,Number2
pause
GOTO :EOF
:operation
cls
echo Choose from the list of Operation given below:
echo [1] UB
echo [3] B
echo [4] C
echo [5] l
echo [6] R
echo [7] JT
echo [8] CT
echo [9] JT
SETLOCAL
set /a "year=%~1"
echo Your have selected year = %year%
set /a "month=%~2"
echo You have selected Branch = %month%
set operation=
set /p operation= Enter your choice:
set /a b=0
set /a bd=9
set /a bdd=10
if %input% equ %b% goto N
if %operation% leq %bd% goto :switch-case-N-%operation% if NOT goto Start2
if %input% geq %bdd% goto N
:switch-case-N-1
echo Januray
echo %year%,%month%,%operation%
goto :switch-case-end
:switch-case-N-2
echo Feburary
echo %year%,%month%,%operation%
goto :switch-case-end
:switch-case-N-3
echo march
echo %year%,%month%,%operation%
goto :switch-case-end
:switch-case-end
echo Task Completed
pause
exit
goto :start2
:Task
cls
echo Choose from the list of Operation given below:
echo [1] UB
echo [3] B
echo [4] C
echo [5] l
echo [6] R
echo [7] JT
echo [8] CT
echo [9] JT
SETLOCAL
set operation=
set /p operation= Enter your choice:
set /a b=0
set /a bd=9
set /a bdd=10
if %input% equ %b% goto N
if %operation% leq %bd% goto :switch-case-N-%operation% if NOT goto Start2
if %input% geq %bdd% goto N
:switch-case-N-1
echo Januray
echo %operation%
goto :switch-case-end
:switch-case-N-2
echo Feburary
echo %year%,%month%,%operation%
goto :switch-case-end
:switch-case-N-3
echo march
echo %year%,%month%,%operation%
goto :switch-case-end
:switch-case-end
echo Task Completed
pause
exit
goto :start2
If if is not working you use:
:switch case %n%=1
statements;
goto :switch case end
etc..
http://lallouslab.net/2016/12/21/batchography-switch-case/
It might be a bit late, but this does it:
set "case1=operation1"
set "case2=operation2"
set "case3=operation3"
setlocal EnableDelayedExpansion
!%switch%!
endlocal
%switch% gets replaced before line execution. Serious downsides:
You override the case variables
It needs DelayedExpansion
Might eventually be usefull in some cases.
Related
So I'm making a very ambitious game using batch to challenge myself. I've been working on the "shop" segment of this game but for some reason when I enter 'b' or 'B' it doesn't send me back to the menu, but reads it as I wanted to buy a medkit and sends me to the "medkit purchased" line of code. I've tried to add pause >nul and pause between the shop line of code and the purchased line of code, but it didn't help. I also tried double checking to see if I typed menu right many times. There has to be something I'm missing, help appreciated, I've been messing with it for almost 2 hours now.
Edit: I have not entered the other events yet, only medkit and go back to menu.
Edit2: I've added some more variables and instead of taking me to them it takes me to the medkit code again.
Edit: I removed the percents, you guys can stop bugging me bout it. The issue still is not fixed and I do not have choice.exe so choice commands don't work.
Here is the code:
:shop
cls
echo Welcome to the shop!
echo Money: $%money%
echo.
echo 1. Buy Med Kit -$30
echo 2. Buy Shotgun Ammo (1) -$15
echo 3. Buy Assult Rifle Ammo (5) -$20
echo 4. Buy Missle (1) -$50
echo 5. View Armor
echo 6. View Modifiers
echo.
echo Enter 'B' to go back.
echo.
set /p %shopOp%=
if '%shopOp%' == '1' goto medkit1
if '%shopOp%' == '2' goto sg1
if '%shopOp%' == '3' goto ar1
if '%shopOp%' == '4' goto rpg1
if '%shopOp%' == '5' goto armors1
if '%shopOp%' == '6' goto mods1
if '%shopOp%' == 'B' goto menu
if '%shopOp%' == 'b' goto menu
:medkit1
cls
set /a money=%money%-30
if %money% LSS 0 goto noBuy1
set /a medK=%medK%+1
echo You bought 1 medkit for $30!
echo You now have %medK% med kits now!
echo.
echo Press enter to continue
pause >nul
goto shop
:noBuy1
cls
set /a money=%money%+30
echo You dont have enough money!
echo You have $%money%. You need $30.
echo.
echo Press enter to continue
pause >nul
goto shop
Okay so you don't have choice. How about xcopy?
A version adapted from the link in my comment that substitutes the choice utility with xcopy to return keypress:
#Echo off
Set Echo.ID=Call :ID.Label "%%~1" "%%~2"
Setlocal EnableDelayedExpansion
Title Menu Navigation Example
:Bar
Set "Left.Date="
IF /I "!Left.Bar!" == "Yes" Goto :Date
Call :[+Menu] "Bar" "Drink Fight Chat Leave"
Goto :Bar
:Date
Set "Left.Bar="
IF /I "!Left.Date!" == "Yes" Goto :Bar
Call :[+Menu] "Date" "Dinner Flirt Leave"
Goto :Date
:[+Menu] <Location / Core Menu option> <Sub Actions / Menu Items as list>
::: - Build menu and choice list for display
CLS
Set "CHOICES="
Set "Actions="
For %%A in (%~2) Do (
Set "Option=%%~A"
Set Actions=!Actions! "%%~A"
Set CHOICES=!CHOICES! "!Option:~0,1!"
Set "Option=[!Option:~0,1!]!Option:~1,100!"
Echo !Option!
)
::: - Return key literal from xcopy command and call relevent menu item with Identifying Params
Set "Option="
Set Key=
For /F "Delims=" %%A in ('xcopy /w "%~f0" "%~f0" 2^>nul') do (
If Not Defined Key Set "Key=%%A"
)
Set "Key=!Key:~-1!"
::: - Restrict keypress to available options, fall through to 'Goto :[Menu]' when no Call is made (Invalid keypress)
For %%O in (%~2) Do (
Set "Option=%%~O"
Set "Option=!Option:~0,1!"
If /I "!Option!" == "!Key!" Call :[%~1_%%~O-!Key!] "%%~1 %%~O" "%~1"
)
Goto :[+Menu]
:[Bar_Drink-D]
%Echo.ID%
Goto :!Loc!
:[Bar_Fight-F]
%Echo.ID%
Goto :!Loc!
:[Bar_Chat-C]
%Echo.ID%
Goto :!Loc!
:[Bar_Leave-L]
%Echo.ID%
Set "Left.Bar=Yes"
Goto :!Loc!
:[Date_Dinner-D]
%Echo.ID%
Goto :!Loc!
:[Date_Flirt-F]
%Echo.ID%
Goto :!Loc!
:[Date_Leave-L]
Set "Left.Date=Yes"
%Echo.ID%
Goto :!Loc!
:ID.Label <%~1> <%~2>
Title %~1
::: - Identify return Label
Set "Loc=%~2"
Exit /B
I am trying to make a fully immersive text adventure using a batch file.
Here is my problem: I want the answers to be a text input, so that the players type in a response which dictates where they will go.
For a lot of questions I need there to be multiple possible inputs. For example when you get to an enemy there are tons of different things you could do, however I can only figure out how to get it to recognise one input.
With other words, I want system to take user input and do actions accordingly.
Here is my code for this section so far:
:forest1
echo you awake in a forest, you do not know where you are or why you are there.
echo infront of you is a small goblin like creature
:recoil1
echo What do you do?
set /p answer=
if %answer%==run (
goto run1
) else (
if %answer%==attack (
goto attack1
) else (
if %answer%==befriend(
goto befriend1
) else (
if %answer%==scream(
goto scream1
) else (
if %answer%==dance (
goto dance1
) else (
echo Nothing happened
timeout /t 1
goto forest1
)
Your way should be modified like this to work:
#echo off
rem Your code before the code you provided above ^^
:forest1
echo You awake in a forest, you do not know where you are or why you are there.
echo In front of you is a small goblin like creature
goto :recoil1
:recoil1
set /p "answer=What do you do? "
if "%answer%" == "run" (
goto :run1
) else (
if "%answer%" == "attack" (
goto :attack1
) else (
if "%answer%" == "befriend" (
goto :befriend1
) else (
if "%answer%" == "scream" (
goto :scream1
) else (
if "%answer%" == "dance" (
goto :dance1
) else (
echo Nothing happened.
timeout /t 1
goto :forest1
)
)
)
)
)
You see: this is complicated a bit; you missed lots of parenthesis!
So, use choice command with some modifications:
#echo off
rem Your code before the code you provided above ^^
:forest1
echo You awake in a forest, you do not know where you are or why you are there.
echo In front of you is a small goblin like creature
goto :recoil1
:recoil1
echo What do you do? Here is a list of options:
echo r - run away
echo a - attack the goblin
echo b - be friend with the goblin
echo s - scream
echo d - dance
echo n - do nothing
choice /C:rabsdn /N
if errorlevel 6 (
echo Nothing happened.
timeout /t 1
goto :forest1
)
if errorlevel 5 goto :dance1
if errorlevel 4 goto :scream1
if errorlevel 3 goto :befriend1
if errorlevel 2 goto :attack1
if errorlevel 1 goto :run1
which is clearer, faster and more readable, isn't it?
Note: the if with the errorlevel should be in descending order because if errorlevel n means if the errorlevel is greater than or equal to n!
Modify the options to better suit for you.
Why not try use if in the for looping to do this job?
#echo off
:forest1
cls & echo/ & if defined answer set answer=<nul
echo/ you awake in a forest, you do not know where you are or why you are there.
echo/ infront of you is a small goblin like creature
:recoil1
set /p "answer= What do you do? "
for %%i in (run attack befriend scream dance) do if /i "%answer%" == "%%i" goto :%answer%1
echo/ Nothing happened
timeout /t 1 & goto forest1
:run1
echo/ Here I'm in Label run1 & exit /b
:attack1
echo/ Here I'm in Label attack1 & exit /b
:befriend1
echo/ Here I'm in Label befriend1 & exit /b
:scream1
echo/ Here I'm in Label scream1 & exit /b
:dance1
echo/ Here I'm in Label dance1 & exit /b
Hi I make simple batch file now what I tried to add correct answers number at the end but it keeps saying zero because the variable values are not changing when the answers are chosen. Here is my code below
#echo off
title Game One
color 1f
::#############################
:one
set correctn=0
set correctn2=0
cls
echo What is 2 + 2?
echo.
echo.
echo A) 6
echo B) 4
echo C) 49
echo D) 17
echo.
echo.
echo Type the correct answer.
set /p ch1=
echo.
echo.
if not defined ch1 (goto one)
if %ch1%==A goto no
if %ch1%==A correctn=0
if %ch1%==B goto yes
if %ch1%==B correctn=1
if %ch1%==C goto no
if %ch1%==C correctn=0
if %ch1%==D goto no
if %ch1%==D correctn=0
pause>null
::#########################################
:no
cls
echo Sorry, that answer is incorrect.
echo.
echo.
echo The correct choice was B, which was 4.
pause>null
goto two
::#########################################
:yes
cls
echo You are correct. Congratulations.
echo Press any key to continue.
pause>null
goto two
::##########################################
:two
cls
echo What is 100 divided by 2?
echo A) 45
echo B) 50
echo C) 90
echo D) 17
echo.
echo.
set/p ch2=
echo.
echo.
if not defined ch2 (goto two)
if %ch2%==A goto no2
if %ch2%==A correctn2=0
if %ch2%==B goto yes2
if %ch2%==B correctn2=1
if %ch2%==C goto no2
if %ch2%==C correctn2=0
if %ch2%==D goto no2
if %ch2%==D correctn2=0
echo Invalid Choice, Please Try Again!
pause>null
::#################################
:no2
cls
echo Sorry, that answer is incorrect.
echo.
echo.
echo The correct choice was B, which was 50.
pause>null
::########################################
:yes2
cls
echo You are correct. Congratulations.
echo Press any key to continue.
pause>null
goto end
::######################################
:end
set/a correct=%correctn% + %correctn2%
echo Number of answers correct was %correct%
pause>null
So how to change variable value in if statement if already variable exists?
You need to set a variable first and then goto. As currently written, your script goes to a label yes first. Hence, if %ch1%==B set correctn=1 line is never reached:
if %ch1%==B goto yes
if %ch1%==B set correctn=1
if %ch1%==B goto yes
Moreover, IF command string comparison is case sensitive without /I switch; try the following:
if /I %ch1%==B (set correctn=1&goto yes)
I'd suggest using (Windows native) CHOICE.EXE instead of set /p for a single key-press user input, e.g as follows:
CHOICE /C abcd
IF %errorlevel%==2 (
set correctn=1
goto yes
) else (
set correctn=0
goto no
)
I am currently making a game that has a persuasion system in it. I had all the code for one of the systems set up, but then I set up 2 more, and it started give me an error that said '(number) was not expected at this time'. when I put in 2 for the second choice, and 3 for the 3rd choice.
The code is like this.
#echo off
SETLOCAL EnableDelayedExpansion
for /F "tokens=1,2 delims=#" %%a in ('"prompt #$H#$E# & echo on & for %%b in (1) do rem"') do (
set "DEL=%%a"
)
set name=Quantum
cls
color 0a
Echo King Redwood: So 2000?
pause >nul
echo.
call :colorText 09 "1. 2500"
echo.
call :colorText 0e "2. 3000"
echo.
call :colorText 0c "3. 4000"
echo.
echo 4. 2000
echo.
set /p "purs=Enter:"
if /i %purs% == 1 (
goto CheckB )
if /i %purs% == 2 (
goto CheckY )
if /i %purs% == 3 (
goto CheckR )
if /i %purs% == 4 (
goto Convo )
:CheckB
set bleu=%random:~-2,1%
if %bleu% GTR 10 (
goto CheckB )
if %bleu% LSS 0 (
goto CheckB )
set /a num = 3
set /a reward = 2500
goto Res
:CheckY
set Yel=%random:~-2,1%
if %Yel% GTR 10 (
goto CheckY )
if %Yel% LSS 0 (
goto CheckY )
set /a num = 5
set reward = 3000
goto Res
:CheckR
set red=%random:~-2,1%
if %red% GTR 10 (
goto CheckB )
if %red% LSS 0 (
goto CheckB )
set /a num = 7
set /a reward = 4000
goto Res
:Convo
set /a reward = 2000
Echo %name%: I think that is a reasonable price.
Echo King Redwood: Very well.
Echo King Redwood: We will now take you to make sure you are
echo ready.
pause >nul
:Res
if %bleu% GEQ %num% goto Succeed
if NOT %bleu% GEQ %num% goto Fail
:Succeed
Echo %name%: I think that the struggles for such a long trip will be more then that
Echo %name%: How about %reward%?
Echo King Redwod: OK %reward% will work.
pause >nul
goto end
:Fail
Echo %name%: I think that you can give me %reward%.
Echo %name%: You know, for the struggles that there will be along the way.
echo If 2000 isn't good enough for you, I'll just have someone else do it.
pause >nul
:end
exit
:colorText
echo off
<nul set /p ".=%DEL%" > "%~2"
findstr /v /a:%1 /R "^$" "%~2" nul
del "%~2" > nul 2>&1i
First, make sure to close the FOR loop by putting a ) before :CheckB.
For the 'was not expected at this time' error, you're sometimes comparing an empty variable to something. For example, by following CheckY, you set Yel, then proceed to Res and check Bleu, which is empty because it hasn't been set. You're putting nothing next to the binary GEQ operator, and that's why it's complaining.
Tip: to debug, try inserting ECHO statements like this:
:Res
echo bleu=%bleu%,num=%num%
Another problem: when using SET, do not surround the = by spaces. SET /a will work with spaces around =, just because of the nature of /a, but plain SET will not. Well, it will append your variable name with a space and prepend your value with a space, which is not what you want.
Another tip: you can constrain what RANDOM returns through SET /a and the modulus operator, like this.
SET /a red=%random% %% 11
This will set red to a number between 0 and 10, so there is no need for the substrings and goto routines you're using after picking your random number.
Also, consider using EXIT /b to exit the batch file and not the whole CMD environment.
i have looked for an answer and have not found one.
#echo off
:a
cls
set /p %a% =
if %a% == 1 goto b
goto c
:b
echo.
echo worked
pause
:C
echo.
echo dident work
pause
i set a = 1 and is said that the goto command was unexpected at this time. any help would be great
Changed
ok it has been change and a new problem occurs. now when a = 1 it always goes to c not b
#echo off
:a
cls
set /p a =
if "%a%" == "1" goto b
goto c
:b
echo.
echo worked
pause
:C
echo.
echo wierd
pause
#echo off
echo.
set /p a=
echo.
if %a%==1 goto b
if not %a%==1 goto c
:b
echo worked
echo.
pause
exit
:c
echo dident work
echo.
pause
exit
change this:
set /p %a% =
to
set /p a=
and
if %a% == 1 goto b
to
if "%a%" EQU "1" goto b
#echo off&cls
set /p a=Enter a number :
if "%a%" EQU "1" goto:b
echo dident work
exit/b
:b
echo Result = 1