第一篇:C語言課設(shè) 貪食蛇 含完整代碼 課設(shè)報(bào)告
《c語言課程設(shè)計(jì)》課程設(shè)計(jì)報(bào)告
課程主題:
聰明的小蛇 Smart Snake 需求分析
【闡述課程設(shè)計(jì)應(yīng)該完成的功能】
使用鍵盤的上下左右鍵來控制蛇的運(yùn)動(dòng)方向,ESC鍵退出,顯示現(xiàn)在得分,三個(gè)難度選擇(每一關(guān)地圖不同,小蛇移動(dòng)速度不同)系統(tǒng)分析和設(shè)計(jì)
2.1 數(shù)據(jù)結(jié)構(gòu)的設(shè)計(jì)和選擇的理由
本游戲中涉及的主要數(shù)據(jù)結(jié)構(gòu)是如何表示運(yùn)動(dòng)的蛇、食物狀態(tài)等問題。
2.1.1 蛇是由一連串舉行組成,用結(jié)構(gòu)體數(shù)組表示蛇每一節(jié)的橫縱坐標(biāo)。用數(shù)組實(shí)現(xiàn)
struct Snake { int x[N];int y[N];int node;/*蛇的節(jié)數(shù)*/ int direction;/*蛇移動(dòng)方向*/ int life;/* 蛇的生命,0活著,1死亡*/ }snake;//這是蛇的結(jié)構(gòu)體
小蛇是在不斷的運(yùn)動(dòng)的,我們研究蛇的運(yùn)動(dòng)可以發(fā)現(xiàn)這樣的特點(diǎn): 1.蛇頭由鍵盤控制,在無操作的時(shí)候蛇需要以原來的方向繼續(xù)前進(jìn) 2.運(yùn)動(dòng)時(shí),蛇身后面一節(jié)移動(dòng)到前面一節(jié)的位置。2.1.2 關(guān)于食物有兩個(gè)屬性: 1.坐標(biāo)位置
2.狀態(tài):存在,或被吃。
(由于三者的存在狀態(tài)基本相同所以我們用一個(gè)結(jié)構(gòu)體表示)struct Food { int x;/*食物的橫坐標(biāo)*/ int y;/*食物的縱坐標(biāo)*/ int yes;/*判斷是否要出現(xiàn)食物的變量*/ }food;/*食物的結(jié)構(gòu)體*/
2.2 系統(tǒng)模塊劃分和模塊結(jié)構(gòu) 開始動(dòng)畫
游戲開始界面 游戲過程界面 游戲結(jié)束界面 2.3 流程圖
2.4 數(shù)據(jù)類型、全局變量和函數(shù)說明
2.4.1數(shù)據(jù)類型&2.4.2全局變量 #include “stdafx.h” #include “graphics.h” #include “stdlib.h” #include “conio.h” #include “time.h” #include “stdio.h” #include “snake.h” #pragma comment(lib,“Winmm.lib”)//播放音樂 #ifndef SNAKE_H #define SNAKE_H #define LEFT 'a' #define RIGHT 'd' #define DOWN 's' #define UP 'w' #define ESC 27 #define N 200 #define ENTER 13 #define JACK 'j' #define KING 'k' #define LONG 'l' int score = 0;int Func = 0;int gamespeed = 200;//蛇運(yùn)行速度 char mx1,mx2;int level=1;char string_score[100];char str[100];
2.5 涉及的函數(shù)
static void Init(void);/*圖形驅(qū)動(dòng)*/ static void Close(void);/*圖形結(jié)束*/ static void Game_interface(void);/*游戲界面*/ static void GameOver(void);/*結(jié)束游戲*/ static void GamePlay(void);/*游戲過程*/ static void PrScore(void);/*輸出成績(jī)*/ static void textdown(void);//選關(guān)焦點(diǎn)鄉(xiāng)下 static void textup(void);//選關(guān)焦點(diǎn)向上 static void choose(void);//選關(guān)界面 static void difficult(void);//難度選擇 程序測(cè)試和運(yùn)行結(jié)果
反復(fù)調(diào)試 效果良好,能正常運(yùn)行 課程報(bào)告小結(jié)
【遇到的問題及解決方法分析等】
4.1小蛇和指示標(biāo)走過有顯示
解決方法:每次都用一塊與背景色相同的的矩形覆蓋。
4.2食物出現(xiàn)在邊界上
解決方法:
if(level==1){ while(food.x%10!= 0)/*食物隨機(jī)出現(xiàn)后必須讓食物能夠在整格內(nèi),這樣才可以讓蛇吃到*/ food.x++;while(food.y%10!= 0)food.y++;food.yes = 0;/*畫面上有食物了*/ } if(level==2){while((food.x%10!= 0)||((food.x>=145)&&(food.x<=510))&&((food.y>=250)&&(food.y<=270)))/*食物隨機(jī)出現(xiàn)后必須讓食物能夠在整格內(nèi),這樣才可以讓蛇吃到*/ food.x++;while(food.y%10!= 0)food.y++;food.yes = 0;/*畫面上有食物了*/ }
/這段代碼保證了食物不被產(chǎn)生在障礙上 附錄 程序源代碼:
// mff.cpp : Defines the entry point for the console application.//
#include “stdafx.h” #include “graphics.h” #include “stdlib.h” #include “conio.h” #include “time.h” #include “stdio.h” #include “snake.h” #pragma comment(lib,“Winmm.lib”)//播放音樂
int score = 0;int Func = 0;int gamespeed = 200;//蛇運(yùn)行速度 char mx1,mx2;int level=1;char string_score[100];char str[100];
static void Init(void);/*圖形驅(qū)動(dòng)*/ static void Close(void);/*圖形結(jié)束*/ static void Game_interface(void);/*游戲界面*/ static void GameOver(void);/*結(jié)束游戲*/ static void GamePlay(void);/*游戲過程*/ static void PrScore(void);/*輸出成績(jī)*/ static void textdown(void);static void textup(void);static void choose(void);static void difficult(void);int _tmain(int argc, _TCHAR* argv[]){
}
/*圖形驅(qū)動(dòng)*/ static void Init(void){ int gd=9,gm=2;
initgraph(&gd,&gm,“ ”);cleardevice();}
/* 開始畫面,左上角坐標(biāo)為(,),右下角坐標(biāo)為(,)的圍墻*/ static void Game_interface(void){ int i;int j;int k;
setcolor(YELLOW);/*setbkcolor(LIGHTGREEN);*/ setlinestyle(PS_SOLID,0,1);/*設(shè)置線型*/ for(i=50;i<=600;i+=10)/*畫邊框*/ { rectangle(i,40,i+10,49);/*上邊框*/ rectangle(i,451,i+10,460);/*下邊框*/ }
if(level==2){ for(j=150;j<=500;j+=10)
} if(level==3)///*畫Level3下兩條橫向隔斷*/ rectangle(j,245,j+10,254);/*畫Level2下橫向隔斷*/ mciSendString(_T(“open 2.mp3 alias mymusic”), NULL, 0, NULL);mciSendString(_T(“play mymusic repeat”), NULL, 0, NULL);choose();return 0;system(“pause”);{ for(j=150;j<=500;j+=10)rectangle(j,180,j+10,189);for(k=150;k<=500;k+=10)rectangle(k,350,k+10,359);} for(i=40;i<=450;i+=10){ rectangle(50,i,59,i+10);/*左邊框*/ rectangle(601,i,610,i+10);/*右邊框*/ } }
/* 游戲主函數(shù)*/ static void GamePlay(void){ int i;srand(time(NULL));/*隨機(jī)數(shù)發(fā)生器*/ food.yes = 1;/*1表示需要出現(xiàn)新食物,0表示已經(jīng)存在食物*/ snake.life = 0;/*活著*/ snake.direction = 1;/*方向往右*/ snake.x[0] = 100;snake.y[0] = 100;snake.x[1] = 110;snake.y[1] = 100;snake.node = 2;/*節(jié)數(shù)*/ PrScore();/*輸出得分*/ while(1)/*可以重復(fù)玩游戲,壓ESC鍵結(jié)束*/ { while(!kbhit())/*在沒有按鍵的情況下,蛇自己移動(dòng)*/ { if(food.yes == 1)/*需要出現(xiàn)新食物*/ { food.x = rand()%400 + 60;food.y = rand()%350 + 60;if(level==1){ while(food.x%10!= 0)/*食物隨機(jī)出現(xiàn)后必須讓食物能夠在整格內(nèi),這樣才可以讓蛇吃到*/ food.x++;while(food.y%10!= 0)food.y++;food.yes = 0;/*畫面上有食物了*/ } if(level==2){while((food.x%10!= 0)||((food.x>=145)&&(food.x<=510))&&((food.y>=250)&&(food.y<=270)))/*食物隨機(jī)出現(xiàn)后必須讓食物能夠在整格內(nèi),這樣才可以讓蛇吃到*/ food.x++;while(food.y%10!= 0)food.y++;food.yes = 0;/*畫面上有食物了*/ }
if(level==3){while((food.x%10!= 0)||(((food.x < 530)&&(food.x > 135))&&((food.y < 185)&&(food.y > 185)))||(((food.x < 530)&&(food.x > 135))&&((food.y < 379)&&(food.y > 350))))/*食物隨機(jī)出現(xiàn)后必須讓食物能夠在整格內(nèi),這樣才可以讓蛇吃到*/ food.x++;while(food.y%10!= 0)food.y++;food.yes = 0;/*畫面上有食物了*/ }
}
if(food.yes == 0)/*畫面上有食物了就要顯示*/ { setcolor(GREEN);rectangle(food.x,food.y,food.x + 10,food.y-10);}
for(i=snake.node-1;i>0;i--)/*蛇的每個(gè)環(huán)節(jié)往前移動(dòng),也就是貪吃蛇的關(guān)鍵算法*/ { snake.x[i] = snake.x[i-1];snake.y[i] = snake.y[i-1];} /*1,2,3,4表示右,左,上,下四個(gè)方向,通過這個(gè)判斷來移動(dòng)蛇頭*/ switch(snake.direction){ case 1: snake.x[0] += 10;break;case 2:
snake.x[0]-= 10;break;case 3: snake.y[0]-= 10;break;case 4: snake.y[0] += 10;break;} /* 從蛇的第四節(jié)開始判斷是否撞到自己*/ for(i=3;i
if(level==3){ if((((snake.x[0] < 520)&&(snake.x[0] > 145))&&((snake.y[0] < 195)&&(snake.y[0] > 175)))||(((snake.x[0] < 510)&&(snake.x[0] > 140))&&((snake.y[0] < 369)&&(snake.y[0] > 330))))/*蛇是否撞到level3中兩條橫向隔斷*/ { GameOver();/*本次游戲結(jié)束*/ snake.life = 1;/*蛇死*/ } }
if(snake.life == 1)/*以上兩種判斷以后,如果蛇死就跳出內(nèi)循環(huán),重新開始*/ break;if((snake.x[0] == food.x)&&(snake.y[0] == food.y))/*吃到食物以后*/ { setcolor(BLACK);/*把畫面上的食物東西去掉*/ rectangle(food.x,food.y,food.x+10,food.y-10);snake.x[snake.node] =-20;snake.y[snake.node] =-20;
/* 新的一節(jié)先放在看不見的位置,下次循環(huán)就取前一節(jié)的位置*/
snake.node++;/*蛇的身體長(zhǎng)一節(jié)*/ food.yes = 1;/*畫面上需要出現(xiàn)新的食物*/ score += 10;PrScore();/*輸出新得分*/ } setcolor(RED);/*畫出蛇*/
for(i=0;i if(snake.life == 1)/*如果蛇死就跳出循環(huán)*/ break; key=getch();/*接收按鍵*/ if(key == ESC)break;/*按ESC鍵退出*/ switch(key){ case UP: if(snake.direction!= 4)/*判斷是否往相反的方向移動(dòng)*/ snake.direction = 3;break;case RIGHT: if(snake.direction!= 2)snake.direction = 1;break;case LEFT: if(snake.direction!= 1)snake.direction = 2;break;case DOWN: if(snake.direction!= 3)snake.direction = 4;break;} }/*endwhile(1)*/ } /*游戲結(jié)束*/ static void GameOver(void){ cleardevice();PrScore();setcolor(RED);setfont(50, 0, _T(“楷體”));outtextxy(200, 200, _T(“GAME OVER”));getch();} /*輸出成績(jī)*/ static void PrScore(void){ setfillstyle(YELLOW);// bar(235, 560, 300, 580);char s[5] = {'