贪吃蛇项目

内容:实现贪吃蛇游戏基本功能,屏幕上随机出现一个“食物”(称为豆子),利用键盘中的方向键(上下左右)控制“蛇”的移动,“蛇”吃到“豆子”后身体加长一点,得分增加,“蛇”碰到边界或蛇头与蛇身相撞,蛇死亡,游戏结束。为游戏设计初始界面,游戏界面及结束界面。

注重游戏的交互设计,要有游戏的开始、暂停和退出的功能。

 代码

#include <stdio.h>
#include <time.h>
#include <string.h>
#include <conio.h>
#include <graphics.h>
#include <mmsystem.h>
extern int  paused = 0;
#pragma comment (lib,"winmm.lib")


struct Button* CreatButton(int x, int y, int width, int height,
	const char* text, int text_x, int text_y, COLORREF buttoncolor, COLORREF textcolor);

#define WIDTH 640
#define HEIGHT 720
#define GRID_WIDTH 16
#define GRID_HEIGHT 16
#define GRID_ROW (HEIGHT/GRID_HEIGHT)
#define GRID_COL (WIDTH/GRID_WIDTH)
#define MAXSIZE (GRID_ROW*GRID_COL)

enum Direction
{
	UP = 0,
	DOWN = 1,
	LEFT = 2,
	RIGHT=3,
};

struct Point
{
	int x;
	int y;
};

struct Snake
{
	struct Point point[MAXSIZE];
	int size;
	int dir;
}snake;

struct Food
{
	struct Point point;
	int flag;
}food;

struct Button
{
	int x;
	int y;
	int width;
	int height;
	int pause;
	char* text;
	int dx;
	int dy;
	COLORREF buttoncolor;
	COLORREF textcolor;
};

IMAGE zw;
struct Button* beginGame = CreatButton(80, 220, 150, 50, "开始游戏", 18, 12, WHITE, RGB(150, 150, 150));
struct Button* endGame = CreatButton(395, 220, 150, 50, "结束游戏", 18, 12, WHITE, RGB(150, 150, 150));




void LoadResource()
{
	loadimage(&zw, "./picture/df.png", WIDTH*1.094, HEIGHT*1.728);
}


void BGM()
{
	mciSendString("open ./music/zw.mp3 alias BGM", NULL, 0, NULL);
	mciSendString("play BGM repeat", NULL, 0, NULL);
}


void GameInit(){
	
	srand((unsigned)time(NULL)*rand());
	snake.size = 5;
	snake.point[0].x = 0;
	snake.point[0].y = 0;
	snake.dir = RIGHT;
	for (int i = 5; i < MAXSIZE; i++)
	{
		snake.point[i].x = -100;
		snake.point[i].y = -100;
	}
}


struct Button* CreatButton(int x, int y, int width, int height, 
	const char* text, int dx, int dy, COLORREF buttoncolor, COLORREF textcolor){
	struct Button* pButton = (struct Button*)malloc(sizeof(struct Button));
	pButton->x = x;
	pButton->y = y;
	pButton->width = width;
	pButton->height = height;
	pButton->text = (char*)malloc(strlen(text) + 1);
	strcpy(pButton->text, text);
	pButton->dx = dx;
	pButton->dy = dy;
	pButton->buttoncolor = buttoncolor;
	pButton->textcolor = textcolor;
	return pButton;
}


void DrawButton(struct Button* pButton)
{
	setbkmode(TRANSPARENT);
	setlinecolor(RGB(240, 240, 240));
	setlinestyle(PS_SOLID, 5);
	setfillcolor(pButton->buttoncolor);
	fillrectangle(pButton->x, pButton->y, pButton->x + pButton->width, pButton->y + pButton->height);
	settextcolor(pButton->textcolor);
	settextstyle(28, 0, "楷体", 0, 0, 1000, 0, 0, 0);
	outtextxy(pButton->x + pButton->dx, pButton->y + pButton->dy, pButton->text);
}


