Your sapper on your body shirts

    image

    Once I wanted to write Minesweeper ... on batch files. And I wrote it.

    Meet !!! Minesweeper for cmd.exe

    So, the features of this product:
    • Original logo
    • Two-color textual graphical interface (background - black, text - gray)
    • The ability to play the program on virtually any computer
    In general, this is a real sapper (and not those miserable similarities - KMines and a sapper for Windows) for real men. And then you can read how to make your own cool sapper.

    image
    Screenshot of the game.

    Any serious bat-program should not leave behind itself traces, such as extra variables. To do this, use the commands setlocal (at the beginning) and endlocal (at the end). More info: setlocal /? .. Okay, let's move on to the game itself.

    First of all, we will create two arrays - real and visible fields. Since there are no arrays, we will improvise - we will create a bunch of variables of the form mfield34 and rfield 69. For this, we will use the for loop.
    for / L %% x in (1,1,9) do for / L %% y in (1,1,9) do set mfield %% x %% y =?
    for / L %% x in (1,1,9) do for / L %% y in (1,1,9) do set rfield %% x %% y =?
    In general, for helps in solving a large number of problems. You can read more by running cmd.exe -> for /?

    Now you need to put bombs on the field. To do this, use the variable% random% (contains a decimal number between 0 and 32767) and extension lines. Details: cmd.exe -> set /? ..
    set / a bx =% random: ~ -2%
    set bx =% bx: ~ 0.1%
    Explanations:
    1. set / a is used to use the variable as a number and perform arithmetic operations (again, read cmd.exe -> set /?)
    2.% random: ~ -2% - a number between 0 and 99
    3.% bx : ~ 0.1% - the first digit of the resulting delirium.

    Now we are trying to create a new bomb (and add one to the bomb counter) using the call command, i.e. We call another procedure and pass two parameters to it: the contents of the variable and the name of the variable (the variable is part of the array). By the way, the contents of a variable can only be obtained using the call command (example: call: procedure %% variable% counter1 %% counter2 %%%). By the way, REM is a comment in bat files.
    : genbomb
    call: newbomb %% rfield% r1 %% r2 %%% rfield% r1 %% r2%
    REM Check for the number of bombs. If equal to the maximum, then exit the procedure.
    if "% bombs%" == "% maxbombs%" goto: eof
    : newbomb
    if not "% 1" == "X" (
    	set% 2 = X
    	set / a bombs =% bombs% + 1
    	)
    REM goto: eof is a quick return from a procedure.
    goto: eof 
    It is also necessary to call the procedure: genbomb from the initialization cycle (i.e. when starting a new game) using call.

    Now we need to put down numbers in all cells not filled with bombs. Using the for loop, we invoke a special procedure that passes four parameters. In this procedure, we simply count the number of bombs standing nearby. It should be noted that for the point (4; 4) there will be 8 neighbors, and for the point (1; 1) - only three.
    for / L %% x in (1,1,9) do for / L %% y in (1,1,9) do call: dosumfield %% x %% y %% rfield %% x %% y %% rfield %% x %% y
    : dosumfield
    REM If there is already something in the cell (bomb), then we exit.
    if not "% 3" == "?" goto: eof
    REM Set the coordinates of the first neighboring cell.
    set / a x1 =% 1 - 1 
    set / a y1 =% 2 + 1
    REM ..... Skipping the code .....
    set sum = 0
    REM If the coordinates of the first point are in the array, then we call the procedure to increase the counter of the number of bombs
    if% 1 GTR 1 if% 2 LSS 9 call: newsum %% rfield% x1 %% y1 %%%
    REM ..... Skipping the code .....
    : newsum
    if "% 1" == "X" set / a sum + = 1
    goto: eof


    So, we have a field, now we need to display it. Again, you need to use a for loop (well, if you're bored, you can manually write everything). By the way, a new feature of the call command is used here: you can enter another command (echo, set) as the first argument. And therefore, you do not need to create single-line procedures.
    for / L %% y in (1,1,9) do call set line %% y =: %% y: %% mfield %% y1 %% %% mfield %% y2 %% %% mfield %% y3% % %% mfield %% y4 %% %% mfield %% y5 %% %% mfield %% y6 %% %% mfield %% y7 %% %% mfield %% y8 %% %% mfield %% y9 %%: %% y:
    REM All cells that do not have neighbor bombs do not display
    for / L %% y in (1,1,9) do call set line %% y = %% line %% y: 0 = %%
    echo% line0%
    echo: ---------------------------------:
    for / L %% y in (1,1,9) do call echo %% line %% y %%
    echo: ---------------------------------:
    echo% line0%


    Now let's try to read user commands. The first character is the command, the second and third are the coordinates. Just in case, delete all the spaces. In order to exclude batch-injection (execution of extraneous commands by entering text) or just the death of a batch file, we work with only three characters. It is also necessary to check whether the last two characters are digits.
    REM Enter a magic line in input, in case the user scores a data entry.
    set input = 0 00
    set / p "input = Input:"
    set input =% input: =%
    REM The first letter is the required action.
    set action =% input: ~ 0.1%
    REM action example
    if "% action%" == "h" (
    	cls
    	REM Call help (call) and go to the game loop (goto)
    	call: help
    	goto: gamecycle
    	)
    REM If the first character is not a command, then we tell something to the user.
    if not "% action%" == "q" if not "% action%" == "h" if not "% action%" == "o" if not "% action%" == "f" if not "% action%" == "n" call: errorIO2
    REM If the second and third characters are not coordinates, then set them to zero. 
    set ix = 0
    set iy = 0
    for / L %% a in (1,1,9) do if "%% a" == "% input: ~ 1,1%" set ix = %% a
    for / L %% a in (1,1,9) do if "%% a" == "% input: ~ 2,1%" set iy = %% a
    REM If the second / third character is not a coordinate, then we will display him a message (call) and move on to the game loop.
    if "% ix%" == "0" (
    	call: errorIO1
    	goto: gamecycle
    	)
    if "% iy%" == "0" (
    	call: errorIO1
    	goto: gamecycle
    	)
    REM Next come the commands requiring the correct coordinates
    


    Now it remains to paint how to open the cells of the field. The sapper has one feature: if there are 0 bombs near the cell, then we open the adjacent cells (not on the diagonal). Those. need to use recursion.
    REM If the user command is to open the cell, then run special. procedure with parameters: coordinates, cell value in a real field, cell value in a visible field.
    if "% action%" == "o" (
    	call: openpoint% ix%% iy% %% rfield% ix %% iy %%% %% mfield% ix %% iy %%%
    	goto: gamecycle
    	)
    REM ..... Skipping a lot of code .....
    : openpoint
    REM If the cell is not empty - we tell the user a lot of interesting things, if there is a bomb in the cell - it's too late to tell anything.
    if not "% 4" == "?" (
    	echo Point x =% 1 y =% 2 already opened
    	pause> nul
    	goto: eof
    	)
    if "% 3" == "X" (
    	REM Set the variable die to unity, and then draw conclusions. 
    	set die = 1
    	for / L %% x in (1,1,9) do for / L %% y in (1,1,9) do call set mfield %% x %% y = %% rfield %% x %% y% %
    	goto: eof
    	)
    REM And if neither one nor the other, then we are trying to open this and the neighboring cells.
    call: oaf% 1% 2% 3% 4
    goto: eof 
    REM And here is a recursive function
    : oaf
    REM If the cell is empty (going out of the field) or there is a bomb in it, we leave here.
    if "% 3" == "" goto: eof
    if "% 3" == "X" goto: eof
    REM Open this cell
    call set mfield% 1% 2 = %% rfield% 1% 2 %%
    REM If there are 0 bombs in this cell, then we try to open all the nearby cells.
    if not "% 3" == "0" goto: eof
    REM xn, yn - coordinates of the next cell. The diagonal is not checked.
    set / a xn =% 1
    set / a yn =% 2 + 1
    REM Checks if this cell is open in the visible field.
    set dooaf = 0
    call: checkoaf %% mfield% xn %% yn %%%
    REM If not (doaf == 1), then we call ourselves, but with different coordinates.
    if% dooaf% == 1 call: oaf% xn%% yn% %% rfield% xn %% yn %%% %% mfield% xn %% yn %%%
    REM ..... There is still a lot of code .....
    goto: eof


    In total, we have two interesting things left - setting flags and checking if the user won. The first is not interesting, unless it is worth noting that the procedure should provide for the installation and removal of the flag from the field with one command.

    The user won in two cases:
    • all flags are affixed correctly;
    • the sum of the flags and unopened cells is equal to the number of bombs;
    The user did not win in one of three cases:
    • the number of flags is greater than the number of bombs;
      if% flags% GTR% maxbombs% goto: eof
    • not all flags are affixed correctly;
    • the sum of the flags and unopened cells is not equal to the number of bombs;
    The last two options are defined as follows:
    REM We count the number of correctly set flags and not open cells.
    set nopoints = 0
    set rflags = 0
    for / L %% x in (1,1,9) do for / L %% y in (1,1,9) do call: checkfo %% mfield %% x %% y %% %% rfield %% x %% y %%
    REM ..... There is a lot of code .....
    : checkfo
    if "% 1" == "?" set / a nopoints + = 1
    if "% 1" == "!" if "% 2" == "X" set / a rflags + = 1
    goto: eof
    
    After working out such a procedure, the nopoints variable will contain the number of empty flags, and in rflags the number of correctly set flags.

    Naturally, I did not paint all the code, but only part of it. The code itself can be viewed here: Google Docs, html or here: Plain Text

    P.S : If you have questions - why so, and not otherwise - ask, I will answer. Unfortunately, I did not paint every line, but only the necessary ones (in my opinion). If something is not clear to you, ask questions. I also apologize for my English and variable / procedure names.
    PPS : Jabber is too lazy to maintain batch files, so I abandoned it :-)

    UPD1 : Corrections:
    • Improved field generation
    • Inability to die on the first move
    • Reduced the number of bombs to 17
    • Added secret command 'r' displaying a high score table (records.log file)

    UPD2 : Corrections:
    • The principle of entering a command has been supplemented: now you can enter only coordinates to open a cell.
    • Changed the principle of opening cells
    • Question marks (?) Are replaced by a period - "."

    UPD3 : Corrections:
    • Fixed problem with records.log

    Also popular now: