2048游戏 - C语言不引入图形库简单实现
声明:本程序绝大部分属于原创,交互部分参考了博客园 Judge Young的原创文章 游戏2048源代码 - C语言控制台界面版,
作者Judge Young的算法思想非常值得参考,感谢作者的分享
附上文章链接:https://www.cnblogs.com/judgeyoung/p/3760515.html
算法总体思想:(请结合思维导图观看,移动合并算法篇幅较大,部分放到函数注释)

- 游戏主体抽象:将游戏数字面板抽象为一个二维数组,0代表空格。
 - 移动合并算法:把每一行/列同等对待,只研究一行/列的移动和合并算法,通过遍历来实现所有行/列的移动合并算法。
 - 游戏结束条件:分为三种情况,主动退出、游戏失败和游戏胜利。
 - 随机数生成:寻找出空格,平均概率生成2 / 4。
 - 界面显示:利用清屏再打印,达到界面刷新效果。
 - 计分系统:游戏结束时,将所有格子中数字相加得到最终分数。
 - 矩阵翻转:为了减少代码量与复用函数,提高练习效果,这里牺牲了部分效率。
 - 备注:移动合并算法也可以通过矩阵翻转90度达到更好的函数复用效果,但效率更低。
 - 再备注:函数声明处有一个撤回功能,可以利用old_squares做出来,但由于作者嫌麻烦所以没有做。
 
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <time.h>
#define N	4				//矩阵大小为N * N
#define Max 2048			//胜利条件 
int squares[N][N];			//游戏矩阵
int sum;					//游戏积分
int old_squares[N][N];		//之前一步操作的矩阵 
void GameStart(void);		//游戏开始界面
void Print(void);			//打印界面、计分
void Operator(char op);		//对用户交互进行处理
int Operated(void);			//判断矩阵是否发生变化
void Copy(void);			//备份上一步的矩阵
void MoveUp(int op);		//上移方格
void MoveLeft(int op);		//左移方块
void Transpose(int op);		//矩阵翻转
int GameOver(char op);		//游戏结束:失败,退出和游戏胜利(需设置条件)
int Win(void);				//判断游戏胜利
//void Recall(void);		//撤回功能
void Random(void);			//生成随机数
int HasNull(void);			//判断矩阵存在空白位置
void PrintSum(void);		//计算游戏积分并打印
int main(void)
{
	char op = ' ';
	GameStart();
	Random();
	Operator(op);
	while (!GameOver(op)) {
		Copy();
		while (!Operated()) {
			op = getch();
			Operator(op);
		}
		Random();
		system("cls");
		Print();
	}
	system("pause");
	return 0;
}
//初始化游戏参数
void GameStart(void) {
	int i, j;
	sum = 0;
	for (i = 0; i < N; i++) {
		for (j = 0; j < N; j++) {
			squares[i][j] = 0;
			old_squares[i][j] = 0;
		}
	}
	printf("Press any key to start the game.\n");
}
//打印矩阵
void Print(void) {
	int i, j;
	for (i = 0; i < N; i++) {
		for (j = 0; j < N; j++) {
			if (squares[i][j] == 0) {
				printf(" \t");
				continue;
			}
			printf("%d\t", squares[i][j]);
		}
		printf("\n\n");
	}
	printf("\n");
	printf("(W)Up (S)Down (A)Left (D)Right\n");
	printf("    (Q)Quit (R)Recall\n\n");
}
void Operator(char op) {
	switch (op) {
	case 'w':
	case 'W':
		MoveUp(1); break;
	case 'a':
	case 'A':
		MoveLeft(1); break;
	case 's':
	case 'S':
		MoveUp(0); break;
	case 'd':
	case 'D':
		MoveLeft(0); break;
	default:
		break;
	}
}
int Operated(void) {
	int i, j;
	for (i = 0; i < N; i++) {
		for (j = 0; j < N; j++) {
			if (old_squares[i][j] != squares[i][j])
				return 1;
		}
	}
	return 0;
}
void Copy(void) {
	int i, j;
	for (i = 0; i < N; i++) {
		for (j = 0; j < N; j++) {
			old_squares[i][j] = squares[i][j];
		}
	}
}
//在一行中,使用两个下标变量来遍历列项,假设使用j和k,其中j总在k的后面,用来寻找k项后面第一个不为0的数字,而k项用于表示当前待比较的项,总是和j项之间隔着若干个数字0,或者干脆紧挨着。
void MoveUp(int op) {
	int i, j, k;
	if (op == 0)
		Transpose(0);
	for (i = 0; i < N; i++) {
		for (j = 1, k = 0; j < 4; j++) {
			if (squares[j][i] > 0) { /* 找出k后面第一个不为空的项,下标为j,之后分三种情况 */
				//合并
				if (squares[k][i] == squares[j][i]) {
					squares[k][i] = 2 * squares[k][i];
					squares[j][i] = 0;
					k++;
				}
				//移动
				else if (squares[k][i] == 0) {
					squares[k][i] = squares[j][i];
					squares[j][i] = 0;
				}
				//碰撞
				else {
					squares[k + 1][i] = squares[j][i];
					if (j != k + 1) { /* 原先两数不挨着 */
						squares[j][i] = 0;
					}
					k++;
				}
			}
		}
	}
	if (op == 0)
		Transpose(0);
}
void MoveLeft(int op) {
	int i, j, k;
	if (op == 0)
		Transpose(1);
	for (i = 0; i < N; i++) {
		for (j = 1, k = 0; j < 4; j++) {
			if (squares[i][j] > 0) {
				//合并
				if (squares[i][k] == squares[i][j]) {
					squares[i][k] = 2 * squares[i][k];
					squares[i][j] = 0;
					k++;
				}
				//移动
				else if (squares[i][k] == 0) {
					squares[i][k] = squares[i][j];
					squares[i][j] = 0;
				}
				//碰撞
				else {
					squares[i][k + 1] = squares[i][j];
					if (j != k + 1) { /* 原先两数不挨着 */
						squares[i][j] = 0;
					}
					k++;
				}
			}
		}
	}
	if (op == 0)
		Transpose(1);
}
void Transpose(int op) {
	int i, j, temp = 0;
	//左右翻转
	if (op == 1) {
		for (i = 0; i < N; i++) {
			for (j = 0; j < N / 2; j++) {
				temp = squares[i][j];
				squares[i][j] = squares[i][N - j - 1];
				squares[i][N - j - 1] = temp;
			}
		}
	}
	//上下翻转
	else {
		for (i = 0; i < N; i++) {
			for (j = 0; j < N / 2; j++) {
				temp = squares[j][i];
				squares[j][i] = squares[N - j - 1][i];
				squares[N - j - 1][i] = temp;
			}
		}
	}
}
int GameOver(char op) {
	int i, j;
	if (op == 'q' || op == 'Q')
		printf("You have quit the game! GameOver!\n");
	else if (Win())
		printf("Congratulation! You win!\n");
	else {
		if (HasNull())
			return 0;
		for (i = 1; i < N; i++) {
			for (j = 0; j < N; j++) {
				//任意两个相邻的单元值相同,游戏继续
				if (squares[i - 1][j] == squares[i][j])
					return 0;
				if (squares[j][i - 1] == squares[j][i])
					return 0;
			}
		}
	}
	PrintSum();
	return 1;
}
int Win(void) {
	int i, j;
	for (i = 0; i < N; i++) {
		for (j = 0; j < N; j++) {
			if (squares[i][j] == Max)
				return 1;
		}
	}
	return 0;
}
//在矩阵中随机位置生成数字2/4
void Random(void) {
	int sitex, sitey;
	sitex = rand() % 4;
	sitey = rand() % 4;
	while (squares[sitex][sitey] != 0) {
		sitex = rand() % 4;
		sitey = rand() % 4;
	}
	//生成2的概率是2/3,生成4的概率是1/3
	if (rand() % 3 == 0)
		squares[sitex][sitey] = 4;
	else
		squares[sitex][sitey] = 2;
}
int HasNull(void) {
	int i, j;
	for (i = 0; i < N; i++) {
		for (j = 0; j < N; j++) {
			if (squares[i][j] == 0)
				return 1;
		}
	}
	return 0;
}
void PrintSum(void) {
	int i, j;
	for (i = 0; i < N; i++)
		for (j = 0; j < N; j++)
			sum += squares[i][j];
	printf("Game Over! Your total score is: %d! \n", sum);
}
												
											2048游戏 - C语言不引入图形库简单实现的更多相关文章
