// greedsnake.cpp #include <bios.h> #include <conio.h> #include <dos.h> #include <graphics.h> #include <stdlib.h> #include <time.h> #include "conf.h"
typedef struct node { int x,y; struct node *next; }Node;
typedef struct { Node *head,*tail; int length; }Snake; typedef struct { int left,top,right,bottom; }Frame;
typedef enum //四个方向 { up,down,left,right }Direction;
typedef enum { false,true }bool;//*/
void InitGraphMode(); //初始化图形驱动 void CloseGraphMode(); void Foot(int,int); void Head(int,int); void CreateFrame(); //完成整个游戏框架的绘制 void CreateSnake(); //创建一条两个节点的蛇,蛇的每一节是队列中的一个节点 bool PlayGame(); //游戏的主体函数, int Hit(int,int); //判断是否越界,或者撞到自身,两个参数分别是新的头接点的x,y坐标 bool GameOver(); //绘制游戏结束时弹出的对话框 void Enqueue(Node); //入队函数 Node Dequeue(); //出队函数 void ClearKeyBuf(); //清除键盘缓冲,此函数可以消除不停的按无效键的影响
Snake snake; Frame frame; void main() { InitGraphMode(); do { CreateFrame(); }while(PlayGame()); CloseGraphMode(); } void InitGraphMode() { int gdriver=DETECT,gmode; initgraph(&gdriver,&gmode,"../bgi/"); cleardevice(); } void CloseGraphMode() { cleardevice(); closegraph(); } void CreateFrame() { setbkcolor(CYAN); //下面的四行代码用于计算主框架的左上角和右下角的坐标 frame.left=(getmaxx()+1-BlockWidth*RowOfFrame)/2; frame.top=(getmaxy()+1-BlockHeight*ColumnOfFrame)/2; frame.right=frame.left+BlockWidth*RowOfFrame; frame.bottom=frame.top+BlockHeight*ColumnOfFrame; Head(frame.left+100,frame.top-20); setfillstyle(SOLID_FILL,LIGHTGRAY); bar(frame.left,frame.top,frame.right,frame.bottom); setlinestyle(SOLID_LINE,1,1); setcolor(DARKGRAY); line(frame.left,frame.top,frame.right,frame.top); line(frame.left,frame.top,frame.left,frame.bottom); setlinestyle(SOLID_LINE,1,1); setcolor(WHITE); line(frame.left,frame.bottom,frame.right,frame.bottom); line(frame.right,frame.top,frame.right,frame.bottom); setlinestyle(DOTTED_LINE,1,1); setcolor(BLUE); for(int row=1;row<RowOfFrame;row++) line(frame.left+row*BlockWidth,frame.top,frame.left+row*BlockWidth,frame.bottom); for(int column=1;column<ColumnOfFrame;column++) line(frame.left,frame.top+column*BlockHeight,frame.right,frame.top+column*BlockHeight); Foot(frame.left,frame.bottom+20); } void CreateSnake() { Node *node1=new Node; Node *node2=new Node; node1->x=frame.left+BlockWidth; node1->y=frame.top; node1->next=NULL; snake.tail=node1; node2->x=frame.left; node2->y=frame.top; node2->next=snake.tail; snake.head=node2; snake.length=2; setfillstyle(SOLID_FILL,BLUE); bar(snake.head->x+1,snake.head->y+1,snake.head->x+BlockWidth-1,snake.head->y+BlockHeight-1); bar(snake.tail->x+1,snake.tail->y+1,snake.tail->x+BlockWidth-1,snake.tail->y+BlockHeight-1); }
bool PlayGame() { int speed=300,key; Direction CurrentDirection=right; Node randomNode; Node newNode,outNode; bool neednode=true; bool overlap=false; int randx,randy; CreateSnake();
while(true) { if(neednode==true) { randomize(); do { randx=frame.left+rand()%RowOfFrame*BlockWidth; randy=frame.top+rand()%ColumnOfFrame*BlockHeight; for(Node *p=snake.head;p!=NULL;p=p->next)//hit itself if(randx==p->x&&randy==p->y) {overlap=true;break;} } while(overlap==true); randomNode.x=randx; randomNode.y=randy; randomNode.next=NULL; setfillstyle(SOLID_FILL,RED); bar(randomNode.x+1,randomNode.y+1,randomNode.x+BlockWidth-1,randomNode.y+BlockHeight-1); neednode=false; }
if((key=bioskey(1))!=0) { switch(key) { case ESC: return false; case UP: if(CurrentDirection!=down) CurrentDirection=up; ClearKeyBuf(); break; case DOWN: if(CurrentDirection!=up) CurrentDirection=down; ClearKeyBuf(); break; case LEFT: if(CurrentDirection!=right) CurrentDirection=left; ClearKeyBuf(); break; case RIGHT: if(CurrentDirection!=left)
CurrentDirection=right; ClearKeyBuf(); break; case PAGEUP:speed=speed-100; if(speed<100) speed=100; ClearKeyBuf(); break; case PAGEDOWN:speed=speed+100; if(speed>500) speed=500; ClearKeyBuf(); break; default :break; } } int headx=snake.tail->x; int heady=snake.tail->y; switch(CurrentDirection) { case up: heady-=BlockHeight;break; case down: heady+=BlockHeight;break; case left: headx-=BlockWidth;break; case right: headx+=BlockWidth;break; } if(Hit(headx,heady)) //whether the snake hit the wall or itself return GameOver(); else { //eat if(headx==randomNode.x&&heady==randomNode.y) { Enqueue(randomNode); setfillstyle(SOLID_FILL,BLUE); bar(randomNode.x+1,randomNode.y+1,randomNode.x-1+BlockWidth,randomNode.y-1+BlockHeight); neednode=true; } else //no eat { newNode.x=headx; newNode.y=heady; newNode.next=NULL; Enqueue(newNode); outNode=Dequeue(); setfillstyle(SOLID_FILL,LIGHTGRAY); bar(outNode.x+1,outNode.y+1,outNode.x+BlockWidth-1,outNode.y+BlockHeight-1); setfillstyle(SOLID_FILL,BLUE); bar(newNode.x+1,newNode.y+1,newNode.x-1+BlockWidth,newNode.y-1+BlockHeight); } } delay(speed); } } void ClearKeyBuf() { do bioskey(0); while(bioskey(1)); }
void Foot(int x,int y) { setcolor(BLUE); outtextxy(x,y,"writer:[T]RealXL E-MAIL:realgeneral@hotmail.com"); } void Head(int x,int y) { setcolor(RED); outtextxy(x,y,"GREEDY SNAKE"); } void Enqueue(Node inNode) { Node *p=new Node; p->x=inNode.x; p->y=inNode.y; p->next=inNode.next; snake.tail->next=p; snake.tail=p; snake.length++; } Node Dequeue() { Node *p=snake.head; Node outNode=*p; snake.head=p->next; snake.length--; delete p; return outNode; }
int Hit(int x,int y) { if(x<frame.left||x>=frame.right||y<frame.top||y>=frame.bottom)//hit the wall return 1;
Node *p=snake.head->next; for(int i=snake.length-1;i>3;i--,p=p->next)//hit itself if(x==p->x&&y==p->y) return 1; return 0; }
bool GameOver() { int x=getmaxx()/2-50; int y=getmaxy()/2-20; setfillstyle(SOLID_FILL,DARKGRAY); bar(x+3,y+3,x+103,y+43); setfillstyle(SOLID_FILL,MAGENTA); bar(x,y,x+100,y+40); setlinestyle(0,3,1); setcolor(RED); rectangle(x,y,x+100,y+40); outtextxy(x+20,y+10,"GAGE OVER!"); char c; while(true) //按q或Q表示退出程序,按r或R表示重新开始游戏 { c=getch(); if(c=='q'||c=='Q') return false; else if(c=='r'||c=='R') return true; } } |