Neverturnback 发表于 2018-5-4 21:19:10

看完小甲鱼老师的视频后自己做了一个贪吃蛇(qwq不喜勿喷)

#include <stdio.h>
#include <windows.h>
#include <conio.h>
#include <time.h>

#define frame_height 25 //边框上下长
#define frame_width 50   //边框左右宽
#define UP 'w'    //宏定义, 将以下出现的up替换成w
#define DOWN 's'//同上
#define WEST 'a'//同上
#define RIGHT 'd' //同上

struct Food   // 定义一个结构体 确认食物坐标
{
        int x;
        int y;
}food;
struct Snake   // 定义一个结构体 用数组的方式储存蛇的每一节身体坐标、身体总长度(节点数量)和速度
{
        int x;
        int y;
        int speed;
        int length;
}snake;
char ch, tempch;//蛇的方向, 蛇暂时的方向(后面改变蛇的方向会用到)
int i, temp_x, temp_y, temp_x2, temp_y2, score; //i循环用 ,两个暂时的坐标(后面完成蛇的移动会用到), 得分

int main(void)
{
        void screen(void);//定义一个函数,用来打印界面
        void initial_data(void); //定义一个函数,用来初始化蛇的身体和食物的位置
        void update_food(void); //定义一个函数,用来生成一个食物
        void move_snake(void); //定义一个函数,用来移动蛇
        void get_speed(void); //定义一个函数,用来确定蛇移动的速度
        int if_dead(void);//定义一个函数,用来确定游戏是否结束
        void end(void);//定义一个函数,用来打印结束画面
        void gotoxy(int x, int y); //定义一个函数,用来移动光标到屏幕上对应的位置(屏幕看成一个坐标系,左上角为原点,向下为X轴,向右为Y轴)
       
        while(1)
        {
                initial_data(); //初始化蛇的身体和食物的位置******这里为我了美观所以先初始化再打印界面(我函数中不完善的地方)*********
                screen();//打印界面                         ******按照逻辑应该先打印界面的(之后定义的函数也有很多不符合逻辑的地方请体谅新手qwq)******
                while(1) //游戏开始
                {
                        update_food(); //生成食物
                        get_speed(); //获得蛇速度
                        move_snake(); // 移动蛇
                        Sleep(snake.speed); //Sleep(100),程序暂停100毫秒。
                        if(if_dead()) //蛇死亡函数返回1,跳出循环即游戏结束
                        {
                                break;
                        }
                }
                end();
                if(getch()==27) //如果输入ESC退出程序即退出游戏
                {
                        break;
                }
                else //输入不为ESC键重新开始游戏
                {
                        gotoxy(12, 20); //把光标移动到(12,20)这个点
                        printf("         ");//这两句清除屏幕中“游戏结束”4个字和“!”一个字符,一个汉字两个字符所以总共打印9个空格覆盖
                        continue;
                }
        }

        return 0;
}

void screen(void)
{
        void gotoxy(int x, int y);

        for(i=0 ; i<=24 ; i++) //打印左右边框
        {
                gotoxy(i, 0);
                printf("+");
                gotoxy(i, frame_width - 1);
                printf("+");
        }
        for(i=1; i<=48 ; i++) //打印上下边框
        {
                gotoxy(0, i);
                printf("+");
                gotoxy(frame_height-1, i);
                printf("+");
        }
        gotoxy(6, 60);   //打印右侧的界面
        printf("欢迎来到贪吃蛇(简易版)");
        gotoxy(9, 60);
        printf("当前得分:%d ", score);
        gotoxy(12, 60);
        printf("操作:'W'上,'S'下,'A'左,'D'右");
        gotoxy(15, 60);
        printf("按空格键开始(重新开始)");
        gotoxy(18, 60);
        printf("ESC键退出游戏!");
        if(getch() != ' ') //如果输入不是空格键就进入下面那个循环
        {
                while(1) // 直到输入空格键跳出循环,相当于按空格键开始游戏
                {
                        if(getch() == ' ')
                        {
                                break;
                        }
                }
        }
}

