C语言 (EasyX) 实现双人对战贪吃蛇 自带BGM

 C语言 (EasyX) 实现贪吃蛇

 

环境:

VC++6.0   

EasyX插件

 

实现功能:

  • 单人/双人模式
  • 毒苹果
  • 速度变化
  • BGM

(排行榜暂未实现)

相关函数可见EasyX教程

 

整体框架源自实验报告,函数重复度高,代码稍有繁冗。

 

代码及注释如下:

#include<graphics.h>
#include<conio.h>
#include<time.h>
#include<windows.h>			//消息弹窗
#include<iostream.h>
#pragma comment(lib,"winmm.lib")    //music

#define ROWS 25			//设置初始地图长宽分别为20×25个方格
#define COLS 30

#define rows 20			//毒苹果生成区域长宽分别为20×25个方格
#define cols 25

#define UP    1			//定义方向
#define DOWN  2
#define LEFT  3
#define RIGHT 4

typedef struct SNAKE	//结构体构建蛇
{
	int left;
	int top;
	int right;
	int bottom;
	struct SNAKE *next;
}snake;

snake *head,*tail;		        //蛇头蛇尾指针
snake *snake2Tail,*snake2Head;		//第二条蛇的头蛇尾指针
snake *food,*badapple;			//食物和毒苹果指针

bool IsExistFood=false;			//定义食物初始状态为false
bool IsexistFood=false;			//用于第二条蛇吃食物的判断
bool IsExistBadApple=false;		//毒苹果

int map[ROWS][COLS];			//定义地图大小
int direction=RIGHT;			//蛇初始移动方向默认为 向右
int direction2=RIGHT;
int direct1;				//用于吃食物时行进方向判定
int direct2;
int score=0;				//定义初始得分
int score2=0;
int score_temp=0;			//用于分数增长的判定(eatmusic(),Outscore())
int score_temp2=0;
int SPEED=130;				//定义初始速度(数值越小速度越快)
int SPEED2=130;
int endgamestatus=0;			//游戏结束判定
int player_number=0;	

/************声明函数*************/
//*********************************
void InitMap();			//*
void playmusic();		//*
void endmusic();		//*
void eatmusic();		//*
void initsnake();		//*
void initsnake2();              //* 
void movesnake();		//*
void movesnake2();  		//*
void hard();			//*
void speed();			//*
void speed2();			//*
void createfood();		//*
void Outscore();		//*
void Outscore2();		//*
void eatefood();		//*
void pause();			//*
void replay();			//*
void endgame();			//*
void endgame2();		//*
int  hitwall();			//*
int  hitwall2();		//*
int  bitself();			//*
int  bitself2();		//*
void GameControl();		//*
void GameControl2();		//*
void OnePlayer();		//*
void DoublePlayer();		//*
void player();			//*
//*********************************


void main()
{
	initgraph(800, 600);		//定义窗口为800*600像素
	IMAGE imgback;
	loadimage(&imgback,"res\\back.jpg");	
                            //加载背景图  (相对路径图片应在该工程文件目录下 )
	putimage(0,0,&imgback);			//在坐标(0,0)处放置图片
	//*******************************************
	MOUSEMSG m; // 定义鼠标消息 
	while(true) 
	{  
		m = GetMouseMsg(); 
		HWND wnd = GetHWnd();	// 获取一条鼠标消息
		switch(m.uMsg) 
		{ 
			case WM_LBUTTONDOWN: // 如果点左键进入游戏 
				if(MessageBox(wnd, "是否开启双人对战?","贪吃蛇",MB_YESNO|MB_ICONQUESTION)==IDYES)		//MessageBox函数:消息弹框
					{
						player_number=2;
						cleardevice();//清除屏幕信息
						DoublePlayer();//界面初始化
						break;
					}
				else
					{
						player_number=1;
						cleardevice();//清除屏幕信息
						//player();
						OnePlayer();//界面初始化	 
						break;
					}
			case WM_RBUTTONUP: return; // 按鼠标右键退出程序 
		} 
	} 	
	//**********************************************
}

