赞
踩
此次课设用到的数据结构是双向链表,算法堆排序,eaxyX图形库,文件操作,鼠标操作。
具体操作步骤代码中有解释,图片信息和文件信息自己可以稍微改进,对窗口设置按钮可用eaxyX图形库实现,我则采用图片了,读者可根据设置按钮来加长代码长度,但贪吃蛇核心功能并不是设置按钮,所以采用图片了。进阶的话可以加入登录和注册操作,模式可以增多一点,如设置地图信息,加入障碍物,这样就可以用到其他的数据结构了。
- #include<graphics.h>//加载easyX图形库信息
- #include<conio.h>
- #include<iostream>
- #include<stdlib.h>
- #include<time.h>
- #include<mmsystem.h>
- using namespace std;
- #pragma comment(lib,"winmm.lib")//加载多媒体接口库文件(固定格式)
- #define WIDTH 960//窗口宽度
- #define HEIGHT 640//窗口高度
- enum DIR//枚举方向
- {
- UP,
- DOWN,
- LEFT,
- RIGHT
- };
-
- enum Menu
- {
- Start,//开始按钮
- Help, //帮助按钮
- Home, //主目录
- Rank,//排行榜
- End,//结束
- Again//继续玩
- };
-
- typedef struct Pos//坐标
- {
- int x;
- int y;
- }Pos;
-
- typedef struct SnakeBody//蛇的节点信息
- {
- Pos Destination;//指针域
- struct SnakeBody* next;
- struct SnakeBody* prior;
- }SnakeBody, SnakeHead;
-
- typedef struct Snake//蛇的属性(6)
- {
- SnakeBody* body;
- int len;//蛇长
- int speed;//蛇速度
- int size;//蛇节数大小
- int dir;//蛇方向
- int score;//蛇得分
- }Snake;
-
- enum Menu menustate = Home;//设定初始界面为Home,主页面
- Snake snake;//建立蛇
- Pos food;//建立食物
- //读入排行榜信息
- void WriteRank(int score)//编写排行榜信息
- {
- FILE* file;
- fopen_s(&file, "SnakeScore.txt", "a");//选择增添数据
- if (file != NULL)
- {
- fprintf_s(file, "\n%d", score);//将得分加入到文件中
- }
- fclose(file);
- }
- //判断鼠标是否在按钮上
- bool isInrect(ExMessage* msg, int x, int y, int w, int h)//x,y坐标,w,h为相应的宽度和高度
- {
- if (msg->x >= x && msg->x <= x + w && msg->y >= y && msg->y <= y + h)
- {
- return true;
- }
- return false;
- }
- //开始状态
- void homeScene(ExMessage* msg)
- {
- IMAGE background;
- loadimage(&background, "Snake4.jpg", WIDTH, HEIGHT);//加载图片2,菜单图片
- putimage(0, 0, &background);//输出图片
- while (peekmessage(msg, EM_MOUSE))
- {
- if (msg->message == WM_LBUTTONDOWN)//左键按下
- {
- //点击帮助按钮
- if (menustate == Home)//条件判断,必须在主菜单时才能进行选择
- {
- if (isInrect(msg, 440, 420, 80, 100))
- {
- menustate = Start;//开始
- }
- if (isInrect(msg, 10, 10, 50, 65))
- {
- menustate = Help;//看帮助信息
- }
- if (isInrect(msg, 390, 560, 190, 56))
- {
- menustate = Rank;//看排行榜信息
- }
- }
- }
- }
-
- }
- //游戏音乐
- void playMusic()
- {
- mciSendString("open ./音乐.mp3", NULL, NULL, NULL);//打开音乐
- mciSendString("play ./音乐.mp3 repeat", NULL, NULL, NULL);//播放音乐
- }
- //主页面音乐
- void HomeMusic()
- {
- mciSendString("open ./音乐2.mp3", NULL, NULL, NULL);
- mciSendString("play ./音乐2.mp3 repeat", NULL, NULL, NULL);
- }
- //食物的随机生成
- void creatFood()
- {
- //设置随机数种子
- srand(time(NULL) + clock());
- cout << rand() << endl;
- food.x = rand() % (WIDTH / 10) * 10;
- food.y = rand() % (HEIGHT / 10) * 10;
- }
- //蛇吃食物
- void eatFood()
- {
- SnakeBody* temp = snake.body;
- if (snake.body->Destination.x == food.x && snake.body->Destination.y == food.y)//蛇吃到食物
- {
- while (temp->next != NULL)
- {
- temp = temp->next;
- }
- SnakeBody* newbody = new SnakeBody;//增加一个蛇身节点
- newbody->next = temp->next;//从末尾插入节点
- temp->next = newbody;
- newbody->prior = temp;
- snake.len++;//蛇的长度加一
- snake.score += 10;//得分加十分
- creatFood();//吃了食物后再次生成食物
- }
- snake.speed = 50;//蛇的速度不变
- }
- //蛇的初始化
- void gameInit()
- {
- snake.size = 10;//蛇节长度
- snake.speed = 200;//蛇的速度
- snake.len = 3;//蛇初始化3节
- snake.dir = RIGHT;//蛇默认方向为右
- snake.score = 0;//得分为0
- snake.body = new SnakeHead;//建立蛇头
- snake.body->Destination = { 50,10 };//默认蛇头的位置
- SnakeBody* body1 = new SnakeBody;//蛇身1
- SnakeBody* body2 = new SnakeBody;//蛇身2
- body1->Destination = { 40,10 };
- body2->Destination = { 30,10 };
- snake.body->next = body1;
- body1->next = body2;
- body2->next = NULL;
- body1->prior = snake.body;
- body2->prior = body1;
- creatFood();//随机生成食物
- }
- //界面绘制
- void gameDraw()
- {
- cleardevice();//清空屏幕
- setbkcolor(WHITE);//背景图片
- SnakeBody* temp = snake.body;
- while (temp)//画蛇
- {
- setlinecolor(BLUE);
- setfillcolor(RED);
- fillrectangle(temp->Destination.x, temp->Destination.y, temp->Destination.x + snake.size, temp->Destination.y + snake.size);
- temp = temp->next;
- }
- setfillcolor(BLUE);//食物颜色
- solidrectangle(food.x, food.y, food.x + snake.size, food.y + snake.size);//绘制食物
- char str[20] ;//绘制分数和蛇的当前节数
- char str1[20] ;
- sprintf_s(str1, "当前节数:%d", snake.len);
- sprintf_s(str, "分数:%d", snake.score);
- settextcolor(RED);
- setbkmode(TRANSPARENT);//将文字背景设为透明
- outtextxy(875, 30, str1);
- outtextxy(907, 10, str);
- }
- //蛇的移动
- void keyModify()
- {
- //获取键盘按键
- //_getch() 阻塞函数 conio.h 这个头文件不是c语言的标准文件,VS可以
- //_kbhit() 判断当前是否有按键产生,如果有返回1 否则0
- if (_kbhit())
- {
- char key = _getch();//获取按键信息
- cout << key << endl;
- if (key == 32)
- {
- snake.speed = 0;//按下空格加速
- }
- if (key == 27)
- {
- system("pause");//按下ESc暂停,按任意键结束暂停
- }
- cout << snake.speed;
- switch (key)
- {
- case 119:
- case 72://上
- if (snake.dir != DOWN)
- snake.dir = UP;
- break;
- case 80://下
- case 115:
- if (snake.dir != UP)
- snake.dir = DOWN;
- break;
- case 75://左
- case 97:
- if (snake.dir != RIGHT)
- snake.dir = LEFT;
- break;
- case 77://右
- case 100:
- if (snake.dir != LEFT)
- snake.dir = RIGHT;
- break;
- }
- }
- }
- void snakeMove()
- {
- keyModify();
- SnakeBody* temp = snake.body;
- while (temp->next != NULL)temp = temp->next;//先找到尾部节点
- while (temp != snake.body)//从尾到头依次复制前一个节点信息,实现蛇移动
- {
- temp->Destination.x = temp->prior->Destination.x;
- temp->Destination.y = temp->prior->Destination.y;
- temp = temp->prior;
- }
- switch (snake.dir)
- {
- case UP:
- snake.body->Destination.y -= 10;
- break;
- case DOWN:
- snake.body->Destination.y += 10;
- break;
- case LEFT:
- snake.body->Destination.x -= 10;
- break;
- case RIGHT:
- snake.body->Destination.x += 10;
- break;
- }
- }
- //对蛇死亡后选择
- void dieDelection(ExMessage* msg)
- {
- IMAGE img;
- loadimage(&img, "SnakeDie.jpg", WIDTH, HEIGHT);
- putimage(0, 0, &img);
- while (menustate != Home && menustate != End && menustate != Again)
- {
- while (peekmessage(msg, EM_MOUSE))
- {
- if (msg->message == WM_LBUTTONDOWN)//如果左键按下
- {
- if (isInrect(msg, WIDTH - 270, 27, 40, 50))//点击关闭按钮时
- {
- menustate = Home;//回到主菜单
- WriteRank(snake.score);//写入排行榜
- mciSendString("close ./音乐.mp3", NULL, NULL, NULL);
- break;
- }
- if (isInrect(msg, WIDTH - 410, HEIGHT - 135, 120, 65))//点击结束按钮时
- {
- WriteRank(snake.score);//写入排行榜
- menustate = End;
- break;
- }
- if (isInrect(msg, 270, HEIGHT - 135, 150, 65))//点击继续按钮时
- {
- WriteRank(snake.score);//写入排行榜
- menustate = Again;
- break;
- }
- }
- }
- }
- if (menustate == Again)
- {
- playMusic();//播放游戏时音乐
- gameInit();//蛇初始化(3个节点)
- BeginBatchDraw();//防止闪屏
- menustate = Start;
- }
- }
- //蛇的死亡判定
- void snakeDie(ExMessage *msg)
- {
- if (snake.body->Destination.x <= 0 || snake.body->Destination.x >= WIDTH || snake.body->Destination.y <= 0 || snake.body->Destination.y >= HEIGHT)
- {
- dieDelection(msg);//调用对蛇死亡后的选择函数
- }
- SnakeBody* temp = snake.body->next;
- while (temp != NULL)
- {
- if (temp->Destination.x == snake.body->Destination.x && temp->Destination.y == snake.body->Destination.y)
- {
- dieDelection(msg);//调用对蛇死亡后的选择函数
- }
- temp = temp->next;
- }
- }
- //帮助界面弹窗
- void helpScene(ExMessage *msg)
- {
- IMAGE help;
- loadimage(&help, "SnakeHelp1.jpg", WIDTH, HEIGHT);//加载图片
- putimage(0, 0, &help);
- while(menustate==Help)
- {
- while (peekmessage(msg, EM_MOUSE))
- {
- if (msg->message == WM_LBUTTONDOWN)
- {
- if (isInrect(msg, WIDTH-270, 27, 40, 50))
- {
- menustate = Home;//返回主菜单
- break;
- }
- }
- }
- }
- }
- //堆排序算法
- void exchange(int* a, int* b)
- {
- int temp = *a;
- *a = *b;
- *b =temp;
- }
- void buildHeap(int* arr, int low, int high)
- {
- int dad = low;
- int son = low * 2 + 1;
- while (son <= high)
- {
- if (arr[son] > arr[son + 1] && son + 1 <= high)
- {
- son++;
- }
- if (arr[dad] < arr[son])
- {
- return;
- }
- else
- {
- exchange(&arr[dad], &arr[son]);
- dad = son;
- son = dad * 2 + 1;
- }
- }
- }
- void heapSort(int *arr,int length)
- {
- for (int i = length / 2 - 1; i<length; i++)
- {
- buildHeap(arr, i, length-1);
- }
- for (int i = length - 1; i >= 0; i--)
- {
- exchange(&arr[0],& arr[i]);
- buildHeap(arr, 0, i-1);
- }
- }
- //排行榜信息显示
- void rankMessage(ExMessage *msg)
- {
- IMAGE img;
- FILE* file;
- int count = 0,mount=0;
- fopen_s(&file, "SnakeScore.txt", "r");
- loadimage(&img, "SnakeRank.jpg", 300, HEIGHT);
- putimage(WIDTH / 4 + 420, 0, &img);
- char player[22][20];
- int Data[10000];
- int play[22];
- while (fscanf_s(file, "%d", &Data[mount], 1) != EOF)
- {
- mount++;
- }
- heapSort(Data, mount);
- while (count < mount && count < 10)
- {
- play[count] = Data[count];
- count++;
- }
-
- for (int i = 0; i < count; i++)
- {
- sprintf_s(player[i], "%d", play[i]);
- }
- fclose(file);
- while (menustate==Rank)
- {
- setbkmode(TRANSPARENT);
- settextcolor(GREEN);
- char arr1[50] = "榜单只显示前10名";
- outtextxy(WIDTH - 210, 85, arr1);
- char arr3[25] = "NO.";//玩家排名
- char arr4[25][20] ;//玩家得分
- char name2[10] = "排名";
- char name3[10] = "得分";
- outtextxy(WIDTH - 300, 110, name2);//排名打印
- outtextxy(WIDTH - 80, 110, name3);//得分打印
- for (int i = 0; i < count; i++)
- {
- sprintf_s(arr4[i],"NO.%d",i+1);
- outtextxy(WIDTH -300,135+i*35,arr4[i]);//玩家排名打印
- outtextxy(WIDTH - 80, 135 + i * 35,player[i]);//玩家分数显示
- }
- while (peekmessage(msg, EM_MOUSE))
- {
- if (msg->message == WM_LBUTTONDOWN)
- {
- if (isInrect(msg, WIDTH - 49, 0, 49, 60))
- {
- menustate = Home;
- break;
- }
- }
- }
- }
- }
- //游戏主干代码
- void playGame()
- {
- initgraph(WIDTH, HEIGHT, SHOWCONSOLE);//如果想显示操作台则加SHOWCONSOLE
- //鼠标消息
- ExMessage msg;
- while (menustate != End)
- {
- switch (menustate)
- {
- case Home:
- while (menustate == Home)//主菜单
- {
- HomeMusic();//播放主菜单音乐
- homeScene(&msg);//主菜单样貌
- if (menustate == Help)
- {
- helpScene(&msg);//帮助窗口
- }
- if (menustate == Rank)
- {
- rankMessage(&msg);//排行榜窗口
- }
- }
- break;
- case Start:
- mciSendString("close ./音乐2.mp3", NULL, NULL, NULL);//当点击开始按钮时,关闭菜单音乐
- playMusic();//播放游戏时音乐
- gameInit();//蛇初始化(3个节点)
- BeginBatchDraw();//防止闪屏
- while (menustate == Start)
- {
- eatFood();//蛇吃食物
- gameDraw();//绘画蛇身等游戏界面的信息
- FlushBatchDraw();//一定要放在绘图下面
- snakeDie(&msg);//判断蛇是否死亡函数
- snakeMove();//蛇移动控制
- Sleep(snake.speed);//速度控制
- EndBatchDraw();//终止绘画工具
- }
- break;
- }
- }
- closegraph();//关闭窗口
- }
- int main()
- {
- playGame();
- return 0;
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。