利用c++实现的贪吃蛇游戏

在tc 3.0下调试通过,因为tc 3.0不支持bool 类型,所以程序中自定义了个枚举类型变量bool
  如果在vc或者bc中运行,可以把这个bool类型注释掉.
  贪吃蛇的核心算法时如何实现移动和吃掉食物.

没有碰到食物的时候,把当前运动方向上的下个节点入队,并以蛇节点的颜色重绘这个节点.
  然后把头指针所指的节点出队,并以游戏框架内部背景色重绘出队的节点,这样就可以达到移动的效果.
  而在吃到食物的时候,则只需把食物入队即可.

// 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;
 }
 }


//conf.h

 #ifndef _conf_h
 #define _conf_h
 #define RowOfFrame    20         //主框架的行数
 #define ColumnOfFrame 20         //主框架的列数
 #define BlockWidth    15        //每个蛇节点的宽度
 #define BlockHeight   15        //每个蛇节点的高度
 #define UP   18432
 #define DOWN  20480
 #define LEFT  19200
 #define RIGHT  19712
 #define ESC   283
 #define ENTER  7181
 #define PAGEUP  18688
 #define PAGEDOWN 20736
 #endif
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值