Batch Processing Sokoban Source Code Explanation:
1. Use of Compact Format for Data Definition
First, put the variable definition set into a variable: (Note that the delimiter is unique, here using the ";" sign)
set a=a=i75;b=i79;str=abc
So the value of variable a is: a=i75;b=i79;str=abc
Use variable value replacement during preprocessing:
set %a:;=&set %
Equivalent to the following statements being executed:
set a=i75&set b=i79&set str=abc
Or:
set a=i75
set b=i79
set str=abc
If there are many variables to define, comprehensively considering from the perspective of occupied space and readability, this method has obvious advantages.
2. "Sokoban" Program Implementation Algorithm
1). Read the level data into an array: lev(n)
Change the value of n, which is to change the level, here n=%lev%
2). Restore the current level map data and store it in a two-dimensional array: r(n).(m)
(1) Collect the variable names r(n).(m) with the value "☆" into variable ke, and store the number of "☆" into variable ji, and convert them to "★" at the same time;
%ke% after expansion is the real-time value of all two-dimensional variables with the source value "☆"; as long as %ke% is equal to !ji! it means the level is passed
(2) Store the two-dimensional variable names as an array by row: r(n)
%r(n)% after expansion is the real-time value of all two-dimensional arrays in row n
3). Variable ebuf is used as a display buffer, all content to be displayed is stored in ebuf, and all is displayed at once with echo !ebuf!
Because after expansion of for variable %%a, the! -quoted variable will be expanded again, so:
for /l %%a in (1,1,!r!) do for %%b in ("!r%%a!") do set ebuf=!ebuf! %%~b!cr!
The above sequentially stores the expanded values of the variable name array r(n) from row 1 to!r! into the display buffer ebuf, and adds the newline character!cr!
4). First define the operations for up, down, left, and right:
"c1=n-;c2=m-;c3=n+;c4=m+"
In this way, through the following code:
set/a sm=m,sn=n,!c%in%!=1,bm=m,bn=n,!c%in%!=1
Respectively obtain the source points: sm.sn, step one: bm.bn, step two: m.n, the values of the three coordinates after pressing up/down/left/right
for /f "tokens=1,2" %%a in ("!r%bn%.%bm%! !r%bn%.%bm%!!r%n%.%m%!") do (
Take out the values of the three coordinates and spread them out as: (step one => %%a) (step one + step two =>%%b) For example: %%a=▓ %%b=▓∷
for %%c in ("!%%a!!%%b!") do (
%%a %%b after re-expansion, grouped into %%c, continuing the example:!▓! => empty,!▓∷! =>▓-∷
Then: ▓-∷ => %%c
for /f "tokens=1,2 delims=-" %%1 in (%%c) do (
Spread out as: %%1=▓, %%2=∷
Next is the if judgment, according to various situations, adjust the values of the three points and a "large" standing! source! point again
Note: There is a point, if the value of %%c is empty, such as when %%b=▓■, then this for will be an empty loop, that is, even the if statement inside will not be executed, making the following set/a m=sm,n=sn be executed
3. Compression and Restoration of Level Data
1). Compression: Since full-width characters are double-byte, converting to single characters can reduce by half. If ▓=a, zf=▓, then: set zf=!%af%! can be converted back
If there are not only one continuous ones, then a number is added after the letter to indicate the number. If it exceeds 9, start a new group, such as: a11, then split into a9a2
2). Restoration, reference: The advantage of starting with 囧,
for /f "tokens=2* delims=囧" %%a in (%~nx0) do (set lev!n!=%%a&set/a n+=1)
In this way, when reading, the reading of other non-data lines can be subtracted, and the speed is accelerated
Similarly, convert the characters back, and then use the 搂 character as the for /l count to repeat to convert all
if "!tn:%%2=!" neq "!tn!" (set k=%%2) else (set k=1)
for /l %%k in (1,1,!k!) do (
The above!k! is the number of characters
4. Get Rid of choice.exe and Screen Flashing
That is, use debug.exe instead, but this is usually available in all DOS systems, so. third-party...
debug <%~nx0>nul
Call itself as pipeline input, the first line is wrong, only two lines are really useful
e 100 cd 16 86 c4 b4 02 cd 10 b4 4C CD 21 Write code
g Execute
Here, key reading is performed, set the current cursor position to the first line, first column, and the key data is used as the return code to: %errorlevel%
Definition: "a=i83=10;i1=7;i72=1;i80=3;i75=2;i77=4;i73=8;i81=9;i57=5;i79=6"
Execution: set in=!i%errorlevel%!
Then get the key situation according to the definition, if not defined, it is empty
Usually, when writing a batch processing to return to the first line to display, only use cls, and then display again. Obviously, the speed is also very fast, but I still feel a bit flashing.
Directly reset the cursor to the first line, first column, without clearing the screen, and when displaying again, it is based on the original one, so the feeling of flashing is reduced
If you look at the assembly source code, it is very simple. Just remove >nul after debug <%~nx0>nul, and add a line u between the e line and the g line.
5. Player Record Saving and Reading
Here, the record is stored in the first line of the batch processing,
1). Reading
set/p yg=< %~nx0 >nul
Take the first line to variable yg
set yg=!yg:~13,52!
set lev=%yg:@=&rem %
Because the current level record and the passed level record are separated by @, so only the part before @ is given to lev, and the part after @ is commented out by rem
set yg= !yg:* =!
Only take the passed data, and keep the space before and after
In this way, the current level and the passed level data are all read into the variable
2). Saving
set a=a 10d`db "!lev!@!yg! "``w`q
(echo %a:`=&echo;%)|debug %~nx0 >nul
Expanded to:
(echo a 10d&echo;db "!lev!@!yg! "&echo;&echo;w&echo;q)|debug %~nx0 >nul
Actually, the following command line is handed to debug to execute:
a 10d
db "!lev!@!yg! "
w
q
Using the a command of debug to input assembly instructions, you can use db to define a string, and then directly use the W command to write to the opened file
And the batch processing program can modify itself during execution
Recent Ratings for This Post
( 2 in total)
Click for details