鱼C论坛

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

[已解决]看不懂小甲鱼的贪吃蛇代码

[复制链接]
发表于 2019-3-19 10:11:53 | 显示全部楼层 |阅读模式
100鱼币
代码如下

  1. #include <windows.h>
  2. #include <time.h>
  3. #include <stdlib.h>

  4. //定义4个方向
  5. #define UP                1  //向上,蛇头y坐标不断减小
  6. #define DOWN        2  //向下,蛇头y坐标不断增大
  7. #define LEFT        3  //向左,蛇头x坐标不断减小
  8. #define RIGHT        4  //向右,蛇头x坐标不断增大

  9. #define SNAKEWIDTH        10  //单节蛇的大小
  10. #define XWIDTH                20  //游戏区的宽度
  11. #define YHEIGHT                20  //游戏区的高度
  12. #define GETSCORE        10        //吃一个食物的得分
  13. #define ID_TIMER        1   //定时器ID
  14. #define TIMERSET        600 //定时间隔

  15. static int                        direct = RIGHT;  //方向(注:方向由蛇头决定)
  16. static int                        Score;  //吃到的食物数量

  17. bool                IsOver = false, bEat = false;

  18. struct Snake
  19. {
  20.         Snake() :next(NULL), before(NULL)
  21.         {
  22.                 pt.x = 0; pt.y = 0;
  23.         }
  24.         Snake(const POINT &npt, Snake *, Snake *);
  25.         POINT        pt;
  26.         Snake * next, *before;
  27. } snake;  //定义蛇头

  28. Snake::Snake(const POINT &npt, Snake * nnext, Snake * nbefore) :
  29.         pt(npt), next(nnext), before(nbefore) {}

  30. Snake * psLast = NULL, *food = NULL;

  31. bool GameClient[XWIDTH][YHEIGHT]; //定义游戏区坐标布尔值,表示相应点的蛇身以及是否有食物。

  32. LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);                                                                             
  33. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
  34. {
  35.         TCHAR                szAppName[] = TEXT("Snake"),
  36.                 szWindowName[] = TEXT("贪吃蛇");
  37.         WNDCLASS        wndcls;
  38.         wndcls.cbClsExtra = 0;
  39.         wndcls.cbWndExtra = 0;
  40.         wndcls.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
  41.         wndcls.hCursor = LoadCursor(hInstance, IDC_ARROW);
  42.         wndcls.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
  43.         wndcls.hInstance = hInstance;
  44.         wndcls.lpfnWndProc = WndProc;
  45.         wndcls.lpszClassName = szAppName;
  46.         wndcls.lpszMenuName = NULL;
  47.         wndcls.style = CS_HREDRAW | CS_VREDRAW;
  48.         RegisterClass(&wndcls);

  49.         HWND hwnd = CreateWindow(szAppName, szWindowName,
  50.                 WS_OVERLAPPED | WS_MINIMIZEBOX | WS_SYSMENU,
  51.                 CW_USEDEFAULT, CW_USEDEFAULT, (XWIDTH + 10) * SNAKEWIDTH, (YHEIGHT + 5) * SNAKEWIDTH,
  52.                 NULL, NULL, hInstance, NULL);
  53.         ShowWindow(hwnd, nCmdShow);
  54.         UpdateWindow(hwnd);

  55.         MSG msg;
  56.         while (GetMessage(&msg, NULL, 0, 0))
  57.         {
  58.                 TranslateMessage(&msg);
  59.                 DispatchMessage(&msg);
  60.         }
  61.         return msg.wParam;
  62. }

  63. //新食物刷新
  64. void NewFood(HWND hwnd)
  65. {
  66.         food = new Snake();
  67.         SYSTEMTIME st;
  68.         GetLocalTime(&st);
  69.         srand(st.wMilliseconds);
  70.         food->pt.x = rand() % XWIDTH, food->pt.y = rand() % YHEIGHT;
  71.         while (GameClient[food->pt.x][food->pt.y])
  72.         {
  73.                 GetLocalTime(&st);
  74.                 srand(st.wMilliseconds);
  75.                 food->pt.x = rand() % XWIDTH, food->pt.y = rand() % YHEIGHT;
  76.         }
  77.         GameClient[food->pt.x][food->pt.y] = true;
  78.         InvalidateRect(hwnd, NULL, TRUE);
  79. }

  80. //判断前方是否是食物
  81. inline bool IsFood()
  82. {
  83.         if (snake.pt.x == food->pt.x && snake.pt.y == food->pt.y)
  84.                 return true;
  85.         else
  86.                 return false;
  87. }

  88. //判断是否撞墙或者撞到自己身体
  89. bool TouchWall()
  90. {
  91.         Snake * temp = psLast;
  92.         //超越边界判断
  93.         if (snake.pt.x >= XWIDTH ||
  94.                 snake.pt.x < 0 ||
  95.                 snake.pt.y < 0 ||
  96.                 snake.pt.y >= YHEIGHT)
  97.                 return true;
  98.         //碰撞自身身体判断
  99.         while (temp != &snake)
  100.         {
  101.                 if (snake.pt.x == temp->pt.x &&
  102.                         snake.pt.y == temp->pt.y)
  103.                         return true;
  104.                 temp = temp->before;
  105.         }
  106.         return false;
  107. }


  108. void Move(HWND hwnd)
  109. {
  110.         int x, y;  //用于记录蛇头的当前位置(未前进时)
  111.         //标记前方是否为食物,默认为不是食物,表示系通常的前进
  112.         Snake * temp = psLast;

  113.         //记录蛇头当前坐标
  114.         x = snake.pt.x;
  115.         y = snake.pt.y;
  116.         //测试前进的地方是否是食物,同时将蛇头前进
  117.         switch (direct)
  118.         {
  119.         case UP:
  120.                 --snake.pt.y;
  121.                 break;
  122.         case DOWN:
  123.                 ++snake.pt.y;
  124.                 break;
  125.         case LEFT:
  126.                 --snake.pt.x;
  127.                 break;
  128.         case RIGHT:
  129.                 ++snake.pt.x;
  130.                 break;
  131.         default:
  132.                 break;
  133.         }
  134.         //如果不是食物,作如下处理
  135.         if (!IsFood())
  136.         {
  137.                 //最后一节不是蛇头
  138.                 if (temp != &snake)
  139.                 {
  140.                         GameClient[temp->pt.x][temp->pt.y] = false;
  141.                         while (temp != snake.next)
  142.                         {
  143.                                 temp->pt.x = temp->before->pt.x;
  144.                                 temp->pt.y = temp->before->pt.y;
  145.                                 temp = temp->before;
  146.                         }
  147.                         temp->pt.x = x;
  148.                         temp->pt.y = y;
  149.                         GameClient[temp->pt.x][temp->pt.y] = true;
  150.                 }
  151.                 else  //psLast == &snake,即蛇只有蛇头
  152.                         GameClient[x][y] = false;
  153.                 if (TouchWall())
  154.                         IsOver = true;                                                //则标记游戏结束
  155.                 else
  156.                         GameClient[snake.pt.x][snake.pt.y] = true;        //不然移动后的蛇头位置标记为有方块了
  157.                 InvalidateRect(hwnd, NULL, TRUE);                //刷新游戏区
  158.         }
  159.         //如果是食物,作如下处理
  160.         else
  161.         {
  162.                 ++Score;
  163.                 food->before = psLast;
  164.                 psLast->next = food;

  165.                 if (temp != &snake)
  166.                 {
  167.                         food->pt.x = psLast->pt.x;
  168.                         food->pt.y = psLast->pt.y;
  169.                         while (temp != snake.next)
  170.                         {
  171.                                 temp->pt.x = temp->before->pt.x;
  172.                                 temp->pt.y = temp->before->pt.y;
  173.                                 temp = temp->before;
  174.                         }
  175.                         temp->pt.x = x;
  176.                         temp->pt.y = y;
  177.                 }
  178.                 else  //psLast == &snake,即蛇只有蛇头
  179.                 {
  180.                         food->pt.x = x; food->pt.y = y;
  181.                 }
  182.                 psLast = food;
  183.                 NewFood(hwnd);
  184.         }
  185. }

  186. LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  187. {
  188.         HDC                                hdc;
  189.         PAINTSTRUCT                ps;
  190.         TEXTMETRIC                tm;
  191.         static int                cxChar, cyChar;
  192.         TCHAR                        szScore[] = TEXT("得分:"),
  193.                 szGameOver[] = TEXT("游戏结束!"),
  194.                 szPause[] = TEXT("游戏暂停!"),
  195.                 szBuffer[20],
  196.                 *szText = NULL;
  197.         int                                x, y;
  198.         static bool                pause = false;

  199.         switch (message)
  200.         {
  201.         case WM_CREATE:
  202.                 direct = RIGHT;   //游戏开局,默认方向向右
  203.                 snake.pt.x = XWIDTH / 2;  //默认显示在游戏区中间位置
  204.                 snake.pt.y = YHEIGHT / 2;
  205.                 psLast = &snake;
  206.                 GameClient[snake.pt.x][snake.pt.y] = true;
  207.                 hdc = GetDC(hwnd);
  208.                 GetTextMetrics(hdc, &tm);
  209.                 cyChar = tm.tmExternalLeading + tm.tmHeight;
  210.                 ReleaseDC(hwnd, hdc);
  211.                 NewFood(hwnd);
  212.                 SetTimer(hwnd, ID_TIMER, TIMERSET, NULL);
  213.                 return 0;

  214.         case WM_TIMER:
  215.                 if (pause) return 0;
  216.                 Move(hwnd);
  217.                 if (IsOver)
  218.                 {
  219.                         KillTimer(hwnd, ID_TIMER);
  220.                         InvalidateRect(hwnd, NULL, TRUE);
  221.                 }
  222.                 return 0;

  223.         case WM_KEYDOWN:
  224.                 if (IsOver || pause) return 0;
  225.                 switch (wParam)
  226.                 {
  227.                 case VK_UP:
  228.                         if (direct != DOWN)
  229.                         {
  230.                                 direct = UP;
  231.                                 Move(hwnd);
  232.                         }
  233.                         break;
  234.                 case VK_DOWN:
  235.                         if (direct != UP)
  236.                         {
  237.                                 direct = DOWN;
  238.                                 Move(hwnd);
  239.                         }
  240.                         break;
  241.                 case VK_LEFT:
  242.                         if (direct != RIGHT)
  243.                         {
  244.                                 direct = LEFT;
  245.                                 Move(hwnd);
  246.                         }
  247.                         break;
  248.                 case VK_RIGHT:
  249.                         if (direct != LEFT)
  250.                         {
  251.                                 direct = RIGHT;
  252.                                 Move(hwnd);
  253.                         }
  254.                         break;
  255.                 default:
  256.                         break;
  257.                 }
  258.                 return 0;

  259.         case WM_CHAR:
  260.                 if (IsOver && wParam != 'r') return 0;
  261.                 switch (wParam)
  262.                 {
  263.                 case 'p':
  264.                 {
  265.                         pause = !pause;
  266.                         InvalidateRect(hwnd, NULL, TRUE);
  267.                 }
  268.                 break;
  269.                 case 'r':
  270.                 {
  271.                         for (int x = 0; x < XWIDTH; ++x)
  272.                                 for (int y = 0; y < YHEIGHT; ++y)
  273.                                         GameClient[x][y] = false;
  274.                 }
  275.                 SetTimer(hwnd, ID_TIMER, TIMERSET, NULL);
  276.                 direct = RIGHT;   //游戏开局,默认方向向右
  277.                 snake.pt.x = XWIDTH / 2;  //默认显示在游戏区中间位置
  278.                 snake.pt.y = YHEIGHT / 2;
  279.                 psLast = &snake;
  280.                 IsOver = false;
  281.                 pause = false;
  282.                 GameClient[snake.pt.x][snake.pt.y] = true;
  283.                 NewFood(hwnd);
  284.                 break;
  285.                 default:
  286.                         break;
  287.                 }
  288.                 return 0;

  289.         case WM_PAINT:
  290.                 hdc = BeginPaint(hwnd, &ps);

  291.                 SetViewportOrgEx(hdc, SNAKEWIDTH, SNAKEWIDTH, NULL);
  292.                 //画游戏区的边框
  293.                 MoveToEx(hdc, -1, -1, NULL);
  294.                 LineTo(hdc, XWIDTH * SNAKEWIDTH + 1, -1);
  295.                 LineTo(hdc, XWIDTH * SNAKEWIDTH + 1, YHEIGHT * SNAKEWIDTH + 1);
  296.                 LineTo(hdc, -1, YHEIGHT * SNAKEWIDTH + 1);
  297.                 LineTo(hdc, -1, -1);

  298.                 TextOut(hdc, (XWIDTH + 1) * SNAKEWIDTH, 0, szScore, lstrlen(szScore));
  299.                 TextOut(hdc, (XWIDTH + 1) * SNAKEWIDTH, cyChar,
  300.                         szBuffer, wsprintf(szBuffer, TEXT("%4d"), Score));
  301.                 if (pause)
  302.                         TextOut(hdc, (XWIDTH + 1) * SNAKEWIDTH, 3 * cyChar, szPause, lstrlen(szPause));
  303.                 else if (IsOver)
  304.                         TextOut(hdc, (XWIDTH + 1) * SNAKEWIDTH, 3 * cyChar, szGameOver, lstrlen(szGameOver));
  305.                 SelectObject(hdc, GetStockObject(BLACK_BRUSH));
  306.                 for (x = 0; x < XWIDTH; ++x)
  307.                 {
  308.                         for (y = 0; y < YHEIGHT; ++y)
  309.                         {
  310.                                 if (GameClient[x][y])
  311.                                         Rectangle(hdc, x * SNAKEWIDTH, y * SNAKEWIDTH,
  312.                                         (x + 1) * SNAKEWIDTH, (y + 1) * SNAKEWIDTH);
  313.                         }
  314.                 }
  315.                 return 0;

  316.         case WM_DESTROY:
  317.                 KillTimer(hwnd, ID_TIMER);
  318.                 PostQuitMessage(0);
  319.                 return 0;
  320.         }
  321.         return DefWindowProc(hwnd, message, wParam, lParam);
  322. }
复制代码


  1. LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);                                                                             
  2. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
复制代码

  1. LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
复制代码


这两句看不懂,想问一下,这部分需要补充什么内容的知识,然后这个代码我的编译器会报一些编译错误,他的main函数在哪里?
最佳答案
2019-3-19 10:11:54
这是windows编程的内容,后面的MFC框架的基础
你可以去简单学习一下windows编程设计课程

最佳答案

查看完整内容

这是windows编程的内容,后面的MFC框架的基础 你可以去简单学习一下windows编程设计课程
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2019-3-19 10:11:54 | 显示全部楼层    本楼为最佳答案   
这是windows编程的内容,后面的MFC框架的基础
你可以去简单学习一下windows编程设计课程

评分

参与人数 1荣誉 +5 鱼币 +5 贡献 +3 收起 理由
RIXO + 5 + 5 + 3 谢谢

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-9-12 16:03:44 | 显示全部楼层
Windows。h这个头文件怎么下载
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-9-17 08:47:51 | 显示全部楼层
好厉害
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-5-21 09:24

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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