貪喫蛇遊戲 C語言程序設計

 

《計算機程序設計》課程設計報告

 

課 題 名 稱     貪喫蛇遊戲          

班       級       軟件1班           

姓       名       neolone                


 



目錄

 

1 需求分析... 1

2 系統分析和設計... 1

2.1 數據結構的設計和選擇的理由... 1

2.2 系統模塊劃分和模塊結構... 2

2.3 流程圖... 3

2.4 數據類型、全局變量和函數說明... 3

3 程序測試和運行結果... 4

4 課程報告小結... 5

4.1分數重疊顯示... 5

4.2速度太快... 5

4.3食物可能出現在蛇身上... 5

附錄A:程序源代碼... 6


1 需求分析

【闡述課程設計應該完成的功能】

使用鍵盤的上下左右,來控制蛇的運動方向,ESC鍵退出,並顯示得分。

 

2 系統分析和設計

2.1 數據結構的設計和選擇的理由

本遊戲中涉及的主要數據結構是如何表示運動的蛇、食物狀態等問題。
2.1.1 從遊戲參考畫面中我們可以看到,貪喫蛇的身體是一節節的,由一個個大小相同的方塊組成,那麼我們可以用一個(x,y)座標爲左上角的、固定寬度的正方形來表示一節蛇身。爲表示連續的多節身體,那麼我們可以採用數組(或鏈表,或線性表)等數據結構來表示。下面以數組方式爲例:
struct Point {
    int x, y;
}

struct Point nodes[MAX_LENGTH];  //蛇身數組,MAX_LENGTH爲最大蛇長

貪喫蛇是在不斷的運動的,我們研究蛇的運動可以發現這樣的特點:
1. 蛇頭由鍵盤控制,鍵盤不操作時,保持原有方向運動;(用 intdirection;表示)
2. 運動時,蛇身後面一節移動到前面一節的位置。當我們用nodes[0]表示蛇頭的時候,nodes[1]運動到nodes[0]處;nodes[2]運動到nodes[1]處...。
3. 喫到一個食物以後,蛇身會增加一節。即該數組中的有效數據個數加一。(用int length;表示)

根據上面的情況,我們可以設計蛇的數據結構如下:
struct Snake {
   struct Point nodes[MAX_LENGTH];  //蛇身數組,保存每節蛇身的座標。MAX_LENGTH爲最大蛇長
    int length;    //當前蛇長
    int direction; //蛇頭運動方向
    int live;      //蛇活的,還是已經死了?
}

2.1.2 關於食物
,有兩個屬性:
1. 座標位置
2. 狀態:存在,或被喫。
故我們用以下結構表示:
struct Food {
    struct Point position;  //食物的位置
    int exist;             //存在?還是被喫?
}

 

2.2 系統模塊劃分和模塊結構

void main() {

       init();                           /*初始化*/

       l=1;                            

       while(l)                          /*循環遊戲*/

       {

          select();                       /*遊戲速度和結束的選擇菜單*/

          gamePlay();                    /*遊戲主程序*/

       }

       close();                           /*關閉遊戲*/

}

2.3 流程圖

 

 

 

 

 

2.4 數據類型、全局變量和函數說明

2.4.1數據類型

struct Point {                                         /*一個存放點座標的結構體*/

       intx, y;          /*被多個結構體調用的基本參數,所以統一用point結構體來表示*/

};

 

struct Snake {                                        /*用來模擬蛇狀態的結構體*/

       structPoint nodes[MAX_LENGTH];                /*用來存放蛇每一節的位置*/

       intlength;                                      /*蛇長*/

       intdirection;                                    /*蛇移動的方向*/

       intlive;                                                      /*蛇是否活着*/

} snake;

                                           /*比較形象的把蛇抽象爲一個數據類型*/

struct Food {                                        /*用來模擬食物狀態的結構體*/

       structPoint position;                             /*食物的位置*/

