小游戏2048设计思路超简单

2023-05-16

2048作为一个经典的小游戏,对于C语言的逻辑练习是一个比较好的案例了,看似很复杂,但是如果掌握了设计思路,那么就不会觉得难了,而且会了这个之后对今后编程的也会有很大的帮助。

        先分析游戏逻辑,游戏其实很简单,一共16个格子,开局两个有数字的方块,2或者4,然后通过控制方向来使得原有的方块移动并且产生新的方块,

三种逻辑:

一种是方块移动的方向没有其他方块

一种是方块移动的方向已经有了方块,但是数字不一样

还有一种就是方块移动的方向已经有了方块,数字一样。

我认为代码其实就分为两个部分,一个是初始化,一个是移动过程。

初始化部分

初始化部分的话先建一个二维数组,存储16个方块的值,接下来分为两个步骤,生成第一个方块和生成第二个方块

生成第一个方块的话其实就很简单,0-15随机生成一个值,生成的值就代表第几个方块的值为2,其余值都为0

void set_value1()
{
	unsigned int i, j;	
	int n,a;
	srand((unsigned int)time(0));//加入time,使得每次随机值都不一样	
	n = rand()%16;
	for(i = 0; i < 4; i++)
	{
		for(j = 0; j < 4; j++)
		{
			nub[i][j] = n == 0 ? 2 : 0;//如果n的值等于0,那么就给nub[i][j]值赋2,否则0
			n--;
		}
	}	
}

那么第一个方块的值便给好了,但是问题来了,第二块方块的值你不能再用这种方法,因为如果生成的值一样,那么方块就重合了。而且不止是第二个方块的值不能这样生成,后续所有方块的值都不能这样生成。这个时候就必须使用另一种方法。

先获取16个格子空格的个数,也就是二维数组里面值为0的个数

int get_null_count()
{
	unsigned int i, j;
	unsigned int n = 0;
	for(i = 0; i < 4; i++)
	{
		for(j = 0; j < 4; j++)
		{
			if(nub[i][j] == 0)
			n++;
		}
	}
	return n;	
}

获取了空格的个数就可以确定循环的次数,并且判断nub[i][j]的值,如果不等于0就说明有方块了,跳过,这里使用的是逻辑与,如果nub[i][j] == 0不成立的话便不会执行n--了,这样确保遍历每一个空格,需要注意的是根据游戏机制,2和4的生成概率是不一样的,所以通过生成随机值的方式来判断是生成2还是4,在0-10之间,如果随机值为0便生成2,否则生成4,这样生成2和4的概率便为10:1。

void set_value2()
{
	unsigned int i, j , n = 0;;
	srand((unsigned int)time(0));	
	n = rand()%get_null_count();
	
	for(i = 0; i < 4; i++)
	{
		for(j = 0; j < 4; j++)
		{
			if(nub[i][j] == 0 && n-- == 0)
			{
				nub[i][j] = rand()%10 == 0 ? 4 : 2;
			}
		}
	}
}

至此,第一部分便完成了。

移动过程部分

移动过程其实就是通过输入方向来控制方块的移动,并产生新的方块。

先获取输入状态

void move()
{
	switch(key_in)
	{
		case 1:move_left();
		break;
		case 2:move_up();
		break;
		case 3:move_right();
		break;
		case 4:move_down();
		break;
		default :break;
	}	
}

接着具体来看移动的控制的逻辑,拿向左移动为例,首先还是遍历二维数组,找到每一个方块,由于我这里是向左移动,由于最左边的方块是不需要移动的,所以从每一行的第二个方块开始,先移动第二个方块,再第三个,第四个,依次移动,如果此方块左边没有方块,那么交换值,并且原来位置值清0,如果此方块左边的方块和此方块值相同,那么左边的值变为原来的2倍,原来位置值清0。如果左边的值和原来值不同,那么便不做处理,不移动。

void move_left()
{
	int i, j , k, n = 0;
	for(i = 0; i < 4; i++)
	{
		for(j = 1; j < 4; j++)
		{
			if(nub[i][j] > 0)//找到方块
			{
				for(k = j - 1; k > -1; k--)//根据位置判断最大移动次数,决定循环次数
				{
					if(nub[i][k] == 0)//如果左边没有方块
					{
						nub[i][k] = nub[i][k+1];
						nub[i][k+1] = 0;
					}
					else if(nub[i][k] == nub[i][k+1])//如果左边的方块等于这个方块的值
					{
						nub[i][k] = nub[i][k+1]*2;
						nub[i][k+1] = 0;
					}
				}			
			}
		}
	}	
}

