当前位置:   article > 正文

大一下贪吃蛇课程设计

大一下贪吃蛇课程设计

此次课设用到的数据结构是双向链表,算法堆排序,eaxyX图形库,文件操作,鼠标操作。

具体操作步骤代码中有解释,图片信息和文件信息自己可以稍微改进,对窗口设置按钮可用eaxyX图形库实现,我则采用图片了,读者可根据设置按钮来加长代码长度,但贪吃蛇核心功能并不是设置按钮,所以采用图片了。进阶的话可以加入登录和注册操作,模式可以增多一点,如设置地图信息,加入障碍物,这样就可以用到其他的数据结构了。

  1. #include<graphics.h>//加载easyX图形库信息
  2. #include<conio.h>
  3. #include<iostream>
  4. #include<stdlib.h>
  5. #include<time.h>
  6. #include<mmsystem.h>
  7. using namespace std;
  8. #pragma comment(lib,"winmm.lib")//加载多媒体接口库文件(固定格式)
  9. #define WIDTH 960//窗口宽度
  10. #define HEIGHT 640//窗口高度
  11. enum DIR//枚举方向
  12. {
  13. UP,
  14. DOWN,
  15. LEFT,
  16. RIGHT
  17. };
  18. enum Menu
  19. {
  20. Start,//开始按钮
  21. Help, //帮助按钮
  22. Home, //主目录
  23. Rank,//排行榜
  24. End,//结束
  25. Again//继续玩
  26. };
  27. typedef struct Pos//坐标
  28. {
  29. int x;
  30. int y;
  31. }Pos;
  32. typedef struct SnakeBody//蛇的节点信息
  33. {
  34. Pos Destination;//指针域
  35. struct SnakeBody* next;
  36. struct SnakeBody* prior;
  37. }SnakeBody, SnakeHead;
  38. typedef struct Snake//蛇的属性(6)
  39. {
  40. SnakeBody* body;
  41. int len;//蛇长
  42. int speed;//蛇速度
  43. int size;//蛇节数大小
  44. int dir;//蛇方向
  45. int score;//蛇得分
  46. }Snake;
  47. enum Menu menustate = Home;//设定初始界面为Home,主页面
  48. Snake snake;//建立蛇
  49. Pos food;//建立食物
  50. //读入排行榜信息
  51. void WriteRank(int score)//编写排行榜信息
  52. {
  53. FILE* file;
  54. fopen_s(&file, "SnakeScore.txt", "a");//选择增添数据
  55. if (file != NULL)
  56. {
  57. fprintf_s(file, "\n%d", score);//将得分加入到文件中
  58. }
  59. fclose(file);
  60. }
  61. //判断鼠标是否在按钮上
  62. bool isInrect(ExMessage* msg, int x, int y, int w, int h)//x,y坐标,w,h为相应的宽度和高度
  63. {
  64. if (msg->x >= x && msg->x <= x + w && msg->y >= y && msg->y <= y + h)
  65. {
  66. return true;
  67. }
  68. return false;
  69. }
  70. //开始状态
  71. void homeScene(ExMessage* msg)
  72. {
  73. IMAGE background;
  74. loadimage(&background, "Snake4.jpg", WIDTH, HEIGHT);//加载图片2,菜单图片
  75. putimage(0, 0, &background);//输出图片
  76. while (peekmessage(msg, EM_MOUSE))
  77. {
  78. if (msg->message == WM_LBUTTONDOWN)//左键按下
  79. {
  80. //点击帮助按钮
  81. if (menustate == Home)//条件判断,必须在主菜单时才能进行选择
  82. {
  83. if (isInrect(msg, 440, 420, 80, 100))
  84. {
  85. menustate = Start;//开始
  86. }
  87. if (isInrect(msg, 10, 10, 50, 65))
  88. {
  89. menustate = Help;//看帮助信息
  90. }
  91. if (isInrect(msg, 390, 560, 190, 56))
  92. {
  93. menustate = Rank;//看排行榜信息
  94. }
  95. }
  96. }
  97. }
  98. }
  99. //游戏音乐
  100. void playMusic()
  101. {
  102. mciSendString("open ./音乐.mp3", NULL, NULL, NULL);//打开音乐
  103. mciSendString("play ./音乐.mp3 repeat", NULL, NULL, NULL);//播放音乐
  104. }
  105. //主页面音乐
  106. void HomeMusic()
  107. {
  108. mciSendString("open ./音乐2.mp3", NULL, NULL, NULL);
  109. mciSendString("play ./音乐2.mp3 repeat", NULL, NULL, NULL);
  110. }
  111. //食物的随机生成
  112. void creatFood()
  113. {
  114. //设置随机数种子
  115. srand(time(NULL) + clock());
  116. cout << rand() << endl;
  117. food.x = rand() % (WIDTH / 10) * 10;
  118. food.y = rand() % (HEIGHT / 10) * 10;
  119. }
  120. //蛇吃食物
  121. void eatFood()
  122. {
  123. SnakeBody* temp = snake.body;
  124. if (snake.body->Destination.x == food.x && snake.body->Destination.y == food.y)//蛇吃到食物
  125. {
  126. while (temp->next != NULL)
  127. {
  128. temp = temp->next;
  129. }
  130. SnakeBody* newbody = new SnakeBody;//增加一个蛇身节点
  131. newbody->next = temp->next;//从末尾插入节点
  132. temp->next = newbody;
  133. newbody->prior = temp;
  134. snake.len++;//蛇的长度加一
  135. snake.score += 10;//得分加十分
  136. creatFood();//吃了食物后再次生成食物
  137. }
  138. snake.speed = 50;//蛇的速度不变
  139. }
  140. //蛇的初始化
  141. void gameInit()
  142. {
  143. snake.size = 10;//蛇节长度
  144. snake.speed = 200;//蛇的速度
  145. snake.len = 3;//蛇初始化3节
  146. snake.dir = RIGHT;//蛇默认方向为右
  147. snake.score = 0;//得分为0
  148. snake.body = new SnakeHead;//建立蛇头
  149. snake.body->Destination = { 50,10 };//默认蛇头的位置
  150. SnakeBody* body1 = new SnakeBody;//蛇身1
  151. SnakeBody* body2 = new SnakeBody;//蛇身2
  152. body1->Destination = { 40,10 };
  153. body2->Destination = { 30,10 };
  154. snake.body->next = body1;
  155. body1->next = body2;
  156. body2->next = NULL;
  157. body1->prior = snake.body;
  158. body2->prior = body1;
  159. creatFood();//随机生成食物
  160. }
  161. //界面绘制
  162. void gameDraw()
  163. {
  164. cleardevice();//清空屏幕
  165. setbkcolor(WHITE);//背景图片
  166. SnakeBody* temp = snake.body;
  167. while (temp)//画蛇
  168. {
  169. setlinecolor(BLUE);
  170. setfillcolor(RED);
  171. fillrectangle(temp->Destination.x, temp->Destination.y, temp->Destination.x + snake.size, temp->Destination.y + snake.size);
  172. temp = temp->next;
  173. }
  174. setfillcolor(BLUE);//食物颜色
  175. solidrectangle(food.x, food.y, food.x + snake.size, food.y + snake.size);//绘制食物
  176. char str[20] ;//绘制分数和蛇的当前节数
  177. char str1[20] ;
  178. sprintf_s(str1, "当前节数:%d", snake.len);
  179. sprintf_s(str, "分数:%d", snake.score);
  180. settextcolor(RED);
  181. setbkmode(TRANSPARENT);//将文字背景设为透明
  182. outtextxy(875, 30, str1);
  183. outtextxy(907, 10, str);
  184. }
  185. //蛇的移动
  186. void keyModify()
  187. {
  188. //获取键盘按键
  189. //_getch() 阻塞函数 conio.h 这个头文件不是c语言的标准文件,VS可以
  190. //_kbhit() 判断当前是否有按键产生,如果有返回1 否则0
  191. if (_kbhit())
  192. {
  193. char key = _getch();//获取按键信息
  194. cout << key << endl;
  195. if (key == 32)
  196. {
  197. snake.speed = 0;//按下空格加速
  198. }
  199. if (key == 27)
  200. {
  201. system("pause");//按下ESc暂停,按任意键结束暂停
  202. }
  203. cout << snake.speed;
  204. switch (key)
  205. {
  206. case 119:
  207. case 72://上
  208. if (snake.dir != DOWN)
  209. snake.dir = UP;
  210. break;
  211. case 80://下
  212. case 115:
  213. if (snake.dir != UP)
  214. snake.dir = DOWN;
  215. break;
  216. case 75://左
  217. case 97:
  218. if (snake.dir != RIGHT)
  219. snake.dir = LEFT;
  220. break;
  221. case 77://右
  222. case 100:
  223. if (snake.dir != LEFT)
  224. snake.dir = RIGHT;
  225. break;
  226. }
  227. }
  228. }
  229. void snakeMove()
  230. {
  231. keyModify();
  232. SnakeBody* temp = snake.body;
  233. while (temp->next != NULL)temp = temp->next;//先找到尾部节点
  234. while (temp != snake.body)//从尾到头依次复制前一个节点信息,实现蛇移动
  235. {
  236. temp->Destination.x = temp->prior->Destination.x;
  237. temp->Destination.y = temp->prior->Destination.y;
  238. temp = temp->prior;
  239. }
  240. switch (snake.dir)
  241. {
  242. case UP:
  243. snake.body->Destination.y -= 10;
  244. break;
  245. case DOWN:
  246. snake.body->Destination.y += 10;
  247. break;
  248. case LEFT:
  249. snake.body->Destination.x -= 10;
  250. break;
  251. case RIGHT:
  252. snake.body->Destination.x += 10;
  253. break;
  254. }
  255. }
  256. //对蛇死亡后选择
  257. void dieDelection(ExMessage* msg)
  258. {
  259. IMAGE img;
  260. loadimage(&img, "SnakeDie.jpg", WIDTH, HEIGHT);
  261. putimage(0, 0, &img);
  262. while (menustate != Home && menustate != End && menustate != Again)
  263. {
  264. while (peekmessage(msg, EM_MOUSE))
  265. {
  266. if (msg->message == WM_LBUTTONDOWN)//如果左键按下
  267. {
  268. if (isInrect(msg, WIDTH - 270, 27, 40, 50))//点击关闭按钮时
  269. {
  270. menustate = Home;//回到主菜单
  271. WriteRank(snake.score);//写入排行榜
  272. mciSendString("close ./音乐.mp3", NULL, NULL, NULL);
  273. break;
  274. }
  275. if (isInrect(msg, WIDTH - 410, HEIGHT - 135, 120, 65))//点击结束按钮时
  276. {
  277. WriteRank(snake.score);//写入排行榜
  278. menustate = End;
  279. break;
  280. }
  281. if (isInrect(msg, 270, HEIGHT - 135, 150, 65))//点击继续按钮时
  282. {
  283. WriteRank(snake.score);//写入排行榜
  284. menustate = Again;
  285. break;
  286. }
  287. }
  288. }
  289. }
  290. if (menustate == Again)
  291. {
  292. playMusic();//播放游戏时音乐
  293. gameInit();//蛇初始化(3个节点)
  294. BeginBatchDraw();//防止闪屏
  295. menustate = Start;
  296. }
  297. }
  298. //蛇的死亡判定
  299. void snakeDie(ExMessage *msg)
  300. {
  301. if (snake.body->Destination.x <= 0 || snake.body->Destination.x >= WIDTH || snake.body->Destination.y <= 0 || snake.body->Destination.y >= HEIGHT)
  302. {
  303. dieDelection(msg);//调用对蛇死亡后的选择函数
  304. }
  305. SnakeBody* temp = snake.body->next;
  306. while (temp != NULL)
  307. {
  308. if (temp->Destination.x == snake.body->Destination.x && temp->Destination.y == snake.body->Destination.y)
  309. {
  310. dieDelection(msg);//调用对蛇死亡后的选择函数
  311. }
  312. temp = temp->next;
  313. }
  314. }
  315. //帮助界面弹窗
  316. void helpScene(ExMessage *msg)
  317. {
  318. IMAGE help;
  319. loadimage(&help, "SnakeHelp1.jpg", WIDTH, HEIGHT);//加载图片
  320. putimage(0, 0, &help);
  321. while(menustate==Help)
  322. {
  323. while (peekmessage(msg, EM_MOUSE))
  324. {
  325. if (msg->message == WM_LBUTTONDOWN)
  326. {
  327. if (isInrect(msg, WIDTH-270, 27, 40, 50))
  328. {
  329. menustate = Home;//返回主菜单
  330. break;
  331. }
  332. }
  333. }
  334. }
  335. }
  336. //堆排序算法
  337. void exchange(int* a, int* b)
  338. {
  339. int temp = *a;
  340. *a = *b;
  341. *b =temp;
  342. }
  343. void buildHeap(int* arr, int low, int high)
  344. {
  345. int dad = low;
  346. int son = low * 2 + 1;
  347. while (son <= high)
  348. {
  349. if (arr[son] > arr[son + 1] && son + 1 <= high)
  350. {
  351. son++;
  352. }
  353. if (arr[dad] < arr[son])
  354. {
  355. return;
  356. }
  357. else
  358. {
  359. exchange(&arr[dad], &arr[son]);
  360. dad = son;
  361. son = dad * 2 + 1;
  362. }
  363. }
  364. }
  365. void heapSort(int *arr,int length)
  366. {
  367. for (int i = length / 2 - 1; i<length; i++)
  368. {
  369. buildHeap(arr, i, length-1);
  370. }
  371. for (int i = length - 1; i >= 0; i--)
  372. {
  373. exchange(&arr[0],& arr[i]);
  374. buildHeap(arr, 0, i-1);
  375. }
  376. }
  377. //排行榜信息显示
  378. void rankMessage(ExMessage *msg)
  379. {
  380. IMAGE img;
  381. FILE* file;
  382. int count = 0,mount=0;
  383. fopen_s(&file, "SnakeScore.txt", "r");
  384. loadimage(&img, "SnakeRank.jpg", 300, HEIGHT);
  385. putimage(WIDTH / 4 + 420, 0, &img);
  386. char player[22][20];
  387. int Data[10000];
  388. int play[22];
  389. while (fscanf_s(file, "%d", &Data[mount], 1) != EOF)
  390. {
  391. mount++;
  392. }
  393. heapSort(Data, mount);
  394. while (count < mount && count < 10)
  395. {
  396. play[count] = Data[count];
  397. count++;
  398. }
  399. for (int i = 0; i < count; i++)
  400. {
  401. sprintf_s(player[i], "%d", play[i]);
  402. }
  403. fclose(file);
  404. while (menustate==Rank)
  405. {
  406. setbkmode(TRANSPARENT);
  407. settextcolor(GREEN);
  408. char arr1[50] = "榜单只显示前10名";
  409. outtextxy(WIDTH - 210, 85, arr1);
  410. char arr3[25] = "NO.";//玩家排名
  411. char arr4[25][20] ;//玩家得分
  412. char name2[10] = "排名";
  413. char name3[10] = "得分";
  414. outtextxy(WIDTH - 300, 110, name2);//排名打印
  415. outtextxy(WIDTH - 80, 110, name3);//得分打印
  416. for (int i = 0; i < count; i++)
  417. {
  418. sprintf_s(arr4[i],"NO.%d",i+1);
  419. outtextxy(WIDTH -300,135+i*35,arr4[i]);//玩家排名打印
  420. outtextxy(WIDTH - 80, 135 + i * 35,player[i]);//玩家分数显示
  421. }
  422. while (peekmessage(msg, EM_MOUSE))
  423. {
  424. if (msg->message == WM_LBUTTONDOWN)
  425. {
  426. if (isInrect(msg, WIDTH - 49, 0, 49, 60))
  427. {
  428. menustate = Home;
  429. break;
  430. }
  431. }
  432. }
  433. }
  434. }
  435. //游戏主干代码
  436. void playGame()
  437. {
  438. initgraph(WIDTH, HEIGHT, SHOWCONSOLE);//如果想显示操作台则加SHOWCONSOLE
  439. //鼠标消息
  440. ExMessage msg;
  441. while (menustate != End)
  442. {
  443. switch (menustate)
  444. {
  445. case Home:
  446. while (menustate == Home)//主菜单
  447. {
  448. HomeMusic();//播放主菜单音乐
  449. homeScene(&msg);//主菜单样貌
  450. if (menustate == Help)
  451. {
  452. helpScene(&msg);//帮助窗口
  453. }
  454. if (menustate == Rank)
  455. {
  456. rankMessage(&msg);//排行榜窗口
  457. }
  458. }
  459. break;
  460. case Start:
  461. mciSendString("close ./音乐2.mp3", NULL, NULL, NULL);//当点击开始按钮时,关闭菜单音乐
  462. playMusic();//播放游戏时音乐
  463. gameInit();//蛇初始化(3个节点)
  464. BeginBatchDraw();//防止闪屏
  465. while (menustate == Start)
  466. {
  467. eatFood();//蛇吃食物
  468. gameDraw();//绘画蛇身等游戏界面的信息
  469. FlushBatchDraw();//一定要放在绘图下面
  470. snakeDie(&msg);//判断蛇是否死亡函数
  471. snakeMove();//蛇移动控制
  472. Sleep(snake.speed);//速度控制
  473. EndBatchDraw();//终止绘画工具
  474. }
  475. break;
  476. }
  477. }
  478. closegraph();//关闭窗口
  479. }
  480. int main()
  481. {
  482. playGame();
  483. return 0;
  484. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/秋刀鱼在做梦/article/detail/820907
推荐阅读
相关标签
  

闽ICP备14008679号