这段代码是一个 UEFI 应用程序,它实现了一个简单的贪吃蛇游戏。
#include <Uefi.h>
#include <Library/UefiLib.h>
#include <Library/ShellCEntryLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <stdio.h>
#include <Library/TimerLib.h>
#include <Library/DebugLib.h>
#define A 1664525
#define C 1013904223
#define M 4294967296UL
static unsigned seed = 1;
BOOLEAN GameoverFlag=FALSE;
#define N 48
#define L 24
char Map[N][L];
typedef struct Position {int x, y;
} Position;
Position snake[4000000], food, next;
int head,tail,lenght,speed,grade;
char dirction,dirbef;
int score=0;
int order,wall,order_type;
int rank[5]={0}; char first[20]={"1."};char second[20]={"2."};char thirst[20]={"3."};char forth[20]={"4."};char fifth[20]={"5."};
void SetFood(){food.x=my_rand()%20 ;food.y=my_rand()%42 ;food.x= my_abs(food.x)+2;food.y=my_abs(food.y)+2;Map[food.x][food.y]='*';DEBUG((DEBUG_INFO, "food.x:%d ,food.y: %d\n", food.x , food.y));xy(food.x,food.y);Print(L"*");
}
// void xy(int y,int x)
// {
// gST->ConOut->SetCursorPosition ( gST->ConOut, x, y);
// }
ShowSnake()
{int index=0;xy( snake[head].x, snake[head].y);Print(L"@");for(index=0;index < 2; index++){xy( snake[index].x, snake[index].y);Print(L"+");}}void Hello(){
Print(L"\n\n\n\t\t\t\t\t\t 1.New Game\n");
Print(L"\n\t\t\t\t\t\t 2.Continue\n");
Print(L"\n\t\t\t\t\t\t 3.Exit\n");
}void SetMap(){ // for(int i=0;i<N;i++){ // for(int j=0;j<N;j++){// Map[i][j]=' ';// }// }// for(int k=0;k<N;k++){ //set map// Map[0][k]=Map[N-1][k]=Map[k][0]=Map[k][N-1]='+';// }// SetFood();Hello();head=2;tail=0;dirction='d'; //default leftdirbef='d';snake[0].x=5; //snakesnake[0].y=4;snake[2].x=5;snake[2].y=6;snake[1].x=5;snake[1].y=5;// Map[1][3]='O';// Map[1][2]='O';// Map[1][1]='O';lenght=3;speed=500;score=0;grade=0;order=1;if(order==1){//cls();Print(L"\n\n\n\t\t\t\t\t\t 1.Normal Mode\n");Print(L"\n\t\t\t\t\t\t 2.No Wall Mode\n");order_type=2;if(order_type==1) wall=1;else wall=0;}if(order==3) return ;for(int time=3;time>0;time--) {cls();Print(L"\n\t\t\t\tready to game %d\n", time);Sleep (1000);cls();}food.x =5;food.y =18;xy(food.x,food.y);Print(L"*");
}
void ShowKK(){ int i,j;//CpuBreakpoint();
for (int i = 1; i < L; i++) {for (int j = 1; j < N; j++) {if (i == 1 || i == L-1 || j == 1|| j == N-1) {Map[i][j]='+';xy(i,j);Print(L"+");} }
}
}void ShowMap(){ int i,j;for (i = 1; i < N-1; i++) {for (j = 1; j < N-1; j++) {Print(L"%c ", Map[i][j]);}// if (i == 2) {// Print(L"\t\tScore=%d", score);// }// if (i == 4) {// Print(L"\t\tLenght=%d", lenght);// }// if (i == 6) {// Print(L"\t\tSpeed=%d", 600 - speed);// }Print(L"\n");
}
}
int Gameover(){ if(dirction=='p'){ cls();Print(L"\n\n\t\t\t\tGame Over\n\n\n");return 0;}if(wall){ if(Map[next.y][next.x] == 'O' ||Map[next.y][next.x]=='+') {Map[next.y][next.x] = '@' ;Map[snake[head].y][snake[head].x]='O';Map[snake[tail].y][snake[tail].x]=' ';ShowMap();return 0;}}else{ if(Map[next.y][next.x] == 'O') {Map[next.y][next.x] = '@' ;Map[snake[head].y][snake[head].x]='O';Map[snake[tail].y][snake[tail].x]=' ';return 0;}}return 1;
}int SnakeMove(){//moveif(score%100==0&&score!=0) speed=500-score; //speedBOOLEAN timeover = TRUE;EFI_EVENT WaitList[2];EFI_EVENT TimeOutEvent;UINTN EventIndex;EFI_STATUS Status;EFI_INPUT_KEY Key;gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimeOutEvent);gBS->SetTimer (TimeOutEvent, TimerRelative, 10 * 1000 * 1000); WaitList[0] = TimeOutEvent;WaitList[1] = gST->ConIn->WaitForKey;while (1) {gBS->WaitForEvent (2, WaitList, &EventIndex);if (EventIndex == 1) {Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);if (Status == EFI_SUCCESS) {//Print(L"GetKey %d",Key.UnicodeChar);DEBUG((DEBUG_INFO, "Key.UnicodeChar:%d\n",Key.UnicodeChar ));if( Key.UnicodeChar== 'w' ||Key.UnicodeChar== 'a'|| Key.UnicodeChar== 's' || Key.UnicodeChar== 'd'){dirction=Key.UnicodeChar;break;}dirction=Key.UnicodeChar;break;}}else{ Status = EFI_TIMEOUT;// Print(L"Status %r",Status);break;}}//getchardirbef=dirction;DEBUG((DEBUG_INFO, "dirction:%d ,dirbef: \n",dirction ,dirbef));if(dirction!='w'&&dirction!='a'&&dirction!='s'&&dirction!='d'||((dirction=='w'&&dirbef=='s')||(dirction=='a'&&dirbef=='d')||(dirction=='s'&&dirbef=='w')||(dirction=='d'&&dirbef=='a')))dirction=dirbef;switch(dirction){case 'a':next.y = snake[head].y-1;next.x = snake[head].x;break;case 'd':next.y = snake[head].y+1;next.x = snake[head].x;break;case 'w':next.y = snake[head].y;next.x = snake[head].x-1;break;case 's':next.y = snake[head].y;next.x = snake[head].x+1;break;case 'p':break;//Gameover();}if((next.y==1)||(next.y==N-1)|| (next.x==1)||(next.x==L-1)) { cls();Print(L"\n\n\t\t\t\tGame Over\n\n\n");GameoverFlag=TRUE;MicroSecondDelay(3*1000*1000);return Status;}// if(next.y==0) next.y=N-2;// if(next.y==N-1) next.y=1;// if(next.x==0) next.x=M-2;// if(next.x==M-1) next.x=1;}void Eat(){//is eat foodif(next.x==food.x&&next.y==food.y){//eat score+=10;xy(next.x,next.y );Print(L"@");xy(snake[head].x,snake[head].y);Print(L"+");head++;snake[head].x=next.x;snake[head].y=next.y;Map[snake[head].x][snake[head].y]='@';lenght++;SetFood();}else{//no eatxy(next.x,next.y );Print(L"@");xy(snake[head].x,snake[head].y);Print(L"+");head++;snake[head].x=next.x;snake[head].y=next.y;xy(snake[head-lenght].x,snake[head-lenght].y);Print(L" ");}xy(5,60);Print(L"Score:%d",score);}EFI_STATUS
EFIAPI
TanchisheInit(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE *SystemTable){ my_srand(11);gST->ConOut->EnableCursor (gST->ConOut, FALSE);while(1){SetMap();if(order==3){}else{ShowKK();ShowSnake();while(1){SnakeMove();if(GameoverFlag){return EFI_SUCCESS;}if(!Gameover()) {if(dirction!='p') break;}Eat();}}Print(L"\n....................press any key continue\n");order=0;dirction=dirbef;}}
游戏界面:
简单介绍下模块
while (1) {
gBS->WaitForEvent (2, WaitList, &EventIndex);
if (EventIndex == 1) {
Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
if (Status == EFI_SUCCESS) {
//Print(L"GetKey %d",Key.UnicodeChar);
DEBUG((DEBUG_INFO, "Key.UnicodeChar:%d\n",Key.UnicodeChar ));
if( Key.UnicodeChar== 'w' ||Key.UnicodeChar== 'a'|| Key.UnicodeChar== 's' || Key.UnicodeChar== 'd')
{
dirction=Key.UnicodeChar;
break;
}
dirction=Key.UnicodeChar;
break;
}
}else
{ Status = EFI_TIMEOUT;
// Print(L"Status %r",Status);
break;
}
}
gBS->WaitForEvent (2, WaitList, &EventIndex);
这行代码是在等待两个事件中的任何一个发生。这两个事件分别是定时器事件和键盘输入事件。
如果 EventIndex == 1
,那么发生的事件是键盘输入事件。在这种情况下,程序会调用 gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
来读取用户输入的键值。
如果读取成功,即 Status == EFI_SUCCESS
,那么程序会检查用户输入的键值。如果键值是 'w'、'a'、's' 或 'd',那么程序会将这些值赋给 dirction
变量,并退出循环。
如果等待的事件不是键盘输入事件,那么程序会设置 Status = EFI_TIMEOUT;
并退出循环。
总的来说,这段代码的作用是等待用户输入方向键,并根据用户的输入来改变蛇的移动方向