十八岁花季少女重出江湖 只为驯服一条贪吃蛇(附代码)

目录

前言

实现思想

蛇和食物是怎么产生的? 

蛇是怎么构成的?

 蛇是怎么移动的?

 蛇是怎么吃食的?

怎么判断蛇die?

控制蛇的速度

程序全代码

总结


前言

     快来看! 十八岁花季少女重出江湖!一举拿下一条贪吃蛇!贪吃蛇可以说是JavaScript的必学关卡啦,但是作为小白来无从下手啊!今天我就用这篇博客来给我的宝贝们讲解一下怎么用JavaScript实现贪吃蛇!先给大家展示一下效果!

      这是整个程序的视频链接 原生js贪吃蛇游戏实战开发_哔哩哔哩_bilibili ,只是视频比较长但是讲解的还是很详细的;我自己的多添加了一个难度的设置,根据不同的难度的蛇运动的速度就会不同。我觉得文字始终是没有视频讲解的更清楚的,所以我简述实现过程,但是给大家详细讲解一下控制蛇的速度。

实现思想

   作为小白都想着它是整体移动的,但是!我们需要把蛇的每个结构分开,就是蛇不是一个整体,分为蛇头、蛇身、蛇尾。而我们的游戏界面并不是一个空白,它是由N个小个子组成的,而蛇的每个部分就是在里面的一个格子里面。如下图所示,每一个部分就是一个格子包括蛇和食物都是这样子的。

蛇和食物是怎么产生的? 

      我们生成每一个部分都需要构建一个20*20的小方块,可以转食物、蛇头、蛇身。同时需要出传递一个参数控制生成的样式,这个在css里面构建就可以了。我们同时在整个页面创建了一个新的坐标系,一个坐标的长度和宽度都为20px。

蛇是怎么构成的?

  蛇是通过链表实现的,在构建蛇的时候就搭建了蛇的链式结构。蛇的链式结构如下图所示:

 蛇是怎么移动的?

        我们已经知道蛇是通过链表组成,所以两个部分之间是必有联系的。我们需要得到蛇头的下一个位置,让蛇头的位置更新。原来蛇头的位置创建一个新的方块,放在原来蛇头位置,与此同时删掉最后一个方块并更新链表。如下图所示:

 蛇是怎么吃食的?

       将食物的坐标和蛇头即将去的下一个位置的坐标进行对比。如果是相同的,食物更新坐标(注意食物的坐标不能出现在蛇身上),同时不需要删除原来的蛇尾,只需要添加新的身体即可,这样子蛇就会变长。  

怎么判断蛇die?

        蛇死掉就是两种情况:撞墙和撞自己。

        判断是不是撞墙了?根据蛇头要去的下一个位置就可以知道。下一个位置为:(列数-1)或者(行数-1),此时蛇都是撞墙的情况。即可判断为蛇死掉了。为什么列数和行数需要-1,因为是以坐标的左上角去定的位置,蛇头本身有20px的宽高,不减就会进墙里面。

      判断是不是撞自己?我们在初始化的时候需要一个数组存储蛇每个部分的位置,此时只需要将数组和蛇即将去的下一个位置进行对比,如果是蛇的身体,说明撞上了,即蛇死了。

控制蛇的速度

     我这里定义了一个全局变量fast,把定时器的固定速度改为fast。在进入游戏的时候,我们需要点击不同盒子来控制fast的值,值越大越慢。我的设置如下所示:

       想法是很简单的,但是需要注意的是,点击事件是异步进程,会放在任务队列里面,所以我们不能把fast赋值后的判断放在click事件外面。否则就fast就会一直处于初始值,以至于无法改变速度。(后面有整体代码)

for (var i = 0; i < difficulty_spans.length; i++) {

        var index;
        difficulty_spans[i].setAttribute('index', i);
        difficulty_spans[i].addEventListener('click', function () {
            difficulty.style.display = 'none';
            startBtn.parentNode.style.display = 'block';
            index = this.getAttribute('index');
           //必须把判断fast写在点击事件里面
            if (index == 0) {
                fast = 300;

            } else if (index == 1) {
                fast = 200;
            }
            else {
                fast = 100;
            }

        });
      //不能放在这个位置

    }

程序全代码

     因为代码比较长,我就放在网盘里面了,需要的小伙伴自行下载。 

     链接:https://pan.baidu.com/s/1lRe14mblOCmHbFxzA_aHbg 
     提取码:zmty

总结

      学习的过程总是痛苦的,但是未来总是光明的。贪吃蛇这个项目就是写完一遍以后就觉得不是很难了,一点点消化知识,学到就是赚到。我们一起雕刻自己叭~

  • 13
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 18
    评论