void InitMap()
{
	cleardevice();			             	//清屏,加载游戏界面
	int i,j;
	for(i=0;i<ROWS;i++)
		for(j=0;j<COLS;j++)
		{
			if( i==0 || i==(ROWS-1) || j==0 || j==(COLS-1) ) 				// 用0 1在800*600像素背景中分出20*25格的游戏区域
				map[i][j]=1;												// 同时也设置了游戏边界,蛇出界死亡判断依据
			else 
				map[i][j]=0;
		}
		IMAGE imgtop,imgleft,imgright,imgbottom,imgback1;	//加载边界图
		loadimage(&imgtop,"res\\top.jpg");
		loadimage(&imgbottom,"res\\bottom.jpg");
		loadimage(&imgleft,"res\\left.jpg");
		loadimage(&imgright,"res\\right.jpg");

		if(player_number==1)								//单人背景图
		{
			loadimage(&imgback1,"res\\back1.jpg");
			putimage(0,0,&imgback1);
		}
		else if(player_number==2)							//双人游戏背景图
		{
			loadimage(&imgback1,"res\\back2.jpg");
			putimage(0,0,&imgback1);
		}
		int left=0,top=80,right=20,bottom=100;		
            //第一格四边边界坐标 (0,80,20,100)	即每格为边长为20像素的正方形
		for(i=0;i<ROWS;i++)
		{
			left=0;right=20;
			for(j=0;j<COLS;j++)			//放置边界图
			{
				if(map[i][j]==1 && i==0)
				{ putimage(left,top,&imgtop); }
				if(map[i][j]==1 && i==(ROWS-1))
				{ putimage(left,top,&imgbottom); }
				if(map[i][j]==1 && j==0)
				{ putimage(left,top,&imgleft); }
				if(map[i][j]==1 && j==(COLS-1))
				{ putimage(left,top,&imgright); }
				if(map[i][j]==0)
				{
					setfillcolor(CYAN);   // 背景颜色
					fillrectangle(left,top,right,bottom);	//画矩形
				}
				left+=20;	right+=20;
			}
			top+=20;	bottom+=20;
		}
}

void playmusic()
{
	if(endgamestatus!=1 || endgamestatus!=2 || endgamestatus!=3 || endgamestatus!=4 || endgamestatus!=6)   //若游戏未结束则循环播放背景音乐
	{
		mciSendString("open res\\backmusic.mp3 alias BackMusic",NULL,0,NULL); 
                                                                     //打开音乐文件
		mciSendString("setaudio BackMusic volume to 200",NULL,0,NULL);  
                                                                      //设音量大小200
		mciSendString("play BackMusic repeat",NULL,0,NULL);  //循环播放
	}
}

void endmusic()
{
	if(endgamestatus==1 || endgamestatus==2 || endgamestatus==3 || endgamestatus==4 || endgamestatus==6)  
                //若游戏结束停下并关掉背景音乐,开始播放结束音乐
	{
		mciSendString("stop Backmusic", NULL, 0, NULL); //暂停
		mciSendString("close Backmusic", NULL, 0, NULL);  //关

		mciSendString("open res\\endmusic.mp3 alias EndMusic",NULL,0,NULL);
		mciSendString("setaudio EndMusic volume to 300",NULL,0,NULL);
		mciSendString("play EndMusic",NULL,0,NULL);
	}
  }

