livcui 发表于 2020-7-6 20:20:18

C++贪吃蛇错误

#include <iostream>
#include <cstdio>
#include <graphics.h>
#include <Windows.h>
#include <conio.h>
#include <time.h>

/********************************
*        初始化蛇1                intiSnake
*        初始化蛇2                intiSnake_2
*        画蛇1                        drawSnake
*        画蛇2                        drawSnake_2
*        移动蛇1                        moveSnake
*        移动蛇2                        moveSnake_2
*        按键处理                keyDown
*        初始化食物                initFood
*        画食物                        drawFood
*        蛇1吃食物                eatFood
*        蛇2吃食物                eatFood_2
*        判断蛇1死亡                snakeDie
*        判断蛇2死亡                snakeDie_2
*        显示蛇1分数                showGrade
*        显示蛇2分数                showGrade_2
*********************************/
void initSnake();
void initSnake_2();
void drawSnake();
void drawSnake_2();
void moveSnake();
void moveSnake_2();
void keyDown();
void initFood();
void drawFood();
void eatFood();
void eatFood_2();
void snakeDie();
void snakeDie_2();
void showGrade();
void showGrade_2();

//坐标
struct point_XY {

        int x;
        int y;

};

//蛇属性
struct {

        int num;                                //蛇的节数
        point_XY snakeXY;//最多100节
        char postion;                        //方向
        int flag;                                //判断是否蛇死亡

}snake, snake_2;

//食物的属性
struct {

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

}food;

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

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

};

HWND hwnd;
int speed = 50;

int main() {

        using namespace std;

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

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

                eatFood();
                eatFood_2();

                while (_kbhit()) {

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

                }

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

        }

        getchar();

        return 0;
}

//初始化蛇1
void initSnake() {

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

        snake.snakeXY.x = 20;
        snake.snakeXY.y = 0;

        snake.snakeXY.x = 10;        //间隔10像素
        snake.snakeXY.y = 0;

        snake.snakeXY.x = 0;
        snake.snakeXY.y = 0;

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

        food.flag = 0;

}

//初始化蛇2
void initSnake_2() {

        snake_2.num = 3;                                //初始化时为三节
       
        snake_2.snakeXY.x = 10;
        snake_2.snakeXY.y = 300;

        snake_2.snakeXY.x = 10;                //间隔10像素
        snake_2.snakeXY.y = 290;

        snake_2.snakeXY.x = 10;
        snake_2.snakeXY.y = 280;

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

        food.flag = 0;

}

//画蛇1
void drawSnake() {

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

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

        }

}

//画蛇2
void drawSnake_2() {

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

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

        }

}

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

                snake.snakeXY.x = snake.snakeXY.x;
                snake.snakeXY.y = snake.snakeXY.y;

        }

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

        case right:
                snake.snakeXY.x += 10;
                break;
        case left:
                snake.snakeXY.x -= 10;
                break;
        case down:
                snake.snakeXY.y += 10;
                break;
        case up:
                snake.snakeXY.y -= 10;
                break;
        default:
                break;

        }

}

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

                snake_2.snakeXY.x = snake_2.snakeXY.x;
                snake_2.snakeXY.y = snake_2.snakeXY.y;

        }

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

        case right_2:
                snake_2.snakeXY.x += 10;
                break;
        case left_2:
                snake_2.snakeXY.x -= 10;
                break;
        case down_2:
                snake_2.snakeXY.y += 10;
                break;
        case up_2:
                snake_2.snakeXY.y -= 10;
                break;
        default:
                break;

        }

}

//按键处理
void keyDown() {

        char userKey;
        userKey = _getch();

        switch (userKey) {

        case right:
                if (snake.postion != down) snake.postion = up;
                break;
        case left:
                if (snake.postion != right) snake.postion = left;
                break;
        case down:
                if (snake.postion != left) snake.postion = right;
                break;
        case up:
                if (snake.postion != up) snake.postion = down;
                break;
        case right_2:
                if (snake_2.postion != down_2) snake_2.postion = up_2;
                break;
        case left_2:
                if (snake_2.postion != right_2) snake_2.postion = left_2;
                break;
        case down_2:
                if (snake_2.postion != left_2) snake_2.postion = right_2;
                break;
        case up_2:
                if (snake_2.postion != up_2) snake_2.postion = down_2;
                break;
        case 49:
                speed = 10;
                break;
        case 50:
                speed = 20;
                break;
        case 51:
                speed = 30;
                break;
        case 52:
                speed = 40;
                break;
        case 53:
                speed = 50;
                break;
        case 54:
                speed = 60;
                break;
        case 55:
                speed = 70;
                break;
        case 56:
                speed = 80;
                break;
        case 57:
                speed = 90;
                break;
        case 48:
                speed = 100;
                break;
        default:
                break;

        }

}

