c语言之简单的贪吃蛇 -- 详解以及源代码

一. 前言

   小时候都玩过贪吃蛇这个经典的小游戏,在我们的普通手机里似乎都是必备的。它伴随着我们的童年,经历了好多好多时光。它带给我们了许多的乐趣。

   我做这个的目的其实想放松放松. 利用了几天的空闲时间做做.

   也是想尝试以前想过但未实现的一个小游戏.

二. 问题描述

   包含等级选择,暂停/继续和分数制。

三. 分析思路

   下面就来讲讲贪吃蛇的设计思路.

1.地图

   地图含简单, 利用char的二维数组, 将外围一圈设置为城墙, 我使用的是’#’代表墙.

2.食物的产生

   利用随机函数(rand())产生随机食物的坐标, 该坐标的值不能与墙重合, 不能与蛇身重合. 若重合的话, 重新找一对xy的值. 食物我这里用的是’O’表示.

3. 构造一条蛇

   使用另一个int类型的二维数组,为什么用int后面讲.用’Q’代表蛇脑袋, ‘a’代表蛇身体, 开始时, 初始化到某以位置上.

4.蛇的移动

   利用上下左右或者wasd空着蛇的走位. 以及当蛇每走一步就利用 system(“cls”)清屏, 重新打印, 模拟蛇的移动.

5. 游戏结束

   当蛇撞墙, 以及咬到自己的身体时候游戏结束.

四. 编程所需知识

1.二维数组
2.一些系统函数
3.随机函数

以上几点所需知识会的话, 完全也可以做出一个来.
可以先自己尝试一番~再继续往下看.

五. 代码具体分析

1.所需的基本的自定义函数,全局变量, 以及头文件

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

string.h : memset();函数
windows.h: gotoxy()函数(尽管这个是自定义的, 内部需要涉及到这个头文件)
stdlib.h: system();
conio.h: getch();
time.h: 随机函数的种子

# define de_lenth 5 //蛇初始长度
# define ROW_MAX 20//地图行
# define LINE_MAX 30//地图列

int Head_x = ROW_MAX/2, Head_y = LINE_MAX/2;//蛇的初始坐标
int Head_v = 5;//判断是否为头
int Tail_x = 0, Tail_y = 0;//蛇尾坐标
int count = 0;//计数
char direct = 'a';//蛇移动的方向
void gotoxy(int x, int y);//将光标定位到某一位置, 用于显示结果, 以及暂停是使用
void CreateMap(char map[ROW_MAX][LINE_MAX]);//创建地图
void TraverseMap(char map[ROW_MAX][LINE_MAX], int snake[ROW_MAX][LINE_MAX]);//输出地图以及蛇的全部
void CreateSnake(int snkae[ROW_MAX][LINE_MAX]);//构造蛇的初始位置
void run(char map[ROW_MAX][LINE_MAX], int snake[ROW_MAX][LINE_MAX]);//蛇的移动
int JudgeWall(void);//判断蛇是否撞墙
void CreateFood(char map[ROW_MAX][LINE_MAX], int snake[ROW_MAX][LINE_MAX]);//产生随机食物
void MoveTail(int snake[ROW_MAX][LINE_MAX]);//蛇尾部的移动
int EatFood(char map[ROW_MAX][LINE_MAX]);//蛇吃到食物的操作
void Result(void);//显示结果

2.主函数

int main()
{
    char map[ROW_MAX][LINE_MAX];
    int snake[ROW_MAX][LINE_MAX];
    srand(time(NULL));

/**************初始画面**************/
    memset(map, 0, sizeof(map));
    memset(snake, 0, sizeof(snake));
    system("cls");
    CreateMap(map); 
//  gotoxy(1, 1);
    CreateSnake(snake);
    CreateFood(map, snake);
    TraverseMap(map, snake);
/**************初始画面**************/

/*********运动*****************/
    run(map, snake);
/******************************/

    Result();

    return 0;
}

3. 创建地图

void CreateMap(char map[ROW_MAX][LINE_MAX]){
//将行为0和ROW_MAX的位置赋值为'#', 以及列为0和LINE_MAX赋值为'#', 表示墙;
    int i, j;   

    for(i = 0; i < ROW_MAX; ++i)
        map[i][0] = '#';
    for(j = 1; j < LINE_MAX; ++j)
        map[0][j] = '#';
    for(i = ROW_MAX-1, j = 1; j < LINE_MAX; ++j)
        map[i][j] = '#';
    for(j = LINE_MAX-1, i = 1; i < ROW_MAX; ++i)
        map[i][j] = '#';
}

3.构造一条蛇

void CreateSnake(int snake[ROW_MAX][LINE_MAX]){

    int i, j;
    int value = Head_v;
    snake[Head_x][Head_y] = value;

    for(i = Head_x, j = Head_y+1; j < Head_y + de_lenth; ++j)
        snake[i][j] = --value;
    Tail_x = i;
    Tail_y = --j;
}

解释: 蛇脑袋的值是最大的(初始为5), 蛇尾是最小的(初始为1), 这样写得目的是为了, 蛇移动时, 只需要移动蛇脑袋和蛇尾部即可, 蛇尾部移动规律就是找到比它大一的那个值. 所以我设置为Int类型.

4.产生随机食物

void CreateFood(char map[ROW_MAX][LINE_MAX], int snake[ROW_MAX][LINE_MAX]){

    int food_x = 0;
    int food_y = 0;

    while (map[food_x][food_y] == '#' || snake[food_x][food_y] != 0){

        food_x = rand()%(ROW_MAX-3) + 1;
        food_y = rand()%(LINE_MAX-3) + 1;
    }

    map[food_x][food_y] = 'O';
}

解释: 为什么是-3呢, 举个例子, 地图22x22/(0.0)-(21.21), 而实际区域是(1.1)-(20.20), 就要产生1-20的随机数, 也就是 0-19的随机数+1, 22-19 = 3, 所以减3.
食物不能与墙以及蛇身体重合.
食物放到地图的数组里.

5.输出地图以及蛇的全部

void TraverseMap(char map[ROW_MAX][LINE_MAX], int snake[ROW_MAX][LINE_MAX]){

    int i, j;

    for (i = 0; i < ROW_MAX; ++i){
        for (j = 0; j < LINE_MAX; ++j){
            if(snake[i][j] == 0)
                printf("%c", map[i][j]);
            else{
                if(snake[i][j] == Head_v)
                    putchar('Q');
                else
                    putchar('a');               
            }
        }
        putchar('\n');
    }
}

解释: 在输出地图的同时顾忌到蛇, 这样就能输出地图的同时输出蛇.

6.判断蛇是否撞墙

int JudgeWall(void){

    if((Head_x == 0 || Head_x == ROW_MAX-1) || (Head_y == 0 || Head_y == LINE_MAX-1))
        return 0;
    else 
        return 1;
}

解释: 如果撞墙则返回0 因为 后面用到的是 if(JudgeWall())

7. 蛇尾部的移动

void MoveTail(int snake[ROW_MAX][LINE_MAX]){

    if (snake[Tail_x][Tail_y]+1 == snake[Tail_x-1][Tail_y]){

        snake[Tail_x][Tail_y] = 0;
        Tail_x--;
    }
    else if (snake[Tail_x][Tail_y]+1 == snake[Tail_x+1][
评论 33
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值