复现贪吃蛇程序——吃食物增加长度(最后一篇)

2023-10-29

        本节便是贪吃蛇程序的最终部分,实现吃食物增加长度的功能,当二维数组canvas[High][Width]的元素值为-2时输出食物数值‘F’。

其实现思路和3.4.2节中小蛇的移动类似,只需保持原蛇尾,不将最大值变为0即可。

先奉上完整的代码:

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

#define High 20               //游戏画面尺寸 
#define Width 30
//全局变量 
int moveDirection;            //小蛇移动的方向,上、下、左、右分别用1、2、3、4表示 
int food_x,food_y;            //食物的位置 
int canvas[High][Width]={0};  //二维数组存储游戏画布中对应的元素 
               //0 为空格,-1为边框#,1为蛇头@,大于1的正数为蛇身* 

void gotoxy(int x,int y)     //将光标移动到(x,y)位置 
{
	HANDLE handle =GetStdHandle(STD_OUTPUT_HANDLE);
	COORD pos;
	pos.X=x;
	pos.Y=y;
	SetConsoleCursorPosition(handle,pos);
}

//下面的moveSnakeByDirection()函数用来实现移动小蛇
//第一步扫描数组canvas的所有元素,找到正数元素都加 1
//找到最大元素(即蛇尾巴),把其变为 0
//找到等于 2 的元素(即蛇头),根据输出的上下左右方向把对应的另一个像素值设为 1(新蛇头) 
void moveSnakeByDirection()
{
	int i,j;
	for(i=1;i<High-1;i++)
	   for(j=1;j<Width-1;j++)
	      if(canvas[i][j]>0)
	         canvas[i][j]++;
	         
	int oldTail_i,oldTail_j,oldHead_i,oldHead_j;
	int max=0;
	
	for(i=1;i<High-1;i++)
	   for(j=1;j<Width-1;j++)
	       if(canvas[i][j]>0)
	         {
	         	if(max<canvas[i][j])
	         	{
	         		max=canvas[i][j];
	         		oldTail_i=i;
	         		oldTail_j=j;
				}
				if(canvas[i][j]==2)
				{
					oldHead_i=i;
					oldHead_j=j;
				}
			 }
	int newHead_i,newHead_j;      //定义一个数组用来存放新蛇头的数据 
	if(moveDirection==1)          //向上移动 
	{
		newHead_i=oldHead_i-1;    // i-1 是因为向上移动因此新蛇头的位置向上移 
		newHead_j=oldHead_j;      //因为是竖直方向的运动并不影响左右 
	}
	if(moveDirection==2)          //向下移动 
	{
		newHead_i=oldHead_i+1;    // i+1 是因为向下移动因此新蛇头的位置向下移 
		newHead_j=oldHead_j;      //因为是竖直方向的运动并不影响左右
	}
	if(moveDirection==3)         //向左移动 
	{
		newHead_i=oldHead_i;     //因为是左右方向的运动并不影响竖直方向 
		newHead_j=oldHead_j-1;   // j-1 是因为向左移动,因此新蛇头的位置向左移动 
	}
	if(moveDirection==4)         //向右移动 
	{
		newHead_i=oldHead_i;     //因为是左右方向的运动并不影响竖直方向 
		newHead_j=oldHead_j+1;   // j-1 是因为向右移动,因此新蛇头的位置向右移动 
	}
	
	//如果新蛇头吃到食物
	if(canvas[newHead_i][newHead_j]==-2)
	{
		canvas[food_x][food_y]=0;
		//产生一个新的食物
		food_x=rand()%(High-5)+2;
		food_y=rand()%(Width-5)+2;
		canvas[food_x][food_y]=-2;
		
		//原本的旧蛇尾留着,长度自动加 1 
	}
	else                            //否则,原来的旧蛇尾减掉,保持长度不变
	   canvas[oldTail_i][oldTail_j]=0;
	   
	// 小蛇是否和自身撞或者边框,游戏失败
	if(canvas[newHead_i][newHead_j]>0||canvas[newHead_i][newHead_j]==-1)
	{
		printf("游戏失败!\n");
		Sleep(2000);
		system("pause");
		exit(0);
	}
	else
	   canvas[newHead_i][newHead_j]=1;
}

void startup()
{
	int i,j;
	
	//初始化边框
	for(i=0;i<High;i++)
	{
		canvas[i][0]=-1;
		canvas[i][Width-1]=-1;
	}
	for(j=0;j<Width;j++)
	{
		canvas[0][j]=-1;
		canvas[High-1][j]=-1;
	}
	
	//初始化蛇头位置 
	canvas[High/2][Width/2]=1;	 
	//初始化蛇身,画布中的元素值分别为2、3、4、5等 
	for(i=1;i<=4;i++)
	   canvas[High/2][Width/2-i]=i+1;
	   
	//初始化小蛇向右移动   
	moveDirection=4;
	
	food_x=rand()%(High-5)+2;
	food_y=rand()%(Width-5)+2;
	canvas[food_x][food_y]=-2;
}