### 回答1: #include <stdio.h> int main() { int i, j, k; int a[25][25], s[25][25]; int x=1, y=0; int m, n, p; int d, e; int h=0; int f=0; int q=3; int w=2; /* 设置游戏场地 */ m=20; n=20; for(i=0;i<m;i++) for(j=0;j<n;j++) a[i][j]=0; /* 设置贪吃蛇 */ for(i=0;i<3;i++) { a[x][y]=1; x++; } /* 初始化蛇头 */ s[0][0]=2; p=1; d=0; e=1; /* 开始游戏 */ while(1) { /* 清屏 */ system("cls"); /* 生成食物 */ if(h==0) { q=rand()%19+1; w=rand()%19+1; if(a[q][w]==0) { a[q][w]=3; h=1; } } /* 打印场地 */ for(i=0;i<m;i++) { for(j=0;j<n;j++) { if(a[i][j]==0) printf("□"); else if(a[i][j]==1) printf("■"); else if(a[i][j]==2) printf("★"); else if(a[i][j]==3) printf("●"); } printf("\n"); } /* 蛇走一步 */ x=x+d; y=y+e; /* 蛇头坐标 */ s[p][0]=x; s[p][1]=y; /* 吃到食物 */ if(a[x][y]==3) { h=0; f=f+100; a[q][w]=1; a[x][y]=2; p++; } /* 撞墙 */ else if(a[x][y]==1) { printf("Game Over!\n"); break; } /* 普通走一步 */ else { a[x][y]=2; a[s[p-1][0]][s[p-1][1]]=0; p++; } /* 移动蛇头 */ for(k=0;k<p-1;k++) { s[k][0]=s[k+1][0]; s[k][1]=s[k+1][1]; } /* 方向控制 */ if(x==m||x==-1||y==n||y==-1) break; if(kbhit()) { switch(getch()) { case 'w': d=-1; e=0; break; case 's': d=1; e=0; break; case 'a': d=0; e=-1; break; case 'd': d=0; e=1; break; } } /* 休眠 */ Sleep(100); } return 0; } ### 回答2: #include <stdio.h> #include <conio.h> #include <windows.h> #define WIDTH 20 // 定义游戏界面的宽度 #define HEIGHT 20 // 定义游戏界面的高度 int score = 0; // 分数 int gameover = 0; // 游戏结束标志 // 定义各个方向的键盘值 #define UP 72 #define DOWN 80 #define LEFT 75 #define RIGHT 77 // 定义蛇的结构体 struct Snake { int x, y; // 蛇头所在的位置 struct Snake* next; // 指向下一个节点的指针 }*head, *tail, *food; // 初始化游戏 void initGame() { score = 0; gameover = 0; head = (struct Snake*)malloc(sizeof(struct Snake)); head->x = WIDTH / 2; head->y = HEIGHT / 2; head->next = NULL; tail = head; // 随机生成食物的位置 food = (struct Snake*)malloc(sizeof(struct Snake)); srand((unsigned)time(NULL)); food->x = rand() % (WIDTH - 2) + 1; food->y = rand() % (HEIGHT - 2) + 1; } // 绘制游戏界面 void drawGame() { system("cls"); for (int i = 0; i < WIDTH + 2; i++) { printf("#"); } printf("\n"); for (int i = 0; i < HEIGHT; i++) { for (int j = 0; j < WIDTH; j++) { if (j == 0 || j == WIDTH - 1) { printf("#"); } else if (i == head->y && j == head->x) { printf("@"); } else if (i == food->y && j == food->x) { printf("$"); } else { struct Snake* temp = head->next; int isBody = 0; while (temp != NULL) { if (temp->x == j && temp->y == i) { printf("*"); isBody = 1; break; } temp = temp->next; } if (!isBody) { printf(" "); } } } printf("\n"); } for (int i = 0; i < WIDTH + 2; i++) { printf("#"); } printf("\n"); printf("Score: %d\n", score); } // 游戏循环 void gameLoop() { int direction = RIGHT; // 初始方向设为向右 while (!gameover) { if (_kbhit()) { int key = _getch(); // 获取键盘输入 switch (key) { case UP: direction = UP; break; case DOWN: direction = DOWN; break; case LEFT: direction = LEFT; break; case RIGHT: direction = RIGHT; break; } } // 移动蛇头 switch (direction) { case UP: head->y--; break; case DOWN: head->y++; break; case LEFT: head->x--; break; case RIGHT: head->x++; break; } // 判断是否吃到食物 if (head->x == food->x && head->y == food->y) { score++; struct Snake* body = (struct Snake*)malloc(sizeof(struct Snake)); body->x = tail->x; body->y = tail->y; body->next = NULL; tail->next = body; tail = body; // 重新生成食物 food->x = rand() % (WIDTH - 2) + 1; food->y = rand() % (HEIGHT - 2) + 1; } // 判断是否撞墙或者撞到自身 if (head->x <= 0 || head->x >= WIDTH - 1 || head->y <= 0 || head->y >= HEIGHT - 1) { gameover = 1; break; } struct Snake* temp = head->next; while (temp != NULL) { if (head->x == temp->x && head->y == temp->y) { gameover = 1; break; } temp = temp->next; } // 重绘游戏界面 drawGame(); // 暂停一些时间,控制游戏速度 Sleep(100); } } // 游戏结束,释放内存 void gameoverFunc() { struct Snake* temp = head; while (temp != NULL) { struct Snake* next = temp->next; free(temp); temp = next; } free(food); } int main() { initGame(); drawGame(); gameLoop(); gameoverFunc(); printf("Game Over!\n"); system("pause"); return 0; }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值