明白向左移动的逻辑后,其他的方向也是这个道理

void move_left()
{
	int i, j , k, n = 0;
	for(i = 0; i < 4; i++)
	{
		for(j = 1; j < 4; j++)
		{
			if(nub[i][j] > 0)
			{
				for(k = j - 1; k > -1; k--)
				{
					if(nub[i][k] == 0)
					{
						nub[i][k] = nub[i][k+1];
						nub[i][k+1] = 0;
					}
					else if(nub[i][k] == nub[i][k+1])
					{
						nub[i][k] = nub[i][k+1]*2;
						nub[i][k+1] = 0;
					}
				}			
			}
		}
	}	
}
void move_up()
{
	int i, j , k, n = 0;
	for(i = 1; i < 4; i++)
	{
		for(j = 0; j < 4; j++)
		{
			if(nub[i][j] > 0)
			{
				for(k = i - 1; k > -1; k--)
				{
					if(nub[k][j] == 0)
					{
						nub[k][j] = nub[k+1][j];
						nub[k+1][j] = 0;
					}
					else if(nub[k][j] == nub[k+1][j])
					{
						nub[k][j] = nub[k+1][j] * 2;
						nub[k+1][j] = 0;
					}
				}			
			}
		}
	}	
}
void move_right()
{
	int i, j , k, n = 0;
	for(i = 0; i < 4; i++)
	{
		for(j = 2; j > -1; j--)
		{
			if(nub[i][j] > 0)
			{
				for(k = j + 1; k < 4; k++)
				{
					if(nub[i][k] == 0)
					{
						nub[i][k] = nub[i][k-1];
						nub[i][k-1] = 0;
					}
					else if(nub[i][k] == nub[i][k-1])
					{
						nub[i][k] = nub[i][k-1]*2;
						nub[i][k-1] = 0;
					}
				}			
			}
		}
	}	
}
void move_down()
{
	int i, j , k, n = 0;
	for(i = 2; i > -1; i--)
	{
		for(j = 0; j < 4; j++)
		{
			if(nub[i][j] > 0)
			{
				for(k = i + 1; k < 4; k++)
				{
					if(nub[k][j] == 0)
					{
						nub[k][j] = nub[k-1][j];
						nub[k-1][j] = 0;
					}
					else if(nub[k][j] == nub[k-1][j])
					{
						nub[k][j] = nub[k-1][j] * 2;
						nub[k-1][j] = 0;
					}
				}			
			}
		}
	}
}

最后在每次移动过后再生成一个新的方块,至此,移动过程部分也完成了,整个游戏大致框架便完成了。

由于开发平台不一致,剩下的细节可能不太一样,但是只要能明白这个思路,那么便能很快的完成这个游戏,希望这篇文章能对大家有所帮助。

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

小游戏2048设计思路超简单 的相关文章

