请选择 进入手机版 | 继续访问电脑版
点击联系客服
客服QQ:509006671 客服微信:mengfeiseo

兰州老站长

 找回密码
 立即注册
查看: 47|回复: 0

蛇游戏——C语言写作贪吃

[复制链接]

1

主题

1

帖子

-7

积分

限制会员

积分
-7
发表于 2021-3-8 14:23:21 | 显示全部楼层 |阅读模式
文章目录

1.效果显示2。设计思路2.1模式是2.2蛇的头部移动2.3食物的生成2.4蛇的身体生成和移动2.5判断墙壁碰撞和打印分数3。完整的代码

1.效果展示





2.设计思路

2.1图案显示

使用二维阵列创建图案。总共有墙、蛇头、蛇身、食物、空白五个元素,所以只要二维阵列的元素有五个不同的值就可以了。








2.2蛇头的移动

贪吃蛇是自动运动的。我们先让蛇头自动移动。使用阵列表示元素在地图上的位置,因此移动元素就是更改元素的坐标。

因此,需要构建完成蛇头坐标自动移动的函数,确定输入的箭头键,并更改移动方向。





2.3食物的生成

食物的生成很简单种下一颗随机数种子,给它一个判断食物生成与否的变量就可以了。请注意,食物的坐标不超过限制





2.4蛇身体的生成与移动

蛇身体的计算:

第一,蛇的身体在运动之前必须制作身体吃东西,可以给一个变量作为柜台来判断有多少尸体。(它是一种食物)。

保存蛇身坐标:

我们需要一个结构体排列。
结构体数组的每个元素有两个成员x和y值,这两个值就代表我们的身体在二维数组中的坐标,
即一个数组成员就代表一截身体;

蛇身体坐标的获得:
通过计数器来判断是否有身体,当计数器不为0时,蛇就有了身体,第一截身体的坐标来源就是蛇头吃到食物前的坐标;
同理,后面吃到的食物增加,计数器的数值变大,就代表我们的结构体数组有多少个有效元素,然后给结构体数组里面的成员进行赋值;
最后一截身体的数组下标=计数器-1,后面的身体坐标就是前面的身体移动前的坐标,由于我们的头是不断移动的,并且可以直接获得其坐标,所以从最后一截身体开始往前进行拷贝赋值;
由于我们的赋值特点,数组(蛇身)从后往前进行覆盖式拷贝赋值,即完成了蛇身体的移动

没有吃到食物时的细节:
没有吃到食物时,蛇的身体长度是不变的,我们的身体坐标进行改变之后,在二维数组中留下了一个隐患;





2.5判断是否撞墙和打印得分
打印得分:得分即身体的长度即计数器的数值

判断是否撞墙:判断蛇头的下一个位置在二维数组中是不是1即是不是墙壁即可



3.完整代码
#ifndef _SNAKE_H_
#define _SNAKE_H_
#include
#include
#include
#include
#include
#define MAX 500 //蛇身个数
#define ROW 20  
#define LINE 20
typedef struct Body
{
        int x;
        int y;
}body;
void MapPrint(char arr[][LINE], int count);//地图打印
void Move(int *row, int *line, char *move);//蛇头移动函数,通过读取输入的键盘方向键来改变蛇头方向
void GetCoordinate(int *row, int *line, char *move);//蛇头自动移动,通过获取的方向信息,决定蛇头往哪个方向自动移
void food(char arr[][LINE], int *x, int *y);//随机生成一个食物
void JudgeFood(int food_x, int food_y, int row, int line, int *count);//判断是否吃到食物
void GetBody(char arr[][LINE], body body[], int count, int temp_x, int temp_y);//蛇体坐标更新
int  Judge(char arr[][LINE], int row, int line);//判断是否撞墙
void Game();
#endif

