不多废话,直接进入正题——用C编写简易贪吃蛇。附上拙劣的源码 * c-snake *

  首先说明使画面动起来的原理:通过 system("cls"); 清除当前控制台的显示,再printf下一步画面进行显示,以此循环形成动画效果(类似手翻书)。因为这是在控制台,难免会有晃眼的感觉,并且不存在美工一说,所以就将就下吧。

  有了使画面动起来的方法,接下来就是贪吃蛇游戏本体的制作思路了,可将游戏本体分解为以下3个部分:

1、边界,即墙:圈定一个范围,蛇只能在墙内移动,食物只能生成在墙内

2、蛇:游戏主角,可视为2部分组成——蛇头和蛇身。蛇头引导了蛇身前行的方向,也用于判定蛇是否吃到食物

3、食物:蛇的猎物,被蛇吃掉后会触发2个事件——蛇身加长、重新生成一个食物

  将本体分解完后,就是解析游戏方式:蛇会自动向蛇头朝向进行移动,玩家需要控制蛇头的方向进行移动,抛却理论不说(理论上可以将蛇身占满整个边界内部),游戏结束的情况有2种:撞墙和撞身

  用人话将贪吃蛇游戏理了一遍,接下来就是将人话变成真正的设计思路:

1、边界的描述:可看作一个二维数组,四周为墙,用“*”表示;内部为空,用“ ”表示