       intexist;                                       /*食物是否存在*/

} food;

 

2.4.2全局變量

Score                                                                                   \\得分

left,top,right,bottom                                                               \\遊戲區域範圍

lastx,lasty                                                                             \\用來保存最後一節蛇的位置

keyCode                                                                               \\用來保存按下的鍵

 

2.4.3函數說明

void init(void);                                                               \\初始化程序,給一些初始值賦值

void gamePlay(void);                                                      \\遊戲主循環

void close(void);                                   \\關閉遊戲

void drawWall(void);                               \\畫牆

void createFood(void);                              \\創造一個食物

void drawFood(void);                                                     \\畫出食物

void drawSnake(void);                                                    \\畫出蛇

void drawScore(void);                                                    \\畫出分數

int touchWall(void);                                 \\判斷是否碰到牆

int touchSelf(void);                                                        \\判斷是否碰到自己

void gameOver(void);                                                       \\遊戲結束

void moveSnake(void);                               \\移動蛇

int oppositeDirection(int keyCode);                     \\判斷是否方向有誤

int foodEat(void);                                                             \\判斷是否喫到食物

void expandSnake(void);                              \\把蛇增長一節

 

3 程序測試和運行結果


----------------------------------------------------------------------------選擇速度開始或退出


----------------------------------------------------------------------------------------遊戲運行中


--------------------------------------------------------------------------------------------------------遊戲結束

4 課程報告小結

【遇到的問題及解決方法分析等】

4.1分數重疊顯示

解決方法:每次都用一塊黑的矩形覆蓋

setfillstyle(1,16);

        bar(45,45,150,80);

4.2速度太快

解決方法:循環delay

for(d=0;d<4;d++)

        delay(GAME_SPEED);

4.3食物可能出現在蛇身上

解決方法:依次判斷,若重疊則重新生成食物

