Home > Blockchain >  is there any way to don't have to check every state between 2 numbers in batch?
is there any way to don't have to check every state between 2 numbers in batch?

Time:01-10

i was creating a rock paper siscors game in batch, i finisced and i wanted to "clean it", becouse it checked every possible combination between the 3 numbers rappresenting rock paper siscors, but i don't know what to do

at first i tried, instead of checking every equal number, i used the "equ" operator, but after that i didn't know what to do, i tried once by making the bigger number the winner, and checked if they were a 0 (paper) and 2 (rock) to make rock weaker than paper on the same "if" function, but the terminal just crashed. i don't know how to do it somwhere else and then check after, i started using batch yesterday, so i dont know praticaly anything. also if i did any error while typing correct me becouse english is not my first language

@echo off
color f
cls
echo welcome to rock paper siscors
:LOOP
echo 0=(paper) 1=(siscors) 2=(rock)
set /p input= select one of the 3:
set /a cpu=%random% %%3
if %input% GTR 2 (echo don't type values bìigger than 2!!!!!!!!!!!!!!)
if %cpu% equ 0 if %input% equ 1 (echo you win!)
if %cpu% equ 0 if %input% equ 2 (echo you lose!)
if %cpu% equ 1 if %input% equ 0 (echo you lose!)
if %cpu% equ 1 if %input% equ 2 (echo you win!)
if %cpu% equ 2 if %input% equ 0 (echo you win!)
if %cpu% equ 2 if %input% equ 1 (echo you lose!)
if %cpu% equ %input% (echo parity!)
if %cpu% equ 0 (echo the cpu selected paper)
if %cpu% equ 1 (echo the cpu selected siscors)
if %cpu% equ 2 (echo the cpu selected rock)
goto :LOOP 

CodePudding user response:

Whilst not a direct fix for your reported problem, here's an rewritten example to study, and which may better suit your purpose:

@Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
Color 0F
Echo Welcome to Rock Paper Scissors

:LOOP
Set /A "Opponent=(%RANDOM% %% 3)   2, Opponent *= Opponent"
%SystemRoot%\System32\choice.exe /C RPS /N /M "[R]ock, [P]aper, or [S]cissors?"
Set /A "Result=Opponent - %ErrorLevel%"
Set "Opponent=Paper"
If %Result% Lss 4 Set "Opponent=Rock"
If %Result% Gtr 8 Set "Opponent=Scissors"
For %%G In (15 6 2) Do If %Result% Equ %%G Set /P "=You WIN: " 0<NUL
For %%G In (14 8 1) Do If %Result% Equ %%G Set /P "=You LOSE: " 0<NUL
For %%G In (13 7 3) Do If %Result% Equ %%G Set /P "=DRAW: " 0<NUL
Echo Opponent chose %Opponent%
%SystemRoot%\System32\choice.exe /M "Would you like to play again"
If Not ErrorLevel 2 Echo(& GoTo LOOP

CodePudding user response:

Mmm.. These are my thoughs...

Scissors 1 win to Paper 0. Rock 2 win to Scissors 1; but Rock 2 should lose vs Paper. This means that Paper=0 should become Paper=3 IF the opponent is Rock 2. That is:

cpu  = (!cpu) * !(input-2) * 3

We will do an extensive use of ! (Boolean NOT) operator, that returns a 1 if its operand is zero, and returns a zero in any other case. In this way, !cpu is 1 if cpu is Paper and is zero in any other case (scissors or rock).

In the same way (input-2) is zero only when input is rock, so !(input-2) returns one only when input is rock (and zero in any other case).

This means that (!cpu) * !(input-2) gives 1 when cpu is Paper AND input is Rock (and 0 in any other case). if you multiply this value times 3 (!cpu) * !(input-2) * 3 and add such a value to cpu: cpu = (!cpu) * !(input-2) * 3 then this expression will convert cpu from Paper=0 to Paper=3 when cpu is Paper and input is Rock. Ta-Da! :)

We must apply the same treatment to input when it is Paper and cpu is Rock, that is:

set /A cpu  = (!cpu) * !(input-2) * 3
set /A input  = (!input) * !(cpu-2) * 3

There is no way that both above expressions be executed on the same data, so it is not necessary to insert any IF to prevent to execute one or the other expression.

Also, it is simpler to get the user input via choice command that directly gives a 1..3 result, so we subtract 1 from its returned ERRORLEVEL in order to manage our standard values: 0=Paper, 1=Scissors and 2=Rock:

set /A "cpu=%random% %% 3"
choice /C PSR /N /M "Select [P]aper, [S]cissors or [R]ock: "
set /A "input=%errorlevel% - 1"
set /A "cpu  = (!cpu) * !(input-2) * 3"
set /A "input  = (!input) * !(cpu-2) * 3"
if %cpu% gtr %input% (echo you lose) else ...

But the SET /A command can execute several operations separated by comma, so above 4 expressions could be given in a single SET /A command. Also, we can get the name of each item via an array of names that can directly give the desired element in a single operation. Here it is the whole thing:

@echo off
setlocal EnableDelayedExpansion

rem Define the "items" array
set "item[0]=Paper" & set "item[1]=Scissors" & set "item[2]=Rock" & set "item[3]=Paper"

:LOOP
    choice /C PSR /N /M "Select [P]aper, [S]cissors or [R]ock: "
    set /A "input=%errorlevel%-1, cpu=%random% %% 3, cpu =(^!cpu)*^!(input-2)*3, input =(^!input)*^!(cpu-2)*3"
    if %cpu% gtr %input% (
       echo you lose
    ) else if %cpu% equ %input% (
       echo parity
    ) else (
       echo you win
    )
    echo cpu selected !item[%cpu%]!
    choice /M "Play again? "
    echo/
if not errorlevel 2 goto LOOP

We could also eliminate the IF's commands used to identify the winner via the following trick. If we analyse the possible values of the expression input - cpu, we'll realize that if the result is 2 or 1, you win; if it is 0, is draw; and if it is -1 or -2, you lose. We could directly use these values to define a "result" array with 5 elements this way:

rem Define the "results" array
set "result[2]=you win"
set "result[1]=you win"
set "result[0]=parity"
set "result[-1]=you lose"
set "result[-2]=you lose"

. . .

set /A "res=input-cpu"
echo !result[%res%]!

However, we could diminish the "result" array to just 3 elements if we use the "Sign" function that returns 1, 0 or -1 for positive, zero or negative values, respectively:

set /A "res=input-cpu, res=(res>>31|1)*!!res"

Here it is the final version:

@echo off
setlocal EnableDelayedExpansion

rem Define the "items" array
set "item[0]=Paper" & set "item[1]=Scissors" & set "item[2]=Rock" & set "item[3]=Paper"

rem Define the "results" array
set "result[1]=you win" & set "result[0]=parity" & set "result[-1]=you lose"

:LOOP
    choice /C PSR /N /M "Select [P]aper, [S]cissors or [R]ock: "
    set /A "input=%errorlevel%-1, cpu=%random% %% 3, cpu =(^!cpu)*^!(input-2)*3, input =(^!input)*^!(cpu-2)*3, res=input-cpu, res=(res>>31|1)*^!^!res""
    echo !result[%res%]!
    echo cpu selected !item[%cpu%]!
    choice /M "Play again? "
    echo/
if not errorlevel 2 goto LOOP
  • Related