int MouseInButton(struct Button* pButton, MOUSEMSG* msg)
{
	if (msg->x >= pButton->x&&msg->x <= pButton->x + pButton->width&&
		msg->y >= pButton->y&&msg->y <= pButton->y + pButton->height){
		pButton->buttoncolor = RGB(220, 220, 220);
		pButton->textcolor = RGB(120, 120, 120);
		return 1;
	}
	pButton->buttoncolor = WHITE;
	pButton->textcolor = RGB(150, 150, 150);
	return 0;
}


int MouseControl(struct Button* pButton1, struct Button* pButton2)
{
	
	if (MouseHit())
	{
		MOUSEMSG msg = GetMouseMsg();
	
		if (MouseInButton(pButton1, &msg) == 1 && msg.uMsg == WM_LBUTTONDOWN)
		{
			return 1;
		}
		else if (MouseInButton(pButton2, &msg) == 1 && msg.uMsg == WM_LBUTTONDOWN)
		{
			exit(0);
		}
	}
	return 0;
}

void Welcome() 
{
	cleardevice();
	putimage(-30, -235, &zw);
	DrawButton(beginGame);
	DrawButton(endGame);


	setbkmode(TRANSPARENT);
	settextcolor(RGB(175, 175, 175));
	settextstyle(25, 0, "楷体", 0, 0, 1000, 0, 0, 0);
	outtextxy(12, 17, "植物大战僵尸");
}


void GameDraw(){
	cleardevice();
	putimage(-30, -235, &zw);	


	setbkmode(TRANSPARENT);
	settextcolor(RGB(175, 175, 175));
	settextstyle(25, 0, "楷体", 0, 0, 1000, 0, 0, 0);
	outtextxy(12, 17, "植物大战僵尸");



	
	for (int i = 0; i < GRID_ROW; i++)
	{
		for (int j = 0; j < GRID_COL; j++)
		{
		
			int x = GRID_WIDTH*j;
			int y = GRID_HEIGHT*i;
		
			setlinecolor(RGB(240, 240, 240));
			setlinestyle(PS_SOLID, 3);
			setfillcolor(WHITE);
			fillrectangle(x, y, x + GRID_WIDTH, y + GRID_HEIGHT);
		}
	}

	
	for (int i = 1; i < snake.size; i++){
		setlinecolor(RGB(240, 240, 240));
		setlinestyle(PS_SOLID, 3);
		setfillcolor(RGB(252, 208, 199));
		fillrectangle(snake.point[i].x, snake.point[i].y, snake.point[i].x + GRID_WIDTH, snake.point[i].y + GRID_HEIGHT);
	}

	setlinecolor(RGB(240, 240, 240));
	setlinestyle(PS_SOLID, 3);
	setfillcolor(RGB(244, 165, 215));
	fillrectangle(snake.point[0].x, snake.point[0].y, snake.point[0].x + GRID_WIDTH, snake.point[0].y + GRID_HEIGHT);

	
	if (food.flag == 1){
		setlinecolor(RGB(240, 240, 240));
		setlinestyle(PS_SOLID, 3);
		setfillcolor(RGB(91, 173, 255));
		fillrectangle(food.point.x, food.point.y, food.point.x + GRID_WIDTH, food.point.y + GRID_HEIGHT);
	}
}

void SnackMove()
{
	 
		if (paused) 
		{  
			return; 
		} 
	for (int i = snake.size - 1; i>0; i--){
		snake.point[i].x = snake.point[i - 1].x;
		snake.point[i].y = snake.point[i - 1].y;
	}
	switch (snake.dir){
	case UP:
		snake.point[0].y -= GRID_HEIGHT;
		break;
	case DOWN:
		snake.point[0].y += GRID_HEIGHT;
		break;
	case LEFT:
		snake.point[0].x -= GRID_WIDTH;
		break;
	case RIGHT:
		snake.point[0].x += GRID_WIDTH;
		break;
	}
	Sleep(30);
}