//初始化食物
void initFood() {

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

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

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

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

                }

        }
}

//画食物
void drawFood() {

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

}

//蛇1吃食物
void eatFood() {

        //蛇变长了
        if (snake.snakeXY.x == food.foodXY.x and snake.snakeXY.y == food.foodXY.y) {

                snake.num++;
                food.eatGrade += 10;
                food.flag = 0;

                //重新画食物

                void drawFood();

        }

}

//蛇2吃食物
void eatFood_2() {

        //蛇变长了
        if (snake_2.snakeXY.x == food.foodXY.x and snake_2.snakeXY.y == food.foodXY.y) {

                snake_2.num++;
                food.eatGrade += 10;
                food.flag = 0;

                //重新画食物

                void drawFood();

        }

}

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

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

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

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

                if (snake.snakeXY.x == snake.snakeXY.x and snake.snakeXY.y == snake.snakeXY.y) {

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

                }

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

                if (snake.snakeXY.x == snake_2.snakeXY.x and snake.snakeXY.y == snake_2.snakeXY.y) {

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

                }

        }
        //两头相撞而死
        if (snake.snakeXY.x == snake_2.snakeXY.x and snake.snakeXY.y == snake_2.snakeXY.y) {

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

        }

}

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

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

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

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

                if (snake_2.snakeXY.x == snake_2.snakeXY.x and snake_2.snakeXY.y == snake_2.snakeXY.y) {

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

                }

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

                if (snake_2.snakeXY.x == snake.snakeXY.x and snake_2.snakeXY.y == snake.snakeXY.y) {

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

                }

        }

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


嘉岳呀 发表于 2020-7-10 14:02:45

/********************************
*      初始化蛇1                intiSnake
*      初始化蛇2                intiSnake_2
*      画蛇1                        drawSnake
*      画蛇2                        drawSnake_2
*      移动蛇1                        moveSnake
*      移动蛇2                        moveSnake_2
*      按键处理                keyDown
*      初始化食物                initFood
*      画食物                        drawFood
*      蛇1吃食物                eatFood
*      蛇2吃食物                eatFood_2
*      判断蛇1死亡                snakeDie
*      判断蛇2死亡                snakeDie_2
*      显示蛇1分数                showGrade
*      显示蛇2分数                showGrade_2
*********************************/

intiSnake是什么

嘉岳呀 发表于 2020-7-10 14:03:20

其他我找不出来

我还是个小学生

superbe 发表于 2020-7-10 21:23:48

本帖最后由 superbe 于 2020-7-12 22:32 编辑

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

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

};

//画蛇2
void drawSnake_2() {

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

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

    }

}

//按键处理
void keyDown() {

    char userKey;
    userKey = _getch();
    //if (userKey == 0 || userKey == -32)
    //    userKey = _getch();

    switch (userKey) {
    case up:
      if (snake.postion != down) snake.postion = up;
      break;
    case down:
      if (snake.postion != up) snake.postion = down;
      break;
    case left:
      if (snake.postion != right) snake.postion = left;
      break;
    case right:
      if (snake.postion != left) snake.postion = right;
      break;
    case up_2:
    case up_2 + 32:
      if (snake_2.postion != down_2) snake_2.postion = up_2;
      break;
    case down_2:
    case down_2 + 32:
      if (snake_2.postion != up_2) snake_2.postion = down_2;
      break;
    case left_2:
    case left_2 + 32:
      if (snake_2.postion != right_2) snake_2.postion = left_2;
      break;
    case right_2:
    case right_2 + 32:
      if (snake_2.postion != left_2) snake_2.postion = right_2;
      break;
    case 49:
      speed = 10;
      break;
    case 50:
      speed = 20;
      break;
    case 51:
      speed = 30;
      break;
    case 52:
      speed = 40;
      break;
    case 53:
      speed = 50;
      break;
    case 54:
      speed = 60;
      break;
    case 55:
      speed = 70;
      break;
    case 56:
      speed = 80;
      break;
    case 57:
      speed = 90;
      break;
    case 48:
      speed = 100;
      break;
    default:
      break;

    }

}

livcui 发表于 2020-7-12 15:36:30

superbe 发表于 2020-7-10 21:23
按键控制乱了,替换以下代码,应该就可以了

确实是你所说的按键的问题,我也尝试着改过,但我觉得可能还是因为getch()函数用的键码值不是代码上的那些(一开始我不确定用的是哪个键码值,而我的代码里所用的是ASCII键码值,而后来我发现字母a ~ z的ASCII键码值是65 ~ 90,这就和我已经确认正确上下左右键的键码值72、80、75、77冲突了),但我又找不到这个函数用的键码值,所以我也放弃了。

superbe 发表于 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下运行是正常的,其它环境没测试。
页: [1]
查看完整版本: C++贪吃蛇错误