学学写个智能蛇

来源:互联网 发布:照片大小调整软件 编辑:程序博客网 时间:2024/05/18 20:33

引言

我先放一张传说中的贪吃智能蛇
这里写图片描述

言归正传

首先,我写了个能够每秒自动走的蛇作为原型

#include<stdio.h>#include<conio.h>#include<string.h>#include<stdlib.h>#include<time.h>#define FOR(i,j,k) for(i=j;i<=k;++i)int d[1000][1000];char map[1000][1000] = { ' ' };int fx, fy, lx, ly;int len = 5;int diffcuilty;void pm();int n, m, w, h;//W 1 ;A 2 ;S 3 ;D 4void CreateTheBackground(int x, int y){    int i, j, k;    FOR(i, 1, w)        FOR(j, 1, h)    {        map[i][j] = ' '; d[i][j] = 0;    }    FOR(i, 1, 5) {        map[1][i] = '*';        d[1][i] = 1;    }    fx = 1; fy = 5;    map[1][5] = '%';    lx = ly = 1;    FOR(i, 0, h + 1) { map[0][i] = '#'; map[w + 1][i] = '#'; }    FOR(i, 0, w + 1) { map[i][0] = '#'; map[i][h + 1] = '#'; }    pm();}void pm(){    srand(time(NULL));    int i, j;    i = rand() % w + 1;    j = rand() % h + 1;    while (map[i][j] != ' ')    {        i = rand() % w + 1;        j = rand() % h + 1;    }    map[i][j] = '$';}int getinp()//W 1 ;A 2 ;S 3 ;D 4{    int dr = 0;    char c = 0;    int tle = 1;    int start = clock();    while (clock() - start <= diffcuilty * 50)    {        if (kbhit()) c = getch();        if (c != 0) { tle--; }        if (c == 'w') dr = 1;        if (c == 'a') dr = 2;        if (c == 's') dr = 3;        if (c == 'd') dr = 4;        if (clock() - start > diffcuilty * 50) return dr;    }    if (c == 'w') dr = 1;    if (c == 'a') dr = 2;    if (c == 's') dr = 3;    if (c == 'd') dr = 4;    return dr;}void pp(){    int i, j;    system("cls");    for (i = h + 1; i >= 0; --i)    {        FOR(j, 0, w + 1)            printf("%c", map[j][i]);        printf("\n");    }}void dead(){    int t;    printf("Failture with the score:%d\n", len);    printf("\n\n\nPress any key to exit.");    getchar();    exit(0);}void movement(int dr){    int tx, ty, t;    d[fx][fy] = dr;    int bj = 0;    map[fx][fy] = '*';    if (dr == 1) fy++;    if (dr == 2) fx--;    if (dr == 3) fy--;    if (dr == 4) fx++;    if (map[fx][fy] == '$') { bj = 1; }    if (map[fx][fy] == '*' || map[fx][fy] == '#') { dead(); return; }    map[fx][fy] = '%';    if (bj) {        pm();        len++;        return;    }    t = d[lx][ly];    map[lx][ly] = ' ';    if (t == 1) ly++;    if (t == 2) lx--;    if (t == 3) ly--;    if (t == 4) lx++;}int u = 1;void done()//W 1 ;A 2 ;S 3 ;D 4{    int d = getinp();    if (d != 0) u = d;    movement(u);    pp();}int main(){BACK:    printf("Firstly, please input the width and height of the area:\n(The width and height are recommanded more than 5)\n");ERROR:    scanf("%d%d", &w, &h);    if (w <= 5 || h <= 5) {        printf("Input illegal,please input again\n");        goto ERROR;    }ERROR2:    printf("Please choose a diffcuilty of this game:\nThe diffcuilty from easy to diffcuilt show 1~16\n");    scanf("%d", &diffcuilty);    if (!(diffcuilty >= 1 && diffcuilty <= 16)) {        printf("Input illegal,please input again\n");        goto ERROR2;    }    diffcuilty = 17 - diffcuilty;    printf("\n");    system("cls");    CreateTheBackground(w, h);    pp();    system("pause");    int d = 1;    while (1)    {        done();    }    return 0;}

