智能蛇的学习记录

步骤

1、创建开始的蛇与框架;
用二维的字符数组构成基本的框架,并指明蛇开始的状态。

char map[12][12]=
{"************",
 "*XXXXH     *",
 "*          *",
 "*          *",
 "*          *",
 "*          *",
 "*          *",
 "*          *",
 "*          *",
 "*          *",
 "*          *",
 "************"
};
int direct=4;
int snakelength=5;
int snakeX[100]={1,2,3,4,5};
int snakeY[100]={1,1,1,1,1};

2、构建一些函数使其完成行进、转弯等动作

void snake_move(int,int);//根据方向移动一次

3、每移动一次后,判断其状态,下一步可以往哪些方向移动,根据移动后距离食物的远近来判断往哪个方向移动,以获得最近的吃到食物的路径。

void calculate(void);//找到下一步方向
int distance(int);//计算通过一个方向的运动后距离食物的距离
void check(void);//找到哪些方向可以运动

4、食物被吃掉后,在空白位置随机生成

void make_food(void);//随机生成一个食物

5、判断是否结束,咬到自己或是撞到框架即死亡,游戏结束。

代码

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

const int width = 12;
const int high = 12;
const int LENGTH_MAX = 100;
#define SNAKE_HEAD 'H'
#define SNAKE_BODY 'X'
#define BLANK_CELL ' '
#define SNAKE_FOOD '$'
#define WALL_CELL '*'

char map[12][12]=
{"************",
 "*XXXXH     *",
 "*          *",
 "*          *",
 "*          *",
 "*          *",
 "*          *",
 "*          *",
 "*          *",
 "*          *",
 "*          *",
 "************"
};
void snake_move(int,int);//根据方向移动一次
void make_food(void);//随机生成一个食物
void make_map(void);//根据坐标得到图案的形状
void output(void);//输出图案
void gameover(void);//游戏结束
void calculate(void);//找到下一步方向
int ifBump(void);//判断蛇是否死亡
int ifReprat(int ,int );//判断食物的坐标是否与蛇的位置重复
int distance(int);//计算通过一个方向的运动后距离食物的距离
void check(void);//找到哪些方向可以运动

char key;//输入的值
int direct=4;//记录方向,给定初始方向
int snakelength=5;//记录蛇的长度
int snakeX[100]={1,2,3,4,5};//组成蛇的各字符的横坐标
int snakeY[100]={1,1,1,1,1};//组成蛇的各字符的纵坐标
int food[2]={5,6};//食物的坐标
int movable[4] = { 0, 1, 0, 1 };//记录各方向是否可运动