void CreatFood(){
	
	food.point.x = rand() % (WIDTH / GRID_WIDTH)*GRID_WIDTH;
	food.point.y = rand() % (HEIGHT / GRID_HEIGHT)*GRID_HEIGHT;

	while (1){
		int flag = 0;
		for (int i = 0; i < snake.size; i++)
		{
			if (snake.point[i].x == food.point.x && snake.point[i].y == food.point.y){
				food.point.x = rand() % (WIDTH / GRID_WIDTH)*GRID_WIDTH;
				food.point.y = rand() % (HEIGHT / GRID_HEIGHT)*GRID_HEIGHT;
				flag = 1;
			}
		}
		if (flag == 0)
		{
			food.flag = 1;
			break;
		}
	}
}
void EatFood(){
	if (snake.point[0].x == food.point.x&&snake.point[0].y == food.point.y){
		mciSendString("close eat", NULL, 0, NULL);
		mciSendString("open ./music/eat.ogg alias eat", NULL, 0, NULL);
		mciSendString("play eat", NULL, 0, NULL);
		snake.size++;
		food.flag = 0;
	}
}


void KeyDown()
{
	while (_kbhit()) {
		char userKey = _getch();
		fflush(stdin);
		switch (userKey) {
		case 'W':
		case 'w':
		case 72:
			if (snake.dir != DOWN) {
				snake.dir = UP;
			}
			break;
		case 'S':
		case 's':
		case 80:
			if (snake.dir != UP) {
				snake.dir = DOWN;
			}
			break;
		case 'A':
		case 'a':
		case 75:
			if (snake.dir != RIGHT) {
				snake.dir = LEFT;
			}
			break;
		case 'D':
		case 'd':
		case 77:
			if (snake.dir != LEFT) {
				snake.dir = RIGHT;
			}
			break;
		case' ':
			if (paused == 0)
			{ 
				 paused = 1; 
			} else
			{
				paused = 0;
			}
			break;
		}
	}
}


int Condition1(){
	
	for (int i = 1; i < snake.size; i++){
		if (snake.point[i].x == snake.point[0].x && snake.point[i].y == snake.point[0].y){
			return 1;
		}
	}
	return 0;
}


int Condition2()
{
	
	if (snake.point[0].x < 0)
	{
		return 1;
	}
	else if (snake.point[0].x > WIDTH -GRID_WIDTH)
	{
		return 1;
	}
	else if (snake.point[0].y < 0){
		return 1; 
	}
	else if (snake.point[0].y > HEIGHT - GRID_HEIGHT)
	{
		return 1;
	}
	return 0;
}


int GameOver(){
	
	if (Condition1() == 1 || Condition2() == 1){
		return 1;
	}
	return 0;
}


int main(){
	LoadResource();
	initgraph(WIDTH, HEIGHT);
	BGM();
	GameInit();

	BeginBatchDraw();
	while (1)
	{
		Welcome();
		FlushBatchDraw();
		if (MouseControl(beginGame, endGame) == 1)
		{
			break;
		}
	}

	fflush(stdin);
	FlushMouseMsgBuffer();

	while(1){
		KeyDown();
		GameDraw();
		FlushBatchDraw();
		SnackMove();
		EatFood();
		if (food.flag == 0)
		{
			CreatFood();
		}
		if (GameOver() == 1)
		{
			mciSendString("close end", NULL, 0, NULL);
			mciSendString("open ./music/end.wav alias end", NULL, 0, NULL);
			mciSendString("play end", NULL, 0, NULL);
			char fileName[25];
			sprintf(fileName, "Game scores:%d", snake.size);
			MessageBox(GetHWnd(), fileName, "Game Over!", MB_OK);
			break;
		}
	}
	EndBatchDraw();

	closegraph();
	return 0;
}


运行结果

得分在右上角

当蛇头碰到墙壁时,游戏结束

当蛇头触碰蛇身时,游戏结束

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值