鱼C论坛

 找回密码
 立即注册
查看: 2306|回复: 30

[已解决]一个贪吃蛇的小问题,百思不得骑姐

[复制链接]
发表于 2018-8-2 03:09:54 | 显示全部楼层 |阅读模式

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

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

x
本帖最后由 sswy 于 2018-8-2 03:14 编辑
//头文件需要用的函数
#include <stdio.h>//标准输入输出的库函数
#include <time.h>//要用随机数所以用time函数
#include <Windows.h>//需要,控制DOS界面,要在DOS界面中设置文字颜色,获取坐标位置
#include <stdlib.h>//宏定义和通用工具函数
#include <conio.h>//接收键盘输入输出

//宏定义用来定义上下左右方向,把方向定义成整型的数字,方便在后面代码中进行逻辑运算
#define U 1
#define D 2
#define L 3
#define R 4

//全局变量
typedef struct Snake   //蛇身的一个节点
{
        int x;                           //用来存放节点X坐标 
        int y;                           //用来存放节点Y坐标
        struct Snake *next;//蛇身的下一个节点
}SNAKE;



int score = 0, add = 10;//总得分,每次吃食物得分

int HighScore = 0;//游戏最高分

int sleeptime = 200;//sleeptime每次运行的时间间隔

int status; //方向

SNAKE *head, *food;//蛇头指针和食物指针

SNAKE *q;//便利蛇身

int endgamestatus = 0;//表示游戏状态结束的情况,因为有3种情况,咬到自己,撞到墙,主动退出

HANDLE hOut;//为了使用windows函数,建立句柄,它本身是void *


                        /*************函数声明**************/
void gotoxy(int x, int y);//光标位置函数
int color(int c);        //设置文字颜色
void printsnake();        //开始界面蛇绘制
void welcometogame();     //开始界面
void creatMap();          //绘制游戏地图
void scoreandtips();      //游戏界面右侧的得分和小提示
void initsnake();         //初始化蛇身,绘制蛇身
void createfood();        //创建并随机出现食物
int biteself();                  //判断是否咬到了自己
void cantcrosswall();     //设置蛇撞墙情况
void speedup();                          //加速
void speeddown();                  //减速
void snakemove();                  //控制蛇前进方向
void keyboardControl();   //控制键盘按键
void lostdraw();                  //游戏结束界面
void endgame();                          //游戏结束
void choose();                          //游戏失败后的选择
void File_out();                  //存储最高分进文件
void File_in();                          //在文件种读取最高分
void explation();                  //游戏说明


//设置颜色函数
int color(int c)
{

        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c);//设置颜色


        return 0;
}

//控制台移动函数
void gotoxy(int x, int y)
{
        COORD c;//通过修改pos.X和pos.Y的值就可以实现光标的位置控制。
        c.X = x;
        c.Y = y;
        SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c);//控制光标位置
}