void eatmusic()
{
	if(score>score_temp)				
//如果得分增加则播放吃苹果音效  (score_temp存储了上一刻吃到苹果数量)
	{
		mciSendString("open res\\eatmusic.mp3 alias EatMusic",NULL,0,NULL);
		mciSendString("setaudio EatMusic volume to 900",NULL,0,NULL);
		mciSendString("play EatMusic repeat",NULL,0,NULL);  
 //播放完以后将进度条归回开头未能实现,所以选用循环播放再关闭的方法代替
	//	Sleep(500)               
//播放,延迟0.5s,关闭音乐 以达到播放效果 (因为延时所以蛇会卡顿)
		mciSendString("stop EatMusic", NULL, 0, NULL);
		mciSendString("close EatMusic", NULL, 0, NULL);
		score_temp++;
	}
	if(score2>score_temp2)
	{
		mciSendString("open res\\eatmusic.mp3 alias EatMusic",NULL,0,NULL);
		mciSendString("setaudio EatMusic volume to 900",NULL,0,NULL);
		mciSendString("play EatMusic repeat",NULL,0,NULL);
	//	Sleep(500)               //延迟0.5s播放但会卡顿
		mciSendString("stop EatMusic", NULL, 0, NULL);
		mciSendString("close EatMusic", NULL, 0, NULL);
		score_temp2++;
	}
}

void initsnake()					//利用单链表构建蛇
{
	head=(snake*)malloc(sizeof(snake));  //分配头
	snake *p;
	int startRow=10,startCol=5;		//蛇初始位置
	head->left=startCol*20;			//转化为坐标
	head->top=startRow*20;
	head->right=(startCol+1)*20;
	head->bottom=(startRow+1)*20;
	p=head;
	for(int i=0;i<3;i++)		//蛇初始长度为3
	{
		tail=(snake*)malloc(sizeof(snake));  //分配尾
		tail->left=startCol*20;
		tail->top=(startRow+i+1)*20;
		tail->right=(startCol+i+1)*20;
		tail->bottom=(startRow+i+1)*20;
		p->next=tail;
		tail->next=NULL;
		p=tail;
	}
	p=head;
	while(p!=NULL)
	{
		setfillcolor(RED);		//蛇头          
		fillrectangle(p->left,p->top,p->right,p->bottom);
		if(p==head)  //找到蛇头
		{
			int x=(p->left+p->right)/2;
			int y=(p->top+p->bottom)/2;
			setfillcolor(YELLOW);    //眼睛
			fillcircle(x,y,2);  //半径为2的圆做眼睛
		}
		p=p->next;
	}
}

void initsnake2() 
{
	snake2Head=(snake *)malloc(sizeof(snake));
	snake *q;
	int startRow=20, startCol=15;

	snake2Head->left=startCol*20;
	snake2Head->top=startRow*20;
	snake2Head->right=(startCol+1)*20;
	snake2Head->bottom=(startRow+1)*20;
	
	q=snake2Head;
	for(int i=0;i<3;i++) 
	{
		snake2Tail=(snake*)malloc(sizeof(snake));
		snake2Tail->left=startCol*20;
		snake2Tail->top=(startRow+i+1)*20;
		snake2Tail->right=(startCol+1)*20;
		snake2Tail->bottom=(startRow+i+2)*20;
		q->next=snake2Tail;
		snake2Tail->next=NULL;
		q=snake2Tail;

	}
	q=snake2Head;
	while(q!=NULL)
	{
		setfillcolor(BLACK);
		fillrectangle(q->left,q->top,q->right,q->bottom);
		if (q==snake2Head)
		{
			int x=(q->left+q->right)/2;
			int y=(q->top+q->bottom)/2;
			setfillcolor(LIGHTBLUE);
			fillcircle(x,y,2);
		}
		q=q->next;
	}
}