随机推荐

  • ISO11898/ISO14229/ISO14230/ISO15031/ISO15765标准对比简介

    各行各业都有很多的国际标准和规范 xff0c 汽车行业也不例外 xff0c 经常遇到一套一套的标准和规范 xff0c 什么ISO11898 xff0c ISO14229 xff0c ISO14230 xff0c ISO15031 xff0c
  • 如何解决UltraCompare中中文显示乱码的问题

    作为一名程序猿 xff0c 对代码进行对比分析是经常避免不了的 xff0c 这时候就需要一个很好用的对比工具 xff0c 我选择了大名鼎鼎的Ultra Compare 但是 xff0c 使用过程中发现 xff0c 这家伙居然不支持中文 xf
  • 一文简单介绍眼图

    搞通信行业的 xff0c 经常要关注信号的传输质量 xff0c 近几年开始出现了一个新的名词 xff0c 叫眼图 xff0c 可以非常直观的体现出信号传输的情况 那么 xff0c 什么是眼图 xff0c 怎么解读眼图 xff0c 下面就为大
  • 下一代CAN通信技术CAN XL简介

    众所周知 xff0c CAN网络具有易于实现 可扩展 并支持复杂拓扑结构等诸多优点 xff0c 所以目前在各个行业特别是汽车领域 xff0c 得到了非常广泛的应用 但是 xff0c 它也存在着诸多问题 xff0c 其中最大的一点就是总线带宽
  • 聊一下质量管理体系中的DQE/SQE/PQE/CQE

    最近接触了不少质量体系的话题 xff0c 反复的听到SQE DQE等 xff0c 大概知道是跟质量管理相关的一些职位 xff0c 但是具体也不是很清楚 xff0c 于是干脆来理一下 正式开始之前 xff0c 先要介绍一下他们的老祖宗 xff
  • C语言字符串库函数 #include <string.h>

    c语言字符串库函数 include lt string h gt 在头文件 lt string h gt 中定义了两组字符串函数 第一组函数的名字以str开头 xff1b 第二组函数的名字以mem开头 只有函数memmove对重叠对象间的拷
  • gcc编译动态库静态库及Makefile知识汇总;

    gcc编译 动态库静态库及Makefile知识汇总 gcc编译过程gcc的常用选项静态库 xff0c 动态库并制作 xff1b Makefile 基本使用make工具简介 gcc编译过程 我们在Linux下使用vim命令写的 c文件 xff
  • 简单学习一下Linux中的环境变量

    环境变量 最近在学习Linux下的C程序编写 xff0c 在运行可执行程序的时候有个问题就是链接的问题 xff0c 最后通过学习才知道是因为环境变量没有设置好 xff1b 环境变量在进行linux开发过程中经常碰到 xff0c 那什么是环境
  • STM32-ESP8266wifi模块实现

    1 ESP8266WiFi模块介绍 1 1ESP8266wifi 模块 低功耗串口WiFi模块ESP8266内置一个Tensilica xff08 泰思立达 xff09 Xtensa架构的32位处理器L106 xff0c 具有5级流水线 A
  • ESP8266WiFi模块实现代码

    ESP8266WiFi模块实现TCP连接服务器 在前面的博客里 xff08 STM32 ESP8266wifi模块实现 xff09 说到了通过AT命令配置ESP8266实现TCP连接 他的流程是 xff0c 1 xff0c 使能串口 xff
  • 2021-05-14 Redis面试题 redis 部署生产环境

    redis 部署生产环境 redis cluster xff0c 10 台机器 xff0c 5 台机器部署了 redis 主实例 xff0c 另外 5 台机器部署了 redis 的从实例 xff0c 每个主实例挂了一个从实例 xff0c 5
  • 实现Basic认证

    Basic认证是一种较为简单的HTTP认证方式 xff0c 客户端通过明文 xff08 Base64编码格式 xff09 传输用户名和密码到服务端进行认证 xff0c 通常需要配合HTTPS来保证信息传输的安全 Maven依赖 lt par
  • STM32的串口空闲中断

    STM32串口使用DMA方式接收数据可以减小CPU的开销 对于接收定长数据 xff0c 可以将DMA接收缓冲区的长度设定为待接收数据的长度 xff0c 这样利用DMA的传输完成中断DMAx IT TCy就可以知道已经接收了一帧数据 对于接收
  • C#完整的通信代码(点对点,点对多,同步,异步,UDP,TCP)

    C code namespace UDPServer class Program static void Main string args int recv byte data 61 new byte 1024 构建TCP 服务器 得到本机
  • http digest认证(Java server)

    背景 xff1a 服务器接收客户端请求 xff0c 处理并验证 并返回服务器的验证结果 关于digest认证的相关概念及验证原理查看相关的说明 xff0c 此处只对处理进行贴码 CODE import com alibaba fastjso
  • 测试apache时出现[error] [client 192.168.6.1] File does not exist: /etc/httpd/htdocs

    问题 xff1a 测试apache时出现 error client 192 168 6 1 File does not exist etc httpd htdocs 解决方法 xff1a 1 创建文件夹htdocs xff08 etc ht
  • HAL库 STM32 串口通信函数

    HAL UART Receive IT串口 xff01 HAL UART Receive IT amp UART1 Handler u8 aRxBuffer RXBUFFERSIZE HAL UART Receive IT函数使用的时候 简
  • linux环境下安装QT超详细

    QT安装 1 首先下载QT安装包 QT官网 xff1a Index of archive qt 我这里使用的是qt opensource linux x64 5 14 0 run版本 2 打开终端 xff0c 输入命令 xff0c 赋予安装
  • 使用ssh连接虚拟机保姆级教程

    首先安装SSH 安装先检测是否已经安装SSH xff1a service ssh status 如果出现提示 xff1a ssh unrecognized service 说明没有安装openSSH xff0c 则需安装ssh SSH 服务
  • 小游戏2048设计思路超简单

    2048作为一个经典的小游戏 xff0c 对于C语言的逻辑练习是一个比较好的案例了 xff0c 看似很复杂 xff0c 但是如果掌握了设计思路 xff0c 那么就不会觉得难了 xff0c 而且会了这个之后对今后编程的也会有很大的帮助 先分析