
Your sapper on your body shirts

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

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.
In general, for helps in solving a large number of problems. You can read more by running cmd.exe -> for /?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 =?
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 /? ..
Explanations:set / a bx =% random: ~ -2% set bx =% bx: ~ 0.1%
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.
It is also necessary to call the procedure: genbomb from the initialization cycle (i.e. when starting a new game) using call.: 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
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 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;
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.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
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