C语言简单游戏编程学习入门之2048

运行结果预览图

![在这里插入图片描述](https://img-blog.csdnimg.cn/2019071402033888.png)

源代码展示

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

//过关数字
#define win_number 2048 
//定义地图行、列、以及本身 
#define row 4
#define col 4
int map[row][col]={0};

//初始化地图
void InitializeMap(); 
//打印地图
void PrintMap(); 
//判断是否已经存在2048
int IsWin();
//随机生成一个2或者4,生成2的概率是生成4的概率的3倍
void CreateANumber(); 
//移动数字
int Move(char turn);
//合并数字
int Combine(char turn); 
//gotoxy函数的实现,把光标移到到指定位置 
void gotoxy(int x,int y);

int main()
{
	srand(time(0));		//时间种子 
	InitializeMap();	//初始化地图,只有两个数字 
	char turn;
	while(1)
	{
		PrintMap();		//展示地图 
		if(IsWin())		//判断是否过关 
		{
			printf("恭喜通关!\n");
			break;
		}
		turn=getch();	//获取用户的移动请求,若移动有效则再次生成一个随机2或4 
		if(Move(turn)==1)
		{
			if(Combine(turn))
			{
				Move(turn);	
			} 
			CreateANumber();
		} 
		else if(Combine(turn))
		{
			Move(turn);
			CreateANumber();
		}
	}
	return 0;
}

//初始化地图
void InitializeMap()
{
	CreateANumber();
	CreateANumber(); 
} 

//打印地图
void PrintMap()
{
	int i,j,k;
	gotoxy(0,0);
	for(i=0;i<row;i++)
	{
		for(k=1;k<=5*col+1;k++)
		{
			printf("-");	
		} 
		printf("\n|");
		for(j=0;j<col;j++)
		{
			if(map[i][j]>0)
			{
				printf("%4d|",map[i][j]);
			}
			else
			{
				printf("%4s|"," ");
			}
		}
		printf("\n");
	}
	for(k=1;k<=5*col+1;k++)
	{
		printf("-");	
	} 
	printf("\n");
}

//判断是否已经存在2048
int IsWin()
{
	int i,j;
	for(i=0;i<row;i++)
	{
		for(j=0;j<col;j++)
		{
			if(map[i][j]==win_number)	
			{
				return 1;
			}
		}	
	}	
	return 0;
}

//随机生成一个2或者4,生成2的概率是生成4的概率的3倍
void CreateANumber()
{
	int number=rand()%4+1;
	if(number!=4)
	{
		number=2;	
	}	
	int i,j;
	while(1)
	{
		i=rand()%row;
		j=rand()%col;
		if(map[i][j]==0)
		{
			map[i][j]=number;
			break;	
		}	
	}
}

//移动数字
int Move(char turn)
{
	int flag=0;	//是否移动或者合并成功。0:否 1:是
	int i,j,k;
	switch(turn)
	{
		case 'w':case 'W'://有空位则下面的非空位往上移 
			for(i=0;i<row-1;i++)
			{
				for(j=0;j<col;j++)
				{
					if(map[i][j]==0)
					{
						for(k=i+1;k<row;k++)
						{
							if(map[k][j]>0)
							{
								map[i][j]=map[k][j];
								map[k][j]=0;
								flag=1;
								break;	
							}	
						}	
					} 
				}
			}
			break;
		case 's':case 'S'://有空位则上面的非空位往下移 
			for(i=row-1;i>=1;i--)
			{
				for(j=0;j<col;j++)
				{
					if(map[i][j]==0)
					{
						for(k=i-1;k>=0;k--)
						{
							if(map[k][j]>0)
							{
								map[i][j]=map[k][j];
								map[k][j]=0;
								flag=1;
								break;	
							}	
						} 
					} 
				}
			}
			break;
		case 'a':case 'A'://有空位则右面的非空位往左移 
			for(j=0;j<col-1;j++)
			{
				for(i=0;i<row;i++)
				{
					if(map[i][j]==0)
					{
						for(k=j+1;k<col;k++)
						{
							if(map[i][k]>0)
							{
								map[i][j]=map[i][k];
								map[i][k]=0;
								flag=1;
								break;
							}
						}
					}
				}
			}
			break;
		case 'd':case 'D'://有空位则左面的非空位往右移 
			for(i=0;i<row;i++)
			{
				for(j=col-1;j>=1;j--)
				{
					if(map[i][j]==0)
					{
						for(k=j-1;k>=0;k--)
						{
							if(map[i][k]>0)
							{
								map[i][j]=map[i][k];
								map[i][k]=0;
								flag=1;
								break;
							}
						}
					}
				}
			}
			break;
		default:
			break;
	}
	return flag;
}

//合并数字
int Combine(char turn)
{
	int flag=0;		//是否合并成功
	int i,j;
	switch(turn)
	{
		case 'w':case 'W'://是否存在下面一个数字和自己的相同且不是0 
			for(i=0;i<row-1;i++)
			{
				for(j=0;j<col;j++)
				{
					if(map[i][j]>0&&map[i][j]==map[i+1][j])
					{
						map[i][j]*=2;
						map[i+1][j]=0;
						flag=1;	
					}	
				}	
			} 
			break;	
		case 's':case 'S'://是否存在上面一个数字和自己的相同且不是0
			for(i=row-1;i>=1;i--)
			{
				for(j=0;j<col;j++)
				{
					if(map[i][j]>0&&map[i][j]==map[i-1][j])
					{
						map[i][j]*=2;
						map[i-1][j]=0;
						flag=1;	
					} 
				}
			}
			break;	
		case 'a':case 'A'://是否存在右面一个数字和自己的相同且不是0
			for(i=0;i<row;i++)
			{
				for(j=0;j<col-1;j++)
				{
					if(map[i][j]>0&&map[i][j]==map[i][j+1])
					{
						map[i][j]*=2;
						map[i][j+1]=0;
						flag=1;
					}
				}
			}
			break;	
		case 'd':case 'D'://是否存在左面一个数字和自己的相同且不是0
			for(i=0;i<row;i++)
			{
				for(j=col-1;j>=1;j--)
				{
					if(map[i][j]>0&&map[i][j]==map[i][j-1])
					{
						map[i][j]*=2;
						map[i][j-1]=0;
						flag=1; 
					}
				}
			}
			break;	
		default:
			break;
	} 
	return flag;
}

//gotoxy函数的实现,把光标移到到指定位置 
void gotoxy(int x,int y)
{
	COORD pos;
	pos.X=y;
	pos.Y=x;
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos); 
} 

