大家好,我是兮帥,Excel也是可以很有趣的!
這次就給大家?guī)硪粋€用Excel制作的推箱子排序的小游戲,先給大家看一下這個熟悉的畫面!^_^這款用Excel制作的小游戲可以說是非常經典又益腦,大家也可以趁老板不在的時候偷偷的打開Excel玩一下,是不是很香呢?
游戲界面
下面就給大家分享怎么制作這款小游戲。
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
m=1
n=1
Dim Rg As Range, Rg2 As Range
If Target.Value="" Then
MsgBox ("別點空白單元格")
[B2].Select
Exit Sub
End If
Set Rg2=Union(Target.Offset(1, 0), Target.Offset(-1, 0), Target.Offset(0, 1), Target.Offset(0, -1))
For Each Rg In Rg2
With Rg
If .Interior.ColorIndex=xlNone Then
.Interior.ColorIndex=36
.Value=Target
With Target
.Interior.ColorIndex=xlNone
.Value=""
End With
End If
End With
Next Rg
End Sub
Sub 初始化()
With Range("B2:E5")
.ClearContents
.Interior.ColorIndex=36
End With
[E5].Interior.ColorIndex=xlNone
Set d=CreateObject("Scripting.Dictionary")
m=1
n=2
Do
num=Fix(Rnd() * 15 + 1)
If Not d.Exists(num) Then
If m < 5 Then
m=m + 1
Cells(m, n)=num
d(num)=1
Else
m=1
n=n + 1
End If
End If
Loop Until Cells(4, 5) > 0
Application.Volatile
End Sub
以上就是制作這個小游戲的全部步驟以及代碼,如果有不清楚怎么操作的,也可以加個關注去看我的視頻,里面有超詳細的介紹哦!
下期將給大家?guī)鞥xcel制作貪吃蛇小游戲的代碼,歡迎大家關注!
推箱子游戲是一款很有趣味的游戲,其開發(fā)過程有一定的技巧和方法,其中涉及軟中斷、二維數組、鍵盤操作以及圖形化函數等方面的知識。本游戲的開發(fā)者需要基本掌握顯示器中斷寄存器的設置、二維數組及結構體的定義、鍵盤上鍵值的獲取、圖形方式下光標的顯示和定位,以及部分圖形函數的使用。在本章中,將使用C語言實現一個典型的推箱子游戲,向讀者講解其具體實現過程,并剖析技術核心和實現的算法。
在軟件項目開發(fā)過程,規(guī)劃分析是首先需要完成的工作。在本節(jié)中,將詳細講解本推箱子游戲的項目規(guī)劃分析方面的工作。
本游戲一共4關,由易到難,每一關都有初始化、按鍵處理、重置及退出功能。
① 初始化包括屏幕初始化和每一關卡的初始化,屏幕被初始化為寬80像素,高25像素。
② 按鍵處理包括移動小人和移動箱子,通過移動上下左右鍵來控制小人的移動,從而推動箱子,以把箱子推到指定的目的地為過關。
③ 每一關都可以重置,按空格鍵可以重置當前關。
④ 按【Esc】鍵可以在任何時候退出游戲。
本程序包括5個模塊,分別是初始化模塊、畫圖模塊、移動箱子模塊、移動小人模塊和功能控制模塊,如圖1-1所示。各個模塊的功能描述如下。
圖1-1 功能模塊圖
(1)初始化模塊
該模塊包括屏幕初始化和游戲第一關的初始化。屏幕初始化用于輸出歡迎信息和操作提示,游戲每一關的初始化是構建每一關的關卡。
(2)畫圖模塊
該模塊主要是被其他模塊調用,用于畫墻、在空地畫箱子、在目的地畫箱子、畫小人和畫目的地。
(3)移動箱子模塊
該模塊用于移動箱子,包括目的地之間、空地之間和目的地與空地之間的箱子移動。
(4)移動小人模塊
該模塊用于控制小人移動,從而推動箱子到目的地。
(5)功能控制模塊
該模塊是幾個功能函數的集合,包括屏幕輸出功能、指定位置狀態(tài)判斷功能和關卡重置功能。
游戲從第一關開始,按上下左右方向鍵控制小人移動來推動箱子,可以在游戲中的任何時候按【Esc】鍵退出。如果游戲無成功希望,可以按空格鍵回到當前任務的開始狀態(tài);如果成功完成當前關,則進入下一關,如果當前關是最后一關,則顯示通關信息,提示游戲結束。圖1-2顯示了任務執(zhí)行的流程。
圖1-2 任務執(zhí)行流程圖
小人移動的方向有4個,move()函數(處理小人移動的函數)對這4個方向移動的處理都一致,只是調用函數時的參數有所不同。首先判斷小人移動的方向,然后根據小人所處的當前狀態(tài)、下一步狀態(tài)或者下下一步狀態(tài)進行適當的處理。處理過程如圖1-3所示。
圖1-3 小人移動流程圖
經過游戲運作流程的分析和試玩過程可知,推箱子游戲是一款很有趣味的游戲,其開發(fā)過程需要一定的技巧和方法,其中涉及到軟中斷、二維數組、鍵盤操作以及圖形化函數等方面的知識。本游戲的開發(fā)者需要基本掌握顯示器中斷寄存器的設置、二維數組及結構體的定義、鍵盤上鍵值的獲取、圖形方式下光標的顯示和定位,以及部分圖形函數的使用。
定義二維數組char status[20][20],用于記錄屏幕一個點的狀態(tài)。其中,“0”表示什么都沒有,“b”表示箱子,“w”表示目的地,“i”表示箱子在目的地。首先將屏幕20×20范圍內的狀態(tài)初始化為0。然后根據具體情況,在畫箱子時,將箱子所在點的狀態(tài)改為“b”;在畫墻壁時,將墻壁所在點的狀態(tài)改為“w”;在畫目的地時,將目的地所在點的狀態(tài)改為“m”;當箱子被推到目的地時,箱子所在點的狀態(tài)改為“i”,如果每一關中所有目的地的狀態(tài)都為“i”,則說明該關已完成。
定義全局變量,char far *printScreen=(char far*)0xB8000000,用于在屏幕上輸出字符。彩色顯示器的字符緩沖區(qū)首地址為0xB8000000,每一個字符占2個字節(jié)(第一個字節(jié)為ASCII值,第二個字節(jié)為顏色值),字符模式下屏幕寬80像素,高25像素,一屏可以寫80×25個字符。
定義結構體struct winer,用于判斷每一關是否已完成。其中x用于存放目的地的橫坐標,y用于存放目的地的縱坐標。如果所有表示目的地坐標對應的狀態(tài)都為“i”,即箱子在目的地,則表示已經過關,可以進入下一關。該結構體的初始化在每一關的初始化時進行,具體代碼如下所示。
typedef struct winer
{
int x;
int y;
struct winer *p;
}winer;
系統(tǒng)函數是整個項目的靈魂,項目中的功能都是通過函數實現的,所以本階段的工作十分重要。在本階段要提前做好分析和規(guī)劃工作,力爭為后面的工作打好基礎。
(1)函數原型:void putoutChar(int y,int x,char ch,char fc,char bc)
(2)功能:putoutChar()函數用于在屏幕上的指定位置輸出指定的字符。其中,x、y指明輸出的位置,ch表示輸出的字符,fc表示輸出的字符顏色,bc表示背景色。
(1)函數原型:void printWall(int x,int y)
(2)功能:printWall()函數用于畫墻壁,傳入參數x、y指明位置。該函數調用putoutChar()進行輸出,以黑色為背景畫綠色墻,用小方塊表示墻(ASCII值為219)。
(1)函數原型:void printBox(int x,int y)
(2)功能:printBox()函數用于在非目的地畫箱子,傳入參數x、y指明位置。該函數調用putoutChar()進行輸出,以黑色為背景白色箱子,用ASCII值為10的字符表示箱子。
(1)函數原型:void printBoxDes(int x,int y)
(2)功能:printBoxDes()函數用于在目的地畫箱子,傳入參數x、y指明位置。該函數調用putoutChar()進行輸出,以黑色為背景畫黃色箱子,仍用ASCII值為10的字符表示箱子。
(1)函數原型:void printDestination(int x,int y)
(2)功能:printDestination()函數用于畫目的地,傳入參數x、y指明位置。該函數調用putoutChar()進行輸出,以黑色為背景畫黃色目的地,用心形表示(ASCII值為003)。
(1)函數原型:void printDestination1(int x,int y,winer **win,winer **pw)
(2)功能:printDestination1()函數與printDestination()函數功能基本相同,都是畫目的地函數,但是printDestination1()增加了記錄每一個目的地位置的功能。其中x、y指明目的地的位置,每一關的所有目的地位置存放在結構體struct winer中,形成一條鏈表,**winer返回鏈表的頭,**pw則指向鏈表的尾部。
(1)函數原型:void printMan(int x,int y)
(2)功能:printMan()函數用于畫小人,x、y指明畫的位置。該函數通過軟中斷來實現,首先設置寄存器AX的高位和低位,設置高位0xa表示在光標位置顯示字符;設置低位02(ASCII值),表示輸出的字符;然后設置寄存器CX為01,表示重復輸出的次數,這里只輸出一次;最后產生類型為0x10的中斷,表示顯示器輸出。
(1)函數原型:void init()
(2)功能:init()函數用于初始化屏幕。該函數首先用兩個for循環(huán)初始化屏幕20*20范圍內的狀態(tài),初始化為0,以后根據實際情況重新賦值;然后設置屏幕輸出狀態(tài),設置寄存器AX的高位為0,低位為3,表示以80*25的彩色方式顯示;最后移動光標到指定的位置輸出操作提示信息以及版權信息。
(1)函數原型:winer *initStep1()、winer *initStep2()、winer *initStep3()、winer *initStep4()
(2)功能:這幾個函數分別初始化游戲的第一關到第四關。這些函數的功能和實現步驟相似。首先根據需要在指定的位置畫墻壁和畫箱子,在這里可以設置游戲的難度,初始化的墻壁越復雜,箱子越多,則游戲就越難。游戲的第一關至第四關難度依次增加。然后分別調用printDestination1()和printMan()函數畫目的地和小人。函數返回包含各個目的地位置的鏈表。
(1)函數原型:void moveBoxSpacetoSpace(int x,int y,char a)、void moveBoxDestoSpace(int x,int y, char a)、void moveBoxSpacetoDes(int x,int y,char a)、void moveBoxDestoDes(int x,int y,char a)
(2)功能:這幾個函數實現的功能分別是人空地移動箱子到空地、從目的地移動箱子到空地、從空地移動箱子到目的地和中從目的地移動箱子到目的地。x、y指明小人當前所處的位置,字符a表示移動的方向,有“u”“d”“l(fā)”和“r”4個值,分別表示向上、下、左、右移動。這幾個函數的實現原理大致相似。對于前面兩個函數,首先判斷移動的方向,從小人所在的位置沿著移動的方向移動一步畫小人,移動兩步畫箱子(調用printBox()函數),并設置狀態(tài)為“b”;對于后面兩個參數,首先判斷移動的方向,從小人所在的位置沿著移動方向移動一步畫小人,移動兩上在目的地畫箱子(調用printBoxDes()函數),并設置狀態(tài)為“i”,表明箱子在目的地上。
(1)函數原型:int judge(int x,int y)
(2)功能:judge()根據結構體struct[x][y]中存的值來判斷該點的狀態(tài)。
(1)函數原型:void moid(int x,int y,char a)
(2)功能:Move()函數根據按下的鍵來處理小人的移動。整個項目的核心是實現推箱子處理,即通過函數move()來實現小人的移動。小人移動的方向有上(“u”)、下(“d”)、左(“l(fā)”)、右(“r”)4個,4個方向的處理方式一樣。首先判斷移動的方向,然后根據小人的當前位置、下一步位置以及下下一步位置所在的狀態(tài)進行處理。
① 若下一步所在位置的狀態(tài)為墻壁(“w”),則直接退出,不做任何處理。
② 若下一步所在位置的狀態(tài)為目的地(“i”)或者什么都沒有(“0”),則:
③ 若下一步所在位置的狀態(tài)為箱子(“b”),則:
④ 若下一步所在位置的狀態(tài)為箱子在目的地(“i”),則:
(1)函數原型:void reset(int i)
(2)功能:reset()函數用于重置當前關。該函數首先判斷當前關是第幾關,然后調用init()函數和初始化當前關的函數進行重置。
主函數首先設置寄存器AX的高位和低位,顯示器軟中斷,進行顯示狀態(tài)的設置,初始化屏幕,初始化第一關,并顯示操作提示信息和版權信息。然后根據按下的鍵(bioskey(0)函數返回按下的鍵值)進行處理,處理過程由move()函數進行(如果按下【Esc】鍵,則退出程序)。對于每一關,如果所有的表示目的地的狀態(tài)都由“m”變成了“i”,則表示通過該關,可以進入下一關。
現在既有項目規(guī)劃書,也有函數規(guī)劃。有了這些資料,整個設計思路就十分清晰了,只需遵循規(guī)劃書的方向,并參照規(guī)劃函數即可輕松完成編碼工作。
程序預處理部分包括加載頭文件、定義全局變量和定義數據結構,并對它們進行初始化工作。具體實現代碼如下所示。
/*加載頭文件*/
#include <dos.h>
#include <stdio.h>
#include <ctype.h>
#include <conio.h>
#include <bios.h>
#include <alloc.h>
/*定義結構體,判斷是否勝利*/
typedef struct winer
{
/*目的地的x和y坐標*/
int x,y;
struct winer *p;
}winer;
/*定義全局變量*/
/*記錄屏幕上各點的狀態(tài)*/
char status [20][20];
/*彩色顯示器字符緩沖區(qū)的首地址為0xB8000000*/
char far *printScreen=(char far* )0xB8000000;
/*自定義原型函數*/
void putoutChar(int y,int x,char ch,char fc,char bc);
void printWall(int x, int y);
void printBox(int x, int y);
void printBoxDes(int x, int y);
void printDestination(int x, int y);
void printDestination1(int x,int y,winer **win,winer **pw);
void printMan(int x, int y);
void init();
winer *initStep1();
winer *initStep2();
winer *initStep3();
winer *initStep4();
void moveBoxSpacetoSpace(int x ,int y, char a);
void moveBoxDestoSpace(int x ,int y, char a) ;
void moveBoxSpacetoDes(int x, int y, char a);
void moveBoxDestoDes(int x, int y, char a);
int judge(int x, int y);
void move(int x, int y, char a);
void reset(int i);
該模塊主要用于對屏幕和關卡的初始化,初始化關卡時是調用畫圖模塊中畫圖函數。該模塊包括以下幾個函數。
① void init():初始化屏幕的大小、顯示方式、顯示操作提示信息和版權信息。
② winer *initStep1():初始化游戲的第一關。
③ winer *initStep2():初始化游戲的第二關。
④ winer *initStep3():初始化游戲的第三關。
⑤ winer *initStep4():初始化游戲的第四關。
具體實現代碼如下所示。
/*初始化全屏幕函數*/
void init()
{
int i,j;
for(i=0;i<20;i++)
for(j=0;j<20;j++)
/*屏幕20*20范圍內的狀態(tài)初始化為0*/
status[i][j]=0;
/*設置寄存器AX的低位,以80*25的色彩方式顯示*/
_AL=3;
_AH=0;
geninterrupt(0x10);
/*移動光標到指定的位置輸出屏幕信息*/
gotoxy(40,4);
printf("Welcome to the box world!");
gotoxy(40,6);
printf("You can use up, down, left,");
gotoxy(40,8);
printf("right key to control it, or");
gotoxy(40,10);
printf("you can press Esc to quit it.");
gotoxy(40,12);
printf("Press space to reset the game.");
gotoxy(40,14);
printf("Wish you have a good time !");
gotoxy(40,16);
printf("April , 2007");
}
/*初始化游戲第一關函數*/
winer *initStep1()
{
int x;
int y;
winer *win=NULL;
winer *pw;
/*在指定位置畫墻,構建第一關*/
for(x=1,y=5;y<=9;y++)
printWall(x+4,y+10);
for(y=5,x=2;x<=5;x++)
printWall(x+4,y+10);
for(y=9,x=2;x<=5;x++)
printWall(x+4,y+10);
for(y=1,x=3;x<=8;x++)
printWall(x+4,y+10);
for(x=3,y=3;x<=5;x++)
printWall(x+4,y+10);
for(x=5,y=8;x<=9;x++)
printWall(x+4,y+10);
for(x=7,y=4;x<=9;x++)
printWall(x+4,y+10);
for(x=9,y=5;y<=7;y++)
printWall(x+4,y+10);
for(x=8,y=2;y<=3;y++)
printWall(x+4,y+10);
printWall(5+4,4+10);
printWall(5+4,7+10);
printWall(3+4,2+10);
/*在指定位置畫箱子*/
printBox(3+4,6+10);
printBox(3+4,7+10);
printBox(4+4,7+10);
/*在指定位置畫目的地*/
printDestination1(4+4,2+10,&win,&pw);
printDestination1(5+4,2+10,&win,&pw);
printDestination1(6+4,2+10,&win,&pw);
/*在指定位置畫小人*/
printMan(2+4,8+10);
return win;
}
/*初始化游戲第二關函數*/
winer *initStep2()
{
int x;
int y;
winer *win=NULL;
winer *pw;
/*指定位置畫墻,構建第二關*/
for(x=1,y=4;y<=7;y++)
printWall(x+4,y+10);
for(x=2,y=2;y<=4;y++)
printWall(x+4,y+10);
for(x=2,y=7;x<=4;x++)
printWall(x+4,y+10);
for(x=4,y=1;x<=8;x++)
printWall(x+4,y+10);
for(x=8,y=2;y<=8;y++)
printWall(x+4,y+10);
for(x=4,y=8;x<=8;x++)
printWall(x+4,y+10);
for(x=4,y=6;x<=5;x++)
printWall(x+4,y+10);
for(x=3,y=2;x<=4;x++)
printWall(x+4,y+10);
for(x=4,y=4;x<=5;x++)
printWall(x+4,y+10);
printWall(6+4,3+10);
/*在指定位置畫箱子*/
printBox(3+4,5+10);
printBox(6+4,6+10);
printBox(7+4,3+10);
/*在指定位置畫目的地*/
printDestination1(5+4,7+10,&win,&pw);
printDestination1(6+4,7+10,&win,&pw);
printDestination1(7+4,7+10,&win,&pw);
/*在指定位置畫小人*/
printMan(2+4,6+10);
return win;
}
/*初始化游戲第三關函數*/
winer *initStep3()
{
int x;
int y;
winer *win=NULL;
winer *pw;
/*在指定位置畫墻,構建第三關*/
for(x=1,y=2;y<=8;y++)
printWall(x+4,y+10);
for(x=2,y=2;x<=4;x++)
printWall(x+4,y+10);
for(x=4,y=1;y<=3;y++)
printWall(x+4,y+10);
for(x=5,y=1;x<=8;x++)
printWall(x+4,y+10);
for(x=8,y=2;y<=5;y++)
printWall(x+4,y+10);
for(x=5,y=5;x<=7;x++)
printWall(x+4,y+10);
for(x=7,y=6;y<=9;y++)
printWall(x+4,y+10);
for(x=3,y=9;x<=6;x++)
printWall(x+4,y+10);
for(x=3,y=6;y<=8;y++)
printWall(x+4,y+10);
printWall(2+4,8+10);
printWall(5+4,7+10);
/*在指定位置畫箱子*/
printBox(6+4,3+10);
printBox(4+4,4+10);
printBox(5+4,6+10);
/*在指定位置畫目的地*/
printDestination1(2+4,5+10,&win,&pw);
printDestination1(2+4,6+10,&win,&pw);
printDestination1(2+4,7+10,&win,&pw);
/*在指定位置畫小人*/
printMan(2+4,4+10);
return win;
}
/*初始化游戲第四關函數*/
winer *initStep4()
{
int x;
int y;
winer *win=NULL;
winer *pw;
/*在指定位置畫墻,構建第四關*/
for(x=1,y=1;y<=6;y++)
printWall(x+4,y+10);
for(x=2,y=7;y<=8;y++)
printWall(x+4,y+10);
for(x=2,y=1;x<=7;x++)
printWall(x+4,y+10);
for(x=7,y=2;y<=4;y++)
printWall(x+4,y+10);
for(x=6,y=4;y<=9;y++)
printWall(x+4,y+10);
for(x=3,y=9;x<=5;x++)
printWall(x+4,y+10);
for(x=3,y=3;y<=4;y++)
printWall(x+4,y+10);
printWall(3+4,8+10);
/*在指定位置畫箱子*/
printBox(3+4,5+10);
printBox(4+4,4+10);
printBox(4+4,6+10);
printBox(5+4,5+10);
printBox(5+4,3+10);
printDestination1(3+4,7+10,&win,&pw);
printDestination1(4+4,7+10,&win,&pw);
printDestination1(5+4,7+10,&win,&pw);
printDestination1(4+4,8+10,&win,&pw);
printDestination1(5+4,8+10,&win,&pw);
/*在指定位置畫小人*/
printMan(2+4,2+10);
return win;
}
該模塊主要用于畫圖操作,包括畫墻、畫箱子、畫目的地和畫小人等。該模塊包括以下幾個函數。
① void printWall(int x,int y):用于畫墻。
② void printBox(int x,int y):在空白地(非目的地)畫箱子。
③ void printBoxDes(int x,int y):在目的地畫箱子。
④ void printDestination(int x,int y):畫目的地函數。
⑤ void printDestination1(int x,int y,winer **win,winer **pw):畫目的地函數,并記錄每個目的地的位置。
⑥ void printMan(int x,int y):畫小人函數。
具體實現代碼如下所示。
/*畫墻函數*/
void printWall(int x,int y)
{
/*以黑色為背景畫綠色墻,用小方塊表示*/
putoutChar(y-1,x-1,219,GREEN,BLACK);
status[x][y]='w';
}
/*非目的地畫箱子函數*/
void printBox(int x,int y)
{
/*以黑色為背景畫白色箱子,用小方塊表示*/
putoutChar(y-1,x-1,10,WHITE,BLACK);
status[x][y]='b';
}
/*畫目的地函數,記錄每個目的地的位置*/
void printDestination1(int x,int y,winer **win,winer **pw)
{
winer *qw;
/*以黑色為背景畫黃色目的地,用心形表示*/
putoutChar(y-1,x-1,003,YELLOW,BLACK);
status[x][y]='m';
if(*win==NULL)
{
/*分配空間*/
*win=*pw=qw=(winer* )malloc(sizeof(winer));
(*pw)->x=x;
(*pw)->y=y;
(*pw)->p=NULL;
}
/*如果當前不是目的地的第一個點*/
else
{
qw=(winer* )malloc(sizeof(winer));
qw->x=x;
qw->y=y;
/*(*pw)的下一個點是qw */
(*pw)->p=qw;
(*pw)=qw;qw->p=NULL;
}
}
/*畫目的地函數*/
void printDestination(int x,int y)
{
/*以黑色為背景畫黃色目的地,用心形表示*/
putoutChar(y-1,x-1,003,YELLOW,BLACK);
status[x][y]='m';
}
void printMan(int x,int y)
{
gotoxy(y,x);
_AL=02;
_CX=01;
_AH=0xa;
geninterrupt(0x10);
}
/*在目的地畫箱子函數*/
void printBoxDes(int x,int y)
{
/*以黑色為背景畫黃色箱子,用小方塊表示*/
putoutChar(y-1,x-1,10,YELLOW,BLACK);
status[x][y]='i';
}
該模塊是實現箱子的移動。根據游戲規(guī)則,箱子可以在空地之間、目的地之間、空地和目的地之間來回移動,因此,實現本模塊共有以下4個函數。
① void moveBoxSpacetoSpace(int x,int y,char a):把箱子從空地移動到空地。
② void moveBoxDestoSpace(int x,int y,char a):把箱子從目的地移動到空地。
③ void moveBoxSpacetoDes(int x,int y,char a):把箱子從空地移動到目的地。
④ void moveBoxDestoDes(int x,int y,char a):把箱子從目的地移動到目的地。
具體實現代碼如下所示。
/*從空地移動箱子到空地*/
void moveBoxSpacetoSpace(int x,int y,char a)
{
switch(a)
{
/*如果是向上鍵*/
case 'u':
status[x-1][y]=0;
printf(" ");
printBox(x-2,y);
printMan(x-1,y);
status[x-2][y]='b';
break;
/*如果是向下鍵*/
case 'd':
status[x+1][y]=0;
printf(" ");
printBox(x+2,y);
printMan(x+1,y);
status[x+2][y]='b';
break;
/*如果是向左鍵*/
case 'l':
status[x][y-1]=0;
printf(" ");
printBox(x,y-2);
printMan(x,y-1);
status[x][y-2]='b';
break;
/*如果是向右鍵*/
case 'r':
status[x][y+1]=0;
printf(" ");
printBox(x,y+2);
printMan(x,y+1);
status[x][y+2]='b';
break;
default:
break;
}
}
/*從目的地移動箱子到空地*/
void moveBoxDestoSpace(int x,int y,char a)
{
switch(a)
{
/*如果是向上鍵*/
case 'u':
status[x-1][y]='m';
printf(" ");
printBox(x-2,y);
printMan(x-1,y);
status[x-2][y]='b';
break;
/*如果是向下鍵*/
case 'd':
status[x+1][y]='m';
printf(" ");
printBox(x+2,y);
printMan(x+1,y);
status[x+2][y]='b';
break;
/*如果是向左鍵*/
case 'l':
status[x][y-1]='m';
printf(" ");
printBox(x,y-2);
printMan(x,y-1);
status[x][y-2]='b';
break;
/*如果是向右鍵*/
case 'r':
status[x][y+1]='m';
printf(" ");
printBox(x,y+2);
printMan(x,y+1);
status[x][y+2]='b';
break;
default:
break;
}
}
/*從空地移動箱子到目的地*/
void moveBoxSpacetoDes(int x,int y,char a)
{
switch(a)
{
/*如果是向上鍵*/
case 'u':
status[x-1][y]=0;
printf(" ");
printBoxDes(x-2,y);
printMan(x-1,y);
status[x-2][y]='i';
break;
/*如果是向下鍵*/
case 'd':
status[x+1][y]=0;
printf(" ");
printBoxDes(x+2,y);
printMan(x+1,y);
status[x+2][y]='i';
break;
/*如果是向左鍵*/
case 'l':
status[x][y-1]=0;
printf(" ");
printBoxDes(x,y-2);
printMan(x,y-1);
status[x][y-2]='i';
break;
/*如果是向右鍵*/
case 'r':
status[x][y+1]=0;
printf(" ");
printBoxDes(x,y+2);
printMan(x,y+1);
status[x][y+2]='i';
break;
default:
break;
}
}
/*從目的地移動箱子到目的地*/
void moveBoxDestoDes(int x,int y,char a)
{
switch(a)
{
/*如果是向上鍵*/
case 'u':
status[x-1][y]='m';
printf(" ");
printBoxDes(x-2,y);
printMan(x-1,y);
status[x-2][y]='i';
break;
/*如果是向下鍵*/
case 'd':
status[x+1][y]='m';
printf(" ");
printBoxDes(x+2,y);
printMan(x+1,y);
status[x+2][y]='i';
break;
/*如果是向左鍵*/
case 'l':
status[x][y-1]='m';
printf(" ");
printBoxDes(x,y-2);
printMan(x,y-1);
status[x][y-2]='i';
break;
/*如果是向右鍵*/
case 'r':
status[x][y+1]='m';
printf(" ");
printBoxDes(x,y+2);
printMan(x,y+1);
status[x][y+2]='i';
break;
default:
break;
}
}
移動小人模塊是本程序的核心模塊,僅由move()函數來實現。move()函數控制小人的移動,并調用畫圖模塊、移動箱子模塊中的函數來實現箱子的重畫、移動等操作。其操作流程如圖1-3所示,具體實現代碼如下所示。
/*移動小人函數*/
void move(int x,int y,char a)
{
switch(a)
{
/*如果按向上鍵*/
case 'u':
/*如果(x-1,y)即小人的下一步狀態(tài)為墻*/
if(!judge(x-1,y))
{
/*則跳轉到(y,x),并跳出循環(huán)*/
gotoxy(y,x);
break;
}
/*如果小人的下一步狀態(tài)為目的地或者什么都沒有*/
else if(judge(x-1,y)==1||judge(x-1,y)==3)
{
/*如果當前狀態(tài)為目的地*/
if(judge(x,y)==3)
{
/*畫目的地*/
printDestination(x,y);
/*在新位置重新畫小人*/
printMan(x-1,y);
break;
}
/*如果下一步狀態(tài)為0*/
else
{
/*輸出空字符,覆蓋當前狀態(tài)的小人*/
printf(" ");
/*在下一步重新畫小人*/
printMan(x-1,y);
break;
}
}
/*如果下一步狀態(tài)是箱子*/
else if(judge(x-1,y)==2)
{
/*如果下下一步為空*/
if(judge(x-2,y)==1)
{
/*則將箱子從空地向上移動到空地*/
moveBoxSpacetoSpace(x,y,'u');
if(judge(x,y)==3)
/*如果當前狀態(tài)為目的地*/
printDestination(x,y);
gotoxy(y,x-1);
}
/*如果下下一步為目的地*/
else if(judge(x-2,y)==3)
{
/*則將箱子從空地向上移動到目的地*/
moveBoxSpacetoDes(x,y,'u');
if(judge(x,y)==3)
printDestination(x,y);
gotoxy(y,x-1);
}
else
gotoxy(y,x);
break;
}
else if(judge(x-1,y)==4)
{
if(judge(x-2,y)==1)
{
moveBoxDestoSpace(x,y,'u');
if(judge(x,y)==3)
printDestination(x,y);
gotoxy(y,x-1);
}
else if(judge(x-2,y)==3)
{
moveBoxDestoDes(x,y,'u');
if(judge(x,y)==3)
printDestination(x,y);
gotoxy(y,x-1);
}
else
gotoxy(y,x);
break;
}
/*如果按向下鍵*/
case 'd':
if(!judge(x+1,y))
{
gotoxy(y,x);
break;
}
else if(judge(x+1,y)==1||judge(x+1,y)==3)
{
if(judge(x,y)==3)
{
printDestination(x,y);
printMan(x+1,y);
break;
}
else
{
printf(" ");
printMan(x+1,y);
break;
}
}
else if(judge(x+1,y)==2)
{
if(judge(x+2,y)==1)
{
moveBoxSpacetoSpace(x,y,'d');
if(judge(x,y)==3)
printDestination(x,y);
gotoxy(y,x+1);
}
else if(judge(x+2,y)==3)
{
moveBoxSpacetoDes(x,y,'d');
if(judge(x,y)==3)
printDestination(x,y);
gotoxy(y,x+1);
}
else
gotoxy(y,x);
break;
}
else if(judge(x+1,y)==4)
{
if(judge(x+2,y)==1)
{
moveBoxDestoSpace(x,y,'d');
if(judge(x,y)==3)
printDestination(x,y);
gotoxy(y,x+1);
}
else if(judge(x+2,y)==3)
{
moveBoxDestoDes(x,y,'d');
if(judge(x,y)==3)
printDestination(x,y);
gotoxy(y,x+1);
}
else
gotoxy(y,x);
break;
}
/*如果按向左鍵*/
case 'l':
if(!judge(x,y-1))
{
gotoxy(y,x);
break;
}
else if(judge(x,y-1)==1||judge(x,y-1)==3)
{
if(judge(x,y)==3)
{
printDestination(x,y);
printMan(x,y-1);
break;
}
else
{
printf(" ");
printMan(x,y-1);
break;
}
}
else if(judge(x,y-1)==2)
{
if(judge(x,y-2)==1)
{
moveBoxSpacetoSpace(x,y,'l');
if(judge(x,y)==3)
printDestination(x,y);
gotoxy(y-1,x);
}
else if(judge(x,y-2)==3)
{
moveBoxSpacetoDes(x,y,'l');
if(judge(x,y)==3)
printDestination(x,y);
gotoxy(y-1,x);
}
else
gotoxy(y,x);
break;
}
else if(judge(x,y-1)==4)
{
if(judge(x,y-2)==1)
{
moveBoxDestoSpace(x,y,'l');
if(judge(x,y)==3)
printDestination(x,y);
gotoxy(y-1,x);
}
else if(judge(x,y-2)==3)
{
moveBoxDestoDes(x,y,'l');
if(judge(x,y)==3)
printDestination(x,y);
gotoxy(y-1,x);
}
else
gotoxy(y,x);
break;
}
/*如果按向右鍵*/
case 'r':
if(!judge(x,y+1))
{
gotoxy(y,x);
break;
}
else if(judge(x,y+1)==1||judge(x,y+1)==3)
{
if(judge(x,y)==3)
{
printDestination(x,y);
printMan(x,y+1);
break;
}
else
{
printf(" ");
printMan(x,y+1);
break;
}
}
else if(judge(x,y+1)==2)
{
if(judge(x,y+2)==1)
{
moveBoxSpacetoSpace(x,y,'r');
if(judge(x,y)==3)
printDestination(x,y);
gotoxy(y+1,x);
}
else if(judge(x,y+2)==3)
{
moveBoxSpacetoDes(x,y,'r');
if(judge(x,y)==3)
printDestination(x,y);
gotoxy(y+1,x);
}
else
gotoxy(y,x);
break;
}
else if(judge(x,y+1)==4)
{
if(judge(x,y+2)==1)
{
moveBoxDestoSpace(x,y,'r');
if(judge(x,y)==3)
printDestination(x,y);
gotoxy(y+1,x);
}
else if(judge(x,y+2)==3)
{
moveBoxDestoDes(x,y,'r');
if(judge(x,y)==3)
printDestination(x,y);
gotoxy(y+1,x);
}
else
gotoxy(y,x);
break;
}
default:
break;
}
}
功能控制模塊包括屏幕輸出功能、關卡重置功能和坐標位置狀態(tài)的判斷功能。該模塊包括以下幾個函數。
① void putoutChar(int y,int x,char fc,char bc):在屏幕上指定的位置輸出指定的字符。
② int judge(int x,int y):判斷位置(x,y)處的狀態(tài),狀態(tài)值可參見1.2節(jié)。
③ void reset (int i):重置關卡。
具體實現代碼如下所示。
/*在屏幕指定位置輸出指定的字符函數*/
void putoutChar(int y,int x,char ch,char fc,char bc)
{
/*屏幕輸出字符ch*/
printScreen[(x*160)+(y<<1)+0]=ch;
/*指定字符顏色fc,背景顏色bc*/
printScreen[(x*160)+(y<<1)+1]=(bc*16)+fc;
}
/*判斷特定坐標的狀態(tài)函數*/
int judge(int x,int y)
{
int i;
/*根據status[x][y]中存的值來判斷該點的狀態(tài)*/
switch(status[x][y])
{
/*如果什么都沒做*/
case 0:
i=1;
break;
/*如果該點表示墻*/
case 'w':
i=0;
break;
/*如果該點表示箱子*/
case 'b':
i=2;
break;
/*如果該點表示箱子在目的地*/
case 'i':
i=4;
break;
/*如果該點表示目的地*/
case 'm':
i=3;
break;
default:
break;
}
return i;
}
/*重置當前關函數*/
void reset(int i)
{
switch(i)
{
/*重置第一關*/
case 0:
init();
initStep1();
break;
/*重置第二關*/
case 1:
init();
initStep2();
break;
/*重置第三關*/
case 2:
init();
initStep3();
break;
/*重置第四關*/
case 3:
init();
initStep4();
break;
default:
break;
}
}
系統(tǒng)主函數main()用于實現整個程序的控制,其游戲操作流程如圖1-2所示,具體代碼如下所示。