2、蛇的描述:由蛇头和蛇身组成,而蛇头可看作蛇身的特殊部分,因此实际并无蛇头一说,仅仅是表示方式不同罢了(蛇头用“@”表示,蛇身用“#”表示),从而将蛇头和蛇身的描述问题转为了蛇身的描述。而蛇身应当如何描述?蛇身由一个又一个的、连续的点组成,因此,该问题实质便是如何去描述一个点。在二维坐标中,点便是用x和y描述,所以蛇的每个蛇身(点)都需要储存x和y这2个”标识符”,同时又需要储存多个xy对,显而易见,依旧是用一个二维数组去描述蛇

3、食物的描述:食物本质上依旧是一个点,但和蛇身不同,食物有且仅有1个,所以用一个一维数组即可描述食物

4、蛇的移动:什么是移动?移动即为位置的改变,所以在确定了方向后,我们要做的仅仅是将蛇头向该方向移动后,后面的蛇身依次覆盖前一个蛇身/头,即拷贝前一个蛇身所储存的xy坐标。当吃到食物时,应当将长度+1

5、蛇的移动方向控制:那么如何控制蛇头所指向的方向呢?虽然方向是蛇头的属性之一,但可将其从蛇中分离出去,定义一个单独的变量去描述方向。当有键盘敲击输入事件发生时,获取输入值并判断输入值与方向的关系,更新方向即可

6、食物的消失与生成:当蛇头与食物的坐标相同时,食物应当消失(被吃),消失后应当生成一个新的食物,而生成食物的x和y应为随机数,且需在墙内,不能生成在蛇上

7、游戏的结束:判断蛇头的位置即可(撞墙:当蛇头的位置处于墙上时;撞身:当蛇头的位置处于蛇身上时)

  

  有了思路,代码其实就自然而然的写出来了:

    定义部分:

  1. /*
  2. 若内部场地大小为x*y:
  3. 墙定义为char wall[y+2][x+2],+2是因为2边的边界
  4. 蛇定义为int snake[x*y][3],snake[i][0]表示x坐标,snake[i][1]表示y坐标,snake[i][2]表示该蛇身是否存在。当然亦可定义为snake[x*y][2],初始化为0,判断x和y值是否为0去确定该蛇身是否存在
  5. 食物定义为int food[3],food[0]表示x坐标,food[1]表示y坐标,food[2]表示食物是否已经存在
  6. 移动的方向定义为int direction,1/2/3/4分别对应4个方向
  7. */
  8.  
  9. char wall[][];
  10. int snake[][];
  11. int food[];
  12. int direction = ; //方向:1-上 2-右 3-下 4-左

define

    功能模块部分:

  1. //初始化围墙属性
  2. void init_wall()
  3. {
  4. extern char wall[][];
  5. int i,j;
  6. for(i = ; i < ; i++)
  7. {
  8. for(j = ; j < ; j++)
  9. {
  10. if(i == || i == )
  11. wall[i][j] = '*';
  12. else if(j == || j == )
  13. wall[i][j] = '*';
  14. else
  15. wall[i][j] = ' ';
  16. }
  17. }
  18. }

init_wall

  1. //初始化蛇属性
  2. void init_snake()
  3. {
  4. /*
  5. snake[i][0]为x坐标
  6. snake[i][1]为y坐标
  7. snake[i][2]值为1或0 1表示存在 0表示不存在
  8. */
  9. extern int snake[][];
  10. snake[][] = ;
  11. snake[][] = ;
  12. snake[][] = ;
  13. snake[][] = ;
  14. snake[][] = ;
  15. snake[][] = ;
  16. snake[][] = ;
  17. snake[][] = ;
  18. snake[][] = ;
  19. }

init_snake

  1. //初始化食物属性
  2. void init_food()
  3. {
  4. /*
  5. food[0]为x坐标
  6. food[1]为y坐标
  7. food[2]值为1或0 1表示不存在 0表示存在
  8. */
  9. extern int food[];
  10. extern int snake[][];
  11.  
  12. int x,y;
  13. int flag = ; //是否在蛇身的标志 1表示在 0表示不在
  14. food[] = ; //生成食物 置0
  15.  
  16. while(flag)
  17. {
  18. srand(time());
  19. x = rand()%+;
  20. y = rand()%+;
  21. int i;
  22. for(i = ; i < ; i++)
  23. {
  24. if(snake[i][])
  25. {
  26. if(snake[i][] == x && snake[i][] == y)
  27. break;
  28. }
  29. else
  30. flag = ;
  31. }
  32. }
  33. food[] = x;
  34. food[] = y;
  35. }

init_food

  1. //在墙中生成蛇和食物
  2. void change()
  3. {
  4. extern char wall[][];
  5. extern int snake[][];
  6. extern int food[];
  7. int i;
  8.  
  9. if(food[])
  10. {
  11. init_food();
  12. }
  13.  
  14. wall[food[]][food[]] = 'O'; //食物
  15.  
  16. for(i = ; i < ; i++)
  17. {
  18. if(snake[i][])
  19. {
  20. int x = snake[i][];
  21. int y = snake[i][];
  22. if(i == )
  23. wall[y][x] = '@'; //蛇头
  24. else
  25. wall[y][x] = '#'; //蛇身
  26. }
  27. }
  28. }

change

  1. //判断是否吃到食物
  2. int ifEat()
  3. {
  4. extern int snake[][];
  5. extern int food[];
  6. extern int score;
  7.  
  8. if(snake[][] == food[] && snake[][] == food[])
  9. {
  10. food[] = ;
  11. return ; //吃到返回1
  12. }
  13. return ; //没吃到返回0
  14. }

ifEat

  1. //判断是否撞墙或自身
  2. int ifBreak()
  3. {
  4. extern int snake[][];
  5. int i;
  6.  
  7. if(snake[][] == || snake[][] == || snake[][] == || snake[][] == )
  8. return ;
  9. for(i = ; i < ; i++)
  10. {
  11. if(snake[][] == snake[i][] && snake[][] == snake[i][])
  12. return ;
  13. }
  14. return ;
  15. }

ifBreak

  1. //获取输入的方向
  2. void getKey()
  3. {
  4. char ch;
  5. if(_kbhit())
  6. {
  7. ch = _getch();
  8. }
  9. switch(ch)
  10. {
  11. case 'w':
  12. case 'W':
  13. if(direction != )
  14. direction = ;
  15. break;
  16. case 'd':
  17. case 'D':
  18. if(direction != )
  19. direction = ;
  20. break;
  21. case 's':
  22. case 'S':
  23. if(direction != )
  24. direction = ;
  25. break;
  26. case 'a':
  27. case 'A':
  28. if(direction != )
  29. direction = ;
  30. break;
  31. default:
  32. break;
  33. }
  34. }

getKey

  1. //移动
  2. void move()
  3. {
  4. extern int direction;
  5. extern int snake[][];
  6. extern int score;
  7. int i = score - ;
  8. int x,y;
  9.  
  10. switch(direction)
  11. {
  12. case :
  13. x = ;
  14. y = -;
  15. break;
  16. case :
  17. x = ;
  18. y = ;
  19. break;
  20. case :
  21. x = ;
  22. y = ;
  23. break;
  24. case :
  25. x = -;
  26. y = ;
  27. break;
  28. default:
  29. break;
  30. }
  31.  
  32. if(ifEat())
  33. {
  34. snake[score][] = snake[score-][];
  35. snake[score][] = snake[score-][];
  36. snake[score][] = ;
  37. score++;
  38. }
  39.  
  40. while(i > )
  41. {
  42. if(snake[i][] != )
  43. {
  44. snake[i][] = snake[i-][];
  45. snake[i][] = snake[i-][];
  46. }
  47. i--;
  48. }
  49.  
  50. snake[][] += x;
  51. snake[][] += y;
  52. }

move

  1. //打印
  2. void print_all()
  3. {
  4. extern char wall[][];
  5. int i,j;
  6. for(i = ; i < ; i++)
  7. {
  8. for(j = ; j < ; j++)
  9. {
  10. printf("%c", wall[i][j]);
  11. }
  12. printf("\n");
  13. }
  14. }

print_all

    最后只需在main中按照顺序将各个模块进行调用即可

  1. void main()
  2. {
  3. extern char wall[][];
  4. extern int snake[][];
  5. extern int score;
  6. int speed = ;
  7. int spot = ;
  8.  
  9. init_snake();
  10. init_food();
  11.  
  12. while()
  13. {
  14. getKey();
  15. system("cls");
  16. init_wall();
  17. move();
  18. change();
  19. print_all(wall[][]);
  20. if(ifBreak())
  21. break;
  22. Sleep(speed);
  23. if(score == spot)
  24. {
  25. speed = 0.9*speed;
  26. spot += ;
  27. }
  28. }
  29. printf("Game Over\n");
  30. printf("score:%d\n",score);
  31. system("pause");
  32. }

main

C - 简易贪吃蛇的编写的更多相关文章

  1. Luat Inside | 致敬经典,使用Air724UG制作简易贪吃蛇

    作者简介: 打盹的消防车--活跃于Luat社群的新生代全能开发者,东北小伙儿爽朗幽默.好学敏思,更是实力行动派.幼年曾手握火红炽铁而后全然无恙,堪称魔幻经历:如今热衷于各类嵌入式软硬件研究,快意物联江 ...

  2. <Android 应用 之路> 简易贪吃蛇

    最简单的贪吃蛇 最近想着忙里偷闲写点简单的Android应用,增加一些生活乐趣,由于平时工作主要精力并不是集中在书写apk上,更多的是解决代码问题和维护模块稳定,但是写代码本身是一件比较有趣的事情,因 ...

  3. Python实例:贪吃蛇(简单贪吃蛇编写)🐍

    d=====( ̄▽ ̄*)b 叮~ Python -- 简易贪吃蛇实现 目录: 1.基本原理 2.需要学习的库 3.代码实现 1.基本原理 基本贪吃蛇所需要的东西其实很少,只需要有一块让蛇动的屏幕, 在 ...

  4. javascript 编写的贪吃蛇

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. pygame编写贪吃蛇

    一直想用pygame做一个小游戏的,可是因为拖延症的缘故一直没有动,结果那天看到了一个12岁的国际友人小盆友用pygame做的一款塔防游戏,突然感觉已经落后超级远了,所以心血来潮做小游戏了.高中陪伴我 ...

  6. 贪吃蛇(简易版)Leslie5205912著

    # include <stdio.h># include <string.h># include <windows.h># include <stdlib.h ...

  7. JavaScript 实现简易版贪吃蛇(Day_13)

    时光永远在变迁,你始终要丢下过去. 使用语言 JavaScript  概述 运用JavaScript  实现简易版<贪吃蛇>.     Html 页面 1 <!DOCTYPE htm ...

  8. 用OpenGL简单编写的一个最简单贪吃蛇游戏

    刚学OpenGL的时候,写的一个最简单的贪吃蛇游戏代码 如下: //贪吃蛇游戏 #include<stdio.h> #include<stdlib.h> #include< ...

  9. Javascript基础示例:用JS写简易版贪吃蛇(面向对象)

    废话不多说,代码如下: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> & ...

随机推荐

  1. Java后台开发精选知识图谱

    1.引言: 学习一个新的技术时,其实不在于跟着某个教程敲出了几行.几百行代码,这样你最多只能知其然而不知其所以然,进步缓慢且深度有限,最重要的是一开始就对整个学习路线有宏观.简洁的认识,确定大的学习方 ...

  2. Job for docker.service failed because the control process exited with error code. See

    在Liunx中使用Docker, 注: Liunx使用的是在虚拟机下的centOS7版本在刚开始安装Docker时没有任何错误, 但是在后续的docker启动过程中, 出现以下问题: Job for ...

  3. FFmpeg之avformat_alloc_context()

    1. avformat_alloc_context /** * Allocate an AVFormatContext. * avformat_free_context() can be used t ...

  4. Qt学习之如何启动和终止一个线程

    先来给出每个文件的相关代码然后再加以分析 //*************dialog.h**************// #ifndef DIALOG_H #define DIALOG_H #incl ...

  5. k8s应用01-----入门实例

    安装一个单机版的K8S 1.关闭防火墙firewalld2.安装etcd和kubernetesyum install -y etcd kubernetes(会自动安装docker)3.修改配置文件修改 ...

  6. AndroidStudio 3.0中之后无法打开DDMS [Android Device Monitor] 问题

    AndroidStudio 3.0中之后无法打开DDMS [Android Device Monitor] 问题    转 https://blog.csdn.net/black_bird_cn/ar ...

  7. 注解方式实现AOP编程

    步骤: 1) 先引入aop相关jar文件           (aspectj  aop优秀组件) spring-aop-3.2.5.RELEASE.jar   [spring3.2源码] aopal ...

  8. harber私有镜像仓库(4)

    一.部署准备: 准备harbor软件包 在部署节点上: #mv harbor-offline-installer-v1.4.0.tgz /opt/ && cd /opt #tar zx ...

  9. Java NIO学习笔记九 NIO与IO对比

    Java NIO与IO Java nio 和io 到底有什么区别,以及什么时候使用nio和io,本文做一个比较. Java NIO和IO之间的主要区别 下表总结了Java NIO和IO之间的主要区别, ...

  10. Spring Cloud(4):断路器(Hystrix)

    Hystrix介绍 相对于单一系统,分布式系统更容易遇到故障,所以我们一般通过构建冗余,使用集群和负载均衡来保证系统的弹性和高可用.当然,这种方式只解决了一部分问题,当服务崩溃时,我们很容易检测到,因 ...