void movesnake()
{
	int left,top,right,bottom;
	int newleft,newtop,newright,newbottom;
	
	snake *p;

	setcolor(WHITE);		//擦除蛇尾 //足迹网格
	setfillcolor(CYAN);     //足迹
	fillrectangle(tail->left,tail->top,tail->right,tail->bottom);  
                     //从头到尾重新输出蛇身
	p=head;
	while(p!=NULL)
	{
		
		Sleep(SPEED);   //画蛇延迟实现移动
		if(p==head)  //找到蛇头
		{
			newleft=p->left;newtop=p->top;newright=p->right;newbottom=p->bottom;	
                //保留蛇头当前坐标
			
	    		if(direction==RIGHT) { p->left+=20;p->right+=20; }		        //蛇头移动,下一位置坐标
			if(direction==LEFT)  { p->left-=20;p->right-=20; }
			if(direction==UP)    { p->top-=20;p->bottom-=20; }
			if(direction==DOWN)  { p->top+=20;p->bottom+=20; }
		}
		else		//其他身体节点同理跟随蛇头
		{
			left=p->left;top=p->top;right=p->right;bottom=p->bottom;
			
			p->left=newleft;p->right=newright;p->top=newtop;p->bottom=newbottom;
			
			newleft=left;newtop=top;newright=right;newbottom=bottom;
		}
		setcolor(WHITE);	//蛇身网格   
		setfillcolor(RED);	//蛇身
		fillrectangle(p->left,p->top,p->right,p->bottom);
		if(p==head)
		{
			fillrectangle(newleft,newtop,newright,newbottom);   
			int x=(p->left+p->right)/2;
			int y=(p->top+p->bottom)/2;
			setfillcolor(YELLOW);
			fillcircle(x,y,2);
		}
		p=p->next;
	}
}

void movesnake2()
{
	int left, top, right, bottom;
	int newleft, newtop, newright, newbottom;

	snake *q;

	setcolor(WHITE); 
	setfillcolor(CYAN);
	fillrectangle(snake2Tail->left, snake2Tail->top, snake2Tail->right, snake2Tail->bottom);
	q=snake2Head;
	while (q!=NULL)
	{
		Sleep(SPEED2);


		if (q==snake2Head)
		{
			newleft=q->left; 
			newtop=q->top; 
			newright=q->right; 
			newbottom=q->bottom;
			if (direction2==UP){ q->top-=20; q->bottom-=20; }
			if (direction2==DOWN){ q->top+=20; q->bottom+=20; }
			if (direction2==RIGHT){ q->left+=20; q->right+=20; }
			if (direction2==LEFT){ q->left-=20; q->right-=20; }
		}

		else
		{
			left=q->left; top=q->top; right=q->right; bottom=q->bottom;
			q->left=newleft; q->right=newright; q->top=newtop; q->bottom=newbottom;
			newleft=left; newtop=top; newright=right; newbottom=bottom;
		}
		setcolor(WHITE); 
		setfillcolor(BLACK);
		fillrectangle(q->left, q->top, q->right, q->bottom);
		if (q==snake2Head)
		{
			fillrectangle(newleft, newtop, newright, newbottom);
			int x=(q->left+q->right)/2;
			int y=(q->top+q->bottom)/2;
			setfillcolor(LIGHTBLUE);
			fillcircle(x,y,2);
		}
		q = q->next;
	}
}

void hard()
{
	setbkmode(TRANSPARENT);				//字体背景透明

	settextstyle(20,0,_T("黑体"));      //字体格式
	settextcolor(BLACK);				//字体颜色
	outtextxy(10,60,"难度:");			//输出文字坐标及内容
	if(score<=3)
	{
		setfillcolor(RGB(24,146,196));  //颜色 RGB
		fillrectangle(100,80,75,55);
		outtextxy(75,60,_T(" D "));						//根据得分划分难度等级 “D”“C”“B”“A”“S”
	}
	else if(score>3 && score<=7)
	{	
		setfillcolor(RGB(24,146,196));    
		fillrectangle(100,80,75,55);
		outtextxy(75,60,_T(" C "));
	}
	else if(score>8 && score<=11)
	{	
		setfillcolor(RGB(24,146,196));    
		fillrectangle(100,80,75,55);
		outtextxy(75,60,_T(" B "));
	}
	else if(score>12 && score<15)
	{	
		setfillcolor(RGB(24,146,196));    
		fillrectangle(100,80,75,55);
		outtextxy(75,60,_T(" A "));
	}
	else if(score>=15)
	{	
		setfillcolor(RGB(24,146,196));    
		fillrectangle(100,80,75,55);
		outtextxy(75,60,_T(" S "));
	}
}

