-2

I recently saw a VSauce 2 video of a game you can always win and I made a program where a player can play the game versus the computer. The problem is that when it's the user's turn, when you enter a number(or anything) the program closes. Me and a friend who also programs tried to fix this, but nothing worked. Think you can help?

Here is the chunk of code that keeps screwing up:

:usr
cls
echo.
echo SUM: %tot%
echo.
echo LAST ENTRY:
echo COMPUTER: %com%
echo YOU: %usr%
echo.
echo.
set/p usr=ENTER A NUMBER BETWEEN 1 AND 10: 
if "%usr%" => "11" (
goto usr
)
if "%usr%" =< "0" (
    goto usr
)
set/a tot=%tot%+%usr%
if "%tot%" == "100" (
    goto win
)
if "%tot%" => "101" (
    goto lose
) else (
    goto com
)

Every GOTO goes somwhere else that exists

Deedee
  • 1
  • 1

1 Answers1

0

1. usr as name for label and variable

The usage of usr as label and as name of an environment variable is no good idea as it makes it difficult to search for label or variable usr.


2. Invalid arguments => and <=

=> and <= are not a valid comparison operators for command IF. Open a command prompt window and run if /? for help on this command listing also all supported operators.

Any internal command of cmd.exe can be executed in a command prompt window with parameter /? to get displayed the help for this command. And most external commands which are the console applications in directory %SystemRoot%\System32 output also help on running them with /? as parameter.


3. Integer versus string comparison

Operators like GEQ (greater or equal) are designed primary for signed 32-bit integer comparisons. By enclosing the two arguments for comparison in double quotes, it is not possible anymore for Windows command processor to convert the double quoted strings into integers and so a string comparison is performed by IF.

The string "2" is greater than the string "11". The first character of the two compared strings is " with decimal code value 34 which is equal on both strings. The second character is 2 with decimal code value 50 on left string which is greater than 1 with decimal code value 49 on right string and so the string "2" is greater than the string "11".

For more details about string versus integer comparison read the answer on Symbol equivalent to NEQ, LSS, GTR, etc. in Windows batch files


4. Correct command syntax

The command line set/p usr=ENTER A NUMBER BETWEEN 1 AND 10:  is not good because of cmd.exe must apply an auto-correction on the command line before it can be executed.

Better would be:

set /P "usr=ENTER A NUMBER BETWEEN 1 AND 10: "

The argument 0 is the command set.

A space is used to separate the command from its first argument which is the option /P.

One more space is used to separate the second argument which is variable=prompt text which is enclosed in double quotes as it contains one or more spaces. Enclosing the argument string in double quotes would not be necessary here in this special case because of command SET has a special argument string parsing which other commands and applications do not have, but it is nevertheless better to enclose the second argument in double quotes in this form to see the trailing space and never get it automatically removed for example by a text editor which trims trailing spaces on file save.

Also possible would be usr="ENTER A NUMBER BETWEEN 1 AND 10: " because of another special parsing of command set on usage with option /P. But the former syntax is better because it can be used on every usage of set, not just on usage for prompting the user for a string.

For more details read the answer on Why is no string output with 'echo %var%' after using 'set var = text' on command line?


5. set /P versus choice

On using set /P to prompt the user for a string the user has the freedom to enter nothing at all or enter what the user is asked for or enter something completely different which can make lots of troubles on further processing the user input string.

For more details see How to stop Windows command interpreter from quitting batch file execution on an incorrect user input?

A code like this one would be needed for fail safe code in this case:

@echo off

:GetValue
set "UserValue="
set /P "UserValue=Enter a number between 1 and 10: "

rem Has the user not entered any string?
if not defined UserValue goto GetValue

rem Remove all double quotes from entered string.
set "UserValue=%UserValue:"=%"

rem Is there no string left anymore?
if not defined UserValue goto GetValue

rem Does the string contain any other character than a digit?
for /F delims^=0123456789^ eol^= %%I in ("%UserValue%") do goto GetValue

rem Remove all leading zeros because of an integer with a leading 0
rem is interpreted on IF comparsion below as an octal number and 08
rem and 09 would be interpreted as 0 because of invalid octal numbers.
:RemoveLeadingZeros
if "%UserValue:~0,1%" == "0" (
    set "UserValue=%UserValue:~1%"
    if not defined UserValue goto GetValue
    goto RemoveLeadingZeros
)

rem More than two digits are not allowed for a number in range 1 to 10.
rem This check must be done because of the user could enter also the
rem string 12345678901234567890 which is greater maximum positive 32-bit
rem integer value 2147483647 supported on conversion from string to integer.
if not "%UserValue:~2,1%" == "" goto GetValue

rem A value greater 10 is not allowed as also value 0 detected already
rem on removing leading zeros because of TempValue not defined anymore.
if %UserValue% GTR 10 goto GetValue

echo You entered the value %UserValue%.
pause

That is a lot of code to make sure that the user has really entered a string which is a number in range 1 to 10.

A much better code would make use of external command CHOICE explained by help output on running choice /? in a command prompt window:

@echo off
%SystemRoot%\System32\choice.exe /C 1234567890 /N /M "Enter 1 to 0 (=10): "
set "UserValue=%ERRORLEVEL%"
echo You entered the value %UserValue%.
pause

That is much easier and the user cannot even make a typing mistake because of CHOICE excepts only 1, 2, ..., 0 and Ctrl+C to exit batch file execution.

Also possible would be:

%SystemRoot%\System32\choice.exe /C 0123456789 /N /M "Enter 0 to 9: "

The result is the same as before because of 0 results in an exit of CHOICE with exit code 1 and 9 with exit code 10.


6. echo. can fail to output a blank line

The DosTips forum topic ECHO. FAILS to give text or blank line - Instead use ECHO/ explains when echo. fails to output a blank line. It is better to use echo/ or echo( to output a blank line.

In this special case the rule as written on point 4 is not followed because of very special argument string parsing of command ECHO ignoring an argument string consisting only of spaces/tabs and printing the status off or on on calling it without a non-whitespace argument string.


7. Fail safe rewritten batch code

Here is the rewritten batch code being fail safe.

@echo off
:UserInput
cls
echo/
echo SUM: %tot%
echo/
echo LAST ENTRY:
echo COMPUTER: %com%
echo YOU: %usr%
echo/
echo/
%SystemRoot%\System32\choice.exe /C 0123456789 /N /M "Enter 0 to 9: "
set /A tot+=%ERRORLEVEL%
if %tot% EQU 100 goto win
if %tot% GTR 100 goto lose
echo Reached code for "com".
goto :EOF

:win
echo Reached code for "win".
goto :EOF

:lose
echo Reached code for "lose".

The command line set /A tot+=%ERRORLEVEL% works even with environment variable tot not defined.

For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.

  • choice /?
  • cls /?
  • echo /?
  • goto /?
  • if /?
  • set /?
Mofi
  • 46,139
  • 17
  • 80
  • 143