基于C语言的“贪吃蛇”游戏设计理念

3.功能描述本游戏主要实现以下几种功能

                         图1.游戏功能模块

3.1. 贪吃蛇的控制功能:通过各种条件的判断,实现对游戏蛇的左移、右移、下移、上移、自由移动,贪吃蛇的加长功能。

3.2. 游戏显示更新功能:当贪吃蛇左右移动、上下移动,以及身体加长时要清除先前的贪吃蛇图像,用新坐标重绘贪吃蛇。

3.3. 游戏分数更新功能:在游戏玩家进行游戏过程中,需要按照一定的游戏规则给游戏玩家计算游戏分数。比如,贪吃蛇每吃到一个事物就加十分。

4.数据结构设计

4.1食物Food结构体

      struct Food

{

        int x;/*食物的横坐标*/

        int y;/*食物的纵坐标*/

      int yes;/*判断是否要出现食物的变量*/

}food;

4.2贪吃蛇snake的结构体

     struct Snake

{

     int x[N];

     int y[N];

     int node;/*蛇的节数*/

     int direction;/*蛇移动方向*/

     int life;/* 蛇的生命,0活着,1死亡*/

}snake;

5.程序设计实现

5.1. 主函数main()

 Main()函数主要实现了对整个程序的运行控制,以及相关功能模块的调用。

void Init(void);/*图形驱动*/

void Close(void);/*图形结束*/

void DrawK(void);/*开始画面*/

void GameOver(void);/*结束游戏*/

void GamePlay(void);/*玩游戏具体过程*/

void PrScore(void);/*输出成绩*/

void main(void)

{

   Init();/*图形驱动*/

   DrawK();/*开始画面*/

   GamePlay();/*玩游戏具体过程*/

   Close();/*图形结束*/

}

5.2. 图形驱动init()

Init()主要功能是初始化屏幕为图形模式函数。

void Init(void)

{

   int gd=DETECT,gm;

   initgraph(&gd,&gm,"c:\\tc");

   cleardevice();

}

5.3. 开始画面,左上角坐标为(50,40),右下角坐标为(610,460)的围墙

void DrawK(void)

{

/*setbkcolor(LIGHTGREEN);*/

   setcolor(11);

   setlinestyle(SOLID_LINE,0,THICK_WIDTH);/*设置线型*/

   for(i=50;i<=600;i+=10)/*画围墙*/

   {

      rectangle(i,40,i+10,49); /*上边*/

      rectangle(i,451,i+10,460);/*下边*/

   }

  for(i=40;i<=450;i+=10)

  {

     rectangle(50,i,59,i+10); /*左边*/

     rectangle(601,i,610,i+10);/*右边*/

  }

}

5.4. 玩游戏具体过程

主要实现游戏运行中的操作,以及分数更新等。

void GamePlay(void)