然后写了第一次作业

#include<stdio.h>#include<time.h>#define FOR(i,j,k) for(i=j;i<=k;++i)#define SNAKE_MAX_LENGTH 20#define SNAKE_HEAD 'H'#define SNAKE_BODY 'X'#define BLANK_CELL ' '#define SNAKE_FOOD '$'#define WALL_CELL '*'int life = 1;int snakey[100] = { 5,4,3,2,1 };int snakex[100] = { 1,1,1,1,1 };int d[1000][1000];char map[12][12] = { "************",//da biao"*XXXXH     *","* ******** *","*          *","*   ****   *","*   ****   *","*   ****   *","*          *","* ******** *","*          *","************" };int fx, fy, lx, ly;int len = 5;int diffcuilty;void pm();int n, m, w, h;//W 1 ;A 2 ;S 3 ;D 4void CreateTheBackground(){    int i, j, k;    w = 10; h = 10;    FOR(i, 1, w)        FOR(j, 1, h)    {        if (map[i][j] != '*') {            map[i][j] = ' ';            d[i][j] = 0;        }    }    FOR(i, 1, 4) {        map[i][10] = 'X';        d[i][10] = 4;    }    fx = 5; fy = 10;    d[5][10] = 4;    map[5][10] = 'H';    lx = 1; ly = 10;    FOR(i, 0, h + 1) { map[0][i] = '*'; map[w + 1][i] = '*'; }    FOR(i, 0, w + 1) { map[i][0] = '*'; map[i][h + 1] = '*'; }    pm();}void pm(){    srand(time(NULL));    int i, j;    i = rand() % w + 1;    j = rand() % h + 1;    while (map[i][j] != ' ')    {        i = rand() % w + 1;        j = rand() % h + 1;    }    map[i][j] = '$';}int getinp()//W 1 ;A 2 ;S 3 ;D 4{    char c;    int dr = 0;    c = getch();    if (c == 'W') dr = 1;    if (c == 'A') dr = 2;    if (c == 'S') dr = 3;    if (c == 'D') dr = 4;    return dr;}void pp(){    int i, j;    for (i = h + 1; i >= 0; --i)    {        FOR(j, 0, w + 1)            printf("%c", map[j][i]);        printf("\n");    }}void dead(){    int t;    printf("Game Over!!!");    //getchar();}void movement(int dr){    int tx, ty, t;    d[fx][fy] = dr;    int bj = 0;    map[fx][fy] = 'X';    if (dr == 1) fy++;    if (dr == 2) fx--;    if (dr == 3) fy--;    if (dr == 4) fx++;    if (map[fx][fy] == '$') { bj = 1; }    if (map[fx][fy] == 'X' || map[fx][fy] == '*') { life = 0; return; }    map[fx][fy] = 'H';    if (bj) {        pm();//fang zhi jian qian        len++;        return;    }    t = d[lx][ly];    map[lx][ly] = ' ';    if (t == 1) ly++;    if (t == 2) lx--;    if (t == 3) ly--;    if (t == 4) lx++;}int u = 1;void done()//W 1 ;A 2 ;S 3 ;D 4{    int d = getinp();    if (d != 0) u = d;    movement(u);    pp();}int main(){    CreateTheBackground();//chuang jian bei jing     pp();//shu chu    int ch;    while (life)    {        ch = getinp();//shu ru        switch (ch)//gen ju shu ru de fang xiang yi dong        {        case 1:movement(1); break;        case 2:movement(2); break;        case 3:movement(3); break;        case 4:movement(4); break;        }        if (life) pp();    }    dead();//shu chu si wang     return 0;}

智能蛇的实现其实只需要写出一个函数替代getinp()函数并每秒执行一次即可