//在界面中绘制蛇
void printsnake()
{
        //利用建立好的移动函数和颜色函数绘制图形

        color(6);//用颜色函数给字体上色
        gotoxy(35, 1);//移动光标到合适位置,打印出图案
        printf("/^\\/^\");//注意哦C语言中要答应出\需要多加一个\

        gotoxy(34, 2);//移动光标到第二行,打印出图案
        printf("|_| o|");
        gotoxy(33, 2);
        color(2);
        printf("_");

        gotoxy(25, 3);
        color(12);
        printf("\\/");                      //蛇信

        gotoxy(31, 3);
        color(2);
        printf("/");

        gotoxy(37, 3);
        color(6);
        printf(" \\_/");                     //蛇眼睛

        gotoxy(41, 3);
        color(10);
        printf(" \");

        gotoxy(26, 4);
        color(12);
        printf("\\____");                   //舌头

        gotoxy(32, 4);
        printf("_________/");

        gotoxy(31, 4);
        color(2);
        printf("|");

        gotoxy(43, 4);
        color(10);
        printf("\");

        gotoxy(32, 5);
        color(2);
        printf("\\_______");     //蛇嘴

        gotoxy(44, 5);
        color(10);
        printf("\");

        gotoxy(39, 6);
        printf("|     |                  \");  //下面都是画蛇身

        gotoxy(38, 7);
        printf("/      /                   \");

        gotoxy(37, 8);
        printf("/      /                    \\ \");

        gotoxy(35, 9);
        printf("/      /                       \\ \");

        gotoxy(34, 10);
        printf("/     /                          \\  \");

        gotoxy(33, 11);
        printf("/     /             _----_         \\   \");

        gotoxy(32, 12);
        printf("/     /           _-~      ~-_         |  |");

        gotoxy(31, 13);
        printf("(      (        _-~    _--_    ~-_     _/  |");

        gotoxy(32, 14);
        printf("\\     ~-____-~    _-~    ~-_    ~-_-~    /");

        gotoxy(33, 15);
        printf("~-_           _-~          ~-_       _-~");

        gotoxy(35, 16);
        printf("~--______-~                ~-___-~");







}

//欢迎界面
void welcometogame()
{
        int n;
        int i, j = 1;
        color(11);//设置"贪吃蛇大作战"字体颜色
                          //gotoxy(43, 18);//调整光标位置
                          //printf("贪 吃 蛇 大 作 战");//打印


        color(14);//设置边框颜色


        for (i = 20; i <= 26; i++)//移动纵横坐标光标,打印边框
        {

                for (j = 27; j < 74; j++)
                {
                        gotoxy(j, i);//移动光标 x不停移动j就是x

                        if (i == 20 || i == 26)//横向定位打印范围      打印横边框
                        {
                                printf("-");
                        }
                        else if (j == 27 || j == 73)//横向定位2条边的位置才打印    打印竖边框
                        {
                                printf("|");
                        }
                }
        }

        //打印选择文字
        color(12);
        gotoxy(35, 22);
        printf("1.开始游戏");
        gotoxy(55, 22);
        printf("2.游戏说明");
        gotoxy(35, 24);
        printf("3.退出游戏");


        //打印下方小文字并根据输入进入函数
        color(3);
        gotoxy(29, 27);
        printf("请选择[1 2 3]:[ ]\b\b");//  \b就是光标退格


        color(14);//输入选择的文字
        scanf("%d", &n);//输入选择

        switch (n)
        {
        case 1:
                system("cls");//发出DOS命令,清屏
                creatMap();


                initsnake();
                createfood();

                break;
        case 2:
                break;

        case 3: exit(0);
                break;

        default:
                printf("乱输入我就退出\n");
                break;
        }

}

//创建地图
void creatMap()
{
        int i, j;

        //打印上下边框(外围)
        for (i = 0; i < 58; i += 2)//因为小方括占用2个字符,所以是i+=2 
        {
                color(5);//边框颜色

                gotoxy(i, 0);//上坐标
                printf("●");

                gotoxy(i, 26);//下坐标
                printf("●");
        }

        //打印左右竖边框(外围)
        for (i = 1; i < 26; i++)
        {
                gotoxy(0, i);//打印左边竖边框
                printf("●");

                gotoxy(56, i);//打印右边竖边框
                printf("●");
        }


        //打印棋盘内部
        for (i = 2; i < 56; i += 2)
        {
                for (j = 1; j < 26; j++)
                {
                        gotoxy(i, j);
                        color(3);
                        printf("●\n\n");
                }

        }






}

//创建地图右侧信息
void scoreandtips()//此函数应该在键盘控制的函数中调用,因为每次按键,如果蛇吃到食物,得分都会变化
{
        //File_out();//读取游戏最高分函数

        //打印最高记录和当前得分信息
        color(11);
        gotoxy(64, 4);
        printf("最高记录:%d", HighScore);
        color(11);
        gotoxy(64, 8);
        printf("得分:%d", score);


        //打印小提示
        color(13);//设置颜色
        gotoxy(73, 11);//移动光标
        printf("小提示");//打印

        color(6);//设置颜色
        gotoxy(60, 13);//移动光标
        printf("------------------------------------");//打印
        gotoxy(60, 25);//移动光标
        printf("------------------------------------");//打印

        color(3);
        gotoxy(64, 14);
        printf("每个食物得分:%d分", add);
        gotoxy(64, 16);
        printf("不能撞墙,不能咬到自己");
        gotoxy(64, 18);
        printf("用↑ ↓ ← →分别控制蛇的移动");
        gotoxy(64, 20);
        printf("F1 为加速,F2 为减速");
        gotoxy(64, 22);
        printf("SPACE:暂停游戏");
        gotoxy(64, 24);
        printf("ESC :退出游戏");



}

//读取文本中最高分
void File_in()
{
        FILE *fp;
        fp = fopen("save.txt", "a+");//a+以附加的方式,打开文件,文件不存在创建文件
        fscanf(fp, "%d", &HighScore);//把读取文件中数据给全局变量
        fclose(fp);
}

//绘制蛇身,其实就是定位蛇的初始位置,调整光标位置,打印结构体
void initsnake()
{
        SNAKE *tail;//蛇身
        int i;
        tail = (SNAKE *)malloc(sizeof(SNAKE));//创建蛇尾
        tail->x = 24;//蛇尾坐标定义
        tail->y = 5;
        tail->next = NULL;


        for (i = 1; i <= 4; i++)//分配蛇的光标位置
        {
                head = (SNAKE *)malloc(sizeof(SNAKE));//创建蛇头
                head->next = tail;//指向蛇身
                head->x = 24 + 2 * i;//2代表一个格子
                head->y = 5;//纵向坐标y,y不动和尾巴在同一排
                tail = head;//类似头插法
        }

        

        //打印蛇身
        while (tail != NULL)//因为tail = head,所以tail在for结束后是头指针
        {
                gotoxy(tail->x, tail->y);//根据每一个结构体坐标调整光标位置,并打印出来
                color(14);
                printf("★");
                tail = tail->next;
        }
}

//创建并随机出现食物
void createfood()
{
        SNAKE *food_1=NULL;//创建食物指针


        srand((unsigned)time(NULL));//随机种子

        food_1 = (SNAKE*)malloc(sizeof(SNAKE));//给食物内存
        food_1->next = NULL;

        while ((food_1->x % 2) != 0)//限制食物只会出现在棋盘中的坐标,准备把坐标给到移动光标,绘制食物           %2这里余2是要求食物在棋盘格中间
        {
                food_1->x = rand() % 25 + 2;//棋盘格子宽度是52  让食物出现在X轴最小限制2-52之间   2因为是2个字符为一个格子


        }
        food_1->y = 24 + 1;//棋盘格子长度是24 让食物出现在Y轴最小限制1-24之间     1因为是纵向1个字符为1列


        q = head;//取得蛇头头指针
        

        //int num = 20;//递归返回的时候可以记录进入递归之前的值,但是如果是指针,无法记录之前的
        char ch = 'n';
        while ( q != NULL)//蛇任何一个部分都不能和食物重叠
        {
                //num -= 1;
                if (q->x == food_1->x && q->y == food_1->y)//如果随机出现的食物坐标和蛇初始化坐标重叠,删除这个食物内容,重新创建
                {
                        free(food_1);//释放当前食物内容

                        /*
                        food_1 = (SNAKE*)malloc(sizeof(SNAKE));
                        while ((food_1->x % 2) != 0)
                        {
                                food_1->x = rand() % 52 + 2;
                                food_1->y = 24 + 1;
                                q = head;
                        }
                        */
                        ch = 'y';
                        createfood();//递归重新创建食物坐标,但是这里注意递归进去后,循环q到NULL运行完毕,函数返回来位置在if(ch=='y'),q坐标已经被移动到NULL了,指针无法记录之前的
                        


                }
                if (ch == 'y')
                {
                        food_1 = food;
                        return;
                }
                q = q->next;//蛇身上任何坐标不能和食物重合

                if (q == NULL)
                {
                        break;
                }
        }

        gotoxy(food_1->x, food_1->y);//把随机好的食物坐标给到移动光标里,并绘制出来
        free(food);
        food = food_1;//把食物指针给出去全局指针

        

        color(12);//食物颜色

        printf("●");//绘制食物

}

//判断蛇咬到自己
int biteself()
{
        SNAKE *self;
        q = head;
        self = head;



        while (q ->next!= NULL)//任何一个点碰到身体算失败
        {
                q = q->next;
                if (self->x == q->x && self->y == q->y)
                {
                        return 1;//返回1表示蛇咬到了自己
                }


        }
        return 0;
}

//判断蛇是否撞墙
void cantcrosswall()
{
        if (head->x == 0 || head->x == 56 || head->y == 0 || head->y == 26)
        {
                endgamestatus = 1;//撞墙情况的失败界面,给全局
                printf("撞墙失败");
                exit(1);
                return;
        }

}

//蛇加速前进
void speedup()
{
        if (sleeptime >= 50)//限制50的刷新率,
        {
                sleeptime = sleeptime - 10; //时间间隔 - 10  刷新更快了
                add = add + 2;//同时每吃一个食物的得分+2,可叠加再吃到14再吃到16   add全局基础得分
        }

}

//蛇减速减速
void speeddown()
{
        if (sleeptime < 350)//限制时间间隔小于350不能太慢了哈 
        {
                sleeptime = sleeptime + 30;//加大刷新间隔,速度就慢了


                add = add - 2;//减速了游戏就很容易,所以降低基础分

                if (sleeptime == 350)//当游戏最慢的时候,基础分为1
                {
                        add = 1;
                }
        }

}

//不按键时蛇前进,蛇的动力都在这里,这个程序就类似,1帧一个执行,1帧一个执行,可以这样想象,用程序执行间隔Sleep控制蛇的运行速度
void snakemove()
{
        //这个动力其实就是把新的结构体节点,根据当前蛇头位置移动一个位置,然后不断捕捉键盘方向,来循环移动

        SNAKE *nexthead;//表示蛇头下一个位置,新的头指针,代表新的位置,类似移动了一步
        cantcrosswall();//判断蛇是否撞墙
        nexthead = (SNAKE*)malloc(sizeof(SNAKE));//为下一步开辟一个空间

        

        if (status == U)//向上移动一个格子,其实就是根据头指针位置放一个新结构体,再删除最后的尾巴
        {
                //不断向上前进
                nexthead->x = head->x;   //新节点保持当前横向坐标不变 ,因为我们要上移一格,所以直接改Y就好了
                nexthead->y = head->y - 1; //新节点,上移动一个光标位置,因为y是间隔1个字符,所以-1
                nexthead->next = head;   //链接老蛇头,并把当前地址设成最新蛇头
                head = nexthead;

                q = head;//给一个全局傀儡方便控制

                if (nexthead->x == food->x && nexthead->y == food->y)
                {
                        

                        while (q != NULL)//当上一移动位置和食物位置重叠,就把当前位置画出来,并不删除尾巴上的
                        {
                                gotoxy(q->x, q->y);
                                color(14);
                                printf("★");
                                q = q->next;
                        }
                        score = score + add;//食物吃到后加10分

                        speedup();//加速 速度初始200  并且提高下次吃到食物的基础分数

                        createfood();//重新生成食物
                }
                else//如果没有吃到食物就把痕迹删除
                {
                        

                        while (q->next->next != NULL)//当上一移动位置和食物位置没有重叠,就打印当前蛇,但是要把最后一个痕迹删除
                        {
                                gotoxy(q->x, q->y);
                                color(14);
                                printf("★");
                                q = q->next;
                        }

                        gotoxy(q->next->x, q->next->y);  //清除蛇尾巴,因为移动了一个位置,就要把后面的去除并还原棋盘格
                        color(3);
                        printf("■");
                        free(q->next);        //释放尾巴结构体
                        q->next = NULL;       //当前结构体,指向空
                }
        }


        if (status == D)//向上移动一个格子,其实就是根据头指针位置放一个新结构体,再删除最后的尾巴
        {
                //不断向上前进
                nexthead->x = head->x;   //新节点保持当前横向坐标不变 ,因为我们要上移一格,所以直接改Y就好了
                nexthead->y = head->y+1; //新节点,上移动一个光标位置,因为y是间隔1个字符,所以-1
                nexthead->next = head;   //链接老蛇头,并把当前地址设成最新蛇头
                head = nexthead;

                q = head;//给一个全局傀儡方便控制

                if (nexthead->x == food->x && nexthead->y == food->y)
                {
                

                        while (q != NULL)//当上一移动位置和食物位置重叠,就把当前位置画出来,并不删除尾巴上的
                        {
                                gotoxy(q->x, q->y);
                                color(14);
                                printf("★");
                                q = q->next;
                        }
                        score = score + add;//食物吃到后加10分

                        speedup();//加速 速度初始200  并且提高下次吃到食物的基础分数

                        createfood();//重新生成食物
                }
                else//如果没有吃到食物就把痕迹删除
                {
                

                        while (q->next->next != NULL)//当上一移动位置和食物位置没有重叠,就打印当前蛇,但是要把最后一个痕迹删除
                        {
                                gotoxy(q->x, q->y);
                                color(14);
                                printf("★");
                                q = q->next;
                        }

                        gotoxy(q->next->x, q->next->y);  //清除蛇尾巴,因为移动了一个位置,就要把后面的去除并还原棋盘格
                        color(3);
                        printf("■");
                        free(q->next);        //释放尾巴结构体
                        q->next = NULL;       //当前结构体,指向空
                }
        }


        if (status == L)//向上移动一个格子,其实就是根据头指针位置放一个新结构体,再删除最后的尾巴
        {
                //不断向上前进
                nexthead->x = head->x-2;   //新节点保持当前横向坐标不变 ,因为我们要上移一格,所以直接改Y就好了
                nexthead->y = head->y; //新节点,上移动一个光标位置,因为y是间隔1个字符,所以-1
                nexthead->next = head;   //链接老蛇头,并把当前地址设成最新蛇头
                head = nexthead;

                q = head;//给一个全局傀儡方便控制

                if (nexthead->x == food->x && nexthead->y == food->y)
                {
                

                        while (q != NULL)//当上一移动位置和食物位置重叠,就把当前位置画出来,并不删除尾巴上的
                        {
                                gotoxy(q->x, q->y);
                                color(14);
                                printf("★");
                                q = q->next;
                        }
                        score = score + add;//食物吃到后加10分

                        speedup();//加速 速度初始200  并且提高下次吃到食物的基础分数

                        createfood();//重新生成食物
                }
                else//如果没有吃到食物就把痕迹删除
                {
                

                        while (q->next->next != NULL)//当上一移动位置和食物位置没有重叠,就打印当前蛇,但是要把最后一个痕迹删除
                        {
                                gotoxy(q->x, q->y);
                                color(14);
                                printf("★");
                                q = q->next;
                        }

                        gotoxy(q->next->x, q->next->y);  //清除蛇尾巴,因为移动了一个位置,就要把后面的去除并还原棋盘格
                        color(3);
                        printf("■");
                        free(q->next);        //释放尾巴结构体
                        q->next = NULL;       //当前结构体,指向空
                }
        }


        if (status == R)//向上移动一个格子,其实就是根据头指针位置放一个新结构体,再删除最后的尾巴
        {
                //不断向上前进
                nexthead->x = head->x + 2;   //新节点保持当前横向坐标不变 ,因为我们要上移一格,所以直接改Y就好了
                nexthead->y = head->y; //新节点,上移动一个光标位置,因为y是间隔1个字符,所以-1
                nexthead->next = head;   //链接老蛇头,并把当前地址设成最新蛇头
                head = nexthead;

                q = head;//给一个全局傀儡方便控制

                if (nexthead->x == food->x && nexthead->y == food->y)
                {
                

                        while (q != NULL)//当上一移动位置和食物位置重叠,就把当前位置画出来,并不删除尾巴上的
                        {
                                gotoxy(q->x, q->y);
                                color(14);
                                printf("★");
                                q = q->next;
                        }
                        score = score + add;//食物吃到后加10分

                        speedup();//加速 速度初始200  并且提高下次吃到食物的基础分数

                        createfood();//重新生成食物
                }
                else//如果没有吃到食物就把痕迹删除
                {
        


                        while (q->next->next != NULL)//当上一移动位置和食物位置没有重叠,就打印当前蛇,但是要把最后一个痕迹删除
                        {
                                gotoxy(q->x, q->y);
                                color(14);
                                printf("★");
                                q = q->next;
                        }

                        gotoxy(q->next->x, q->next->y);  //清除蛇尾巴,因为移动了一个位置,就要把后面的去除并还原棋盘格
                        color(3);
                        printf("■");
                        free(q->next);        //释放尾巴结构体
                        q->next = NULL;       //当前结构体,指向空
                }
        }








        if (biteself() == 1)//判断是否吃到自己    为什么先判断撞墙呢,因为要判断当前蛇头位置是否和最开始的边沿重合    

                                            //而吃到自己是要在自己移动后判断是否蛇头和身体重合
        {
                endgamestatus = 2;
        }


}

//控制键盘按键
void keyboardControl()
{
        status = R;//设置初始移动方向为右

        while (1)//可以一直按键所以设置循环
        {
                scoreandtips();//游戏右侧得分小提示

                if (GetAsyncKeyState(VK_UP) && status != D)//运行方向不是向下,就可以记录上
                {
                        status = U;
                }
                else if (GetAsyncKeyState(VK_DOWN) && status != U)
                {
                        status = D;
                }
                else if (GetAsyncKeyState(VK_LEFT) && status != R)
                {
                        status = L;
                }
                else if (GetAsyncKeyState(VK_RIGHT)  && status != L)
                {
                        status = R;
                }


                if (GetAsyncKeyState(VK_SPACE))//如果按下空格键,暂停游戏300毫秒
                {
                        Sleep(300);
                        if (GetAsyncKeyState(VK_SPACE))
                        {
                                break;

                        }
                }
                else if (GetAsyncKeyState(VK_ESCAPE))//如果按了ESC键就退出游戏
                {
                        endgamestatus = 3;
                        break;
                }
                else if (GetAsyncKeyState(VK_F1))//如果按了F1键就加速
                {

                        speedup();
                }
                else if (GetAsyncKeyState(VK_F2))//如果按了F1键就加速
                {
                        speeddown();
                }

                Sleep(sleeptime);//控制刷新率

                snakemove();
        }
}





int main(void)//每一个函数解决一个单一问题,进行组合,在以后编程中也要这样
{
        system("mode con cols=100 lines=30");//让C语言发一个DOS命令,设置窗口宽度高度
        printsnake();//输出绘制图案


        welcometogame();//输出边框和文
        //File_in();//把文件中最高分读取进来

        
        keyboardControl();


        return 0;
}





代码有点长,但是只需要看 <创建并随机出现食物函数>   那里就好了。   
问题是这样的:在游戏初始化的时候,随机出现食物,代码如下,并且食物如果随机出现的坐标和蛇身坐标重合,就重新定位食物坐标。
实现方式我用了递归和常规2种方式,常规的没有问题,但是递归的在游戏运行的时候就会卡死,关键是我找了很久很久问题所在都觉得是正确的,但是程序就是要卡死。希望老师们能看看这个隐藏问题,当研究研究玩耍,但是请b21老师绕道,哈哈哈




while ( q != NULL)//蛇任何一个部分都不能和食物重叠
        {
                //num -= 1;
                if (q->x == food_1->x && q->y == food_1->y)//如果随机出现的食物坐标和蛇初始化坐标重叠,删除这个食物内容,重新创建
                {
                        free(food_1);//释放当前食物内容

                        /*
                        food_1 = (SNAKE*)malloc(sizeof(SNAKE));
                        while ((food_1->x % 2) != 0)
                        {
                                food_1->x = rand() % 52 + 2;
                                food_1->y = 24 + 1;
                                q = head;
                        }
                        */
                        ch = 'y';
                        createfood();//递归重新创建食物坐标,但是这里注意递归进去后,循环q到NULL运行完毕,函数返回来位置在if(ch=='y'),q坐标已经被移动到NULL了,指针无法记录之前的
                       


                }
                if (ch == 'y')
                {
                        food_1 = food;
                        return;
                }
                q = q->next;//蛇身上任何坐标不能和食物重合

                if (q == NULL)
                {
                        break;
                }
        }





最佳答案
2018-8-2 13:28:39
y坐标一直是24 + 1
一直是25
x坐标虽然是随机的,但是很难超过20
如果蛇占用了这些位置,那就一直递归

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

使用道具 举报

发表于 2018-8-2 08:35:25 | 显示全部楼层
407行那个赋值坏了事,把ch又还原了。
另外我的vs2013编译通过不了你用的是vc6还是cb?

点评

你应该判断food_1是不是NULL  发表于 2018-8-2 08:39
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-8-2 13:28:39 | 显示全部楼层    本楼为最佳答案   
y坐标一直是24 + 1
一直是25
x坐标虽然是随机的,但是很难超过20
如果蛇占用了这些位置,那就一直递归

2.png
1.png
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-8-2 13:32:24 | 显示全部楼层
再说一个问题
1.png
2.png
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-8-2 14:49:59 | 显示全部楼层
无符号整形 发表于 2018-8-2 08:35
407行那个赋值坏了事,把ch又还原了。
另外我的vs2013编译通过不了你用的是vc6还是cb?

vs2017 嘻嘻

点评

……哎~  发表于 2018-8-2 14:50
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-8-2 14:52:36 | 显示全部楼层

谢谢老师,太牛了,您应该当版主
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-8-2 14:59:46 | 显示全部楼层

老师,您好,因为那个Y坐标,我也是故意不随机的,希望食物经常和身体重合,但是用DBUG调试,照理说一直递归,就别跳出来嘛,结果用DBUG调试就不会一直递归,而且感觉没问题,但是一运行程序才显现问题
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-8-2 15:03:14 | 显示全部楼层
人造人 发表于 2018-8-2 13:28
y坐标一直是24 + 1
一直是25
x坐标虽然是随机的,但是很难超过20

我觉得问题可能不是在这里,因为照理说,食物和身体重合,递归进去,X坐标还是会随机,一直随机到不在身体上为止,不会因为说食物和身体重合,就一直递归。。。。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-8-2 15:20:40 | 显示全部楼层
本帖最后由 人造人 于 2018-8-2 15:21 编辑
sswy 发表于 2018-8-2 15:03
我觉得问题可能不是在这里,因为照理说,食物和身体重合,递归进去,X坐标还是会随机,一直随机到不在身 ...


1.png
看这个程序
我想要10个随机数
调用10次GetRand
应该得到10个不同的值
但是,这10个值是相同的

原因是 srand
srand要在程序开始时调用一次,之后不需要再次调用了,如果这个程序要运行很长时间,例如服务器的守护进程,这个可以每隔一天调用一次srand,详情可以百度srand的用法

2.png

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

使用道具 举报

发表于 2018-8-2 15:27:59 | 显示全部楼层
1.png
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int GetRand(void)
{
        //srand((unsigned int)time(NULL));
        return rand();
}

int main(void)
{
        srand(0);
        for(int i = 0; i < 10; ++i)
                printf("%d\n", GetRand());

        srand(1);
        for(int i = 0; i < 10; ++i)
                printf("%d\n", GetRand());

        srand(2);
        for(int i = 0; i < 10; ++i)
                printf("%d\n", GetRand());
        printf("***********************************\n");

        srand(0);
        for(int i = 0; i < 10; ++i)
                printf("%d\n", GetRand());

        srand(1);
        for(int i = 0; i < 10; ++i)
                printf("%d\n", GetRand());

        srand(2);
        for(int i = 0; i < 10; ++i)
                printf("%d\n", GetRand());
        printf("***********************************\n");
        
        return 0;
}
38
7719
21238
2437
8855
11797
8365
32285
10450
30612
41
18467
6334
26500
19169
15724
11478
29358
26962
24464
45
29216
24198
17795
29484
19650
14590
26431
10705
18316
***********************************
38
7719
21238
2437
8855
11797
8365
32285
10450
30612
41
18467
6334
26500
19169
15724
11478
29358
26962
24464
45
29216
24198
17795
29484
19650
14590
26431
10705
18316
***********************************
请按任意键继续. . .

种子值一样,得到的随机值就一样
这就是伪随机
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-8-2 15:36:17 | 显示全部楼层
1.png

Stack overflow
不断的递归,导致堆栈溢出了
因为蛇占用了位置,导致的不断递归
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-8-2 15:52:19 | 显示全部楼层
1.png
你能确定这里是25吗?
还是说你把52写成了25?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-8-2 16:15:25 | 显示全部楼层
人造人 发表于 2018-8-2 15:27
种子值一样,得到的随机值就一样
这就是伪随机

醍醐灌顶,请问老师如此隐蔽的问题,老师您是怎么发现的?之前遇上过这样的问题?
太感谢人造人老师了,谢谢谢谢谢谢,太谢谢了

我其实找这个问题至少找了8小时,真的百思不得其解,没想到是这个随机数问题,我开始以为是内存堆栈溢

出,或者是内存没释放干净,或者是内存污染,太没想到了,按正常思维,根本想不到是伪随机数,再次感谢人造人老师!

~~而且这个问题DBUG根本不会报错,递归还有去有回,程序还每一步执行的好好的,太烧人了,还好有老

师解答,要不这个问题不知道什么时候我才会明白
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-8-2 16:16:35 | 显示全部楼层
人造人 发表于 2018-8-2 15:27
种子值一样,得到的随机值就一样
这就是伪随机

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

使用道具 举报

发表于 2018-8-2 16:34:08 | 显示全部楼层
sswy 发表于 2018-8-2 16:15
醍醐灌顶,请问老师如此隐蔽的问题,老师您是怎么发现的?之前遇上过这样的问题?
太感谢人造人老师了, ...

没错,之前遇到过这样的问题
^_^
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-8-2 16:38:55 | 显示全部楼层
1.png
2.png
3.png
4.png

这是在调试,需要一个合适的速度,太快了没办法调试,太慢了也不行

然后就是调试运行
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-8-2 16:40:53 | 显示全部楼层
本帖最后由 人造人 于 2018-8-2 16:43 编辑

每一次吃到食物就会停下来
然后多次观察生成的这个食物的坐标,就会看到问题
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-8-2 16:43:48 | 显示全部楼层
5.png
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-8-2 16:49:33 | 显示全部楼层
人造人 发表于 2018-8-2 15:52
你能确定这里是25吗?
还是说你把52写成了25?

这里不是25老师,是52或者53我记不清楚了,但是这里是因为我故意把x位置调小,让程序多出错,我好方便看为什么
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-8-2 16:51:22 | 显示全部楼层
sswy 发表于 2018-8-2 16:49
这里不是25老师,是52或者53我记不清楚了,但是这里是因为我故意把x位置调小,让程序多出错,我好方便看 ...


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

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-10-2 08:21

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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