void speed()			//根据得分决定蛇1移动速度快慢
{
	if(score>2 && score<=5)
	{SPEED-=22;}
	else if(score>5 && SPEED>30)
	{SPEED-=8;}
	else if(score>25 && SPEED>15)
	{SPEED-=1;}
}

void speed2()			//根据得分决定蛇2移动速度快慢
{
	if(score2>2 && score2<=5)
	{SPEED2-=22;}
	else if(score2>5 && SPEED>230)
	{SPEED-=8;}
	else if(score2>25 && SPEED2>15)
	{SPEED2-=1;}
}

void createfood()
{
	snake *p;
	srand((unsigned)time(NULL));		//利用时间函数产生随机数
	food=(snake*)malloc(sizeof(snake));
	int row=rand()%ROWS; 				//规范产生范围不超出游戏区域
	int col=rand()%COLS;
	if(row==0) row=1;
	if(row==(ROWS-1)) row=ROWS-2;
	if(col==0) col=1;
	if(col==(COLS-1)) col=COLS-2;
	food->left=col*20;   food->right=food->left+20;    //转化坐标
	food->top=row*20+80; food->bottom=food->top+20;
	p=head;
	bool ISSame=false;    //设定蛇身与食物是否重合状态为否
	while(p!=NULL)
	{
		if(p->left==food->left && p->top==food->top && p->right==food->right && p->bottom==food->bottom)		//判断蛇身与食物是否重合
		{
			ISSame=true;     //如果重合则释放掉重新生成
			free(food);
			createfood();
		}
		p=p->next;
	}
	if(!ISSame)    //如果不重合放置食物
	{
		IMAGE imgfood;
		loadimage(&imgfood,"res\\food.jpg");
		putimage(food->left+1,food->top+1,&imgfood);
		IsExistFood=true;  	//食物存在
	}
}

void Badapple()				//毒苹果 蛇吃到会死亡 构造与苹果一样
{
	snake *p,*q;
    srand((unsigned)time(NULL));
    badapple=(snake*)malloc(sizeof(snake));
    int row=rand()%rows;
    int col=rand()%cols;
    if(row==0)
        row=1;
    if(row==(ROWS-1))
        row=ROWS-2;
    if(col==0)
        col=1;
    if(col==(COLS-1))
        col=COLS-2;
    badapple->left=col*20,badapple->right=badapple->left+20;
    badapple->top=row*20+80,badapple->bottom=badapple->top+20;
    p=head,q=food;
    bool ISSame=false;
    while(p!=NULL)
    {
        if(p->left==badapple->left && p->top==badapple->top &&
           p->right==badapple->right && p->bottom==badapple->bottom)
        {
            ISSame=true;
            free(badapple);
            Badapple();
        }
        p=p->next;
    }
	if(q->left==badapple->left && q->top==badapple->top &&
           q->right==badapple->right && q->bottom==badapple->bottom)
	{
		ISSame=true;
        free(badapple);
        Badapple();
	}
    if(!ISSame)
    {
        IMAGE imagbadapple;
        loadimage(&imagbadapple,"res\\badapple.jpg");
        putimage(badapple->left+1,badapple->top+1,&imagbadapple);
        IsExistBadApple=true;
    }
}

void Outscore()
{
	char GetScore[10];   //字符数组用于存放得分
	itoa(score,GetScore,10); //将字符型得分转化为10进制
	setbkmode(TRANSPARENT);  //字体背景透明
	
	setfillcolor(RGB(24,146,196));      //背景颜色
	fillrectangle(100,55,75,30);		//位置
	settextcolor(WHITE);				//字体颜色
	settextstyle(20,0,_T("黑体"));      //字体格式
	outtextxy(10,30,"得分1:");
	outtextxy(80,30,GetScore);

	if(score>score_temp)  //得分时更新成绩
	{
	//	Sleep(50);
		outtextxy(80,30,GetScore);
		score_temp++;  
	}
}