下面着重讲下搜索策略
方案1.0
在一个矩形中,每一时刻有一个食物,贪吃蛇要在不撞到自己的条件下,
找到一条路(未必要最优),然后沿着这条路运行,去享用它的美食

显然这个仅仅一个bfs即可实现,此蛇很容易被自己直接绕住

方法2.0
一开始,蛇很短(初始化长度为1),它看到了一个食物, 使用BFS得到矩形中每个位置到达食物的最短路径长度。在没有蛇身阻挡下, 就是曼哈顿距离。然后,我要先判断一下,贪吃蛇这一去是否安全。 所以我需要一条虚拟的蛇,它每次负责去探路。如果安全,才让真正的蛇去跑。 当然,虚拟的蛇是不会绘制出来的,它只负责模拟探路。那么, 怎么定义一个布局是安全的呢? 如果你把文章开头那张动态图片中蛇的销魂走位好好的看一下, 会发现即使到最后蛇身已经很长了,它仍然没事一般地走出了一条路。而且, 是跟着蛇尾走的!嗯,这个其实不难解释,蛇在运动的过程中,消耗蛇身, 蛇尾后面总是不断地出现新的空间。蛇短的时候还无所谓,当蛇一长, 就会发现,要想活下来,基本就只能追着蛇尾跑了。在追着蛇尾跑的过程中, 再去考虑能否安全地吃到食物。

本人写的代码
基本实现了上述的算法

