鱼C论坛

 找回密码
 立即注册
查看: 2264|回复: 3

[技术交流] C-贪吃蛇

[复制链接]
发表于 2015-12-17 10:50:10 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
学了一个多月,花了几天时间,查了一些资料,撸了几百行代码。
用了线程和回调函数,有点四不像。
有个程序猿看了代码说像shi一样。请大家指点一下,什么问题。
另外,有时候不产生食物,不知道问题出在哪。
工具:VS2013

  1. #include <stdio.h>
  2. #include <time.h>
  3. #include <windows.h>
  4. #include <stdlib.h>
  5. #include <conio.h>
  6. #include <stdbool.h>
  7. #include <stdint.h>
  8. #include <string.h>

  9. ///////////////////////////////////////////////////////////////////////
  10. #define printBeginUIPos 40
  11. #define printPoolUIPos 75
  12. //////////////////////////////////////////////////////////////////////

  13. typedef struct        SNAKE                        //定义蛇的结构
  14. {
  15.         POINT        snakeHeadPos;                //蛇头坐标
  16.         int                Len;                                //蛇身长度
  17.         char        direction;                        //当前行动方向
  18.         int                score;                                //游戏得分
  19.         struct SNAKE *next;                        //指向下一个节点的指针
  20. }Snake;

  21. typedef struct FOOD                                //定义食物的坐标
  22. {
  23.         int x;
  24.         int y;
  25. }food;                       

  26. food *Food;

  27. int gameStatus = 1;                                        //定义当前游戏状态
  28.                                                                 //1、正常游戏;2、退出游戏;3、暂停游戏;4、撞到墙壁;5、吃到自己

  29. HWND g_hConsoleOutPut;                        //控制台句柄

  30. Snake *head,*p;

  31. HANDLE hThread;
  32. DWORD ThreadID;

  33. //HHOOK glhHook = NULL;
  34. //HINSTANCE glhInstance;
  35. /////////////////////////////------函数声明-------//////////////////////////////////
  36. void initBeginUI();                                //初始化开始界面
  37. void printGamePool();                        //打印游戏池
  38. void gotoxy(short x, short y);        //鼠标移动到 x,y
  39. void initGame();                                //初始化游戏
  40. void createFood();                                //产生食物
  41. int playGame();
  42. void decideDirection(key);                //由按键字母得到方向
  43. void moveSnake();
  44. void endGame();
  45. void CALLBACK TimeProc(HWND,UINT,UINT,DWORD);                //时间类的回调函数
  46. //void CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);
  47. void threadMoveSnake();                        //线程--蛇移动

  48. /////////////////////////////----Main----////////////////////////
  49. int main()
  50. {
  51.         initBeginUI();
  52.         initGame();
  53.         playGame();

  54.         system("pause > nul");
  55.         system("cls");

  56.         return 0;
  57. }

  58. ///////////////////////////////////////////////////////////////////////
  59. void initBeginUI()                                //初始化开始界面
  60. {
  61.         g_hConsoleOutPut = GetStdHandle(STD_OUTPUT_HANDLE);

  62.         CONSOLE_CURSOR_INFO cursorInfo = { 1, false };
  63.         SetConsoleCursorInfo(g_hConsoleOutPut,&cursorInfo);
  64.         SetConsoleTitleA("Snake---By fpx");
  65.         system("mode con cols=100 lines=30");

  66.         SetConsoleTextAttribute(g_hConsoleOutPut, 0x0F);  //API设置控制台窗口字体颜色和背景色的函数
  67.         gotoxy(printBeginUIPos, 5);
  68.         printf("┏━━━━━━━┓");
  69.         gotoxy(printBeginUIPos, 6);
  70.         printf("┃ %2s%s%2s ┃", "", "-贪吃蛇-", "");
  71.         gotoxy(printBeginUIPos, 7);
  72.         printf("┗━━━━━━━┛");
  73.         gotoxy(printBeginUIPos, 10);
  74.         printf("    Made By fpx");
  75.         gotoxy(printBeginUIPos-2, 12);
  76.         printf("Press any key to continue...");

  77.         while (1)
  78.         {
  79.                 if (_kbhit())
  80.                 {
  81.                         break;
  82.                 }
  83.         }
  84.         //fflush(stdin);        //清除标准输入设备(即键盘)的缓冲区。
  85.         _getch();
  86.         system("cls");

  87.         printGamePool();
  88. }

  89. void printGamePool()                        //打印游戏池
  90. {
  91.         int i;
  92.         for (i = 0; i < 70; i += 2)
  93.         {
  94.                 gotoxy(i, 0);
  95.                 printf("■");
  96.                 gotoxy(i, 29);
  97.                 printf("■");
  98.         }
  99.         for (i = 0; i < 30; i++)
  100.         {
  101.                 gotoxy(0, i);
  102.                 printf("■");
  103.                 gotoxy(70, i);
  104.                 printf("■");
  105.         }

  106.         SetConsoleTextAttribute(g_hConsoleOutPut, 0xB);
  107.         gotoxy(printPoolUIPos, 8);
  108.         printf("□向左移动:← A");
  109.         gotoxy(printPoolUIPos, 10);
  110.         printf("□向右移动:→ D");
  111.         gotoxy(printPoolUIPos, 12);
  112.         printf("□向下移动:↓ S");
  113.         gotoxy(printPoolUIPos, 14);
  114.         printf("□向下移动:↑ W");
  115.         gotoxy(printPoolUIPos, 16);
  116.         printf("□Score   : 0");
  117.         gotoxy(printPoolUIPos, 18);
  118.         printf("■By: fpx 15.11.18");

  119. }

  120. void gotoxy(short x, short y)
  121. {
  122.         COORD pos = { x, y };
  123.         SetConsoleCursorPosition(g_hConsoleOutPut, pos);
  124. }
  125. ///////////////////////////////////////////////////////////////////////
  126. void initGame()                                        //初始化游戏
  127. {
  128.         int i;

  129.         Snake *tail;
  130.         tail = (Snake *)malloc(sizeof(Snake));        //定义蛇尾
  131.         tail->next = NULL;
  132.         tail->snakeHeadPos.x = 20;
  133.         tail->snakeHeadPos.y = 5;

  134.         for (i = 0; i < 2; i++)
  135.         {
  136.                 head = (Snake *)malloc(sizeof(Snake));
  137.                 head->next = tail;
  138.                 head->snakeHeadPos.x = 20 + 2 * (i+1); head->snakeHeadPos.y = 5;
  139.                 tail = head;
  140.         }

  141.         head = tail;
  142.         head->direction = 'D';
  143.         head->Len = 3;
  144.         head->score = 0;

  145.         while (tail != NULL)
  146.         {
  147.                 gotoxy(tail->snakeHeadPos.x, tail->snakeHeadPos.y);
  148.                 printf("■");
  149.                 tail = tail->next;
  150.         }
  151.         createFood();
  152. }

  153. void createFood()                                        //产生食物
  154. {
  155.         food *food_1;
  156.         srand((unsigned)time(NULL));
  157.         food_1 = (food *)malloc(sizeof(food));

  158.         while ((food_1->x % 2) != 0 || food_1->x < 2)                //保证食物的横坐标为2的偶数
  159.         {
  160.                 food_1->x = rand() % 67 + 2;
  161.         }
  162.         food_1->y = rand() % 28 + 1;

  163.         p = head;
  164.         while (p->next != NULL)
  165.         {
  166.                 if (food_1->x == p->snakeHeadPos.x && food_1->y == p->snakeHeadPos.y)
  167.                 {
  168.                         createFood();
  169.                         return 0;
  170.                 }
  171.                 p = p->next;
  172.         }
  173.         Food = food_1;
  174.         gotoxy(food_1->x, food_1->y);
  175.         printf("☆");
  176. }
  177. //////////////////////////////////////////////////////////////////////
  178. int playGame()
  179. {
  180.         char direction,key;
  181.         //clock_t clockNow, clockLast;

  182.         //clockLast = clock();

  183.         hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadMoveSnake, NULL, 0, &ThreadID);
  184.        
  185.         while (1)
  186.         {
  187.                 key = _getch();
  188.                 if (key == 27)
  189.                 {
  190.                         gameStatus = 2;
  191.                 }

  192.                 if (gameStatus > 2)
  193.                 {
  194.                         return 0;
  195.                 }

  196.                 decideDirection(key);
  197.                 Sleep(150);
  198.         }

  199. }

  200. void decideDirection(key)                //由按键字母得到方向
  201. {
  202.         char returnValue;
  203.         switch (key)
  204.         {
  205.         case 'W':
  206.         case 'w':
  207.         case 72:
  208.                 if (head->direction != 'S')
  209.                 {
  210.                         head->direction = 'W';
  211.                 }
  212.                 break;
  213.         case 'S':
  214.         case 's':
  215.         case 80:
  216.                 if (head->direction != 'W')
  217.                 {
  218.                         head->direction = 'S';
  219.                 }
  220.                 break;
  221.         case 'A':
  222.         case 'a':
  223.         case 75:
  224.                 if (head->direction != 'D')
  225.                 {
  226.                         head->direction = 'A';
  227.                 }
  228.                 break;
  229.         case 'D':
  230.         case 'd':
  231.         case 77:
  232.                 if (head->direction != 'A')
  233.                 {
  234.                         head->direction = 'D';
  235.                 }
  236.                 break;
  237.         default:
  238.                 head->direction = head->direction;
  239.                 break;
  240.         }
  241. }

  242. void moveSnake()
  243. {
  244.         //1、判断是否撞墙
  245.         //2、由方向确定坐标的变化
  246.         //3、判断下一个是否为食物,若是,则加长;否则移动蛇身
  247.         //4、判断是否吃到自己
  248.         int x, y;

  249.         if (head->snakeHeadPos.x < 2 || head->snakeHeadPos.x > 68 || head->snakeHeadPos.y < 1 || head->snakeHeadPos.y > 29)
  250.         {
  251.                 gameStatus = 4;
  252.                 endGame();
  253.         }

  254.         x = head->snakeHeadPos.x;
  255.         y = head->snakeHeadPos.y;

  256.         Snake *nextsnake,*q;
  257.         nextsnake = (Snake *)malloc(sizeof(Snake));
  258.         q = (Snake *)malloc(sizeof(Snake));
  259.         //ZeroMemory(&p,sizeof(p));                //清空结构体

  260.         switch (head->direction)
  261.         {
  262.         case 'W':y--; break;
  263.         case 'S':y++; break;
  264.         case 'A':x -= 2; break;
  265.         case 'D':x += 2; break;
  266.         }

  267.         nextsnake->snakeHeadPos.x = x;                        //对新节点赋值
  268.         nextsnake->snakeHeadPos.y = y;
  269.         nextsnake->Len = head->Len;
  270.         nextsnake->direction = head->direction;
  271.         nextsnake->score = head->score;
  272.         nextsnake->next = head;

  273.         if (nextsnake->snakeHeadPos.x == Food->x && nextsnake->snakeHeadPos.y == Food->y)
  274.         {
  275.                 head = nextsnake;
  276.                 p = head;

  277.                 while (p != NULL)
  278.                 {
  279.                         gotoxy(p->snakeHeadPos.x, p->snakeHeadPos.y);
  280.                         printf("■");
  281.                         p = p->next;
  282.                 }
  283.                 head->Len += 1;
  284.                 head->score += 10;
  285.                 gotoxy(printPoolUIPos, 16);
  286.                 printf("□Score   : %d",head->score);
  287.                 createFood();
  288.         }
  289.         else
  290.         {
  291.                 head = nextsnake;
  292.                 p = head;

  293.                 while (p->next->next != NULL)
  294.                 {
  295.                         gotoxy(p->snakeHeadPos.x, p->snakeHeadPos.y);
  296.                         printf("■");
  297.                         p = p->next;
  298.                 }
  299.                 gotoxy(p->next->snakeHeadPos.x, p->next->snakeHeadPos.y);
  300.                 printf("  ");
  301.                 p->next = NULL;
  302.         }

  303.         q = head->next;
  304.         while (q)
  305.         {
  306.                 if (head->snakeHeadPos.x == q->snakeHeadPos.x && head->snakeHeadPos.y == q->snakeHeadPos.y)
  307.                 {
  308.                         gameStatus = 5;
  309.                         endGame();
  310.                 }
  311.                 q = q->next;
  312.         }
  313. }

  314. void CALLBACK TimeProc(HWND hwnd, UINT message, UINT idTimer, DWORD dwTime)
  315. {
  316.         moveSnake();
  317. }

  318. //void CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
  319. //{
  320. //        switch (wParam)
  321. //        {
  322. //        case VK_UP:
  323. //        case 'W':
  324. //        case 'w':
  325. //        case 72:
  326. //                if (head->direction != 'S')
  327. //                {
  328. //                        head->direction = 'W';
  329. //                }
  330. //                break;
  331. //        case VK_DOWN:
  332. //        case 'S':
  333. //        case 's':
  334. //        case 80:
  335. //                if (head->direction != 'W')
  336. //                {
  337. //                        head->direction = 'S';
  338. //                }
  339. //                break;
  340. //        case VK_LEFT:
  341. //        case 'A':
  342. //        case 'a':
  343. //        case 75:
  344. //                if (head->direction != 'D')
  345. //                {
  346. //                        head->direction = 'A';
  347. //                }
  348. //                break;
  349. //        case VK_RIGHT:
  350. //        case 'D':
  351. //        case 'd':
  352. //        case 77:
  353. //                if (head->direction != 'A')
  354. //                {
  355. //                        head->direction = 'D';
  356. //                }
  357. //                break;
  358. //        //default:
  359. //        //        head->direction = head->direction;
  360. //                //break;
  361. //        }
  362. //}

  363. void threadMoveSnake()                        //线程中移动蛇身
  364. {
  365.         SetTimer(NULL, 1, 300, TimeProc);
  366.         MSG msg;
  367.         while (GetMessage(&msg, NULL, 0, 0))
  368.         {
  369.                 if (msg.message == WM_TIMER)
  370.                 {
  371.                         DispatchMessage(&msg);
  372.                 }
  373.                 //if (msg.message == WM_KEYDOWN)
  374.                 //{
  375.                 //        TranslateMessage(&msg);
  376.                 //        DispatchMessage(&msg);
  377.                 //}
  378.         }
  379. }
  380. ////////////////////////////////////////////////////////////////////////////
  381. void endGame()
  382. {
  383.         /*TerminateThread(hThread, 0);*/
  384.        
  385.         KillTimer(g_hConsoleOutPut,1);

  386.         system("cls");
  387.         gotoxy(40, 12);

  388.         switch (gameStatus)
  389.         {
  390.         case 2:
  391.                 printf("您的已经结束了游戏。"); break;
  392.         case 4:
  393.                 printf("您撞到墙了。游戏结束."); break;
  394.         case 5:
  395.                 printf("您咬到自己了。游戏结束."); break;
  396.         }
  397.         gotoxy(40, 15);
  398.         printf("您的得分是 %d\n", head->score);

  399.         //ExitThread(0);

  400.         system("pause > nul");
  401.         /*system("cls");*/
  402.         exit(0);
  403. }
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2015-12-17 12:08:43 | 显示全部楼层
:call:看一看
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-4-15 21:02:46 | 显示全部楼层
厉害
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2016-4-16 14:57:31 | 显示全部楼层
支持楼主
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-24 04:04

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表