void show()                 //显示画面 
{
	gotoxy(0,0);            //光标移动到原点位置,以下重画清屏 
	int i,j;
	for(i=0;i<High;i++)
	{
		for(j=0;j<Width;j++)
		{
			if(canvas[i][j]==0)
			   printf(" ");     //输出空格 
			else if(canvas[i][j]==-1)
			   printf("#");     //输出边框# 
			else if(canvas[i][j]==1)
			   printf("@");     //输出蛇头@ 
			else if(canvas[i][j]>1)
			   printf("*");     //输出蛇身* 
			else if(canvas[i][j]==-2)
			   printf("F");     //输出食物 F
		}
		printf("\n");
    }
    Sleep(100);
}

void updateWithoutInput()       //与用户输入无关的更新 
{
	moveSnakeByDirection();
}

void updateWithInput()          //与用户输入有关的更新 
{
	char input;
	if(kbhit())                 //判断是否有输入 
	{
		input=getch();          //根据用户的不同输入来移动,不必输入回车 
		if(input=='a')
		{
			moveDirection=3;    //位置左移 
			moveSnakeByDirection();
		}
		else if(input=='d')
		{
			moveDirection=4;    //位置右移 
			moveSnakeByDirection();
		}
		else if(input=='w')
		{
			moveDirection=1;   //位置上移 
			moveSnakeByDirection();
		}
		else if(input=='s')
		{
			moveDirection=2;  //位置下移 
			moveSnakeByDirection();
		}
	}
}

int main()
{
	startup();                  //数据的初始化 
	while(1)                    //游戏循环执行 
	{
		show();                 //显示画面 
		updateWithoutInput();   //与用户输入无关的更新 
		updateWithInput();      //与用户输入有关的更新 
	}
	return 0;
} 

通过之前的学习相信都能对整个代码有了理解和掌握。

老规矩这次依然指出一些需要注意和理解的地方:

food_x=rand()%(High-5)+2;
food_y=rand()%(Width-5)+2;

首先要了解 rand()函数 的用法,举个例子:

        rand()%100  代表的意思是从0~99里面随机出现一个数字。

        因此 rand()%100+1  代表的意思是从1~10里面随机出现的一个数字。

        故上述代码可以保证食物的”行数“和”列数“可以随机生成,从而保证食物的位置随机生成。

明白这些相信对完整的代码有更深的理解和掌握。 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

复现贪吃蛇程序——吃食物增加长度(最后一篇) 的相关文章

  • android 项目中出现红色感叹号的解决方法

    文本转载 http www apkbus com forum php mod viewthread tid 5629 问题原因 工程中classpath中指向的包路径错误 解决办法 右键项目名称 BuildPath gt Configure
  • Unicode(UTF-8, UTF-16)令人混淆的概念

    为啥需要Unicode 我们知道计算机其实挺笨的 它只认识0101这样的字符串 当然了我们看这样的01串时肯定会比较头晕的 所以很多时候为了描述简单都用十进制 十六进制 八进制表示 实际上都是等价的 没啥太多不一样 其他啥文字图片之类的其他

