| 導購 | 订阅 | 在线投稿
分享
 
 
 

利用C++實現的貪吃蛇遊戲

2008-06-01 02:08:25  編輯來源:互聯網  简体版  手機版  評論  字體: ||
 
  在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();
利用C++實現的貪吃蛇遊戲
更多內容請看C/C++技術專題 網絡遊戲攻略 遊戲開發專題,或
  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++;
  }
利用C++實現的貪吃蛇遊戲
更多內容請看C/C++技術專題 網絡遊戲攻略 遊戲開發專題,或
  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.leftx>=frame.righty<frame.topy>=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
 
  在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(); [url=/bbs/detail_1785424.html][img]http://image.wangchao.net.cn/it/1323423447034.gif[/img][/url] 更多內容請看C/C++技術專題 網絡遊戲攻略 遊戲開發專題,或   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++;   } [url=/bbs/detail_1785424.html][img]http://image.wangchao.net.cn/it/1323423462154.gif[/img][/url] 更多內容請看C/C++技術專題 網絡遊戲攻略 遊戲開發專題,或   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.leftx>=frame.righty<frame.topy>=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
󰈣󰈤
 
 
 
>>返回首頁<<
 
 
 
 
 熱帖排行
 
王朝網路微信公眾號
微信掃碼關註本站公眾號 wangchaonetcn
 
  免責聲明:本文僅代表作者個人觀點,與王朝網絡無關。王朝網絡登載此文出於傳遞更多信息之目的,並不意味著贊同其觀點或證實其描述,其原創性以及文中陳述文字和內容未經本站證實,對本文以及其中全部或者部分內容、文字的真實性、完整性、及時性本站不作任何保證或承諾,請讀者僅作參考,並請自行核實相關內容。
 
© 2005- 王朝網路 版權所有