#include<stdio.h>#include<time.h>#define FOR(i,j,k) for(i=j;i<=k;++i)#define SNAKE_MAX_LENGTH 20#define SNAKE_HEAD 'H'#define SNAKE_BODY 'X'#define BLANK_CELL ' '#define SNAKE_FOOD '$'#define WALL_CELL '*'#define mal 0x7fffffffint life = 1;int snakey[100] = { 5,4,3,2,1 };int snakex[100] = { 1,1,1,1,1 };int d[1000][1000];char map[12][12] = { "************",//da biao"*XXXXH     *","*          *","*          *","*          *","*          *","*          *","*          *","*          *","*          *","************" };int fx, fy, lx, ly;int len = 5;int mx,my;int diffcuilty;void pm();int n, m, w, h;//W 1 ;A 2 ;S 3 ;D 4char cp[12][12];int f[12][12];int qx[1000],qy[1000];int qboo[12][12];int dxx[5]={0,0,-1,0,1};int dyy[5]={0,1,0,-1,0};void bfs(int lx,int ly)//yi (lx,ly) kuo zhang chu bfs ju li (man ha dun ju li){    int ux=lx,uy=ly;int tx,ty;    int i,j,k;    int be=0,en=0;    FOR(i,1,10)        FOR(j,1,10)            {                qboo[i][j]=1;                f[i][j]=mal;            }    qx[0]=lx;qy[0]=ly;qboo[lx][ly]=0;    f[lx][ly]=0;    while(be<=en)    {        k=be;be++;        ux=qx[k];        uy=qy[k];        qboo[ux][uy]=0;        FOR(i,1,4)        {            tx=dxx[i]+ux;            ty=dyy[i]+uy;            if ((cp[tx][ty]==' '||cp[tx][ty]=='H')&&qboo[tx][ty])                {                    f[tx][ty]=f[ux][uy]+1;                    en++;                    qx[en]=tx;                    qy[en]=ty;                }        }    }}void cop()//jiang mu qian zhuang tai fu zhi gei cp[][];{    int i,j;    FOR(i,0,11)        FOR(j,0,11)            cp[i][j]=map[i][j];}int ddd()//qiu fang xiang jie{    cop();int i,j,k=10000;int l;    bfs(mx,my);    if (f[fx][fy]!=mal)//ruo she tou ke yi di da        {            FOR(i,1,4)                if (f[fx+dxx[i]][fy+dyy[i]]<k)                    {                        k=f[fx+dxx[i]][fy+dyy[i]];                        j=i;                    }            return j;        }    else    {        bfs(lx,ly);        k=-1;        FOR(i,1,4)                if (f[fx+dxx[i]][fy+dyy[i]]>k&&f[fx+dxx[i]][fy+dyy[i]]!=mal)                    {                        k=f[fx+dxx[i]][fy+dyy[i]];                        j=i;                    }            return j;    }}void CreateTheBackground(){    int i, j, k;    w = 10; h = 10;    FOR(i, 1, w)        FOR(j, 1, h)    {        if (map[i][j] != '*') {            map[i][j] = ' ';            d[i][j] = 0;        }    }    FOR(i, 1, 4) {        map[i][10] = 'X';        d[i][10] = 4;    }    fx = 5; fy = 10;    d[5][10] = 4;    map[5][10] = 'H';    lx = 1; ly = 10;    FOR(i, 0, h + 1) { map[0][i] = '*'; map[w + 1][i] = '*'; }    FOR(i, 0, w + 1) { map[i][0] = '*'; map[i][h + 1] = '*'; }    pm();}void pm(){    srand(time(NULL));    int i, j;    i = rand() % w + 1;    j = rand() % h + 1;    while (map[i][j] != ' ')    {        i = rand() % w + 1;        j = rand() % h + 1;    }    mx=i;    my=j;    map[i][j] = '$';}int getinp()//W 1 ;A 2 ;S 3 ;D 4{    int start = clock();    int dr;    while (clock() - start <= 1000);    dr=ddd();    return dr;}void pp(){    int i, j;    system("cls");    for (i = h + 1; i >= 0; --i)    {        FOR(j, 0, w + 1)            printf("%c", map[j][i]);        printf("\n");    }}void dead(){    int t;    printf("Game Over!!!");    //getchar();}void movement(int dr){    int tx, ty, t;    d[fx][fy] = dr;    int bj = 0;    map[fx][fy] = 'X';    if (dr == 1) fy++;    if (dr == 2) fx--;    if (dr == 3) fy--;    if (dr == 4) fx++;    if (map[fx][fy] == '$') { bj = 1; }    if (map[fx][fy] == 'X' || map[fx][fy] == '*') { life = 0; return; }    map[fx][fy] = 'H';    if (bj) {        pm();//fang zhi jian qian        len++;        return;    }    t = d[lx][ly];    map[lx][ly] = ' ';    if (t == 1) ly++;    if (t == 2) lx--;    if (t == 3) ly--;    if (t == 4) lx++;}int u = 1;void done()//W 1 ;A 2 ;S 3 ;D 4{    int d = getinp();    if (d != 0) u = d;    movement(u);    pp();}int main(){    CreateTheBackground();//chuang jian bei jing     pp();//shu chu    int ch;    int las=4;    while (life)    {        ch = getinp();//shu ru        if (!(ch>=1&&ch<=4) ) ch=las;        las=ch;        switch (ch)//gen ju shu ru de fang xiang yi dong        {        case 1:movement(1); break;        case 2:movement(2); break;        case 3:movement(3); break;        case 4:movement(4); break;        }        if (life) pp();    }    dead();//shu chu si wang     return 0;}
阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 黎族纹身 黎族三月三 黎族成人礼 九黎族蚩尤 黎族竹筒饭 黎族分布在哪里 海南黎族历史文化 黎族服饰图片 黎族服饰图案 黎族服装图片 liming 黎星 涂黎曼 黎曼函数 黎曼 黎曼可积 黎曼假设 黎曼积分 黎曼空间 黎曼定理 黎曼和 黎曼zeta函数 黎曼可积的定义 黎曼几何 下载 涂黎曼比基尼照 黎朔 黎朔赵锦辛 黎朝 黎村 容县黎村蛋糕店 黎氏 黎氏八兄弟 顾盼美人兮 黎洛 黎玉 黎笋 黎笋晚年为何含恨而去 黎簇 黎芦 黎芦是什么 黎芦图片 黎芦为什么反人参