void initial_data(void)
{
        void gotoxy(int x, int y);
        void update_food(void);
       
        snake.x = frame_width / 3;
        snake.y = frame_height / 3; //蛇的坐标(X,Y)在(25/3, 50/3)处
        snake.length = 3; //蛇有3节
        ch = RIGHT; //蛇的方向向右;
        for(i=1 ; i<=snake.length ; i++)//从第二节蛇身开始每一节的Y坐标都比蛇头少1,循环输入除了蛇头其余身体节点的坐标
        {                                 //这里循环了3次,按道理身体长度为3时除了蛇头应该只要循环两次
                snake.x = snake.x;   //所以除了蛇目前身体的坐标确定以外,未来吃到食物的一节身体的坐标也是确定的(目前这节身体还不在)。
                snake.y = snake.y - 1;//目前确定的点有snake,snake,snake,snake,除了snake以外蛇的身体是确实存在的
                gotoxy(snake.x, snake.y);//所以打印了除了snake的节点 (为了方便就简写成snake的形式了,其实是snake.x, snake.y,以后出现同理)
                printf("*");//我用的“*”来表示蛇的身体,也可以用其他的字符表示
        }
        food.x = snake.x;
        food.y = snake.y; //暂定食物在蛇头位置(这里只是为了初始化食物的数据以方便后面调用update_food函数)
        score = 0;
        update_food();
}

void update_food(void)
{
        void gotoxy(int x, int y);

        if(snake.x == food.x && snake.y == food.y)
        {
                while(1)
                {
                        srand(time(NULL)); //srand(),time(),rand()详细说明自行百度,这里的作用就是得到一个随机数
                        food.x = rand()%23 + 1; //(rand()%23+1实际上是rand()%(24-1)+1,得到一个范围再[1,24)的随机数)
                        food.y = rand()%48 + 1;
                        for(i=0 ; i<=snake.length - 1 ; i++)//如果食物的随机位置在蛇身位置重新随机一个食物位置
                        {
                                if(food.x==snake.x && food.y==snake.y)
                                {
                                        break;
                                }
                                if(i == snake.length - 1)
                                {
                                        i = snake.length;
                                }
                        }
                        if(i == snake.length + 1)//直到食物位置不在蛇身位置退出循环
                        {
                                break;
                        }
                }
                gotoxy(food.x, food.y);//光标移动到食物的位置
                printf("o"); //我用的“o”表示食物,也可以用其他字符表示
        }
}

void get_speed(void)
{
        if(snake.length < 5)
        {
                snake.speed = 300;
        }
        else if(snake.length < 10)
        {
                snake.speed = 250;
        }
        else if(snake.length < 15)
        {
                snake.speed = 200;
        }
        else if(snake.length < 20)
        {
                snake.speed = 150;
        }
        else
        {
                snake.speed = 100;
        }
}

void move_snake(void)
{
        void gotoxy(int x, int y);

        temp_x = snake.x;
        temp_y = snake.y;//暂时把蛇头snake的坐标保存再temp中
        if(kbhit())//kbhit()详细说明自行百度,这里作用是如果键盘输入了字符就判断为真
        {
                tempch = getch();//读入键盘输入的字符
                if(tempch == 'w' || tempch == 's' || tempch == 'a' || tempch == 'd')
                {
                        ch = tempch;
                }
        }
        switch(ch)//只移动蛇头,并不是移动整个蛇身
        {
        case 'w' : snake.x = snake.x - 1;break;
        case 's' : snake.x = snake.x + 1;break;
        case 'a' : snake.y = snake.y - 1;break;
        case 'd' : snake.y = snake.y + 1;break;
        }
        if(food.x == snake.x && food.y == snake.y)//如果吃到食物,蛇身+1,分数+1
        {
                snake.length = snake.length +1;
                score++;
                gotoxy(9, 69);
                printf("%d", score);
        }
        for(i=snake.length ; i>=2 ; i--)//从未来吃到食物的一节蛇的身体开始,把前一节的身体坐标赋给当前这节,以达到蛇的移动
        {                               //第二节身体还保持原样, 因为蛇头的位置变动了
                snake.x = snake.x;
                snake.y = snake.y;
        }
        snake.x = temp_x;
        snake.y = temp_y;//把蛇头移动前的坐标赋给第二节身体
        gotoxy(snake.x, snake.y);
        printf("*");//打印蛇头
        gotoxy(snake.x, snake.y);
        printf(" ");//清除“*”未来吃到食物的一节蛇的身体(即移动前,蛇的最后一节身体),不懂的话可以单步调试(我语文学的不太好。。。)
}