void Outscore2()
{
	char GetScore[10];
	itoa(score2,GetScore,10);
	setbkmode(TRANSPARENT);
	
	setfillcolor(RGB(24,146,196));    
	fillrectangle(100,85,75,60);
	settextcolor(WHITE);
	settextstyle(20,0,_T("黑体"));      //字体格式
	outtextxy(10,60,"得分2:");
	outtextxy(80,60,GetScore);

	if(score2>score_temp2)
	{
	//	Sleep(50);
		outtextxy(80,60,GetScore);
		score_temp2++;
	}
}

void eatefood()
{
	snake *p;
	p=head;
	bool IsEated=false;    //初始状态 

	if( head->left+20==food->left && head->top==food->top && head->right+20==food->right && head->bottom==food->bottom  && direct1==RIGHT )     
	{														//食物在蛇行进前方且蛇头坐标与食物重合时判定为吃
		food->next=head;
		head=food;
		IsEated=true;     //更改吃食物状态为真
		IsExistFood=false;  //更改食物存在状态为假
	}
	if( head->left-20==food->left && head->top==food->top && head->right-20==food->right && head->bottom==food->bottom  && direct1==LEFT )
	{
		food->next=head;
		head=food;
		IsEated=true;
		IsExistFood=false;
	}
	if( head->left==food->left && head->top+20==food->top && head->right==food->right && head->bottom+20==food->bottom  && direct1==DOWN )
	{
		food->next=head;
		head=food;
		IsEated=true;
		IsExistFood=false;
	}
	if( head->left==food->left && head->top-20==food->top && head->right==food->right && head->bottom-20==food->bottom  && direct1==UP )
	{
		food->next=head;
		head=food;
		IsEated=true;
		IsExistFood=false;
	}
	if(IsEated)				//如果吃到食物
	{
		score++;				//得分+1		
		eatmusic();				//播放音效
		fillrectangle(p->left,p->top,p->right,p->bottom);	
         //增加蛇长  (从蛇头增加一格作为新蛇头)
		int x=(head->left+head->right)/2;
		int y=(head->bottom+head->top)/2;
		setfillcolor(YELLOW);
		fillcircle(x,y,2);
		speed();				//速度判断是否改变
	}
	Outscore();				//输出得分
}

void eatefood2()
{
	snake *q;
	q=snake2Head;
	bool Iseated=false;

	if( snake2Head->left+20==food->left && snake2Head->top==food->top && snake2Head->right+20==food->right && snake2Head->bottom==food->bottom  && direct2==RIGHT ) 
	{
		food->next=snake2Head;
		snake2Head=food;
		Iseated=true;
		IsexistFood=false;
	}
	if( snake2Head->left-20==food->left && snake2Head->top==food->top && snake2Head->right-20==food->right && snake2Head->bottom==food->bottom  && direct2==LEFT )
	{
		food->next=snake2Head;
		snake2Head=food;
		Iseated=true;
		IsexistFood=false;
	}
	if( snake2Head->left==food->left && snake2Head->top+20==food->top && snake2Head->right==food->right && snake2Head->bottom+20==food->bottom  && direct2==DOWN )
	{
		food->next=snake2Head;
		snake2Head=food;
		Iseated=true;
		IsexistFood=false;
	}
	if( snake2Head->left==food->left && snake2Head->top-20==food->top && snake2Head->right==food->right && snake2Head->bottom-20==food->bottom  && direct2==UP )
	{
		food->next=snake2Head;
		snake2Head=food;
		Iseated=true;
		IsexistFood=false;
	}
	if(Iseated)
	{
		score2++;
		eatmusic();
		fillrectangle(q->left,q->top,q->right,q->bottom);
		int x=(snake2Head->left+snake2Head->right)/2;
		int y=(snake2Head->bottom+snake2Head->top)/2;
		setfillcolor(LIGHTBLUE);
		fillcircle(x,y,2);
		speed2();
	}
	Outscore2();
}