- 2048游戏C语言代码
		
如果程序里面有错误,希望大家能够批评指正! #include<stdio.h> #include<stdlib.h> #include<conio.h> #incl ...
 - C++学习(三十九)(C语言部分)之 游戏项目(2048游戏)
		
/***************************项目 2048**********************c语言编写 图形库制作时间:2019.04.03 准备工具: vs2013 图形库 i ...
 - 一个用 C 语言写的迷你版 2048 游戏,仅仅有 500个字符
		
Jay Chan 用 C 语言写的一个迷你版 2048 游戏,仅仅有 487 个字符. 来围观吧 M[16],X=16,W,k;main(){T(system("stty cbreak&qu ...
 - powershell字符界面的,powershell加WPF界面的,2048游戏
		
------[序言]------ 1 2048游戏,有段时间很火,我在地铁上看有人玩过.没错,坐地铁很无聊,人家玩我就一直盯着看. 2 我在电脑上找了一个,试玩了以下,没几次格子就满了.我就气呼呼的放 ...
 - iOS雪花动画、音频图、新闻界面框架、2048游戏、二维码条形码扫码生成等源码
		
iOS精选源码 粒子雪花与烟花的动画 iOS 2048游戏 JHSoundWaveView - 简单地声波图.音波图 一个可快速集成的新闻详情界面框架,类似今日头条,腾讯新闻 二维码/条形码扫描及扫描 ...
 - [python] python实现2048游戏,及代码解析。
		
我初学python,有不对之处望大家指教.转载请征得同意. 我在网络上也找了一些2048游戏代码的讲解,但都不是特别详细.所以我希望能够尽量详细的讲解.同时,有的地方我也不懂,希望大家能帮助补充.我会 ...
 - cocos2d-x游戏开发实战原创视频讲座系列1之2048游戏开发
		
 cocos2d-x游戏开发实战原创视频讲座系列1之2048游戏开发 的产生 视持续更新中.... 视频存放地址例如以下:http://ipd.pps.tv/user/1058663622 ...
 - 用Python做2048游戏  网易云课堂配套实验课。通过GUI来体验编程的乐趣。
		
第1节 认识wxpython 第2节 画几个形状 第3节 再做个计算器 第4节 最后实现个2048游戏 实验1-认识wxpython 一.实验说明 1. 环境登录 无需密码自动登录,系统用户名shiy ...
 - android 2048游戏、kotlin应用、跑马灯、动画源码
		
Android精选源码 2048游戏源码 android实现获取号码归属地和其他信息诈骗.骚扰 android kotlin仿开眼app源码 android多种reveal动画效果 android K ...
 
随机推荐
- Linux学习笔记之ubuntu如何在vi中写入中文注释
			
点击左边设置system settings,再点击Language Suppotr 点击Remind Me Later 选择ibus 然后关闭,在终端写入ibus-setup,弹出设置框,选择INPU ...
 - 了解学习 Javascript, ES5 和 ES6之间的亲密关系
			
什么是Javascript JavaScript一种动态类型.弱类型.基于原型的客户端脚本语言,用来给HTML网页增加动态功能. JavaScript 的标准是 ECMAScript.截至 201 ...
 - Java Filter过滤器(拦截路径的配置+拦截方式的配置+生命周期+多个过滤器的先后执行顺序)
			
Java Filter过滤器+Listen监听器 啥是过滤器 顾名思义即过滤掉一些东西,比如我们经历的高考中考都是过滤器,他过滤掉一些在学习这一方面不是很好的人,而那些成绩好的人则升入高中,大学. 但 ...
 - C#LeetCode刷题-树
			
树篇 # 题名 刷题 通过率 难度 94 二叉树的中序遍历 61.6% 中等 95 不同的二叉搜索树 II 43.4% 中等 96 不同的二叉搜索树 51.6% 中等 98 验证二叉搜索树 ...
 - 使用Python Openssl库解析X509证书信息
			
X.509 证书结构描述 常见的X.509证书格式包括: 后缀 作用 cer/crt 用于存放证书,它是2进制形式存放的,不含私钥 pem 以Ascii来表示,可以用于存放证书或私钥. pfx/p12 ...
 - JDBC API阐述
			
JDBC API JDBC API 是一系列的接口,它使得应用程序能够进行数据库联接,执行SQL语句,并且得到返回结果. Driver 接口 Java.sql.Driver 接口是所有 JDBC 驱动 ...
 - 高德地图marker事件监听-高德地图marker绑定事件就执行了[解决立即执行]
			
官方的demo是这样的:地址:[http://lbs.amap.com/api/javascript-api/example/infowindow/add-infowindows-to-multipl ...
 - src rpm 下载地址
			
drbd: http://mirror.rackspace.com/elrepo/elrepo/el7/SRPMS/ rabbitmq: https://dl.bintray.com/rabbitmq ...
 - Robot Framework(7)——接口测试
			
一.准备工作 1.安装requests工具(2.22.0) 下载地址:https://pypi.org/project/requests/ 安装方式: 1>下载压缩文件,解压,目录切到解压目录, ...
 - Federated Optimization: Distributed Machine Learning for On-Device Intelligence
			
郑重声明:原文参见标题,如有侵权,请联系作者,将会撤销发布! arXiv:1610.02527v1 [cs.LG] 8 Oct 2016 坐标下降法:https://blog.csdn.net/qq_ ...