{

   randomize();/*随机数发生器*/

   food.yes=1;/*1表示需要出现新食物,0表示已经存在食物*/

   snake.life=0;/*活着*/

   snake.direction=1;/*方向往右*/

   snake.x[0]=100;snake.y[0]=100;/*蛇头*/

   snake.x[1]=110;snake.y[1]=100;

   snake.node=2;/*节数*/

   PrScore();/*输出得分*/

   while(1)/*可以重复玩游戏,压ESC键结束*/

   {

      while(!kbhit())/*在没有按键的情况下,蛇自己移动身体*/

      {

  if(food.yes==1)/*需要出现新食物*/

  {

      food.x=rand()%400+60;

      food.y=rand()%350+60;

      while(food.x%10!=0)/*食物随机出现后必须让食物能够在整格内,这样才可以让蛇吃到*/

  food.x++;

      while(food.y%10!=0)

  food.y++;

  food.yes=0;/*画面上有食物了*/

  }

  if(food.yes==0)/*画面上有食物了就要显示*/

  {

              setcolor(GREEN);

              rectangle(food.x,food.y,food.x+10,food.y-10);

  }

         for(i=snake.node-1;i>0;i--)/*蛇的每个环节往前移动,也就是贪吃蛇的关键算法*/

         {

            snake.x[i]=snake.x[i-1];

     snake.y[i]=snake.y[i-1];

  }

       /*1,2,3,4表示右,左,上,下四个方向,通过这个判断来移动蛇头*/

  switch(snake.direction)

  {

     case 1:snake.x[0]+=10;break;

     case 2: snake.x[0]-=10;break;

     case 3: snake.y[0]-=10;break;

     case 4: snake.y[0]+=10;break;

  }

  for(i=3;i<snake.node;i++)/*从蛇的第四节开始判断是否撞到自己了,因为蛇头为两节,第三节不可能拐过来*/

  {

     if(snake.x[i]==snake.x[0]&&snake.y[i]==snake.y[0])

     {

               GameOver();/*显示失败*/

               snake.life=1;

               break;

     }

        }

 if(snake.x[0]<55||snake.x[0]>595||snake.y[0]<55||

    snake.y[0]>455)/*蛇是否撞到墙壁*/

 {

     GameOver();/*本次游戏结束*/

     snake.life=1; /*蛇死*/

 }

 if(snake.life==1)/*以上两种判断以后,如果蛇死就跳出内循环,重新开始*/

           break;

 if(snake.x[0]==food.x&&snake.y[0]==food.y)/*吃到食物以后*/

 {

           setcolor(0);/*把画面上的食物东西去掉*/

           rectangle(food.x,food.y,food.x+10,food.y-10);

    snake.x[snake.node]=-20;snake.y[snake.node]=-20;

          /*新的一节先放在看不见的位置,下次循环就取前一节的位置*/

    snake.node++;/*蛇的身体长一节*/

    food.yes=1;/*画面上需要出现新的食物*/

    score+=10;

    PrScore();/*输出新得分*/

 }

 setcolor(4);/*画出蛇*/

 for(i=0;i<snake.node;i++)

    rectangle(snake.x[i],snake.y[i],snake.x[i]+10,

               snake.y[i]-10);

 delay(gamespeed);

 setcolor(0);/*用黑色去除蛇的的最后一节*/

 rectangle(snake.x[snake.node-1],snake.y[snake.node-1],

 snake.x[snake.node-1]+10,snake.y[snake.node-1]-10);

     }  /*endwhile(!kbhit)*/

    if(snake.life==1)/*如果蛇死就跳出循环*/

        break;

    key=bioskey(0);/*接收按键*/

    if(key==ESC)/*按ESC键退出*/

       break;

    else

       if(key==UP&&snake.direction!=4)

/*判断是否往相反的方向移动*/

   snake.direction=3;

       else

   if(key==RIGHT&&snake.direction!=2)

      snake.direction=1;

   else

      if(key==LEFT&&snake.direction!=1)

  snake.direction=2;

      else

  if(key==DOWN&&snake.direction!=3)

     snake.direction=4;

   }/*endwhile(1)*/

}

5.5. 游戏结束

结束游戏的运行。

void GameOver(void)

{

    cleardevice();

    PrScore();

   setcolor(RED);

   settextstyle(0,0,4);

   outtextxy(200,200,"GAME OVER");

   getch();

}

5.6. 输出成绩

其功能是输出玩家游戏结束后的分数。

void PrScore(void)

{   

   char str[10];

   setfillstyle(SOLID_FILL,YELLOW);

   bar(50,15,220,35);

   setcolor(6);

   settextstyle(0,0,2);

   sprintf(str,"score:%d",score);

   outtextxy(55,20,str);

}

5.7. 图形结束

结束图形驱动函数,退出程序。

void Close(void)

{    getch();

    closegraph();

}

6.游戏设计过程与思路

      首先,明确该游戏所拥有的功能与游戏规则。

贪吃蛇的要求为:一条蛇在封密的围墙内,在围墙内随机出现一个食物。通过按键盘上的四个光标控键控制蛇向上下左右四个方向移动,蛇头撞到食物,则表示食物被蛇吃掉,这时蛇的身体长一节,同时计10分,接着又出现食物,等待被蛇吃掉。如果蛇在移动过程中,撞到墙壁或蛇头撞到自己身体游戏结束。

这个程序的关键点是表示蛇的图形以及蛇的移动。可以用一个小矩形表示蛇的一节身体,身体每长一节,增加一个矩形块,蛇头用两节表示。移动时必须从蛇头开始,所以蛇不能向相反移动,也就是蛇尾不能改作蛇头。如果不按任何键,蛇自行在当前方向上前移,当游戏者按了有效的方向键后,蛇头朝指定的方向移动,一步移动一节身体,所以当按了有效的方向键后,先确定蛇头的位置,然后蛇身体随着蛇头移动,图形的实现是从蛇头的新位置开始画出蛇。这时,由于没有清屏的原因,原来蛇的位置和新蛇的位置差一个单位,所以看起来蛇会多一节身体,应将蛇的最后一节用背景覆盖。食物的出现和消失也可以用画矩形块和覆盖矩形块方法实现。为了便于理解,可以定义两个结构体:食物和蛇。

