Thanks to Julio Marchi for this space in MSX All |
||
Basic Portugues On this version we focus on the game main routines. They were written in Basic for an easier understanding. The following program creates an 8x8 game map, selects randomly the 10 mines locations and notifies all neighborhood about the mines. 5 ' MarMSX 2018 10 COLOR15,1,1:SCREEN0:WIDTH40:KEYOFF 20 DIM MA$(8,8) 30 GOSUB 500:GOSUB 800 40 END 500 ' 501 ' Create mines 502 ' 510 GOSUB 600 520 FOR M=1 TO 10 530 X=INT(8*RND(-TIME))+1 540 Y=INT(8*RND(-TIME))+1 550 IF MA$(X,Y)="*" THEN 530 ELSE MA$(X,Y)="*" 560 NEXT M 570 GOSUB 700:RETURN 600 ' 601 ' Clear map 602 ' 610 FOR X=1 TO 8:FOR Y=1 TO 8 620 MA$(X,Y)="0" 630 NEXT Y,X 640 RETURN 700 ' 701 ' Neighborhood mapping 702 ' 710 FOR X=1 TO 8:FOR Y=1 TO 8 720 IF MA$(X,Y)="*" THEN GOSUB 750 730 NEXT Y,X 740 RETURN 750 ' 751 ' Notify neighbors 752 ' 760 FOR VX=X-1 TO X+1:FOR VY=Y-1 TO Y+1 770 IF VX<1 OR VX>8 OR VYX<1 OR VY>8 THEN 780 ELSE IF MA$(VX,VY)="*" THEN 780 775 MA$(VX,VY)=RIGHT$(STR$(VAL(MA$(VX,VY))+1),1) 780 NEXT VY,VX 790 RETURN 800 ' 801 ' Print map 802 ' 810 FOR X=16 TO 23:FOR Y=2 TO 9 820 LOCATE X,Y:PRINT MA$(X-15,Y-1); 830 NEXT Y,X 840 RETURN The chapter 4 from the game development manual explains the game map process. The next step creates an user's map "MU" to control the map coordinates opened by the user. The printing rules are the following: places not opened are printed as "."; if a flag is being used, print "+"; at last, print the information according to the game's map "MA$". For the first map printing, we may use "." directly. As soon the user opens a place, we print it using the rules above. 5 ' MarMSX 2018 10 COLOR15,1,1:SCREEN0:WIDTH40:KEYOFF 20 DIM MA$(8,8) MU values:
This routine controls the player's actions. 40 CX=16:CY=2 50 LOCATE CX,CY:A$=INPUT$(1):A=ASC(A$) 60 IF A=29 THEN CX=CX-1:IF CX<16 THEN CX=16 70 IF A=28 THEN CX=CX+1:IF CX>23 THEN CX=23 80 IF A=30 THEN CY=CY-1:IF CY<2 THEN CY=2 90 IF A=31 THEN CY=CY+1:IF CY>9 THEN CY=9 100 IF A=13 THEN IF MU(CX-15,CY-1)<>1 THEN MU(CX-15,CY-1)=-(MU(CX-15,CY-1)=0)*2: GOSUB 850 110 IF A=32 THEN IF MU(CX-15,CY-1)=0 THEN MU(CX-15,CY-1)=1:GOSUB 850 120 GOTO 50 ... 850 ' 851 ' Print current position 852 ' 860 LOCATE CX,CY 870 IF MU(CX-15,CY-1)=0 THEN PRINT".":RETURN 875 IF MU(CX-15,CY-1)=2 THEN PRINT"+":RETURN 880 IF MA$(CX-15,CY-1)="0" THEN PRINT" " ELSE PRINT MA$(CX-15,CY-1) 890 RETURN Everytime the user opens a place on the map, if there is a mine, it blows up and the game is over. Thus, if all clean places on the map are opened, the player wins and the game ends. 40 CX=16:CY=2 A little "trick" is applied to verify if all "clean" places were opend: we just count the number of opened places, and when the number 54 is reached, the player wins and game ends. Hint: in order to verify the code, add the following line to print also the game map: 825 LOCATE X-16,Y+10:PRINT MA$(X-15,Y-1) The flood-fill algorithm may be used to open some clear places automatically. Once the Basic has no function call like Pascal and C, let's make use of flood-fill with stack. The pseudo-code for a 4-neighbors flood-fill is: var stack : array [1..M, 1..N] of integer; p : integer; procedure flood_fill(x, y : integer) begin p ← 0; push(x,y); while (p>0) pop(); if test_condition(X,Y) = true then do_something(); push(x+1,y); push(x-1,y); push(x,y+1); push(x,y-1); end_if end_while end_procedure Game changes using 8-neighbors flood-fill: 20 DIM MA$(8,8):DIM MU(8,8) Note: although we open a place anyway, we spread new coordinates only if the current position is "0". Control:
5 ' MarMSX 2018 10 COLOR15,1,1:SCREEN0:WIDTH40:KEYOFF 20 DIM MA$(8,8):DIM MU(8,8):DEFINT S:DIM S(64,2) 30 GOSUB 500:GOSUB 800 40 CX=16:CY=2:LA=0 50 LOCATE CX,CY:A$=INPUT$(1):A=ASC(A$) 60 IF A=29 THEN CX=CX-1:IF CX<16 THEN CX=16 70 IF A=28 THEN CX=CX+1:IF CX>23 THEN CX=23 80 IF A=30 THEN CY=CY-1:IF CY<2 THEN CY=2 90 IF A=31 THEN CY=CY+1:IF CY>9 THEN CY=9 100 IF A=13 THEN IF MU(CX-15,CY-1)<>1 THEN MU(CX-15,CY-1)=-(MU(CX-15,CY-1)=0)*2 :GOSUB 850 110 IF A=32 THEN IF MU(CX-15,CY-1)=0 THEN GOSUB 1000:GOSUB900 120 GOTO 50 500 ' 501 ' Create mines 502 ' 510 GOSUB 600 520 FOR M=1 TO 10 530 X=INT(8*RND(-TIME))+1 540 Y=INT(8*RND(-TIME))+1 550 IF MA$(X,Y)="*" THEN 530 ELSE MA$(X,Y)="*" 560 NEXT M 570 GOSUB 700:RETURN 600 ' 601 ' Clear map 602 ' 610 FOR X=1 TO 8:FOR Y=1 TO 8 620 MA$(X,Y)="0":MU(X,Y)=0 630 NEXT Y,X 640 RETURN 700 ' 701 ' Neighborhood mapping 702 ' 710 FOR X=1 TO 8:FOR Y=1 TO 8 720 IF MA$(X,Y)="*" THEN GOSUB 750 730 NEXT Y,X 740 RETURN 750 ' 751 ' Notify neighbors 752 ' 760 FOR VX=X-1 TO X+1:FOR VY=Y-1 TO Y+1 770 IF VX<1 OR VX>8 OR VY<1 OR VY>8 THEN 780 ELSE IF MA$(VX,VY)="*" THEN 780 775 MA$(VX,VY)=RIGHT$(STR$(VAL(MA$(VX,VY))+1),1) 780 NEXT VY,VX 790 RETURN 800 ' 801 ' Print map 802 ' 810 FOR X=16 TO 23:FOR Y=2 TO 9 820 LOCATE X,Y:PRINT"." 830 NEXT Y,X 840 RETURN 850 ' 851 ' Print current position 852 ' 860 LOCATE CX,CY 870 IF MU(CX-15,CY-1)=0 THEN PRINT".":RETURN 875 IF MU(CX-15,CY-1)=2 THEN PRINT"+":RETURN 880 IF MA$(CX-15,CY-1)="0" THEN PRINT" " ELSE PRINT MA$(CX-15,CY-1) 890 RETURN 900 ' 901 ' Check game ending 902 ' 910 IF MA$(CX-15,CY-1)="*" THEN LOCATE 0,12:PRINT"You found a bomb. Gave over." :END 920 IF LA>53 THEN LOCATE 0,12:PRINT"Congratulations. You cleaned the area.":END 930 RETURN 1000 ' 1001 ' Flood-fill 1002 ' 1010 P=0:SX=CX:SY=CY 1020 P=P+1:S(P,1)=CX:S(P,2)=CY 1030 CX=S(P,1):CY=S(P,2):P=P-1 1040 IF CX<16 OR CX>23 OR CY<2 OR CY>9 THEN 1110 1045 IF MU(CX-15,CY-1)=1 THEN 1110 1050 MU(CX-15,CY-1)=1:GOSUB 850:LA=LA+1 1060 IF MA$(CX-15,CY-1)<>"0" THEN 1110 1070 P=P+1:S(P,1)=CX+1:S(P,2)=CY 1075 P=P+1:S(P,1)=CX+1:S(P,2)=CY+1 1080 P=P+1:S(P,1)=CX:S(P,2)=CY+1 1085 P=P+1:S(P,1)=CX-1:S(P,2)=CY+1 1090 P=P+1:S(P,1)=CX-1:S(P,2)=CY 1095 P=P+1:S(P,1)=CX-1:S(P,2)=CY-1 1100 P=P+1:S(P,1)=CX:S(P,2)=CY-1 1105 P=P+1:S(P,1)=CX+1:S(P,2)=CY-1 1110 IF P>0 THEN 1030 1120 CX=SX:CY=SY:RETURN |
||