内容:实现贪吃蛇游戏基本功能,屏幕上随机出现一个“食物”(称为豆子),利用键盘中的方向键(上下左右)控制“蛇”的移动,“蛇”吃到“豆子”后身体加长一点,得分增加,“蛇”碰到边界或蛇头与蛇身相撞,蛇死亡,游戏结束。为游戏设计初始界面,游戏界面及结束界面。
注重游戏的交互设计,要有游戏的开始、暂停和退出的功能。
代码
#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;
}
运行结果
得分在右上角
当蛇头碰到墙壁时,游戏结束
当蛇头触碰蛇身时,游戏结束