int main(){
    output();
    while(1){
        calculate();
        system("cls");//清屏
        Sleep(30);
        snake_move(snakelength,direct);
        if((food[0]==0)&&(food[1]==0))
            make_food();
        make_map();
        output();
        if(ifBump()){
            gameover();
            break;
        }
        check();
    }
    getchar();
    return 0;
}
void output(void){//根据数组输出将图案打印出来
    int i,j;
    for(i=0;i<high;++i){
        for(j=0;j<width;++j){
            printf("%c",map[i][j]);
        }
        putchar('\n');
    }
}
void make_map(void){//根据数组得到图案字符数组
    int i,j;
    for(i=0;i<width;++i){
        for(j=0;j<high;++j){
            if((i==0)||(j==0)||(i==width-1)||(j==high-1))
                map[i][j]=WALL_CELL;
            else
                map[i][j]=BLANK_CELL;
        }
    }
    for(i=0;i<snakelength-1;++i){
        map[snakeY[i]][snakeX[i]]=SNAKE_BODY;
    }
    int x=snakeY[snakelength-1],y=snakeX[snakelength-1];
    map[x][y]=SNAKE_HEAD;
    map[food[1]][food[0]]=SNAKE_FOOD;
}
void make_food(void){
    srand(time(0));
    int x = rand() % 10 + 1, y = rand() % 10 + 1;//生成一个1-11的数作为横坐标,1-11的数作为纵坐标
    while (ifReprat(x,y)) {//如果有重复就重新生成一个,直到不重复为止
        x = rand() % 10 + 1, y = rand() % 10 + 1;
    }
    food[0] = y;
    food[1] = x;
}
int ifReprat(int x,int y){//判断食物的坐标是否与蛇的位置重复
    int i;
    for(i=0;i<snakelength;++i){
        if((snakeX[i]==x)&&(snakeY[i]==y))
            return 0;
    }
    return 1;
}
void snake_move(int len,int dir){
    int x=snakeX[len-1],y=snakeY[len-1];//记住蛇头此时的坐标
    switch(dir){
        case 1://向上
                snakeY[len-1]--;//横坐标不变,纵坐标-1
                break;
        case 2://向下
                snakeY[len-1]++;//横坐标不变,纵坐标+1
                break;
        case 3://向左
                snakeX[len-1]--;//纵坐标不变,横坐标-1
                break;
        case 4://向右
                snakeX[len-1]++;//纵坐标不变,横坐标+1
                break;
    }
    if((snakeX[len-1]==food[0])&&(snakeY[len-1]==food[1])){
        snakeX[len]=snakeX[len-1];
        snakeY[len]=snakeY[len-1];
        snakeX[len-1]=x;
        snakeY[len-1]=y;
        food[0]=0;
        food[1]=0;
        snakelength++;
    }
    else{
        int j;
        for(j=0;j<len-2;j--){
            snakeX[j]=snakeX[j+1];
            snakeY[j]=snakeY[j+1];
        }
        snakeX[len-2]=x;
        snakeY[len-2]=y;
    }


}
void calculate(){//得到下一步运动的方向
    int i,j,n;
    for(i=0;i<4;++i){
        if((movable[i]==1)||(i<3))
            for(j=i+1;j<4;j++){
                if(movable[j]==1)
                    if(distance(i+1)>distance(j+1))
                        n=j;
                    else
                        n=i;
        }
    }
    direct=n;
}
int distance(int dir){//一次运动后的距离,根据其计算最优的方向
    switch(dir){
        case 1:
            return abs(snakeX[snakelength-1]-food[0])+abs(snakeY[snakelength-1]-1-food[1]);
        case 2:
            return abs(snakeX[snakelength-1]-food[0])+abs(snakeY[snakelength-1]+1-food[1]);
        case 3:
            return abs(snakeX[snakelength-1]-1-food[0])+abs(snakeY[snakelength-1]-food[1]);
        case 4:
            return abs(snakeX[snakelength-1]+1-food[0])+abs(snakeY[snakelength-1]-food[1]);
    }
}
void check(){//判断哪些方向可运动
    if((map[snakeX[snakelength-1]][snakeY[snakelength-1]-1]==WALL_CELL)||(map[snakeX[snakelength-1]][snakeY[snakelength-1]-1]==SNAKE_BODY))
        movable[0]=0;
    else
        movable[0]=1;
    if((map[snakeX[snakelength-1]][snakeY[snakelength-1]+1]==WALL_CELL)||(map[snakeX[snakelength-1]][snakeY[snakelength-1]+1]==SNAKE_BODY))
        movable[1]=0;
    else
        movable[1]=1;
    if((map[snakeX[snakelength-1]-1][snakeY[snakelength-1]]==WALL_CELL)||(map[snakeX[snakelength-1]-1][snakeY[snakelength-1]]==SNAKE_BODY))
        movable[2]=0;
    else
        movable[2]=1;
    if((map[snakeX[snakelength-1]+1][snakeY[snakelength-1]]==WALL_CELL)||(map[snakeX[snakelength-1]+1][snakeY[snakelength-1]]==SNAKE_BODY))
        movable[3]=0;
    else
        movable[3]=1;
}
int ifBump(){//判断蛇是否与框相撞或咬到自己而死亡
    int x=snakeX[snakelength-1],y=snakeY[snakelength-1];
    if((x==0)||(x==width-1)||(y==0)||(y==high-1))
        return 1;
    int i;
    for(i=0;i<snakelength-2;++i){
        if((x==snakeX[i])&&(y==snakeY[i]))
            return 1;
    }
    return 0;
}
void gameover(){//输出游戏结束
    printf("游戏结束!");
}

考虑较为粗略,是为学习的一点总结。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值