貪吃蛇C語(yǔ)言實(shí)現(xiàn)

前言

本投稿作為首次嘗試將Bilibili作為代碼管理網(wǎng)站上傳代碼。代碼主要來(lái)自Bilibili某C語(yǔ)言貪吃蛇教學(xué)視頻,但由于時(shí)間過(guò)長(zhǎng),播放歷史已無(wú)從尋找。有興趣可以按F12點(diǎn)擊CSDN鏈接https://blog.csdn.net/qq_43437166/article/details/105564096

代碼段
/*
1.數(shù)據(jù)設(shè)計(jì)
2.模塊化設(shè)計(jì)
3.實(shí)現(xiàn)功能
/////////////////////////////////////////////////////////////////////
//?? ??? ??? ??? ??? ??? ??? ??? ?貪吃蛇
//????????????????????????? 編寫(xiě) 20190818?? bug:蛇撞左右墻不死
*/?? ??? ??? ??? ?//?? ??? ??? ?改寫(xiě) 20191002?? 20190818bug未修復(fù) 原因未知
/*????????????????????????? 修復(fù) 20191228?? 20190818bug修復(fù)?????????????????????????????????????? */
#include<stdio.h>
#include<windows.h>
#include<conio.h>
#include<stdlib.h>
#include<time.h>
#include<iostream>
////////////////////輔助宏定義
#define?? ?MAPHEIGHT 20?? //高度
#define MAPWIDTH 30?? ? //寬度
#define MAXSIZE 30?? ?//最大長(zhǎng)度
using namespace std;?? ??? ??? ??? ??? ?
//數(shù)據(jù)設(shè)計(jì)
//?? ??? ??? ??? ??? ??? ??? ??? ?食物
struct Food
{? int x,y;?? ?//坐標(biāo)定位
}food;
//?? ??? ??? ??? ??? ??? ??? ??? ?蛇
struct Snake?? ?// 每一節(jié)蛇的 坐標(biāo)
{? int x[MAXSIZE];
?? int y[MAXSIZE];
?? ?int len;
?? ?int speed;
}snake;
/////////////////////////////////////////
/////////全局變量
int key_last = 'w' ;?? ? //上次運(yùn)動(dòng)初始方向
int key_next='w';?? ??? ?? //新的運(yùn)動(dòng)方向
int changeflag? = 0;//運(yùn)動(dòng)方向改變標(biāo)志
//模塊化設(shè)計(jì)? --》功能劃分--》》抽象到函數(shù)
?? ??? ??? ??? ??? ??? ??? ??? ??? ?
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?
//1.畫(huà)地圖
void drawmap();
//2. 食物
void creatfood();
//3.按鍵操作
void KeyDown();
//4.蛇的狀態(tài)
int snakestatus();
//5.輔助函數(shù) 光標(biāo)移動(dòng)
void gotoxy(int x,int y);
void pausemenu();
int main ()
{
//?? ?gotoxy(1,1);
?? ?drawmap();
?? ?
?? ?while (1)
?? ?{?? ??? ?creatfood();
?? ??? ??? ?Sleep(snake.speed*2);
?? ??? ??? ?KeyDown();
?? ??? ??? ?if(!snakestatus())
?? ??? ??? ??? ?{
?? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ?} ?
?? ?}
?? ?gotoxy(MAPWIDTH/2-4,MAPHEIGHT/2);
?? ?printf("Game over!\t");
?? ?
?? ?system("pause");
?? ??? ?
return 0;
} ?
?? ?
void gotoxy(int x,int y)
{
?//調(diào)用win32的API 去設(shè)置控制臺(tái)的光標(biāo)位置
//1.找到控制臺(tái)窗口
?? ?HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
//2.光標(biāo)的結(jié)構(gòu)體
?? ?COORD coord;
//3.設(shè)置坐標(biāo) 光標(biāo)
?? ?coord.X=x;
?? ?coord.Y=y;
//4.同步到控制臺(tái)
?? ?SetConsoleCursorPosition(handle,coord);
}
void drawmap()
{ ??? ?
//////////////////////////??? ?? +
?? ?//int height=40,width=30;
?? //1.圈地
?? ?for(int i=0;i<=MAPHEIGHT;i++)
?? ?{
?? ??? ?gotoxy(0,i);
?? ??? ?printf("■");
?? ??? ?gotoxy(MAPWIDTH,i);
?? ??? ?printf("■");
?? ?}
?? ?for(int j=2 ;j<=MAPWIDTH;j+=2)
?? ?{
?? ??? ?gotoxy(j,0);
?? ??? ?printf("■");
?? ??? ?gotoxy(j,MAPHEIGHT);
?? ??? ?printf("■");
?? ?
?? ?}?? ??? ?
?? ?//2.畫(huà)蛇?? ??? ??? ??? ??? ?
?? ?//2.1蛇的屬性
?? ?snake.len=3;
?? ?snake.speed=100;
?? ?snake.x[0]=MAPWIDTH/2;?? ??? ?//蛇頭置于屏幕中間
?? ?snake.y[0]=MAPHEIGHT/2;
?? ?//蛇頭
?? ?gotoxy(snake.x[0],snake.y[0]);
?? ?printf("■");
?? ?//蛇身體
?? ?for(int k=1;k<snake.len;k++)
?? ?{
?? ??? ?snake.x[k]=snake.x[k-1]+2;
?? ??? ?snake.y[k]=snake.y[k-1];
?? ??? ?gotoxy(snake.x[k],snake.y[k]);
?? ??? ?printf("■");
?? ?}?? ?
?? ?
?? ?//3.畫(huà)食物
?? ?//3.1 坐標(biāo)
?? ??? ?
?? ??? ?while(1)
?? ??? ?{
?? ??? ??? ?int flag=1;
?? ??? ??? ?srand((unsigned int)time(NULL));//隨機(jī)函數(shù)種子
?? ??? ??? ?food.x=rand()%((MAPWIDTH-4))+2;
?? ??? ??? ?food.y=rand()%((MAPHEIGHT-2))+1;?? ??? ?
?? ??? ??? ?//不能在蛇的身上
?? ??? ??? ?for(int k=0 ;k<snake.len;k++)
?? ??? ??? ??? ?{
?? ??? ??? ??? ??? ?if(snake.x[k]==food.x && snake.y[k]== food.y)? //食物在蛇的身上
?? ??? ??? ??? ??? ??? ?{
?? ??? ??? ??? ??? ??? ??? ?flag=0;?? ??? ??? ??? ??? ??? ??? ??? ??? //標(biāo)志置于0 ,即食物位置不對(duì),需要重來(lái)
?? ??? ??? ??? ??? ??? ?}
?? ??? ??? ??? ?}
?? ??? ??? ?/*if(food.x%2!=0)
?? ??? ??? ??? ??? ??? ? {
?? ??? ??? ??? ??? ?//?? ?food.x+=1;?? ??? ??? ??? ? ??? ?//食物位置正確?? ??? ?而且 食物在偶數(shù)位置
?? ??? ??? ??? ?//?? ??? ?break;
?? ??? ??? ??? ??? ??? ?}?? ?? */
?? ??? ??? ?if(flag&&(food.x!=2&&food.x!=MAPWIDTH-2||food.x!=1||food.x!=MAPHEIGHT-1)&&food.x%2!=0)?? ?//位置正確?? ?且食物不在墻里?? ?
?? ??? ??? ??? ??? ??? ?{
?? ??? ??? ??? ??? ??? ?break;?? ?
?? ??? ??? ??? ??? ??? ?}?? ??? ??? ??? ?
?? ??? ?} ?
?? ?//3.2 畫(huà)畫(huà)
?? ??? ?gotoxy(food.x,food.y);
?? ??? ?printf("●");?? ?
?? ??? ?
}
void creatfood()
{?? ?//食物被吃
?? ?if(food.x==snake.x[0]&&food.y==snake.y[0])?? ?? //說(shuō)明食物被吃掉
?? ?{
?? ??? ?//隨機(jī)種子
?? ??? ? srand((unsigned int)time(NULL));
?? ??? ?//產(chǎn)生的食物不能在蛇的身上
?? ??? ?//食物坐標(biāo)應(yīng)該是偶數(shù)? 否則會(huì)只能吃一半
?? ??? ?while(1)
?? ??? ?{
?? ??? ??? ?int flag = 1;
?? ??? ??? ??? ? //準(zhǔn)備產(chǎn)生新的食物
?? ??? ??? ?food.x=rand()%(MAPWIDTH-4)+2;
?? ??? ??? ?food.y=rand()%(MAPHEIGHT-2)+1;?? ??? ?
?? ??? ?//不能在蛇的身上
?? ??? ??? ?for(int k=0 ;k<snake.len;k++)
?? ??? ??? ??? ?{
?? ??? ??? ??? ??? ?if(snake.x[k]==food.x && snake.y[k]== food.y)? //食物在蛇的身上
?? ??? ??? ??? ??? ??? ?{
?? ??? ??? ??? ??? ??? ??? ?flag=0;?? ??? ??? ??? ??? ??? ??? ??? ??? //標(biāo)志置于0 ,即食物位置不對(duì)
?? ??? ??? ??? ??? ??? ?}
?? ??? ??? ??? ?}
?? ??? ??? ?
?? ??? ??? ?if(flag&&food.x%2!=0)?? ??? ?//食物位置正確?? ??? ?而且 食物在偶數(shù)位置?? ??? ??? ???? ???? food.x%2!=0?? ?成功 原因未知
?? ??? ??? ???? {
?? ??? ??? ??? ??? ?break;?? ?
?? ??? ??? ??? ?}
?? ??? ?}
?? ?
?? ?gotoxy(food.x,food.y);
?? ?printf("●"); ?? ? //⊙⊙⊙⊙▇
?? ?snake.len++;
?? ?changeflag=1;//不執(zhí)行擦除尾巴操作?? ??? ?即長(zhǎng)度增加
?? ?}
?? ?
?? ??? ?
}?? ? ?
//3.按鍵操作
void? KeyDown()
{
? //如果按下
?? ?if(_kbhit())
?? ?{
?? ??? ?fflush(stdin);
?? ??? ?key_next = _getch();?? ?
?? ?}
///////擦除之前的蛇? 的尾巴
?? ?if(!changeflag)//如果方向不變 擦除之前的蛇? 的尾巴
?? ?{
?? ??? ?gotoxy(snake.x[snake.len-1],snake.y[snake.len-1]);
?? ??? ?printf("? ");
?? ?}
?? ? //其他蛇身
?? ?for(int i =snake.len-1 ;i>0;i--)
?? ?{
?? ??? ?snake.x[i]=snake.x[i-1];
?? ??? ?snake.y[i]=snake.y[i-1];
?? ?}
?? ?
?? ?//如果有 按下
?? ?//移動(dòng)方向有變化
?? ?switch (key_next)
?? ?{
?? ??? ?case 'w':
?? ??? ?case 'W':
?? ?
?? ??? ??? ?snake.y[0]--;
?? ?
?? ??? ??? ?key_last=key_next;
?? ??? ??? ?break;
?? ??? ?case 'a':
?? ??? ?case 'A':
?? ??? ??? ?
?? ??? ??? ?snake.x[0]-=2;
?? ??? ??? ?key_last=key_next;
?? ??? ??? ?break;
?? ??? ?case 's':
?? ??? ?case 'S':
?? ??? ?
?? ??? ??? ?snake.y[0]++;
?? ??? ??? ?key_last=key_next;
?? ??? ??? ?break;
?? ??? ?case 'D':
?? ??? ?case 'd':
?? ??? ?
?? ??? ??? ?snake.x[0]+=2; //一個(gè)符號(hào)橫向占兩個(gè)字符?? ?
?? ??? ??? ?key_last=key_next;
?? ??? ??? ?break;
?? ??? ?case 27:
?????????? ?
?????????? ?
??????????? pausemenu();?? ??? ??? ?
?? ??? ??? ?break;
?? ??? ?
?? ??? ?}
?? ?
?? ?gotoxy(snake.x[0],snake.y[0]);//new snake head position
?? ?printf("■");?? ??? ??? ??? ?//draw new snake head
?? ?changeflag=0;?? ??? //方向改變標(biāo)志reset
?? ?gotoxy(MAPHEIGHT+2,0); //移動(dòng)光標(biāo)到頭
?? ?//否則移動(dòng)方向無(wú)變化
?? ?//則方向不變 keynext =keylast
?? ?
?? ?
}?? ?
//4.蛇的狀態(tài)
int snakestatus()
{?? ? ?
?? ??? ??? ??? //4.2蛇不能撞到墻壁
?? ??? ??? ?if(snake.x[0]==1||snake.x[0]==MAPWIDTH-1||snake.y[0]==0||snake.y[0]==MAPHEIGHT)?? ?//將?? ? snake.x[0]==0
?? ??? ??? ?{?? ??? ??? ??? ??? ??? ?//只有當(dāng)snake.x[0]為奇數(shù)時(shí)才判斷為真?? ??? ??? ??? ??? ??? ??? ?// snake.x[0]==MAPWIDTH?? ?
?? ??? ??? ??? ?return 0;?? ??? ??? ?//但snake.x[0]不可能為奇數(shù)?? ??? ??? ??? ??? ??? ??? ??? ??? ?//?? ?修改 snake.x[0]==1
?? ??? ??? ? }?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?? // snake.x[0]==MAPWIDTH-1
?? ??? ? //4.1蛇不能撞到自己?? ?的身體?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?//bug修復(fù)完成
?? ??? ??? ?for(int k=2;k<snake.len;k++)
?? ??? ??? ?{
?? ??? ??? ??? ?if(snake.x[0]==snake.x[k]&&snake.y[0]==snake.y[k])
?? ??? ??? ??? ??? ?return 0;?? ?//失敗?? ??? ??? ?
?? ??? ?
?? ??? ??? ?}?? ??? ??? ??? ??? ??? ?
?? ??? ?//?? ?if(snake.x[0]==snake.x[1]&&snake.y[0]==snake.y[1])return 1;
?? ??? ??? ?
?? ??? ??? ?//蛇不能倒退 否則無(wú)效
?? return 1;?? ??? ??? ?
}
void pausemenu()
{
?????????? ?
??????????? //保存數(shù)據(jù):蛇的長(zhǎng)度和坐標(biāo)位置
??????????? FILE *fp=NULL;
??????????? fp=fopen("C:\\Users\\Administrator\\Documents\\Visual Studio 2012\\Projects\\Snake\\Project4\\SnakeLenth.txt","w+");
??????????? char ch1[]={(char)snake.len};???? //const char ch[]="1";
??????????? fputs(ch1 ,fp);
??????????? fclose(fp);
??????????? FILE *fpf=NULL;
??????????? fpf=fopen("C:\\Users\\Administrator\\Documents\\Visual Studio 2012\\Projects\\Snake\\Project4\\SnakeLocation.txt","w+");
??????????????????? for(int i=0;snake.len>i;i++)
??????????????????????? {
??????????????????????? char ch2[]={(char)snake.x[i]};
??????????????????????? fputs(ch2,fp);
?????????????????????? ?
??????????????????????? char ch3[] = {(char)snake.y[i]};
??????????????????????? fputs(ch3,fp);
??????????????????????? }
??????????? fclose(fpf);
??????????? system("pause");//首先暫停
??????????? //gotoxy(MAPWIDTH/2-4,MAPHEIGHT/2);
?? ???????? cout<<"******************************************************\t\n";
?? ???????? cout<<"??????????????????????????????????????????????????????? \n";
?? ???????? cout<<"??????????????????????????????????????????????????????? \n";
?? ???????? cout<<"?????? 0。繼續(xù)游戲??????????????????????????????????????? \n";
?? ???????? cout<<"??????????????????????????????????????????????????????? \n";
?? ???????? cout<<"??????????????????????????????????????????????????????? \n";
?? ???????? cout<<"?????? 1。退出游戲??????????????????????????????????????? \n";
?? ???????? cout<<"??????????????????????????????????????????????????????? \n";
?? ???????? cout<<"??????????????????????????????????????????????????????? \n";
?? ???????? cout<<"?????? 2。保存存檔??????????????????????????????????????? \n";
?? ???????? cout<<"??????????????????????????????????????????????????????? \n";
?? ???????? cout<<"??????????????????????????????????????????????????????? \n";
?? ???????? cout<<"******************************************************\t\n";
?? ??????? ?
??????????? char ch;
??????????? cin>>ch;
??????????? switch (ch)
??????????????? {
??????????????? case '0':
??????????????????? break;
??????????????? case '1':
??????????????????? exit(0);
??????????????????? break;
??????????????? case '2':
??????????????? default:
??????????????????? break;
??????????????? }
?????? ?
?? ?
}