int eatbadapple()
{
	if(head->left+20==badapple->left&&head->top==badapple->top&&head->right+20==badapple->right&&head->bottom==badapple->bottom && (direct1==RIGHT || direct2==RIGHT))
    {
		endgamestatus=6;
	}
	if(head->left-20==badapple->left&&head->top==badapple->top&&head->right-20==badapple->right&&head->bottom==badapple->bottom && (direct1==LEFT || direct2==LEFT))
    {
        endgamestatus=6;
    }
	if(head->left==badapple->left&&head->top+20==badapple->top&&head->right==badapple->right&&head->bottom+20==badapple->bottom && (direct1==DOWN || direct2==DOWN))
    {
        endgamestatus=6;
    }
	if(head->left==badapple->left&&head->top-20==badapple->top&&head->right==badapple->right&&head->bottom-20==badapple->bottom && (direct1==UP || direct2==UP))
    {
        endgamestatus=6;
    }
	return endgamestatus;
}

void pause()			//暂停函数
{
	while(1)
	{
		Sleep(300);			//延迟暂停
		if(GetAsyncKeyState(VK_SPACE))		//按空格退出
		{
			break;
		}
	}
}

void replay()
{
	score=0;				//将数据归零
	score2=0;
	SPEED=130;
	SPEED2=130;
	endgamestatus=0;
	direction=RIGHT;
	direction2=UP;
	IsExistFood=false;
	IsexistFood=false;
	IsExistBadApple=false;		    //再次调用主函数重新开始
	main();
}

void endgame()
{
	settextcolor(DARKGRAY);	//字体颜色
	setbkmode(TRANSPARENT); //字体背景透明
	if(endgamestatus==1)									//根据游戏结束判定值判定由何原因结束并输出
	{
		settextstyle(40,0,_T("黑体"));		//字体格式
		outtextxy(150,202,"您撞到墙了!");
	}
	else if(endgamestatus==2)
	{
		settextstyle(40,0,_T("黑体"));		//字体格式
		outtextxy(150,202,"您咬到自己了!");
	}
	else if(endgamestatus==6)
	{
		settextstyle(40,0,_T("黑体"));		//字体格式
		outtextxy(150,202,"您吃到毒苹果了!");
	}

	HWND wnd = GetHWnd();				//调用窗口   	

	if(MessageBox(wnd, "游戏结束。\n是否重新开始?","贪吃蛇",MB_YESNO|MB_ICONQUESTION)==IDYES)		//是否重新开始(弹窗)
	   replay();

   else
	   exit(0);				//退出
}

void endgame2()
{
	settextcolor(DARKGRAY);	//字体颜色
	setbkmode(TRANSPARENT); //字体背景透明

		if((endgamestatus==1 || endgamestatus==2) && score<=score2)
		{
			settextstyle(40,0,_T("黑体"));		//字体格式
			outtextxy(150,202,"二号玩家获胜!");
		}
		else if((endgamestatus==1 || endgamestatus==2) && score>score2)
		{
			settextstyle(40,0,_T("黑体"));		//字体格式
			outtextxy(150,202,"一号玩家获胜!");
		}
		else if((endgamestatus==3 || endgamestatus==4) && score2<=score)
		{
			settextstyle(40,0,_T("黑体"));		//字体格式
			outtextxy(150,202,"一号玩家获胜!");
		}
		else if((endgamestatus==3 || endgamestatus==4) && score2>score)
		{
			settextstyle(40,0,_T("黑体"));		//字体格式
			outtextxy(150,202,"二号玩家获胜!");
		}

	HWND wnd = GetHWnd();
	if(MessageBox(wnd, "游戏结束。\n是否重新开始?","贪吃蛇",MB_YESNO|MB_ICONQUESTION)==IDYES)
	   replay();
   else
	   exit(0);
}

int hitwall()
{
	if(head->left==0 || head->top==80||head->right==600||head->bottom==580)		//蛇头与边界重合,蛇头坐标超出范围则为撞墙
	{
		endgamestatus=1;			//游戏结束判定为1
		return 1;
	}
	return 0;
}

