鱼C论坛

 找回密码
 立即注册
查看: 763|回复: 5

[已解决]C++贪吃蛇错误

[复制链接]
发表于 2020-7-6 20:20:18 | 显示全部楼层 |阅读模式

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

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

x
  1. #include <iostream>
  2. #include <cstdio>
  3. #include <graphics.h>
  4. #include <Windows.h>
  5. #include <conio.h>
  6. #include <time.h>

  7. /********************************
  8. *        初始化蛇1                intiSnake
  9. *        初始化蛇2                intiSnake_2
  10. *        画蛇1                        drawSnake
  11. *        画蛇2                        drawSnake_2
  12. *        移动蛇1                        moveSnake
  13. *        移动蛇2                        moveSnake_2
  14. *        按键处理                keyDown
  15. *        初始化食物                initFood
  16. *        画食物                        drawFood
  17. *        蛇1吃食物                eatFood
  18. *        蛇2吃食物                eatFood_2
  19. *        判断蛇1死亡                snakeDie
  20. *        判断蛇2死亡                snakeDie_2
  21. *        显示蛇1分数                showGrade
  22. *        显示蛇2分数                showGrade_2
  23. *********************************/
  24. void initSnake();
  25. void initSnake_2();
  26. void drawSnake();
  27. void drawSnake_2();
  28. void moveSnake();
  29. void moveSnake_2();
  30. void keyDown();
  31. void initFood();
  32. void drawFood();
  33. void eatFood();
  34. void eatFood_2();
  35. void snakeDie();
  36. void snakeDie_2();
  37. void showGrade();
  38. void showGrade_2();

  39. //坐标
  40. struct point_XY {

  41.         int x;
  42.         int y;

  43. };

  44. //蛇属性
  45. struct {

  46.         int num;                                //蛇的节数
  47.         point_XY snakeXY[100];  //最多100节
  48.         char postion;                        //方向
  49.         int flag;                                //判断是否蛇死亡

  50. }snake, snake_2;

  51. //食物的属性
  52. struct {

  53.         point_XY foodXY;        //食物坐标(X和Y)
  54.         int eatGrade;                //吃掉食物所得分数
  55.         int flag;                    //食物是否存在

  56. }food;

  57. //枚举方向  模拟键码值
  58. enum movPostion {

  59.         right = 72, left = 75, down = 77, up = 80,                        //对应右左下上键的键码值
  60.         right_2 = 68, left_2 = 65, down_2 = 83, up_2 = 87        //对应dasw的键码值

  61. };

  62. HWND hwnd;
  63. int speed = 50;

  64. int main() {

  65.         using namespace std;

  66.         srand((unsigned int)time(NULL));
  67.         hwnd = initgraph(640, 480);
  68.         setbkcolor(WHITE);                //窗口颜色为白White
  69.         cleardevice();                        //刷新
  70.         initSnake();                        //创建蛇1
  71.         initSnake_2();                        //创建蛇2
  72.         snake.flag = 0;                        //蛇1活着
  73.         snake_2.flag = 0;                //蛇2活着
  74.         initFood();                                //创建食物

  75.         while (true) {
  76.                 cleardevice();                //刷新背景
  77.                 drawSnake();                //画蛇1
  78.                 drawSnake_2();                //画蛇2
  79.                 moveSnake();                //移动蛇1
  80.                 moveSnake_2();                //移动蛇2
  81.                 snakeDie();                        //判断蛇1死亡
  82.                 snakeDie_2();                //判断蛇2死亡
  83.                 if (snake.flag == 1 or snake_2.flag == 1) break;                        //如果死了,停止循环
  84.                 if (food.flag != 1) initFood();                //初始化食物
  85.                 if (food.flag == 1) drawFood();                //画食物

  86.                 eatFood();
  87.                 eatFood_2();

  88.                 while (_kbhit()) {

  89.                         keyDown();                //如果有键盘输入,检测输入

  90.                 }

  91.                 Sleep(speed);                //间隔时间50ms

  92.         }

  93.         getchar();

  94.         return 0;
  95. }

  96. //初始化蛇1
  97. void initSnake() {

  98.         snake.num = 3;        //初始化时为三节

  99.         snake.snakeXY[0].x = 20;
  100.         snake.snakeXY[0].y = 0;

  101.         snake.snakeXY[1].x = 10;        //间隔10像素
  102.         snake.snakeXY[1].y = 0;

  103.         snake.snakeXY[2].x = 0;
  104.         snake.snakeXY[2].y = 0;

  105.         snake.postion = right;                //初始化方向为右

  106.         food.flag = 0;

  107. }

  108. //初始化蛇2
  109. void initSnake_2() {

  110.         snake_2.num = 3;                                //初始化时为三节
  111.        
  112.         snake_2.snakeXY[0].x = 10;
  113.         snake_2.snakeXY[0].y = 300;

  114.         snake_2.snakeXY[1].x = 10;                //间隔10像素
  115.         snake_2.snakeXY[1].y = 290;

  116.         snake_2.snakeXY[2].x = 10;
  117.         snake_2.snakeXY[2].y = 280;

  118.         snake_2.postion = down_2;                //初始化方向为右

  119.         food.flag = 0;

  120. }

  121. //画蛇1
  122. void drawSnake() {

  123.         for (int i = 0; i < snake.num; i++) {

  124.                 setlinecolor(BLACK);        //矩形边框颜色为黑Black
  125.                 setfillcolor(BLUE);                //矩形内部颜色为蓝blue
  126.                 fillrectangle(snake.snakeXY[i].x, snake.snakeXY[i].y, snake.snakeXY[i].x + 10, snake.snakeXY[i].y + 10);

  127.         }

  128. }

  129. //画蛇2
  130. void drawSnake_2() {

  131.         for (int i = 0; i < snake.num; i++) {

  132.                 setlinecolor(BLACK);        //矩形边框颜色为黑Black
  133.                 setfillcolor(GREEN);                //矩形内部颜色为绿Green
  134.                 fillrectangle(snake_2.snakeXY[i].x, snake_2.snakeXY[i].y, snake_2.snakeXY[i].x + 10, snake_2.snakeXY[i].y + 10);

  135.         }

  136. }

  137. //移动蛇1
  138. void moveSnake() {
  139.         //除蛇第一节以外的移动坐标处理
  140.         for (int i = snake.num - 1; i > 0; i--) {

  141.                 snake.snakeXY[i].x = snake.snakeXY[i - 1].x;
  142.                 snake.snakeXY[i].y = snake.snakeXY[i - 1].y;

  143.         }

  144.         //第一节坐标处理
  145.         switch (snake.postion) {

  146.         case right:
  147.                 snake.snakeXY[0].x += 10;
  148.                 break;
  149.         case left:
  150.                 snake.snakeXY[0].x -= 10;
  151.                 break;
  152.         case down:
  153.                 snake.snakeXY[0].y += 10;
  154.                 break;
  155.         case up:
  156.                 snake.snakeXY[0].y -= 10;
  157.                 break;
  158.         default:
  159.                 break;

  160.         }

  161. }

  162. //移动蛇2
  163. void moveSnake_2() {
  164.         //除蛇第一节以外的移动坐标处理
  165.         for (int i = snake_2.num - 1; i > 0; i--) {

  166.                 snake_2.snakeXY[i].x = snake_2.snakeXY[i - 1].x;
  167.                 snake_2.snakeXY[i].y = snake_2.snakeXY[i - 1].y;

  168.         }

  169.         //第一节坐标处理
  170.         switch (snake_2.postion) {

  171.         case right_2:
  172.                 snake_2.snakeXY[0].x += 10;
  173.                 break;
  174.         case left_2:
  175.                 snake_2.snakeXY[0].x -= 10;
  176.                 break;
  177.         case down_2:
  178.                 snake_2.snakeXY[0].y += 10;
  179.                 break;
  180.         case up_2:
  181.                 snake_2.snakeXY[0].y -= 10;
  182.                 break;
  183.         default:
  184.                 break;

  185.         }

  186. }

  187. //按键处理
  188. void keyDown() {

  189.         char userKey;
  190.         userKey = _getch();

  191.         switch (userKey) {

  192.         case right:
  193.                 if (snake.postion != down) snake.postion = up;
  194.                 break;
  195.         case left:
  196.                 if (snake.postion != right) snake.postion = left;
  197.                 break;
  198.         case down:
  199.                 if (snake.postion != left) snake.postion = right;
  200.                 break;
  201.         case up:
  202.                 if (snake.postion != up) snake.postion = down;
  203.                 break;
  204.         case right_2:
  205.                 if (snake_2.postion != down_2) snake_2.postion = up_2;
  206.                 break;
  207.         case left_2:
  208.                 if (snake_2.postion != right_2) snake_2.postion = left_2;
  209.                 break;
  210.         case down_2:
  211.                 if (snake_2.postion != left_2) snake_2.postion = right_2;
  212.                 break;
  213.         case up_2:
  214.                 if (snake_2.postion != up_2) snake_2.postion = down_2;
  215.                 break;
  216.         case 49:
  217.                 speed = 10;
  218.                 break;
  219.         case 50:
  220.                 speed = 20;
  221.                 break;
  222.         case 51:
  223.                 speed = 30;
  224.                 break;
  225.         case 52:
  226.                 speed = 40;
  227.                 break;
  228.         case 53:
  229.                 speed = 50;
  230.                 break;
  231.         case 54:
  232.                 speed = 60;
  233.                 break;
  234.         case 55:
  235.                 speed = 70;
  236.                 break;
  237.         case 56:
  238.                 speed = 80;
  239.                 break;
  240.         case 57:
  241.                 speed = 90;
  242.                 break;
  243.         case 48:
  244.                 speed = 100;
  245.                 break;
  246.         default:
  247.                 break;

  248.         }

  249. }

  250. //初始化食物
  251. void initFood() {

  252.         food.foodXY.x = rand() % 65 * 10;        //坐标一定要是10的倍数
  253.         food.foodXY.y = rand() % 48 * 10;
  254.         food.flag = 1;

  255.         for (int i = 0; i < snake.num; i++) {

  256.                 //如果坐标重复,重新生成
  257.                 if (food.foodXY.x == snake.snakeXY[i].x and food.foodXY.y == snake.snakeXY[i].y or food.foodXY.x == snake_2.snakeXY[i].x and food.foodXY.y == snake_2.snakeXY[i].y) {

  258.                         food.foodXY.x = rand() % 65 * 10;
  259.                         food.foodXY.y = rand() % 48 * 10;

  260.                 }

  261.         }
  262. }

  263. //画食物
  264. void drawFood() {

  265.         fillrectangle(food.foodXY.x, food.foodXY.y, food.foodXY.x + 10, food.foodXY.y + 10);
  266.         setlinecolor(BLACK);        //矩形边框颜色为黑Black
  267.         setfillcolor(BLUE);                //矩形内部颜色为蓝blue

  268. }

  269. //蛇1吃食物
  270. void eatFood() {

  271.         //蛇变长了
  272.         if (snake.snakeXY[0].x == food.foodXY.x and snake.snakeXY[0].y == food.foodXY.y) {

  273.                 snake.num++;
  274.                 food.eatGrade += 10;
  275.                 food.flag = 0;

  276.                 //重新画食物

  277.                 void drawFood();

  278.         }

  279. }

  280. //蛇2吃食物
  281. void eatFood_2() {

  282.         //蛇变长了
  283.         if (snake_2.snakeXY[0].x == food.foodXY.x and snake_2.snakeXY[0].y == food.foodXY.y) {

  284.                 snake_2.num++;
  285.                 food.eatGrade += 10;
  286.                 food.flag = 0;

  287.                 //重新画食物

  288.                 void drawFood();

  289.         }

  290. }

  291. //判断蛇1死亡
  292. void snakeDie() {

  293.         //撞墙而死
  294.         if (snake.snakeXY[0].x > 640 or snake.snakeXY[0].x < 0 or snake.snakeXY[0].y > 480 or snake.snakeXY[0].y < 0) {

  295.                 outtextxy(200, 200, "玩家1撞南墙了!");
  296.                 MessageBox(hwnd, "玩家2赢了!", "玩家1撞墙了!!!", MB_OK);
  297.                 snake.flag = 1;                        //蛇1死亡,游戏结束

  298.         }
  299.         //自杀而死
  300.         for (int i = 1; i < snake.num; i++) {

  301.                 if (snake.snakeXY[0].x == snake.snakeXY[i].x and snake.snakeXY[0].y == snake.snakeXY[i].y) {

  302.                         outtextxy(200, 200, "玩家1撞自己了!");
  303.                         MessageBox(hwnd, "玩家2赢了了!", "玩家1自杀了!!!", MB_OK);
  304.                         snake.flag = 1;                //蛇1死亡,游戏结束

  305.                 }

  306.         }
  307.         //头撞到对方身上而死
  308.         for (int i = 1; i < snake_2.num; i++) {

  309.                 if (snake.snakeXY[0].x == snake_2.snakeXY[i].x and snake.snakeXY[1].y == snake_2.snakeXY[i].y) {

  310.                         outtextxy(200, 200, "玩家2赢了了!");
  311.                         MessageBox(hwnd, "玩家1撞到玩家2了", "GameOver!!!", MB_OK);
  312.                         snake.flag = 1;                //蛇1死亡,游戏结束

  313.                 }

  314.         }
  315.         //两头相撞而死
  316.         if (snake.snakeXY[0].x == snake_2.snakeXY[0].x and snake.snakeXY[0].y == snake_2.snakeXY[0].y) {

  317.                 outtextxy(200, 200, "两头蛇相撞了");
  318.                 MessageBox(hwnd, "两个都输了!", "两败俱伤!!!", MB_OK);
  319.                 snake.flag = 1;                        //两蛇死亡,游戏结束

  320.         }

  321. }

  322. //判断蛇2死亡
  323. void snakeDie_2() {

  324.         //撞墙而死
  325.         if (snake_2.snakeXY[0].x > 640 or snake_2.snakeXY[0].x < 0 or snake_2.snakeXY[0].y > 480 or snake_2.snakeXY[0].y < 0) {

  326.                 outtextxy(200, 200, "玩家2撞南墙了!");
  327.                 MessageBox(hwnd, "玩家1赢了!!!", "玩家2撞南墙了!!!", MB_OK);
  328.                 snake_2.flag = 1;                        //蛇2死亡,游戏结束

  329.         }
  330.         //自杀而死
  331.         for (int i = 1; i < snake_2.num; i++) {

  332.                 if (snake_2.snakeXY[0].x == snake_2.snakeXY[i].x and snake_2.snakeXY[0].y == snake_2.snakeXY[i].y) {

  333.                         outtextxy(200, 200, "玩家2撞自己了!");
  334.                         MessageBox(hwnd, "GameOver!!!", "玩家2自杀了!!!", MB_OK);                //蛇死亡,游戏结束
  335.                         snake_2.flag = 1;                //蛇2死亡,游戏结束

  336.                 }

  337.         }       
  338.         //头撞到对方身上而死
  339.         for (int i = 1; i < snake_2.num; i++) {

  340.                 if (snake_2.snakeXY[0].x == snake.snakeXY[i].x and snake_2.snakeXY[1].y == snake.snakeXY[i].y) {

  341.                         outtextxy(200, 200, "玩家1赢了了!");
  342.                         MessageBox(hwnd, "玩家2撞到玩家1了!", "玩家1赢了了!!!", MB_OK);
  343.                         snake_2.flag = 1;                //蛇2死亡,游戏结束

  344.                 }

  345.         }

  346. }
