0

So I'm writing a script that can tell if an action has already been performed. I started off with a 2x2 array with 0s in it. I wanted to randomly store three 1s among the four elements and if the element is already storing 1, echo Repeated to notify the user. This is the code I have so far and it doesn't echo Repeated even if the same element is chosen more than once.

@echo off
setlocal EnableDelayedExpansion
::::::::::::::::::::::::::::::::::::::::::::Creating a 2x2 zero array
for /l %%y in (0,1,1) do (
    for /l %%x in (0,1,1) do (
        set map[%%x][%%y]=0
    )
)
::::::::::::::::::::::::::::::::::::::::::::Putting 1s in elements randomly
for /l %%x in (1,1,3) do (
    set /a j=!Random!%%2
    set /a i=!Random!%%2
    if !map[%i%][%j%]! EQU 0 (set map[!i!][!j!]=1) else (echo Repeated)
)
::::::::::::::::::::::::::::::::::::::::::::Result
echo !map[0][0]!!map[1][0]!
echo !map[0][1]!!map[1][1]!
echo.
pause

I read something related online and am pretty sure it has something to do with the "setlocal EnableDelayedExpansion" thing but I don't know how to do it. Thanks in advance.

jacknip
  • 13
  • 3
  • You may use `for /F "tokens=1,2" %%i in ("!i! !j!") do if !map[%%i][%%j]! EQU 0 (set map[%%i][%%j]=1) else ...`. This type of management is fully described at [this post](https://stackoverflow.com/questions/10166386/arrays-linked-lists-and-other-data-structures-in-cmd-exe-batch-script/10167990#10167990) – Aacini Sep 23 '17 at 17:15
  • Thanks for your sugguestion but can you explain what "for /F "tokens=1,2" %%i in ("!i! !j!") do" means? I'm still new to batch. I just tried your code, it didn't show how many times it repeated tho – jacknip Sep 24 '17 at 02:03
  • You may type `for /?` at the command-prompt and read the help screen, or review anyone of the numerous descriptions about `for` command that exists in the web, like [this](https://ss64.com/nt/for_f.html) or [this](https://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/ntcmds_shelloverview.mspx?mfr=true), etc... In this case, it assigns the value of `!i!` and `!j!` into `%%i` and `%%j`, so `!map[%%i][%%j]!` could be correctly used. – Aacini Sep 24 '17 at 22:50

1 Answers1

0
for /l %%x in (1,1,3) do (
    set /a j=!Random!%%2
    set /a i=!Random!%%2
    SET /a s=map[!i!][!j!]
    if !s! EQU 0 (set map[!i!][!j!]=1) else (echo Repeated)
)

In your code, %i% and %j% will each be resolved to nothing since neither i nor j is set when the for is encountered - %var% means "the value of var when the block is started" hence your if is resolved to if !map[][]! EQU 0 ... - map[][] is a valid varname.

To access the value of the variable as it changes with the block's operation (ie the "run-time" value) you need to use !var! with delayed expansion in operation. This would yield (theoretically)

if !map[!i!][!j!]! EQU 0 (set map[!i!][!j!]=1) else (echo Repeated)

BUT this won't work since there is no way for cmd to resolve which pairs of ! to resolve first (it will choose !map[!,!][! and !]! reulting in if ij equ 0 ... which will obviously always fail)

So - I chose to set s to the value extracted from map and then test that.

Magoo
  • 77,302
  • 8
  • 62
  • 84
  • Thank you so much! I have been stuck at this for a day and I did try "if !map[!i!][!j!]! EQU 0 (set map[!i!][!j!]=1) else (echo Repeated)" and it doesn't work. Never knew that I can set s to the value to do that. – jacknip Sep 23 '17 at 03:55
  • Although this answer solves this problem, it is not a general solution. i.e. this method does not work if the array have non-numeric values... – Aacini Sep 23 '17 at 17:19