int if_dead(void)
{
        for(i=1 ; i<=snake.length-1 ; i++)//蛇头的坐标与蛇身体任意一节的坐标相同的话判断死亡
        {
                if((snake.x == snake.x && snake.y == snake.y))
                {
                        return 1;
                }
        }
        if((snake.x == 0 || snake.x == 24) || (snake.y == 0 || snake.y == 49))
        {                     //蛇头的坐标与边界的坐标一样的话判断死亡
                return 1;
        }
        return 0;
}

void end(void)
{
        void gotoxy(int x, int y);

        gotoxy(snake.x, snake.y);
        printf("+");
        gotoxy(food.x, food.y);
        printf(" ");
        for(i=1 ; i<=snake.length-1 ; i++)
        {
                gotoxy(snake.x, snake.y);
                printf(" ");
        }//清除蛇和食物
        gotoxy(12, 20);
        printf("游戏结束!");
}

void gotoxy(int x, int y) //这个函数作用是把屏幕坐标化,详细说明请自行百度
{
        HANDLE hout;
        COORD cor;
        hout=GetStdHandle(STD_OUTPUT_HANDLE);
        cor.X=y;
        cor.Y=x;
        SetConsoleCursorPosition(hout,cor);
}

13572044595 发表于 2018-5-4 22:15:25

亲~,这么多行代码,请问您这是什么语言?

Neverturnback 发表于 2018-5-4 22:34:27

13572044595 发表于 2018-5-4 22:15
亲~,这么多行代码,请问您这是什么语言?

C语言啊0- 0

溯影 发表于 2018-5-4 23:25:06

可以的,加油,我得向楼主看起,其实这个程序感觉就是C语言的面向对象编程了{:10_275:}

Neverturnback 发表于 2018-5-5 11:29:03

溯影 发表于 2018-5-4 23:25
可以的,加油,我得向楼主看起,其实这个程序感觉就是C语言的面向对象编程了

谢谢{:5_91:}

鱼头骨 发表于 2018-5-7 22:07:41

真厉害!我已经从入门到放弃了。看来还得加油学习啊

魔法虫虫 发表于 2018-5-8 17:52:33

弄过去全是繁体中文

魔法虫虫 发表于 2018-5-8 17:59:56

不过我还是凭借我的聪明机智猜到怎么玩了,厉害了我的哥

千里光 发表于 2018-5-8 19:03:07

厉害

Neverturnback 发表于 2018-5-8 19:03:08

魔法虫虫 发表于 2018-5-8 17:59
不过我还是凭借我的聪明机智猜到怎么玩了,厉害了我的哥

谢谢夸哦{:5_91:}

Neverturnback 发表于 2018-5-8 19:03:44

鱼头骨 发表于 2018-5-7 22:07
真厉害!我已经从入门到放弃了。看来还得加油学习啊

嗯嗯,一起加油{:5_108:}

拖延症。 发表于 2018-5-31 00:14:04

楼主学了多久啊

拖延症。 发表于 2018-5-31 00:14:34

楼主学习了多久啊。。
页: [1]
查看完整版本: 看完小甲鱼老师的视频后自己做了一个贪吃蛇(qwq不喜勿喷)