自顶向下设计C语言贪吃蛇

来源:互联网 发布:电子琴入门软件 编辑:程序博客网 时间:2024/05/21 10:46

本篇博客适于c语言界的小白,大神请移步~~~
关于自顶向下,之前写的一篇博客TOP-DOWN里面有记录一丢丢。
言归正传,自顶向下设计的思路就是break down

设计思路

相信大家都有玩过贪吃蛇的游戏,贪吃蛇可分解为以下部分:
1、框架、蛇的表示
2、将图形输出
3、移动蛇的位置
4、食物的出现与消失(被吃)
5、撞墙over
下面开始逐个击破。

start

1、框架、蛇的表示
因为蛇、食物都在框架里面,那么单纯c语言输出,必须是将其全部囊括在一个字符数组里面,即char screen[15][15], 表示15*15的框架。
然后需要明白的一点就是:移动的过程其实只是蛇尾与蛇头的移动
用面向对象的方法,蛇头(head)、蛇尾(tail)的属性为x,y坐标,移动方向。将它们的信息储存在结构体turn中

typedef struct T{    int x;    int y;    char dir;}turn;turn tail, head;

将框架与蛇初始化:

void initial(char(*Screen)[15])//初始化输出数组{    for (i = 0; i < 15; i++)    {        for (j = 0; j < 15; j++)        {            if (i == 0 || j == 0 || j == 14 || i == 14)                Screen[i][j] = '#';            else                Screen[i][j] = ' ';        }    }    Screen[1][1] = '*';//*表示尾巴    Screen[1][2] = Screen[1][3] = 'O';//O表示身体    Screen[1][4] = '@';//@表示头    tail.x = 1;    tail.y = 1;    tail.dir = 'd';    head.x = 1;    head.y = 4;    head.dir = 'd';}

2、输出看看

out (screen);void out(char(*SCREEN)[15]){    for (i = 0; i < 15; i++)    {        for (j = 0; j < 15; j++)        {            printf("%c", SCREEN[i][j]);        }        printf("\n");    }}

如图 这里写图片描述
3、移动蛇的位置
蛇分为两种行进,前进与转弯,这里的转弯包括蛇尾与蛇头的转弯。
(1)前进