复制代码
今天把我之前写的贪吃蛇改成双人模式,结果最后运行发现第二条蛇控制不了(用asdw键),第一条蛇上下左右键还可以正常控制(头大),希望有dalao看看我的代码


最佳答案
2020-7-12 22:23:27
本帖最后由 superbe 于 2020-7-12 22:28 编辑

别放弃。。。改成虚拟键码试试,字母键的虚拟键码就是ASCII码,方向键的虚拟键码要调用函数得到。
大概是下面这样的,不知道我的理解对不对,参考下。

enum movPostion {

    up = VK_UP, down = VK_DOWN, left = VK_LEFT, right = VK_RIGHT,
    up_2 = 87, down_2 = 83, left_2 = 65, right_2 = 68

};

void keyDown() {

    int userKey = virtkey();

    switch (userKey) {

    (下面代码同上......)


int virtkey()
{
    int ch = _getch();
    if (ch == 0 || ch == 0xE0)
        ch = MapVirtualKey(_getch(), MAPVK_VSC_TO_VK_EX);
    return ch;
}

在VS2015下运行是正常的,其它环境没测试。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-7-10 14:02:45 | 显示全部楼层
  1. /********************************
  2. *        初始化蛇1                intiSnake
  3. *        初始化蛇2                intiSnake_2
  4. *        画蛇1                        drawSnake
  5. *        画蛇2                        drawSnake_2
  6. *        移动蛇1                        moveSnake
  7. *        移动蛇2                        moveSnake_2
  8. *        按键处理                keyDown
  9. *        初始化食物                initFood
  10. *        画食物                        drawFood
  11. *        蛇1吃食物                eatFood
  12. *        蛇2吃食物                eatFood_2
  13. *        判断蛇1死亡                snakeDie
  14. *        判断蛇2死亡                snakeDie_2
  15. *        显示蛇1分数                showGrade
  16. *        显示蛇2分数                showGrade_2
  17. *********************************/
复制代码


intiSnake是什么
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-7-10 14:03:20 | 显示全部楼层
其他我找不出来

我还是个小学生
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-7-10 21:23:48 | 显示全部楼层
本帖最后由 superbe 于 2020-7-12 22:32 编辑

按键控制乱了,替换以下代码,应该就可以了
  1. //枚举方向  模拟键码值
  2. enum movPostion {

  3.     up = 72, down = 80, left = 75, right = 77,
  4.     up_2 = 87, down_2 = 83, left_2 = 65, right_2 = 68

  5. };
复制代码

  1. //画蛇2
  2. void drawSnake_2() {

  3.     for (int i = 0; i < snake_2.num; i++) {

  4.         setlinecolor(BLACK);        //矩形边框颜色为黑Black
  5.         setfillcolor(GREEN);        //矩形内部颜色为绿Green
  6.         fillrectangle(snake_2.snakeXY[i].x, snake_2.snakeXY[i].y, snake_2.snakeXY[i].x + 10, snake_2.snakeXY[i].y + 10);

  7.     }

  8. }
复制代码

  1. //按键处理
  2. void keyDown() {

  3.     char userKey;
  4.     userKey = _getch();
  5.     //if (userKey == 0 || userKey == -32)
  6.     //    userKey = _getch();

  7.     switch (userKey) {
  8.     case up:
  9.         if (snake.postion != down) snake.postion = up;
  10.         break;
  11.     case down:
  12.         if (snake.postion != up) snake.postion = down;
  13.         break;
  14.     case left:
  15.         if (snake.postion != right) snake.postion = left;
  16.         break;
  17.     case right:
  18.         if (snake.postion != left) snake.postion = right;
  19.         break;
  20.     case up_2:
  21.     case up_2 + 32:
  22.         if (snake_2.postion != down_2) snake_2.postion = up_2;
  23.         break;
  24.     case down_2:
  25.     case down_2 + 32:
  26.         if (snake_2.postion != up_2) snake_2.postion = down_2;
  27.         break;
  28.     case left_2:
  29.     case left_2 + 32:
  30.         if (snake_2.postion != right_2) snake_2.postion = left_2;
  31.         break;
  32.     case right_2:
  33.     case right_2 + 32:
  34.         if (snake_2.postion != left_2) snake_2.postion = right_2;
  35.         break;
  36.     case 49:
  37.         speed = 10;
  38.         break;
  39.     case 50:
  40.         speed = 20;
  41.         break;
  42.     case 51:
  43.         speed = 30;
  44.         break;
  45.     case 52:
  46.         speed = 40;
  47.         break;
  48.     case 53:
  49.         speed = 50;
  50.         break;
  51.     case 54:
  52.         speed = 60;
  53.         break;
  54.     case 55:
  55.         speed = 70;
  56.         break;
  57.     case 56:
  58.         speed = 80;
  59.         break;
  60.     case 57:
  61.         speed = 90;
  62.         break;
  63.     case 48:
  64.         speed = 100;
  65.         break;
  66.     default:
  67.         break;

  68.     }

  69. }
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-7-12 15:36:30 | 显示全部楼层
superbe 发表于 2020-7-10 21:23
按键控制乱了,替换以下代码,应该就可以了

确实是你所说的按键的问题,我也尝试着改过,但我觉得可能还是因为getch()函数用的键码值不是代码上的那些(一开始我不确定用的是哪个键码值,而我的代码里所用的是ASCII键码值,而后来我发现字母a ~ z的ASCII键码值是65 ~ 90,这就和我已经确认正确上下左右键的键码值72、80、75、77冲突了),但我又找不到这个函数用的键码值,所以我也放弃了。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-7-12 22:23:27 | 显示全部楼层    本楼为最佳答案   
本帖最后由 superbe 于 2020-7-12 22:28 编辑

别放弃。。。改成虚拟键码试试,字母键的虚拟键码就是ASCII码,方向键的虚拟键码要调用函数得到。
大概是下面这样的,不知道我的理解对不对,参考下。

enum movPostion {

    up = VK_UP, down = VK_DOWN, left = VK_LEFT, right = VK_RIGHT,
    up_2 = 87, down_2 = 83, left_2 = 65, right_2 = 68

};

void keyDown() {

    int userKey = virtkey();

    switch (userKey) {

    (下面代码同上......)


int virtkey()
{
    int ch = _getch();
    if (ch == 0 || ch == 0xE0)
        ch = MapVirtualKey(_getch(), MAPVK_VSC_TO_VK_EX);
    return ch;
}

在VS2015下运行是正常的,其它环境没测试。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-4-27 20:01

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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