简易贪吃蛇游戏设计(字符化)

emmm……这篇主要是介绍一个小小的用代码做出来的贪吃蛇,这对于一个新手的我来说可是费了好大一股劲,其实对于贪吃蛇来说,它本身的特性就决定了它适合用链表来做,emmm……但我不会,所以对于新手的我,我用了一种相似的方法,通过记录蛇的每一个身体点的坐标来操作蛇的移动。以下,我会用源代码的形式简单介绍。
首先,我们需要构造整个图形的边框架构,所以我们要构造如下的二维数组

char map[12][12]=
     {"***********",
      "*xxxxH    *",
      "*         *",
      "*         *",
      "*         *",
      "*         *",
      "*         *",
      "*         *",
      "*         *",
      "*         *",
      "*         *",
      "***********"};//initialize the picture

我们还需要考虑随机放置蛇的食物,这里要用到rand()函数以下展示代码

void put_money(void)//put the money randomly
{
    int x=0,y=0; 
    srand((unsigned int)time(0));
    while(map[x][y]=='*'||map[x][y]==snake_body||map[x][y]==snake_head)
    {
        x = rand()%10 + 1;
        y = rand()%10 + 1;
    }
    map[x][y] = '$';
}

然后我们需要描每个蛇的身体的坐标,定义为snake_x,snake_y,分别为一数组

int snake_x[max_length]={1,2,3,4,5};
int snake_y[max_length]={1,1,1,1,1};

当然,我们打好了整个字符边框之后还要懂得将它们输出

void output(void)// output the picture
{
    int i =0;
    while(i<12)
    {
        printf("%s\n",map[i]);
        i++;
    }
}

然后以下便是重头戏,也就是贪吃蛇的重点(贪吃蛇的移动):
首先判断贪吃蛇不会撞到墙的情况,我们有‘w’‘s’‘a’‘d’四个键来判断贪吃蛇的运动,思考,我们如果按了’s’键,那么蛇头会和它下方的空格交换位置,然后每一个都与它前面的交换位置,那么我们先定义蛇头的移动,

    switch (c) //move the snake head
            {
                case 'w': snakeHeadMove(0,-1); break;
                case 's': snakeHeadMove(0,1); break;
                case 'a': snakeHeadMove(-1,0); break;
                case 'd': snakeHeadMove(1,0); break;
            }
void snakeHeadMove(int m,int n)// move the snake head
{
    snake_x[snake_length]=snake_x[snake_length-1]+m;
    snake_y[snake_length]=snake_y[snake_length-1]+n;
}

上述的snake_length是蛇头将要移动的下一个的方向,而snake_length-1就是现在蛇头的坐标,然后将蛇头的坐标一个一个往前推:

void snakemove(void)//move the snake
{
    int i,j;
    char ins;
    for(i=snake_length;i > 0;i--)
        {
            ins=map[snake_y[i]][snake_x[i]];
            map[snake_y[i]][snake_x[i]]=map[snake_y[i-1]][snake_x[i-1]];
            map[snake_y[i-1]][snake_x[i-1]]=ins;//move
        }
        for(j=0;j<=snake_length;j++)//change the ordinate of snake 
        {
            snake_x[j]=snake_x[j+1];
            snake_y[j]=snake_y[j+1];
        }
        snake_x[snake_length]=0;
        snake_y[snake_length]=0;
}

上述由于我们将数组的长度调到了snake_length+1,因为蛇头和前面的坐标置换了,所以我们要将所有的坐标前移并将最后的蛇头前一个坐标,也就是snake_length设置(0,0)
我们已经考虑了蛇的移动,然后我们需要考虑蛇是否会撞墙,也就是如果简单地走动,蛇才执行上述的操作,但是吃到东西后,或撞墙,我们也要考虑。
首先,考虑撞墙,刚刚我们移动是让蛇头先和它要移动的方向的空格交换位置,所以移动,现在,我们采用类似的方法,首先,将蛇头的下一个位置标出来,如果它是墙的字符然后就结束死掉
然后,我们考虑吃掉食物的情况,当蛇头将要移动的位置坐标为食物,将其改为蛇的身体,然后与蛇头交换位置,同时蛇的长度加一,蛇的坐标增加一个食物的坐标的位置,然后重新放置食物

int gameover(void)
{
    int i,j,mid;
    char ins;
    if(map[snake_y[snake_length]][snake_x[snake_length]]==snake_body||map[snake_y[snake_length]][snake_x[snake_length]]=='*')
        return 1;//return 1 if snake is dead
    else if(map[snake_y[snake_length]][snake_x[snake_length]]=='$')//eat the money
        {
            mid = snake_length;
            map[snake_y[mid]][snake_x[mid]] = snake_body;//put 'x' in the front of head
            ins = map[snake_y[mid-1]][snake_x[mid-1]];
            map[snake_y[mid-1]][snake_x[mid-1]] = map[snake_y[mid]][snake_x[mid]];
            map[snake_y[mid]][snake_x[mid]] = ins;//change the position of snakehead and 'x'
            snake_length++;//the length of snake add 1
            put_money();//put money
            output();
            return 0;
        }
    else 
        {
            snakemove();// move the snake
            output();
            return 0;
        }
}

以下是整个的源代码:

/*WHILE not ÓÎÏ·½áÊø DO
        ch£½µÈ´ýÊäÈë
        CASE ch DO
        ¡®A¡¯:×óÇ°½øÒ»²½£¬break
        ¡®D¡¯:ÓÒÇ°½øÒ»²½£¬break
        ¡®W¡¯:ÉÏÇ°½øÒ»²½£¬break
        ¡®S¡¯:ÏÂÇ°½øÒ»²½£¬break
        END CASE
        If
          Ç°½øÒ»²½ = *
          Êä³ö Game Over!!!
          END WHILE
          Ç°½øÒ»²½ = ÉíÌå
          Êä³ö Game Over!!!
          END WHILE
        Else   
        Êä³ö×Ö·û¾ØÕó
END WHILE
Êä³ö Game Over!!!
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h>
#define max_length 50
#define snake_body 'x'
#define snake_head 'H'
void output(void);
void put_money(void);
void snakeHeadMove(int m,int n);
int gameover(void);
void snakemove(void);
char map[12][12]=
     {"***********",
      "*xxxxH    *",
      "*         *",
      "*         *",
      "*         *",
      "*         *",
      "*         *",
      "*         *",
      "*         *",
      "*         *",
      "*         *",
      "***********"};//initialize the picture
int snake_length=5;
int snake_x[max_length]={1,2,3,4,5};
int snake_y[max_length]={1,1,1,1,1};
int main()
{
    int i=0;
    char input,c;
    put_money();
    output();//output the picture
    while(!input)
    {
        c = getch();//read the botton
        switch (c) //move the snake head
            {
                case 'w': snakeHeadMove(0,-1); break;
                case 's': snakeHeadMove(0,1); break;
                case 'a': snakeHeadMove(-1,0); break;
                case 'd': snakeHeadMove(1,0); break;
            }
        input = gameover();
        if(input)
        break;
        /*if(gameover()) break;//judge if game is over
        while(getchar() != '\n')//cancel the '\n' when to entry the botton 
            break;*/    
    }
    printf("Game over!!!");
}
void output(void)// output the picture
{
        #ifdef _WIN32
    system("cls");
    #else
    system("clear");
    #endif
    int i =0;
    while(i<12)
    {
        printf("%s\n",map[i]);
        i++;
    }
}
void put_money(void)//put the money randomly
{
    int x=0,y=0; 
    srand((unsigned int)time(0));
    while(map[x][y]=='*'||map[x][y]==snake_body||map[x][y]==snake_head)
    {
        x = rand()%10 + 1;
        y = rand()%10 + 1;
    }
    map[x][y] = '$';
}

void snakeHeadMove(int m,int n)// move the snake head
{
    snake_x[snake_length]=snake_x[snake_length-1]+m;
    snake_y[snake_length]=snake_y[snake_length-1]+n;
}

int gameover(void)
{
    int i,j,mid;
    char ins;
    if(map[snake_y[snake_length]][snake_x[snake_length]]==snake_body||map[snake_y[snake_length]][snake_x[snake_length]]=='*')
        return 1;//return 1 if snake is dead
    else if(map[snake_y[snake_length]][snake_x[snake_length]]=='$')//eat the money
        {
            mid = snake_length;
            map[snake_y[mid]][snake_x[mid]] = snake_body;//put 'x' in the front of head
            ins = map[snake_y[mid-1]][snake_x[mid-1]];
            map[snake_y[mid-1]][snake_x[mid-1]] = map[snake_y[mid]][snake_x[mid]];
            map[snake_y[mid]][snake_x[mid]] = ins;//change the position of snakehead and 'x'
            snake_length++;//the length of snake add 1
            put_money();//put money
            output();
            return 0;
        }
    else 
        {
            snakemove();// move the snake
            output();
            return 0;
        }
}

void snakemove(void)//move the snake
{
    int i,j;
    char ins;
    for(i=snake_length;i > 0;i--)
        {
            ins=map[snake_y[i]][snake_x[i]];
            map[snake_y[i]][snake_x[i]]=map[snake_y[i-1]][snake_x[i-1]];
            map[snake_y[i-1]][snake_x[i-1]]=ins;//move
        }
        for(j=0;j<=snake_length;j++)//change the ordinate of snake 
        {
            snake_x[j]=snake_x[j+1];
            snake_y[j]=snake_y[j+1];
        }
        snake_x[snake_length]=0;
        snake_y[snake_length]=0;
}

上述的操作由于一直按回车比较麻烦所以我用了getch()函数,它内置在conio.h头文件,但它不在标准库,如果不嫌麻烦也可用:

while(!input)
    {
        c = getchar();//read the botton
        switch (c) //move the snake head
            {
                case 'w': snakeHeadMove(0,-1); break;
                case 's': snakeHeadMove(0,1); break;
                case 'a': snakeHeadMove(-1,0); break;
                case 'd': snakeHeadMove(1,0); break;
            }
        input = gameover();
        if(input) break;//judge if game is over
        while(getchar() != '\n')//cancel the '\n' when to entry the botton 
            break;  
    }

然后我用了清屏的system,也可不用,可以去掉那4行代码,就是会不停的输出
emmm……上述就是我差不多的学做贪吃蛇的一些小小的小经验,也就是自顶向下了,但愿对想做的人有些帮助。
这里写图片描述
如果想创新可以试试放置不同的食物,然后这些食物会对贪吃蛇有加速、变长几秒、头身分离、放置围墙等等,还可以让蛇迟到自己不会死,而是减短长度,当然,有条件和能力的同学可以试试。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值