整个游戏可分为四个步骤:

1. 自行设计开始界面,按键或鼠标点击开始游戏。

2. 显示游戏界面,按游戏规则进行游戏。

3. 画面实时显示选手得分,贪吃蛇每吃一个食物,蛇身长一节。

4. 结束时给出提示和得分。

7.结论

本文讲述了贪吃蛇游戏的实现原理,对程序的模块设计、数据结构设计做了简单分析。并通过源码分析讲述了各个模块的实现方法。在几个模块的实现过程中渗透了部分图形功能函数。通过本文的编写过程 ,掌握了以下几点知识点:

  1. 图形系统的初始化和关闭
  2. 各种画图函数的使用
  3. 结构体的定义
  4. 数组定义及应用
  5. 函数嵌套及调用
  6. 键盘操作

参考文献:

【1】姜灵芝,余健.  C语言课程设计案例精编 . 清华大学出版社   2008

【2】何援军 .计算机图形学.  机械工业出版社  2002

【3】 谭浩强 .C程序设计(第三版).  清华大学出版社  2005

【4】李春葆. 数据结构教程(第二版).   清华大学出版社  2007.3

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/752837.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

容器只适用于微服务吗?

容器是一种技术&#xff0c;它将应用及其依赖项打包成一个可移植的单元&#xff0c;以便在不同的计算环境中一致地运行。这种技术确实在微服务架构中得到了广泛应用&#xff0c;因为容器可以帮助实现微服务的快速部署、水平扩展和管理。 然而&#xff0c;容器并不仅限于用于微…

操作系统笔记之进程调用API中的getpid、fork、wait、exec补充

操作系统笔记之进程调用API中的getpid、fork、wait、exec补充 code review! —— 杭州 2024-03-17 夜 文章目录 操作系统笔记之进程调用API中的getpid、fork、wait、exec补充1.getpid()2.fork()3.wait()4.exec()5.通常&#xff0c;exec() 调用与 fork() 调用一起使用&#xff…

Leetcode 3080. Mark Elements on Array by Performing Queries

Leetcode 3080. Mark Elements on Array by Performing Queries 1. 解题思路2. 代码实现 题目链接&#xff1a;3080. Mark Elements on Array by Performing Queries 1. 解题思路 这一题我们只需要按照题意进行一下实现就行了。具体来说的话&#xff0c;我们只需要依序遍历一…

算法笔记p154最大公约数和最小公倍数

目录 最大公约数辗转相除法证明例子代码实现 最小公倍数代码实现 最大公约数 正整数a与b的最大公约数是指a与b的所有公约数中最大的那个公约数&#xff0c;一般用gcd(a, b)表示a和b的最大公约数。 辗转相除法 设a、b均为正整数&#xff0c;则gcd(a, b) gcd(b, a % b)。即被…

【C语言_字符函数和字符串函数_复习篇】

目录 一、字符函数 1.1 字符分类函数 1.2 字符转换函数 二、字符串函数 2.1 strlen函数 2.1.1 strlen函数的使用 2.1.2 strlen函数的模拟实现 2.2 strcpy函数 2.2.1 strcpy函数的使用 2.2.2 strcpy函数的模拟实现 2.3 strcat函数 2.3.1 strcat函数的使用 2.3.2 strcat函数的…

hololens2发布unity设置

生成vs工程再向hololens发布时&#xff0c; Architecture选X64或ARM64都可以成功发布

es索引操作命令

索引操作 index 创建索引 put 方法创建索引 使用 put 创建索引时必须指明文档id&#xff0c;否则报错 # PUT 创建命令 # test1 索引名称 # type1 类型名称&#xff0c;默认为_doc&#xff0c;已经被废弃 # 1 文档id PUT /test1/type1/1 {"name":"zhangsan&…

能不能绕过c去学c++?

目前做工程开发&#xff0c;基本都是c/c混着用的&#xff0c;c/c是同源的&#xff0c;c/是在c的基础上发展起来的&#xff0c;它们之间有些联系和区别&#xff1a; 区别&#xff1a; 1.可用库不同 c基本是系统底层语言&#xff0c;一般系统底层开发用c&#xff08;例如&…

【leetcode】二叉树的前序遍历➕中序遍历➕后序遍历

大家好&#xff0c;我是苏貝&#xff0c;本篇博客带大家刷题&#xff0c;如果你觉得我写的还不错的话&#xff0c;可以给我一个赞&#x1f44d;吗&#xff0c;感谢❤️ 目录 1. 二叉树的前序遍历2. 二叉树的中序遍历3. 二叉树的后序遍历 1. 二叉树的前序遍历 点击查看题目 根…