随机推荐

  • 2023年全国普通高校学科竞赛排行榜,中国高等教育学会版,84项(新增27项)

    2023年全国普通高校学科竞赛排行榜 中国高等教育学会版 84项 新增27项 文章目录 2023榜单竞赛 2023年3月22日 中国高等教育学会高校竞赛评估与管理体系研究专家工作组发布 2022全国普通高校大学生竞赛分析报告 以下简称 分析
  • 八、基础教程-数据列(Series)

    数据列配置是 Highcharts 最复杂也是最灵活的配置 如果说 Highcharts 是灵活多变 细节可定制的话 那么数据列配置就是这个重要特性的核心 一 什么是数据列 数据列是一组数据集合 例如一条线 一组柱形等 图表中所有点的数据都
  • 在create-react-app项目下,使用eslinit和prettier美化代码

    虽然官方脚手架create react app当中默认提供了eslint 但是由于官方的配置不是很充分 导致了在是进行代码优化方面不是很理想 但是 我们可以自行配置达到写出高质量代码的目的 ESlint 不是自带格式化吗 为什么还要用 Pr
  • 央行发行数字货币对我们意味着什么?

    实际上恰恰在这种行情下 我们才能不受价格暴涨和利益诱惑沉下心来研究业界实质性的进展 发现孕育下一波红利的机遇 央行数字货币有了实质性进展 8月10日 中国人民银行支付结算司副司长穆长春表示人民银行的数字货币已经呼之欲出 并介绍了人行数字货币
  • 电路基础(1)电路模型和电路定律

    电路中的电压 电流之间具有两种约束 一种是由电路元件决定的元件约束 另一种是元件间连接而引入的几何约束 就是拓扑约束 后者由基尔霍夫定律来表达 基尔霍夫定律是集总参数电路的基本定律 1 电路和电路模型 电源又称为激励源或激励 由激励在电路中
  • python使用HanLP命名实体识别(以识别人名为例)

    首先需要安装依赖包 pip install pyhanlp 识别人名的代码如下 from pyhanlp import HanLP def extract chinese name string str gt list 使用HanLP人名识
  • C++ do...while 循环

    不像 for 和 while 循环 它们是在循环头部测试循环条件 do while 循环是在循环的尾部检查它的条件 do while 循环与 while 循环类似 但是 do while 循环会确保至少执行一次循环 语法 C 中 do wh
  • Nginx 4层代理部署

    Yum安装Nginx 系统环境 Centos 添加yum源并安装 CentOS 7 rpm Uvh http nginx org packages centos 7 noarch RPMS nginx release centos 7 0
  • JS 数组去重复数据、处理数组数据

    需求 去除数组里id重复的对象 let arr id 1 name zhang id 1 name li id 2 name he id 2 name zhao id 2 name zhao id 3 name liu name li id
  • Web端报错

    Chunk vendors 2a8c602b js 48混合内容 位于 https 3323 sfdy13168 com goodsManage 的页面通过HTTPS加载 但请求了不安全的XMLHttpRequest端点 http 110
  • nacos配置文件优先级

    1 通过工程的应用名字找到德配置文件的优先级最高 比如content api工程功程对应的content api dev yaml文件是最先的优先级 2 扩展配置 项目中会依赖其他模块的配置文件所依赖的nacos配置 的优先级其次 举例 c
  • cuda 安装

    零 修订记录 序号 修订内容 修订时间 1 新增 20210708 2 支持tensorflow 20210715 一 摘要 本文主要介绍cuda 的安装 二 环境信息 一 软件信息 2 1 1 操作系统 root localhost ca
  • 【Java】* 给定一个整数数组 nums 和一个目标值 target, * 请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。

    leetcode 刷题 数组 题目 给定一个整数数组 nums 和一个目标值 target 请你在该数组中找出和为目标值的那 两个 整数 并返回他们的数组下标 示例 给定 nums 2 7 11 15 target 9 因为 nums 0
  • openGauss学习笔记-64 openGauss 数据库管理-创建和管理表空间

    文章目录 openGauss学习笔记 64 openGauss 数据库管理 创建和管理表空间 64 1 背景信息 64 2 注意事项 64 3 操作步骤 64 3 1 创建表空间 64 3 2 在表空间中创建对象 64 3 3 查询表空间
  • git checkout切换到指定commit

    切换分支是 git checkout 最常见的功能 这里不做介绍 今天主要介绍下它在撤销文件改动上的应用 放弃单个文件修改 注意不要忘记中间的 不写就成了检出分支了 git checkout filepathname 放弃所有的文件修改 g
  • 值得推荐的C/C++框架和库,包含很多开源项目 (真的很强大)

    值得学习的C语言开源项目 1 Webbench Webbench是一个在linux下使用的非常简单的网站压测工具 它使用fork 模拟多个客户端同时访问我们设定的URL 测试网站在压力下工作的性能 最多可以模拟3万个并发连接去测试网站的负载
  • mysql分组统计占比/百分比

    需求 统计当前数据库user tasks表中 不同status字段值对应的记录条数及占比 sql语句 SELECT status number concat round number total 100 00 2 percent FROM
  • Week 2 Git &Github 5: Amending commits

    git commit amend overwirte 上一次commit 用这个命令的前提是只能对本地的commit进行这样的操作 不要在跟他人公用仓库时使用这个操作 容易出现错误 使用案例 win10通过左下角windows图标 右键打开
  • 量化投资学习-17:庄家和主力为啥要在牛市到顶后砸盘?

    一直很奇怪 为啥庄家和主力要留一小部分筹码在牛市的顶部砸盘 你赚完自己的钱 走人就是了 走人之后 让散户自己玩不就得了 为啥要做这种损人不利己的事情呢 砸盘是要牺牲砸盘筹码的利益的 不理解这一点 是因为格局不够大 这是散户的眼光局限性所决定
  • 复现贪吃蛇程序——吃食物增加长度(最后一篇)

    本节便是贪吃蛇程序的最终部分 实现吃食物增加长度的功能 当二维数组canvas High Width 的元素值为 2时输出食物数值 F 其实现思路和3 4 2节中小蛇的移动类似 只需保持原蛇尾 不将最大值变为0即可 先奉上完整的代码 inc