int bitself()
{
	snake *self;		//遍历蛇身指针
    self=head->next;
    while(self!=NULL)
    {
        if(self->left==head->left && self->top==head->top && self->right==head->right && self->bottom==head->bottom)	//若蛇头与蛇身重合
		{
			endgamestatus=2;							//游戏结束判定为2
			return 1;
		}
        else
			self=self->next;
    }
	return 0;
}

int hitwall2()			//蛇2撞墙
{
	if(snake2Head->left==0 || snake2Head->top==80 || snake2Head->right==600 || snake2Head->bottom==580)
	{
		endgamestatus=3;
		return 1;
	}
	return 0;
}

int bitself2()			//蛇2
{
	snake *self2;
	self2=snake2Head->next;
    while(self2!=NULL)
    {
        if(self2->left==snake2Head->left && self2->top==snake2Head->top && self2->right==snake2Head->right && self2->bottom==snake2Head->bottom)
		{
			endgamestatus=4;
			return 1;
		}
        else
			self2=self2->next;
    }
	return 0;
}

void GameControl()			//单人模式游戏控制
{
	while(1)					
	{
		if( GetAsyncKeyState(VK_UP) )		//获键盘按键信息  更改蛇移动方向
		{ direction=UP; direct1=UP; }
		else if( GetAsyncKeyState(VK_DOWN) )
		{ direction=DOWN; direct1=DOWN; }
		else if( GetAsyncKeyState(VK_RIGHT) )
		{ direction=RIGHT; direct1=RIGHT; }
		else if( GetAsyncKeyState(VK_LEFT) )
		{ direction=LEFT; direct1=LEFT; }		
                else if( GetAsyncKeyState(VK_ESCAPE) )		//按空格调用暂停函数
		{ pause(); }
		movesnake();
		if(!IsExistFood)		//食物和毒苹果产生判断
			{createfood();}
		if(!IsExistBadApple)
			{Badapple();}
		eatefood();
		hard();
		if(bitself()==1||hitwall()==1||eatbadapple()==6)	//游戏结束判段
		{endmusic();endgame();}
	}
}

void GameControl2()				//双人模式游戏控制
{
	while(1)
	{
		if( GetAsyncKeyState(VK_UP) )		//玩家1 方向移动 
		{ direction=UP; direct1=UP; }
		else if( GetAsyncKeyState(VK_DOWN) )
		{ direction=DOWN; direct1=DOWN; }
		else if( GetAsyncKeyState(VK_RIGHT) )
		{ direction=RIGHT; direct1=RIGHT; }
		else if( GetAsyncKeyState(VK_LEFT) )
		{ direction=LEFT; direct1=LEFT; }
	
		else if( GetAsyncKeyState(VK_ESCAPE) )
		{ break; }				
	
		if( GetAsyncKeyState('W') )			//玩家2 方向移动 
		{ direction2=UP; direct2=UP; }
		else if( GetAsyncKeyState('S') )
		{ direction2=DOWN; direct2=DOWN; }
		else if( GetAsyncKeyState('D') )
		{ direction2=RIGHT; direct2=RIGHT; }
		else if( GetAsyncKeyState('A') )
		{ direction2=LEFT; direct2=LEFT; }		movesnake();
		movesnake2();
		if(!IsExistFood)
			{createfood();}
		eatefood();
		eatefood2();
		if(bitself2()==1||hitwall2()==1||bitself()==1||hitwall()==1)
		{endmusic();endgame2();}
	}
}

void OnePlayer()		//单人游戏界面及涉及函数
{
	initgraph(800,600);
	InitMap();
	playmusic();
	initsnake();
	GameControl();
	getch();
	closegraph();
}

void DoublePlayer()		//双人模式界面及涉及函数
{
	initgraph(800,600);
	InitMap();
	playmusic();
	initsnake();
	initsnake2();
	GameControl2();
	getch();
	closegraph();
}


 

游戏文件:

游戏界面:

 

  • 3
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 17
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值