void move(turn *Tail, turn *Head){    screen[Tail->x][Tail->y] = ' ';    switch (Tail->dir)//尾巴向着蛇尾的方向前进    {    case 'd'://s/S、d/D、w/W、a/A分别表示下、右、上、左    case 'D':        Tail->y++;        break;    case 'a':    case 'A':        Tail->y--;        break;    case 'w':    case 'W':        Tail->x--;        break;    case 's':    case 'S':        Tail->x++;        break;    default:        break;    }    screen[Tail->x][Tail->y] = '*';    screen[Head->x][Head->y] = 'O';    switch (Head->dir)//头向着头的方向前进    {    case 'd':    case 'D':        Head->y++;        break;    case 'a':    case 'A':        Head->y--;        break;    case 'w':    case 'W':        Head->x--;        break;    case 's':    case 'S':        Head->x++;    default:        break;    }    screen[Head->x][Head->y] = '@';}

(2)转弯
蛇头的转弯比较容易,输入方向,改变head.dir就可以了。
如下

if (_kbhit())//判断是否有输入方向        {            change = getchar();//记录方向            head.dir = change;//头部方向变为所记录的方向            Ticks();//Tick是函数,作用下面解释        }        Free();//Free是函数,作用下面解释

那么蛇尾就尴尬了,当前输入的方向并不能改变tail.dir。
那怎么办呢??
首先我们知道,蛇尾运行到某些位置会转弯,那么把那些位置记下来,看看蛇尾是否在那个位置即可。
记下位置属性:

turn ticks[14];int times=0;//记录位置数量void Ticks()//增加位置{    ticks[times] = head;//增加的位置恰好就蛇头的位置    times++;}void Free()//减少位置{    int n;    if (screen[ticks[0].x][ticks[0].y] == '*')    {        tail.dir = ticks[0].dir;        for (n = 0; n < times; n++)        {            ticks[n] = ticks[n + 1];//第一个位置要删除,将后面的位置信息给前一个        }        times--;    }}

4、食物的出现与消失
首先明白:屏幕上始终只有一个食物,一个食物的消失伴随另一个食物的出现。
那么,就让它消失吧!

int food[2]={1,4};//初始化食物的位置刚好在蛇头void eat(){    srand(time(NULL));    if (head.x == food[0] && head.y == food[1])    //蛇头坐标与食物坐标相同,就被吃掉    {        screen[head.x][head.y] = 'O';//食物位置变成身体的一节        switch (head.dir)//蛇头位置向前        {        case 'd':        case 'D':            head.y++;            break;        case 'a':        case 'A':            head.y--;            break;        case 'w':        case 'W':            head.x--;            break;        case 's':        case 'S':            head.x++;        default:            break;        }        screen[head.x][head.y] = '@';重新制造蛇头        while (screen[food[0]][food[1]] != ' ')        {//制造食物,随机食物坐标不在蛇身            food[0] = rand() % 13 + 1;//坐标范围1~13            food[1] = rand() % 13 + 1;        }        screen[food[0]][food[1]] = '$';//$是食物    }}

5、撞墙over
肯定是头撞墙。

if (head.x == 0 || head.y == 14 || head.x == 14 || head.y == 0)        {            printf("game over");            break;//这里是跳出主循环        }

主函数完整代码,其中有些部分已在前面出现

int main(){    char change;    initial(screen);    out(screen);    eat();    while (1)    {        if (_kbhit())        {            change = getchar();            head.dir = change;            Ticks();        }        Free();        move(&tail, &head);        eat();        system("cls");//清屏        out(screen);        if (head.x == 0 || head.y == 14 || head.x == 14 || head.y == 0)        {            break;        }        Sleep(500);//延时500毫秒    }    system("cls");    printf("\n    game over!\n");    system("pause");    return 0;}

将主函数与辅助函数整合在一起,如下

#include <stdio.h>#include <stdlib.h>#include<string.h>#include<time.h>#include<conio.h>#include<Windows.h>char screen[15][15];int i, j, times=0, food[2] = { 1,4 };typedef struct T{    int x;    int y;    char dir;}turn;turn ticks[14], tail, head;void initial(char(*Screen)[15])//初始化输出数组{    for (i = 0; i < 15; i++)    {        for (j = 0; j < 15; j++)        {            if (i == 0 || j == 0 || j == 14 || i == 14)                Screen[i][j] = '#';            else                Screen[i][j] = ' ';        }    }    Screen[1][1] = '*';    Screen[1][2] = Screen[1][3] = 'O';    Screen[1][4] = '@';    for (i = 0; i < 14; i++)    {        ticks[i].x = 0;        ticks[i].y = 0;    }    tail.x = 1;    tail.y = 1;    tail.dir = 'd';    head.x = 1;    head.y = 4;    head.dir = 'd';}void out(char(*SCREEN)[15]){    for (i = 0; i < 15; i++)    {        for (j = 0; j < 15; j++)        {            printf("%c", SCREEN[i][j]);        }        printf("\n");    }}void move(turn *Tail, turn *Head){    screen[Tail->x][Tail->y] = ' ';    switch (Tail->dir)    {    case 'd':    case 'D':        Tail->y++;        break;    case 'a':    case 'A':        Tail->y--;        break;    case 'w':    case 'W':        Tail->x--;        break;    case 's':    case 'S':        Tail->x++;        break;    default:        break;    }    screen[Tail->x][Tail->y] = '*';    screen[Head->x][Head->y] = 'O';    switch (Head->dir)    {    case 'd':    case 'D':        Head->y++;        break;    case 'a':    case 'A':        Head->y--;        break;    case 'w':    case 'W':        Head->x--;        break;    case 's':    case 'S':        Head->x++;    default:        break;    }    screen[Head->x][Head->y] = '@';}void eat(){    srand(time(NULL));    if (head.x == food[0] && head.y == food[1])    {        screen[head.x][head.y] = 'O';        switch (head.dir)        {        case 'd':        case 'D':            head.y++;            break;        case 'a':        case 'A':            head.y--;            break;        case 'w':        case 'W':            head.x--;            break;        case 's':        case 'S':            head.x++;        default:            break;        }        screen[head.x][head.y] = '@';        while (screen[food[0]][food[1]] != ' ')        {            food[0] = rand() % 13 + 1;            food[1] = rand() % 13 + 1;        }        screen[food[0]][food[1]] = '$';    }}void Ticks(){    ticks[times] = head;    times++;}void Free(){    int n;    if (screen[ticks[0].x][ticks[0].y] == '*')    {        tail.dir = ticks[0].dir;        for (n = 0; n < times; n++)        {            ticks[n] = ticks[n + 1];        }        times--;    }}int main(){    char change;    initial(screen);    out(screen);    eat();    while (1)    {        if (_kbhit())        {            change = getchar();            head.dir = change;            Ticks();        }        Free();        move(&tail, &head);        eat();        system("cls");        out(screen);        if (head.x == 0 || head.y == 14 || head.x == 14 || head.y == 0)        {            break;        }        Sleep(500);    }    system("cls");    printf("\n    game over!\n");    system("pause");    return 0;}
原创粉丝点击