#include "snake.h"
void gotoxy(int x, int y)//将光标移动到(x,y)位置
{
        HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
        COORD pos;
        pos.X = x;
        pos.Y = y;
        SetConsoleCursorPosition(handle, pos);
}
void MapPrint(char arr[][LINE],int count)
{       
        gotoxy(0, 0);
        for (int i = 0; i  ROW; i++)
        {
                for (int j = 0; j  LINE; j++)
                {
                        //第一行,最后一行,第一列,最后一列都是墙壁
                        if (arr[j]==1)
                                printf("■");
                        else if (arr[j] == 2)
                                printf("⊙");//蛇头
                        else if (arr[j] == 3)
                                printf("¤");//打印食物¤
                        else if (arr[j] == 4)
                                printf("●");//打印身体●
                        else
                                printf("  ");//一个墙体占两个空格
                }
                printf("\n");
        }
        printf("                                \n");
        printf("             当前得分:%d\n", count);
        printf("                                \n");
}
void Move(int *row, int *line,char *move)//蛇头移动函数,通过读取输入的键盘方向键来改变蛇头方向
{
                if (GetAsyncKeyState(VK_UP))//上
                {
                        *move = 'w';
                }
                else if (GetAsyncKeyState(VK_DOWN))//下
                {
                        *move = 's';
                }
                else if (GetAsyncKeyState(VK_LEFT))//左
                {
                        *move = 'a';
                }
                else if (GetAsyncKeyState(VK_RIGHT))//右
                {
                        *move = 'd';
                }
                GetCoordinate(row, line, move);//将获得的方向键信息传输过去
}
void GetCoordinate(int *row, int *line, char *move)//蛇头自动移动,通过获取的方向信息,决定蛇头往哪个方向自动移
{
        if (*move == 'w')
                (*row)--;
        else if (*move == 's')
                (*row)++;
        else if (*move == 'a')
                (*line)--;
        else if (*move == 'd')
                (*line)++;
}
void food(char arr[][LINE],int *x,int *y)//随机生成一个食物
{
        int flag = 0;
        for (int i = 0; i  ROW; i++)
        {
                for (int j = 0; j  ROW; j++)
                {
                        if (arr[j] == 3)//食物为3
                                flag = 1;
                }
        }
        if (!flag)//没有食物就生成食物
        {
                //食物不能在边框上
                *x = rand() % (ROW-2)+1;
                *y = rand() % (LINE-2)+1;
        }
}
void JudgeFood(int food_x,int food_y,int row,int line,int *count)//判断是否吃到食物
{
        if (food_x == row&&food_y == line)//吃到食物
        {
                (*count)++;//吃到食物身体个数+1
        }
}
void GetBody(char arr[][LINE], body body[], int count, int temp_x, int temp_y)//蛇体坐标更新
{
        //保留前一个蛇体的坐标
        int befor_x = 0;
        int befor_y = 0;
        if (count > 0)//最少有一个蛇身
        {
                //记录下最后一个蛇身的位置
                befor_x = body[count - 1].x;
                befor_y = body[count - 1].y;
        }
       
       
        int keep = count;//保存一份蛇体个数
        while (count)//蛇体坐标覆盖,后面的覆盖前面的
        {
                if (count == 1)//只有一个蛇体时,为原来蛇头位置
                {
                        body[count - 1].x = temp_x;
                        body[count - 1].y = temp_y;
                }
                else
                {
                        body[count - 1].x = body[count - 2].x;
                        body[count - 1].y = body[count - 2].y;
                }
                count--;
        }
        while (keep)//将对应的蛇体坐标赋值
        {
                arr[body[keep-1].x][body[keep-1].y] = 4;
                keep--;
        }
        if (befor_x!=0)//最后一个蛇身的上一次所在位置清空
        {
                arr[befor_x][befor_y] = 0;
        }
       
}
int  Judge(char arr[][LINE],int row,int line)//判断是否撞墙
{
        if (arr[row][line] == 1)
        {
                printf("         --------------\n");
                printf("        |   撞到墙壁   |\n");
                printf("        |   游戏结束   |\n");
                printf("         --------------\n");
                system("pause");
                return 0;
        }
        return 1;
}
void Game()
{
        char arr[ROW][LINE]=
        {
                { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ,1 },
                { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
                { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
                { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
                { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
                { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
                { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
                { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
                { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
                { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
                { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
                { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
                { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
                { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
                { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
                { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
                { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
                { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
                { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
                { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
        };//地图
        int row = 10, line = 10;//蛇头起始位置
        arr[row][10] = 2;
        char move = 'w';//蛇头开始往上移动
        int food_x = 0, food_y = 0;//食物的x,y坐标
        srand((unsigned)time(NULL));//随机数种子
        //保留一份蛇头移动前坐标
        int temp_x = row;
        int temp_y = line;
        int count = 0;//蛇身体个数
        body body[MAX] = { 0 };//蛇身坐标记录结构体数组
        while (1)
        {       
                //生成食物
                food(arr, &food_x, &food_y);
                arr[food_x][food_y] = 3;
                MapPrint(arr,count);//打印图形
                if (count==0)
                arr[row][line] = 0;//没有身体的时候,蛇头原来位置变为空白
               
                //保留蛇头移动前的位置
                temp_x = row;
                temp_y = line;
                Move(&row, &line,&move);//蛇头移动
                if (Judge(arr, line, row) == 0)//判断是否撞墙
                {
                        break;
                }
                JudgeFood(food_x,food_y,row, line, &count);//判断是否吃到食物
                GetBody(arr, body, count, temp_x, temp_y);//蛇身构造
                arr[row][line] = 2;//新位置变成蛇头
                Sleep(200);//通过控制休眠时间来控制蛇头移动速度
        }
}

#include "snake.h"
int main()
{
       
        Game();
        printf("游戏结束\n");
        system("pause");
        return 0;
}
回复

使用道具 举报

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

本版积分规则

QQ|无图版|手机版|小黑屋|兰州@IT精英团

GMT+8, 2021-4-14 18:40 , Processed in 0.082316 second(s), 25 queries .

Powered by Discuz! X3.4

Copyright © 2021, Tencent Cloud.

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