lv17 安防监控项目实战 3

代码目录 框架 our_storage 编译最终生成的目标文件obj 编译生成中间的.o文件 data_global.c 公共资源定义&#xff08;使用在外extern即可&#xff09;定义了锁定义了条件变量消息队列id、共享内存id、信号量id及key值发送短信、接收短信的号码向消息队列发送消息的函数&am…

Ollama部署本地大模型

ollama run gemma:2b "菊花为什么是红色的&#xff1f;" 如今 LLM 早已不再等同于昂贵的 GPU&#xff0c;而是可以在大部分消费级计算机上运行推理的应用了——俗称本地大模型。 Ollama 安装十分简单&#xff0c;macOS 直接在官网下载安装包打开运行&#xff1b;Wi…

华为汽车业务迎关键节点,长安深蓝加入HI模式,车BU预计今年扭亏

‍编辑 |HiEV 一年之前&#xff0c;同样是在电动汽车百人会的论坛上&#xff0c;余承东在外界对于华为和AITO的质疑声中&#xff0c;第一次公开阐释了华为选择走智选车模式的逻辑。 一年之后&#xff0c;伴随问界M7改款、问界M9上市&#xff0c;华为智选车模式的面貌已经发生了…

【Maven篇】解锁 Maven 的智慧:依赖冲突纷争下的版本调停者

缘起 软件开发世界是一个充满无限可能的领域&#xff0c;但同时也伴随着诸多挑战。其中之一&#xff0c;就是依赖冲突的问题。在这篇文章中&#xff0c;我们将揭开 Maven 这位“版本调停者”的神秘面纱&#xff0c;深入探讨如何在版本纠纷的盛宴中解决依赖问题。 Maven&#…

集成学习bagging与boosting

集成学习是机器学习中的一种策略&#xff0c;旨在结合多个学习器的预测结果&#xff0c;以提高总体性能&#xff0c;减少过拟合&#xff0c;增强模型的泛化能力。Boosting和Bagging是集成学习中两种非常著名的方法&#xff0c;它们虽然共享集成多个学习器以达到更好性能的共同目…

《建造者模式(极简c++)》

本文章属于专栏《设计模式&#xff08;极简c版&#xff09;》 继续上一篇《工厂模式&#xff08;极简c&#xff09;》。本章简要说明建造者模式。本文分为模式说明、本质思想、实践建议、代码示例四个部分。 模式说明&#xff1a; 方案&#xff1a;不同场景对类的构建有不同需…

python内置函数 L

python内置函数 L Python 解释器内置了很多函数和类型&#xff0c;任何时候都能使用。 L 名称描述len返回对象的长度。list返回一个新列表。locals返回一个字典&#xff0c;表示当前局部符号表。 len(s) 返回对象的长度&#xff08;元素个数&#xff09;。实参可以是序列&…

什么是docker(docker客户端、镜像、容器、仓库)

一、docker Docker 是一个开源的容器化平台&#xff0c;它可以让开发者打包应用程序及其依赖项成为一个轻量级、可移植的容器&#xff0c;然后在任何环境中运行。Docker 容器将应用程序及其依赖项打包到一个标准化单元中&#xff0c;包括代码、运行时环境、系统工具、系统库等…

RDP爆破

工具&#xff1a;超级弱口令检查工具 第一步&#xff1a;双击打开工具 第二步&#xff1a;导入账号 第三步&#xff1a;导入密码 第三步&#xff1a;线程 线程默认是50&#xff0c;如果担心影响业务可以修改为5 第四步&#xff1a;填写目标 第五步&#xff1a;选择需要检查的…

前端入职配置新电脑!!!

前端岗位入职第一天到底应该做些什么呢&#xff1f;又该怎样高效的认识、融入团队&#xff1f;并快速进入工作状态呢&#xff1f;这篇文章就来分享一下&#xff0c;希望对即将走向或初入前端职场的你&#xff0c;能够有所帮助。内含大量链接&#xff0c;欢迎点赞收藏&#xff0…

feigni请求添加拦截器

FeignClient 的 configuration 属性&#xff1a; Feign 注解 FeignClient 的 configuration 属性&#xff0c;可以对 feign 的请求进行配置。 包括配置Feign的Encoder、Decoder、 Interceptor 等。 feign 请求添加拦截器&#xff0c;也可以通过这个 configuration 属性 来指…