void createFood() {

       inti;

label:

   food.position.x=left+10*((int)rand()%11);

   food.position.y=top+10*((int)rand()%11);

       for(i=0;i<=snake.length-1;i++){

        if(snake.nodes[i].x==food.position.x&&snake.nodes[i].y==food.position.y)

              gotolabel;

       }

附錄A:程序源代碼

 

/*writer:  neolone*/
#include<graphics.h>
#include<stdlib.h>
#include<time.h>
#include<stdio.h>
#include<dos.h>
#include<conio.h>
#include<bios.h>
 
#define TRUE 1
#define FALSE 0
 
#define UP0x4800
#define DOWN0x5000
#define LEFT0x4B00
#define RIGHT0x4D00
#define ESC0x011B
#define SPEED10x0231
#define SPEED20x0332
#define SPEED30x0433
#defineQUIT  0x0B30
#define ENTER 0x1C0D
 
#defineMAX_LENGTH 100         /* max length ofsnake nodess */
#defineGAME_SPEED 100      /* game speed */
 
 
/* datastructure */
struct Point {
                                  int x, y;
};
 
struct Snake {
                                  struct Pointnodes[MAX_LENGTH];
                                  int length;
                                  int direction;
                                  int live;
} snake;
 
struct Food {
                                  struct Pointposition;
                                  int exist;
} food;
 
 
 
intscore=0,max,max1,max2,max3,left=200,top=200,right=300,bottom=300,lastx,lasty,keyCode,keyCode2,sp,l,sel,times=1;
char text[80];
 
/* functionsdeclaration */
void init(void);
voidgamePlay(void);
voidclose(void);
voiddrawWall(void);
voidcreateFood(void);
voiddrawFood(void);
voiddrawSnake(void);
voiddrawScore(void);
inttouchWall(void);
inttouchSelf(void);
voidgameOver(void);
void moveSnake(void);
intoppositeDirection(int keyCode);
intfoodEat(void);
voidexpandSnake(void);
voidselect(void);
/*------------------------*/
void main() {
                                  init();
                                  l=1;
                                  while(l)
                                  {
                                     select();
                                     gamePlay();
                                  }
                                  close();
}
 
void init() {
 
    int gdriver=VGA ,gmode=VGAHI ;
 
 
    snake.nodes[0].x=250;
    snake.nodes[0].y=250;
    snake.nodes[1].x=250;
    snake.nodes[1].y=260;
    snake.length=2;
                                  snake.live=1;
                                  snake.direction=UP;
 
                                  score=0;
    food.exist=0;
    initgraph(&gdriver,&gmode,"C:\\tc20\\BGI");
 
 
    randomize();/*sui ji shu fa sheng qi*/
 
                                  drawWall();
 
 
 
}
 
void close() {
                                  FILE *fp;
                                  closegraph();
                                  if((fp=fopen("data.txt","w"))==NULL)   /*關閉時保存最高分*/
                                  {
                                    exit(0);
                                  }
                                  else
                                  {
                                   fprintf(fp,"%d,%d,%d",max1,max2,max3);
                                   fclose(fp);
                                  }
                                  printf("pessany key to continue");
}
 
void  gamePlay() {
 
                                  int keyCode,d;
                                  getch();
                                  while(TRUE) {
                                   drawScore();
                                   drawWall();
                                   if(touchWall() || touchSelf()) {
                                          gameOver();
                                          return;
                                   }
                                   if(!food.exist) createFood();
                                   food.exist=1;
                                   drawFood();
                                   drawSnake();
                                   for(d=0;d<sp;d++)
                                   delay(GAME_SPEED);
                                   if(bioskey(1) != 0) {
                                          keyCode= bioskey(0);
                                          switch(keyCode){
                                                 caseESC:
                                                        gameOver();
                                                        return;
                                                 default:
                                       lastx=snake.nodes[snake.length-1].x;
                                       lasty=snake.nodes[snake.length-1].y;
                                                        if(!oppositeDirection(keyCode)) {
                                                               snake.direction= keyCode;
                                                        }
                                                        }
                                   }
                                   moveSnake();
                                   if(foodEat()) {
                                          food.exist= FALSE;
                                          score+= 10;
                                          expandSnake();
                                   }
                                  }
}
 
void drawWall(){
    rectangle(left,top,right+10,bottom+10);
}
 
voidcreateFood() {
                                  int i;
label:
    food.position.x=left+10*((int)rand()%11);
    food.position.y=top+10*((int)rand()%11);
                                  for(i=0;i<=snake.length-1;i++){
                                    if(snake.nodes[i].x==food.position.x&&snake.nodes[i].y==food.position.y)
                                   goto label;
                                  }
 
}
 
void drawFood(){
 
    setfillstyle(1,2);
   bar(food.position.x,food.position.y,food.position.x+10,food.position.y+10);
 
}
 
void drawSnake(){
    int j;
 
    setfillstyle(1,4);
    for(j=0;j<=snake.length-1;j++)
    {
      bar(snake.nodes[j].x,snake.nodes[j].y,snake.nodes[j].x+10,snake.nodes[j].y+10);
 
    }
 
 
}
 
voiddrawScore(void) {
 
     setfillstyle(1,16);
     bar(45,45,150,80);
 
 
     setcolor(WHITE);
     sprintf(text,"writer:neolone");
     outtextxy(170,50,text);
     sprintf(text,"score:%5d",score);
     outtextxy(50,50,text);
 
}
 
int touchWall(){
    int x1=snake.nodes[0].x;
    int y1=snake.nodes[0].y;
   if(x1<left||x1>right||y1<top||y1>bottom)
       return TRUE;
    else
       return FALSE;
 
}
 
int touchSelf(){
    int i;
    for (i=3;i<snake.length-1;i++)
    {
      if(snake.nodes[0].x==snake.nodes[i].x&&snake.nodes[0].y==snake.nodes[i].y)
       return TRUE;
 
    }
    return FALSE;
 
}
 
void gameOver(){
                                  FILE *fp;
    int x2,y2;
                                  x2=180;
                                  y2=250;
 
 
                                  setcolor(WHITE);
                                  sprintf(text,"Gameover !!your score is %d,%d",score,sel);
                                  outtextxy(x2,y2,text);
                                  delay(1000);
                                  getch();
                                  switch(sel%4)
                                  {
                                     case 1:
                                           if(score>max1)
                                           {
                                                 max1=score;
                                           }
                                           break;
                                     case 2:
                                           if(score>max2)
                                           {
                                                 max2=score;
                                           }
                                           break;
                                     case 3:
                                           if(score>max3)
                                           {
                                                 max3=score;
                                           }
                                           break;
                                     default :
                                           {
                                                 break;
                                           }
                                  }
}
 
void moveSnake(){
    int k;
    setfillstyle(1,16);
   lastx=snake.nodes[snake.length-1].x;
    lasty=snake.nodes[snake.length-1].y;
 bar(snake.nodes[snake.length-1].x,snake.nodes[snake.length-1].y,snake.nodes[snake.length-1].x+10,snake.nodes[snake.length-1].y+10);
    for(k=snake.length-2;k>=0;k--)
    {
                                  snake.nodes[k+1].x=snake.nodes[k].x;
                                  snake.nodes[k+1].y=snake.nodes[k].y;
    }
                                  if(snake.direction==UP)
       snake.nodes[0].y-=10;
    else if(snake.direction==DOWN)
       snake.nodes[0].y+=10;
    else if(snake.direction==LEFT)
       snake.nodes[0].x-=10;
    else if(snake.direction==RIGHT)
       snake.nodes[0].x+=10;
    else
                                  ;
}
 
intoppositeDirection(int keyCode) {
   if(keyCode==UP&&snake.direction==DOWN){
      return 1;
      }
    elseif(keyCode==DOWN&&snake.direction==UP) {
      return 1;
      }
    elseif(keyCode==LEFT&&snake.direction==RIGHT){
      return 1;
      }
    elseif(keyCode==RIGHT&&snake.direction==LEFT){
      return 1;
      }
    else
      return 0;
}
 
int foodEat() {
   if(snake.nodes[0].x==food.position.x&&snake.nodes[0].y==food.position.y)
       return 1;
    else
       return 0;
}
 
voidexpandSnake() {
    if(keyCode==UP){
      lastx-=10;
      }
    else if(keyCode==DOWN) {
      lastx+=10;
      }
    else if(keyCode==LEFT){
      lasty-=10;
      }
    else if(keyCode==RIGHT){
      lasty+=10;
      }
    else
     ;
 
      snake.nodes[snake.length].x=lastx;
      snake.nodes[snake.length].y=lasty;
    snake.length++;
}
 
void select()
{
   setfillstyle(1,7);                             /*實現選擇速度的可視化菜單*/
   bar(420,220,490,310);
   setfillstyle(1,9);
   bar(430,230,480,240);
   setfillstyle(1,5);
   setcolor(WHITE);
   sprintf(text,"speed1");
   outtextxy(430,230,text);
   bar(430,250,480,260);
   sprintf(text,"speed2");
   outtextxy(430,250,text);
   bar(430,270,480,280);
   sprintf(text,"speed3");
   outtextxy(430,270,text);
   bar(430,290,480,300);
   sprintf(text," quit ");
   outtextxy(430,290,text);
 
   sel=1;
   t=1;
 
   while(t){
   delay(10);
   if (bioskey(1) != 0) {
                                   keyCode =bioskey(0);
                                   switch(keyCode){
                                          caseUP:
                                                  sel--;break;
                                          caseDOWN:
                                                  sel++;break;
                                          caseENTER:
                                               t=0;break;
                        default :
                             break;
                                                  }
 
 
switch(sel%4) {
                                          case0:
                        setfillstyle(1,9);
                        bar(430,290,480,300);
                        setcolor(WHITE);
                                                               setfillstyle(1,5);
                                                               bar(430,230,480,240);
                       sprintf(text,"speed1");
                          outtextxy(430,230,text);
                        bar(430,250,480,260);
                       sprintf(text,"speed2");
                          outtextxy(430,250,text);
                        bar(430,270,480,280);
                       sprintf(text,"speed3");
                           outtextxy(430,270,text);
 
                        sprintf(text,"quit ");
                          outtextxy(430,290,text);
                                          break;
 
                                          case1:
                        setfillstyle(1,9);
                        bar(430,230,480,240);
                                                               setfillstyle(1,5);
                                                               setcolor(WHITE);
                                                               sprintf(text,"speed1");
                                                               outtextxy(430,230,text);
                                                               bar(430,250,480,260);
                                                               sprintf(text,"speed2");
                                                               outtextxy(430,250,text);
                                                               bar(430,270,480,280);
                                                               sprintf(text,"speed3");
                                                               outtextxy(430,270,text);
                                                               bar(430,290,480,300);
                                                               sprintf(text,"quit ");
                                                               outtextxy(430,290,text);
                                                               break;
 
                                          case2:
                        setfillstyle(1,9);
                                                               bar(430,250,480,260);
                                                               setfillstyle(1,5);
                                                               bar(430,230,480,240);
                                                               setcolor(WHITE);
                                                               sprintf(text,"speed1");
                                                               outtextxy(430,230,text);
                                                               sprintf(text,"speed2");
                                                               outtextxy(430,250,text);
                                                               bar(430,270,480,280);
                                                               sprintf(text,"speed3");
                                                               outtextxy(430,270,text);
                                                               bar(430,290,480,300);
                                                               sprintf(text,"quit ");
                                                               outtextxy(430,290,text);
                                                               break;
 
                                          case3:
                                                               setfillstyle(1,9);
                                                               bar(430,270,480,280);
                                                               setfillstyle(1,5);
                                                               bar(430,230,480,240);
                                                               setcolor(WHITE);
                                                               sprintf(text,"speed1");
                                                               outtextxy(430,230,text);
                                                               bar(430,250,480,260);
                                                               sprintf(text,"speed2");
                                                               outtextxy(430,250,text);
                                                               sprintf(text,"speed3");
                                                               outtextxy(430,270,text);
                                                               bar(430,290,480,300);
                                                               sprintf(text,"quit ");
                                                               outtextxy(430,290,text);
                                                               break;
 
                                          default:
                                          break;
                                   }
 
                                               }
   }
   /*ch=getch();*/
 
   if(times==1)                               /*讀取歷史最高分*/
   {
                                   if((fp=fopen("data.txt","r"))==NULL)
                                    {
                                    sprintf(text,"Can not open thefile");
                                    exit(0);
                                    }
                                    else
                                    {
                                    fscanf(fp,"%d,%d,%d",&max1,&max2,&max3);
                                    }
                                    fclose(fp);
                                    times=0;
   }
 
   switch(sel%4) {                                 /*選擇速度*/
                                          case0:
                                          l=0;
                                          gameOver();
                                          close();
                                          break;
 
                                          case1:
                                          sp=5;
                                          init();
                                          sprintf(text,"Hightestscore:%d",max1);
                                          outtextxy(50,90,text);
                                          break;
 
                                          case2:
                                          sp=3;
                                          init();
                                          sprintf(text,"Hightestscore:%d",max2);
                                          outtextxy(50,90,text);
                                          break;
 
                                          case3:
                                          sp=1;
                                          init();
                                          sprintf(text,"Hightestscore:%d",max3);
                                          outtextxy(50,90,text);
                                          break;
 
                                          default:
                                          break;
                                   }
 
}

這是資源地址,源代碼http://download.csdn.net/source/3483954

設計報告http://download.csdn.net/source/3483963


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章