设计解析

总体来说,我们需要准备以下几个步骤:
1.设计存储地图的二维数组
2.打印地图
3.是否已经过关的判断
4.随机将地图中一个为0的元素生成2或4
5.获取玩家的移动或合并请求
6.处理移动和合并是否成功,成功则重新再将一个随机元素为0的生成2或4
7.优化,调用gotoxy使得不闪屏
8.有兴趣的还可以在满屏数字的时候加上判断,判断是否已经无法移动或者合并(提示,在移动和合并的基础上修改便可达到)

设计总结

2048曾是一个广为人知的小游戏,以其简单、有趣的游戏规则深受大家的喜爱,和当初俄罗斯方块刚设计出来一样备受欢迎,如今我们在日渐深入学习c语言的道路上,就可以将平时所见所知尝试着用编程去实现,让编程成为生活不可或缺的一部分。
在设计这个小游戏的过程中,我们首先需要懂得它的详细规则,这意味着我们完成它的制作会涉及到很多逻辑思考,比如生成随机数怎么控制生成2的概率是生成4的概率的3倍呢?怎么让数字移动起来呢?怎么合并数字?合并之后需要再移动一次吗?无形之中,我们的逻辑思维能力会得到很好的提高,为日后用编程处理复杂问题打下基础。
每次设计完成一个作品,然后就写个博客记录下来。以后回头翻看自己的记录,可能会觉得当初的设计非常幼稚,但是肯定也会非常庆幸以前的自己没有学完就把知识扔一边,而是把它运用到最容易提起自己兴趣的地方,每每想到这里,应该会挺开心的吧!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值