#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<graphics.h> //图形库头文件
#include<conio.h>
#include<mmsystem.h> //包含多媒体文件接口头文件
#pragma comment(lib,"winmm.lib") //加载静态库
#define WIDE 720 //定义窗体宽度
#define HIGH 480 //定义窗体高度
#define R 7 //定义蛇的半径
#define SNAKEmax 600 //定义蛇的最大长度
int score = 0; //初始得分;
int flag; //判断程序是否暂停
void Food_Create();
void Game_init();
void Game_Draw();
void Snake_Move();
void change();
void Keycontrol();
void EateFood();
void main_fuction();
bool GameOver();
void Music1();
void Music2();
void Music3();
void Music4();
void Music_bgm();
enum DIR //方向枚举(其中的元素都为整数值,默认为0开始)
{
UP, //向上
DOWN, //向下
RIGHT, //向右
LEFT, //向左
};
struct SnakeHead //蛇的结构体
{
int size; //长度
int dir; //方向
int speed; //速度
POINT coor[SNAKEmax]; //用来放蛇的坐标
}snake;
struct Body //得分蛇身的长度
{
POINT coor[SNAKEmax];
}body;
struct Food //食物得结构体
{
int x; //食物坐标
int y;
int r; //食物半径
bool flag; //判断食物是否被吃
DWORD color; //食物颜色 Double Word, 每个word为2个字节的长度,
//DWORD 双字即为4个字节,每个字节是8位,共32位
}food;
int main() //主函数入口
{
char choice;
printf_s("---------------开始菜单----------------\n");
printf_s("游戏介绍:贪吃蛇,是一款经典的休闲小游戏\n在游戏中你可以通过按下W,S,A,D来上下左右移动\n");
printf_s("---------------------------------------------------------\n ");
printf_s("---------------- 空格键暂停 --------------------------\n");
printf_s("-----------你是否现在开始游戏?---------------------\n");
printf_s("---------------------YES / NO--------------------------------\n");
printf_s(" 确定输入y,取消输入n...............\n");
scanf_s("%c", &choice);
if (choice == 'y')
{
//Game_init();
//change();
//Music1();
//while (1)
//{
// while (!GameOver())
// {
// Snake_Move();
// Game_Draw();
// Keycontrol();
// if (flag == -1) //游戏暂停
// {
// while (1)
// {
// Keycontrol();
// if (flag == 1) //游戏继续
// {
// break;
// }
// }
// }
// EateFood();
// Sleep(100); //操作延迟100毫秒,防止蛇移动过快
// }
//}*/
main_fuction();
}
else if (choice == 'n')
{
exit(0);
}
return 0;
}
void Food_Create() //生成食物
{
food.x = rand() % (WIDE - R - 24); //随机函数,并限制生成范围(rand函数随机生成大于0小于1的数)
food.y = rand() % (HIGH - R - 54);
food.color = RGB(rand() % 256, rand() % 256, rand() % 256);
//用随机函数来得到颜色
food.r = R + 1;
food.flag = true;
}
void Game_init() //游戏初始化
{
initgraph(WIDE, HIGH); //初始化窗口
score = 0; //初始化分数
flag = 1; //游戏开始
srand(GetTickCount()); //srand也是取随机数函数,不过他可以得到随机种子,
//gettickcount()为获得系统开机时间毫秒数,以这个时间为种子
//每次程序打开得时间不同那么得到的随机数也不同
snake.size = 3; //初始化蛇的长度
snake.speed = 2 * R; //初始化蛇的速度
snake.dir = RIGHT; //初始化蛇的方向
snake.coor[snake.size - 1].x = (2 * R + 2) * (snake.size - 1) + (2 * R - 2); //初始化蛇头坐标
snake.coor[snake.size - 1].y = 2 * R;
for (int i = snake.size - 2; i >= 0; i--)
{
snake.coor[i].x = 2 * R * i + 2 * R;
snake.coor[i].y = 2 * R; //蛇身的坐标
}
Food_Create(); //初始化食物
}
void Game_Draw() //绘制游戏
{
Music_bgm();
BeginBatchDraw(); //双缓冲绘图,防止闪屏
setbkcolor(RGB(128, 128, 128)); //设置背景颜色(灰色)
cleardevice(); //清屏
setfillcolor(BLUE); //设置边框颜色
for (int i = 0; i < 450 / 3; i++)
{
solidrectangle(0, i * 3, 3, (i + 1) * 3);
}
for (int i = 1; i < (WIDE / 3); i++)
{
solidrectangle(i * 3, 0, (i + 1) * 3, 3); //利用四个for循环绘制边框
}
for (int i = 1; i < 450 / 3; i++)
{
solidrectangle(717, i * 3, 720, (i + 1) * 3);
}
for (int i = 1; i < (WIDE / 3) - 1; i++)
{
solidrectangle(i * 3, 447, (i + 1) * 3, 450);
}
int x = 0;
outtextxy(50, 465, "Score Now: "); //显示得分
outtextxy(410, 465, "History score: ");
setfillcolor(RED); // 设置蛇头颜色
solidcircle(snake.coor[snake.size - 1].x, snake.coor[snake.size - 1].y, R + 1);
setfillcolor(YELLOW); //设置蛇身颜色
for (int i = 0; i < snake.size - 1; i++)
{
solidcircle(snake.coor[i].x, snake.coor[i].y, R); //绘制蛇身
}
for (int i = 0; i < score; i++)
{
solidcircle(body.coor[i].x, body.coor[i].y, R); //绘制得分部分
}
if (food.flag) //食物存在 solidrectangle(矩形函数)
{
solidcircle(food.x, food.y, food.r);
}
EndBatchDraw();
}
void main_fuction() //将主函数功能放入该函数以此来重新调用
{ //主函数
Game_init();
//change();
Music1();
while (1)
{
while (!GameOver())
{
Snake_Move();
Game_Draw();
Music_bgm();
Keycontrol();
if (flag == -1) //游戏暂停
{
while (1)
{
Keycontrol();
if (flag == 1) //游戏继续
{
break;
}
}
}
EateFood();
Sleep(100); //操作延迟100毫秒,防止蛇移动过快
}
Sleep(1000); //延迟
mciSendString("close bgm", 0, 0, 0);
// cleardevice();
mciSendString("play ./fail.mp3 ", 0, 0, 0);
change();
mciSendString("stop ./fail.mp3", 0, 0, 0);
// int isok=MessageBox(NULL, "你撞墙死了是否要重新游戏?", "提示", MB_OKCANCEL);
//if (isok == IDOK)
//{
// main_fuction();
//}
//if (isok == IDCANCEL)
//{
// exit(0);
//}
}
}
void Snake_Move() //蛇的移动
{
if (score > 0) //得分
{
for (int i = 0; i < score - 1; i++)
{
body.coor[i] = body.coor[i + 1]; //得分的蛇身
}
body.coor[score - 1] = snake.coor[0];
}
for (int i = 0; i < snake.size - 1; i++)
{
snake.coor[i] = snake.coor[i + 1]; //蛇身的移动
}
switch (snake.dir) //判断当前蛇的移动方向(移动蛇头)
{
case UP: //向上
snake.coor[snake.size - 1].y -= snake.speed;
break;
case DOWN:
snake.coor[snake.size - 1].y += snake.speed; //向下
break;
case RIGHT:
snake.coor[snake.size - 1].x += snake.speed; //向右
break;
case LEFT:
snake.coor[snake.size - 1].x -= snake.speed; //向左
break;
}
}
void change()
{
HWND head = GetHWnd();
SetWindowTextW(head, L"Snake--2.0");
int isok=MessageBox(head, "你撞墙死了是否重新开始?", "提示", MB_OKCANCEL);
if (isok == IDOK)
{
mciSendString("stop ./fail.mp3", 0, 0, 0);
main_fuction();
}
else if (isok == IDCANCEL)
{
exit(0);
}
}
void Keycontrol() //键盘控制
{
if (_kbhit()) //判断是否使用键盘
{
switch (_getch())
{
case 'w':
case 'W':
if (snake.dir != DOWN) //如果原来方向不为下,则可以改为向上
{
snake.dir = UP;
}
break;
case 's':
case 'S':
if (snake.dir != UP)
{
snake.dir = DOWN; //如果原来方向不为上,则可以改为向下
}
break;
case 'a':
case 'A':
if (snake.dir != RIGHT)
{
snake.dir = LEFT; //如果原来方向不为右,则可以改为向左
}
break;
case 'd':
case 'D':
if (snake.dir != LEFT)
{
snake.dir = RIGHT; //如果原来方向不为左,则可以改为向右
}
break;
case ' ': //空格,游戏暂停
//MessageBox(NULL, "你干嘛哎呦", "食不食油饼", MB_OKCANCEL);
bool isflag = false;
mciSendString("close bgm", 0, 0, 0);
flag = -flag;
mciSendString("open ./你干嘛.mp3 alias ikun", 0, 0, 0);
while (1) {
if (flag == -1)
{
mciSendString("play ikun ", 0, 0, 0);
}
break;
}
}
}
}
void EateFood() //吃掉食物
{
if (food.flag == true && abs(snake.coor[snake.size - 1].x - food.x) <= 8 && abs(snake.coor[snake.size - 1].y - food.y <= 8))
{ //判断食物是否被吃掉,如果被吃掉
food.flag = false; //标记食物被吃
score++; //得分加1
char str[10]; //定义字符数组存放得分
sprintf_s(str, "%d", score);
outtextxy(150, 465, str);
Food_Create(); //重新生成食物
}
}
void Music1()
{
mciSendString("open ./真的是你.mp3 alias BGM1", 0, 0, 0);
mciSendString("play BGM1 ", 0, 0, 0);
}
void Music2()
{ //导入音乐
mciSendString("open ./厉不厉害.mp3 alias BGM2", 0, 0, 0);
mciSendString("play BGM2 ", 0, 0, 0);
}
void Music3()
{
mciSendString("open ./你干嘛.mp3 alias BGM3", 0, 0, 0);
mciSendString("play BGM3", 0, 0, 0);
}
void Music_bgm()
{
mciSendString("open ./背景.mp3 alias bgm", 0, 0, 0);
mciSendString("play bgm repeat", 0, 0, 0);
}
void Music4()
{
mciSendString("open ./fail.mp3 alisa Fail", 0, 0, 0);
mciSendString("play Fail repeat", 0, 0, 0);
}
bool GameOver() //判断游戏是否结束(触碰墙壁)
{
if (snake.coor[snake.size - 1].y <= 3 && snake.dir == UP) //向上撞墙
{
return true;
}
if (snake.coor[snake.size - 1].y >= 447 && snake.dir == DOWN) //向下撞墙
{
return true;
}
if (snake.coor[snake.size - 1].x <= 3 && snake.dir == LEFT) //向左撞墙
{
return true;
}
if (snake.coor[snake.size - 1].x >= 717 && snake.dir == RIGHT) //向右撞墙
{
return true;
}
return false;
}
以上是源代码,但其中还有一些bug(虽然我设置了分数记录但是不知到为什么他显示的时候会一闪而过,还有就是我没有保存得分。。)
要说明的是游戏中添加了音乐使用的mciSendString()函数,具体用法大家自行搜索这里就不赘述了。这里是我下载音频的网址音效 音效网 声音网 音效素材 音效下载 游戏音效 - 爱给网 (aigei.com)
如有问题欢迎指正。