IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 游戏2048(C语言实现) -> 正文阅读

[C++知识库]游戏2048(C语言实现)

游戏2048总结

游戏逻辑:

初始化地图—>打印地图—>移动,旋转—>记录历史—>添加随机数—>判断是否失败

知识点:

  • 打印

  • 移动:一个方向里有相同大小的两个数且中间没有其他数字则可以合并

数组中默认下标为-1 当遇到不为0的数时候 index的值由-1改为该不为零的数的下标,然后用标记的该数第二层for循环执行j++ 与下一个数进行比较 如果相同执行加法 把标记的该数+=[i][j] 且 相同数的索引改为-1表示不满足 继续寻找!=0的数 修改其索引执行加法

//移动
	for (int i = 0; i < N; i++)
	{
		int index = -1; //默认下标为-1         
		for (int j = 0; j < N; j++)
		{        //下一次进来j++变为1      0  1
			if (index != -1 && g_2048map[i][j] == g_2048map[i][index])  //下标不为-1 且 两个位置的数相同
			{
				g_2048map[i][index] += g_2048map[i][j];  
				g_2048map[i][j] = 0;   
			}
			else if (g_2048map[i][j] != 0)  //[0][0]  index=0
			{
				index = j;   //如果此位置不为0 则赋值index为此位置的下标
			}
		}
	}

2 2 0 0 先执行index=j;此时index为0 j++ j的值由0改为1 然后进入if=>第一个不为0的数和他的下一位数进行比较 如果相同做加法 不同继续修改索引为下一个不为0的数的下标

  • 合并:寻找0的位置 找到后挨个与本行不为0的数比较 如果位置在不为0的数之前则调换位置
	//合并
	for (int i = 0; i < N; i++)
	{
		int k = 99;   //k用来记录下标  默认99为无效
		for (int j = 0; j < N; j++)
		{
			for (int m = 0; m < N; m++)   //m循环用于辅助寻找0的位置
			{
				if (g_2048map[i][m] == 0)  //有空位置的时候记录空位置
				{
					k = m;  //此时m已经赋值给k 存放着0的位置
					break;
				}
			}

			if (k == 99) // 如果没有0 则=99 如果k=99则执行跳出本行从下一行开始
			{
				break;
			}

			if (k < j && g_2048map[i][j] != 0)  //k在j的前面 j前有0 则 调换j和0的位置
			{
				g_2048map[i][k] = g_2048map[i][j];
				g_2048map[i][j] = 0;
			}

		}

	}
  • 矩阵旋转:逆时针旋转的公式:int x=j; int y=N-i-1;
//TODO 矩阵旋转  逆时针
static void Rotation()
{
	int map[N][N] = { 0 };
	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < N; j++)
		{
			int x = j;
			int y = N - i - 1;
			map[x][y] = g_2048map[i][j];

		}

	}

	//把map中的内容复制给g_2048map
	memcpy(g_2048map, map, sizeof(int) * N * N);
}
  • 环形数组:数组长度固定但是记录的内容是循环的,当超过长度内容后覆盖掉先进入的内容

环形数组的头:g_historyStart=-1; 之所以等于-1 是因为g_historyStart++执行后从0开始

环形数组的尾:g_historyEnd;当head-tail=长度时候 tail++;

//TODO  记录历史
static void WriteHistory()
{
	//生成历史记录
	g_historyStart++;
	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < N; j++)
		{
			g_2048history[g_historyStart % g_historyLength][i][j] = g_2048map[i][j];
		}
	}
	if (g_historyStart - g_historyEnd == g_historyLength)
	{
		g_historyEnd++;
	}

}

回退的条件是头只能大于等于尾 不能小于尾

//TODO  回退
static void BackHistory()
{
	if (g_historyStart >= g_historyEnd)
	{
		for (int i = 0; i < N; i++)
		{
			for (int j = 0; j < N; j++)
			{
				g_2048map[i][j] = g_2048history[g_historyStart % g_historyLength][i][j];
			}
		}
		g_historyStart--;
	}
}
  • 拷贝内存:用一个新的数组(copymap[][])记录移动之前的地图,移动之后用地图(g_2048map[][])和之前拷贝的地图进行比较,判断是否为有效移动。
  • 初始化地图:初始化地图中元素的数量,初始化地图中元素的位置。

使用随机数函数rand(); 设置随机数种子srand((unsigned)time(NULL));

//TODO 初始化地图
static void InitMap()
{
	srand((unsigned)time(NULL));
	//地图里面有几个数
	int num = 2 + 2 * (rand() % 3 + 1);
	for (int i = 0; i < num; i++)
	{
		int xx = rand() % 4;
		int yy = rand() % 4;
		if (g_2048map[xx][yy] == 0)
		{
			g_2048map[xx][yy] = (rand() % 2 + 1) * 2;
		}
		else  //如果不为0继续放置一个数
		{
			num++;
		}

	}
}
  • 判断是否为满:如果有位置为0的时候就返回1 否则返回0 只有所有位置都不为0的时候才返回1
//TODO判断是否为满  满的时候返回0
static int IsFull()
{
	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < N; j++)
		{
			if (g_2048map[i][j] == 0)
			{
				return 1; //不满的时候返回1
			}

		}

	}
	return 0;  //满的时候返回0

}
  • 生成新的元素:在有空位且有效移动的时候生成新的元素 判断是否有效移动是在移动前和移动后进行比较,移动前备份与移动后进行比较。
//TODO 生成新的随机数
static void AddNum()
{
	if (IsFull())
	{
		int xx = rand() % 4;
		int yy = rand() % 4;

		while (g_2048map[xx][yy] != 0) //当随机生成的位置不为0的时候
		{
			//再次生成随机数  直到位置没有数的时候
			xx = rand() % 4;
			yy = rand() % 4;
		}
		int bflag = rand() % 2;  //随机生成的数是多少
		if (bflag == 0)
		{
			g_2048map[xx][yy] = 2;
		}
		else
			g_2048map[xx][yy] = 4;

		printf("[%d] %[%d]--->[%d]\n", xx, yy, g_2048map[xx][yy]);
	}

}
  • 判断游戏是否结束:判断每个数的右边和下面是否可以合并 内存循环N-1 只要其中有一个方向可以移动就返回1,否则表示不可以移动返回0!!!
//TODO 是否失败  失败返回0
static int IsFail()
{
	//判断每个数右边和下边的还能不能继续合并
	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < N - 1; j++)
		{
			if (g_2048map[i][j] == g_2048map[i][j + 1])  //判断右边的
			{
				return 1;
			}
			else if (g_2048map[j][i] == g_2048map[j + 1][i]) //判断下面的
			{
				return 1;
			}

		}

	}
	return 0;
}
  • main函数:逻辑要正确,每次记录的是它旋转移动好之后的地图,所以写入历史记录是在移动和旋转之后的;

每次摁一个方向键,旋转和移动加起来执行的次数是4次 只是不同方向的旋转移动执行的先后顺序不同;

p=Left(); 用于记录是否是有效移动,left函数是移动函数,都会执行!!!!!

int main()
{
	int pause = 1;   //游戏是否暂停
	int bflag = -2;  //移动的次序
	InitMap();
	Print();
	while (1)
	{
		char c = _getch();
		switch (c)
		{
		case 'w':bflag = 3;
			break;
		case 'a':bflag = 0;
			break;
		case 's':bflag = 1;
			break;
		case 'd':bflag = 2;
			break;
		case 'p': pause = !pause;
			printf("游戏暂停或继续\n");
			break;
		case 'z':BackHistory();
			break;
		default:
			break;
		}

		//摁过P之后不会执行以下代码  游戏暂停
		if (pause)
		{
			//记录是否相同  p为返回的值     
			int p = 0; 
            
			//移动和旋转  次序不同
			for (int i = 0; i < N; i++)
			{
				if (bflag == i)
				{
					//都执行  p和left()都执行  移动->合并->返回值
					p = Left();
				}
				Rotation();
			}

			//记录历史
			WriteHistory();
            //是否为有效移动  如果是添加随机数生成新的元素
			if (p)
			{
				AddNum();
			}
            
			//判断游戏是否结束
			if (!IsFail())
			{
				break;
			}

		}
		Print();
	}
	return 0;
}

附上2048源码(可回退,保存历史记录)

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <time.h>
#include <windows.h>
#define M 100
#define N 4

//2048的地图
static int g_2048map[N][N];
//2048的历史记录
static int g_2048history[M][N][N];
//环形数组的起点
static int g_historyStart = -1;
//环形数组的终点
static int g_historyEnd = 0;
//最大记录次数
static int g_historyLength = 10;

//TODO 打印地图 
static void Print()
{

	system("cls");
	printf("-----------------------------\n");
	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < N; j++)
		{
			printf("%4d", g_2048map[i][j]);
		}
		printf("\n\n");
	}
	printf("-----------------------------\n");

}

//TODO 初始化地图
static void InitMap()
{
	srand((unsigned)time(NULL));
	//地图里面有几个数
	int num = 2 + 2 * (rand() % 3 + 1);
	for (int i = 0; i < num; i++)
	{
		int xx = rand() % 4;
		int yy = rand() % 4;
		if (g_2048map[xx][yy] == 0)
		{
			g_2048map[xx][yy] = (rand() % 2 + 1) * 2;
		}
		else
		{
			num++;
		}

	}
}

//TODO 向左移动
static int Left()
{
	//拷贝当前地图用于判断是否生成新的数
	int copymap[N][N];
	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < N; j++)
		{
			copymap[i][j] = g_2048map[i][j];
		}
	}

	//移动
	for (int i = 0; i < N; i++)
	{
		int index = -1; //默认下标为-1          2 2 0 0
		for (int j = 0; j < N; j++)
		{
			if (index != -1 && g_2048map[i][j] == g_2048map[i][index])  //下标不为-1 且 两个位置的数相同
			{
				g_2048map[i][index] += g_2048map[i][j];  
				g_2048map[i][j] = 0;   
			}
			else if (g_2048map[i][j] != 0)  //[0][0]  index=0
			{
				index = j;   //如果此位置不为0 则赋值index为此位置的下标
			}
		}
	}

	//合并
	for (int i = 0; i < N; i++)
	{
		int k = 99;   //k用来记录下标  默认99为无效
		for (int j = 0; j < N; j++)
		{
			for (int m = 0; m < N; m++)   //m循环用于辅助寻找0的位置
			{
				if (g_2048map[i][m] == 0)  //有空位置的时候记录空位置
				{
					k = m;  //此时m已经赋值给k 存放着0的位置
					break;
				}
			}

			if (k == 99) // 如果没有0 则=99 如果k=99则执行跳出本行从下一行开始
			{
				break;
			}

			if (k < j && g_2048map[i][j] != 0)  //k在j的前面 j前有0 则 调换j和0的位置
			{
				g_2048map[i][k] = g_2048map[i][j];
				g_2048map[i][j] = 0;
			}

		}

	}

	//判断地图是否改变
	//备份上一次的地图和本次进行比较
	//如果移动后和移动前地图不变返回 0
	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < N; j++)
		{
			if (copymap[i][j] != g_2048map[i][j])
			{
				return 1;
			}

		}

	}
	return 0;
}

//TODO 生成新的随机数
static void AddNum()
{
	if (IsFull())
	{
		int xx = rand() % 4;
		int yy = rand() % 4;

		while (g_2048map[xx][yy] != 0) //当随机生成的位置不为0的时候
		{
			//再次生成随机数
			xx = rand() % 4;
			yy = rand() % 4;
		}
		int bflag = rand() % 2;
		if (bflag == 0)
		{
			g_2048map[xx][yy] = 2;
		}
		else
			g_2048map[xx][yy] = 4;

		printf("[%d] %[%d]--->[%d]\n", xx, yy, g_2048map[xx][yy]);
	}

}

//TODO 矩阵旋转
static void Rotation()
{
	int map[N][N] = { 0 };
	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < N; j++)
		{
			int x = j;
			int y = N - i - 1;
			map[x][y] = g_2048map[i][j];

		}

	}

	//把map中的内容复制给g_2048map
	memcpy(g_2048map, map, sizeof(int) * N * N);
}

//TODO判断是否为满  满的时候返回0
static int IsFull()
{
	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < N; j++)
		{
			if (g_2048map[i][j] == 0)
			{
				return 1; //不满的时候返回1
			}

		}

	}
	return 0;  //满的时候返回0

}

//TODO 是否失败  失败返回0
static int IsFail()
{
	//判断每个数右边和下边的还能不能继续合并
	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < N - 1; j++)
		{
			if (g_2048map[i][j] == g_2048map[i][j + 1])  //判断右边的
			{
				return 1;
			}
			else if (g_2048map[j][i] == g_2048map[j + 1][i]) //判断下面的
			{
				return 1;
			}

		}

	}
	return 0;
}

//TODO  记录历史
static void WriteHistory()
{
	//生成历史记录
	g_historyStart++;
	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < N; j++)
		{
			g_2048history[g_historyStart % g_historyLength][i][j] = g_2048map[i][j];
		}
	}
	if (g_historyStart - g_historyEnd == g_historyLength)
	{
		g_historyEnd++;
	}

}

//TODO  回退
static void BackHistory()
{
	if (g_historyStart >= g_historyEnd)
	{
		for (int i = 0; i < N; i++)
		{
			for (int j = 0; j < N; j++)
			{
				g_2048map[i][j] = g_2048history[g_historyStart % g_historyLength][i][j];
			}
		}
		g_historyStart--;
	}
}

int main8112()
{
	system("title 姓名:苏林波 学校:湖南文理学院 年份:2021 项目名称:2048-指针之前");
	int pause = 1;
	int bflag = -2;
	InitMap();
	Print();
	while (1)
	{
		char c = _getch();
		switch (c)
		{
		case 'w':bflag = 3;
			break;
		case 'a':bflag = 0;
			break;
		case 's':bflag = 1;
			break;
		case 'd':bflag = 2;
			break;
		case 'p': pause = !pause;
			printf("游戏暂停或继续\n");
			break;
		case 'z':BackHistory();
			break;
		default:
			break;
		}

		//摁过P之后不会执行以下代码
		if (pause)
		{
			//记录是否相同返回的值     
			int p = 0; 
			//移动和旋转  次序不同
			for (int i = 0; i < N; i++)
			{
				if (bflag == i)
				{
					//都执行  p和left()都执行  移动->合并->返回值
					p = Left();
				}
				Rotation();
			}

			//记录历史
			WriteHistory();
			if (p)
			{
				AddNum();
			}
			//判断游戏是否结束
			if (!IsFail())
			{
				break;
			}

		}
		Print();



	}
	return 0;
}

双人模式的2048可回退,有历史记录
在这里插入图片描述

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <time.h>
#include <windows.h>
#define M 10
#define N 4


//2048数据结构
//游戏是否结束 
//是否可以移动
//地图是否有改变

//玩家Squre

typedef struct tagSqure
{
	//是否可以移动
	int bmove;
	//地图是否改变
	int bchange;
	//游戏是否结束
	int bover;
	//数字是否满
	int bfull;
	//游戏是否暂停
	int bstop;
	//旋转次数
	int rtime;
	//移动次数
	int movetime;
	//最大分数
	int mostScore;
	//历史记录的地图
	int hismap[M][N][N];
	//环形数组头
	int start;
	//环形数组尾巴
	int end;
	//长度
	int len;
	//结构体类型
	int bpause;

	//游戏地图
	int gmap[N][N];
	//用于拷贝的游戏地图
	int gcmap[N][N];


}TSqure, * PTSqure;




//初始化玩家Squre
static void InitSqure(PTSqure* pSqure)
{
	//PTSqure p = *pSqure;
	(*pSqure)->bmove = 0;
	(*pSqure)->bchange = 0;
	(*pSqure)->bover = 0;
	(*pSqure)->bfull = 0;
	(*pSqure)->bstop = 0;
	(*pSqure)->rtime = 0;
	(*pSqure)->bpause = 0;
	(*pSqure)->mostScore = 0;
	(*pSqure)->movetime = 0;
	memset((*pSqure)->hismap, 0, sizeof(int) * M * N * N);
	memset((*pSqure)->gmap, 0, sizeof(int) * N * N);
	memset((*pSqure)->gcmap, 0, sizeof(int) * N * N);
	(*pSqure)->start = -1;
	(*pSqure)->end = 0;
	(*pSqure)->len = 10;
	return *pSqure;
}





//释放玩家Squre
static void FreeSqure(PTSqure pSqure)
{
	if (pSqure == NULL)
	{
		return;
	}
	free(pSqure);
}



//输出
static void PrintSqure(PTSqure pSqure)
{
	COORD coord1;
	coord1.X = 20; //列
	coord1.Y = 6;  //行
	for (int i = 0; i < N; i++)
	{
		SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord1);
		for (int j = 0; j < N; j++)
		{
			printf("%4d", pSqure->gmap[i][j]);
		}
		coord1.Y += 2;
	}
	printf("\033[5;20H\033[36m   >>>\033[35m玩家Squre\033[36m<<<\033[0m");
	printf("\033[6;20H\033[36m=====================\033[0m");
	printf("\033[14;20H\033[36m=====================\033[0m");
	printf("\033[7;22H\033[36m|\033[0m");
	printf("\033[8;22H\033[36m|\033[0m");
	printf("\033[9;22H\033[36m|\033[0m");
	printf("\033[10;22H\033[36m|\033[0m");
	printf("\033[11;22H\033[36m|\033[0m");
	printf("\033[12;22H\033[36m|\033[0m");
	printf("\033[13;22H\033[36m|\033[0m");
	printf("\033[7;38H\033[36m|\033[0m");
	printf("\033[8;38H\033[36m|\033[0m");
	printf("\033[9;38H\033[36m|\033[0m");
	printf("\033[10;38H\033[36m|\033[0m");
	printf("\033[11;38H\033[36m|\033[0m");
	printf("\033[12;38H\033[36m|\033[0m");
	printf("\033[13;38H\033[36m|\033[0m");

	printf("\033[16;22H有效移动步数=>%d", pSqure->movetime);
	printf("\033[17;22H2048游戏得分=>%d", pSqure->mostScore);
	if (pSqure->bstop)
		printf("\033[18;22H2048游戏状态=>暂停中");
	else
		printf("\033[18;22H2048游戏状态=>游戏中");
	printf("\033[19;22H游戏记录步数=>%d", pSqure->start + 1);



}



//输出Block
static void PrintBlock(PTSqure pSqure)
{
	COORD coord;
	coord.X = 60;//li
	coord.Y = 6;//h
	for (int i = 0; i < N; i++)
	{
		SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
		for (int j = 0; j < N; j++)
		{
			printf("%4d", pSqure->gmap[i][j]);
		}
		coord.Y += 2;
	}
	printf("\033[5;60H\033[36m   >>>\033[35m玩家Block\033[36m<<<\033[0m");
	printf("\033[6;60H\033[36m=====================\033[0m");
	printf("\033[14;60H\033[36m=====================\033[0m");
	printf("\033[7;62H\033[36m|\033[0m");
	printf("\033[8;62H\033[36m|\033[0m");
	printf("\033[9;62H\033[36m|\033[0m");
	printf("\033[10;62H\033[36m|\033[0m");
	printf("\033[11;62H\033[36m|\033[0m");
	printf("\033[12;62H\033[36m|\033[0m");
	printf("\033[13;62H\033[36m|\033[0m");
	printf("\033[7;78H\033[36m|\033[0m");
	printf("\033[8;78H\033[36m|\033[0m");
	printf("\033[9;78H\033[36m|\033[0m");
	printf("\033[10;78H\033[36m|\033[0m");
	printf("\033[11;78H\033[36m|\033[0m");
	printf("\033[12;78H\033[36m|\033[0m");
	printf("\033[13;78H\033[36m|\033[0m");

	printf("\033[16;62H有效移动步数=>%d", pSqure->movetime);
	printf("\033[17;62H2048游戏得分=>%d", pSqure->mostScore);
	if (pSqure->bstop)
		printf("\033[18;62H2048游戏状态=>暂停中");
	else
		printf("\033[18;62H2048游戏状态=>游戏中");
	printf("\033[19;62H游戏记录步数=>%d", pSqure->start + 1);

}


//初始化地图
static void InitMap(PTSqure pSqure)
{

	//地图里面有几个数
	int num = (rand() % 3 + 1) * 2 + 2;
	for (int j = 0; j < num; j++)
	{
		//srand((unsigned)time(NULL));
		int xx = rand() % 4;
		int yy = rand() % 4;
		if (pSqure->gmap[xx][yy] == 0)
		{
			pSqure->gmap[xx][yy] = (rand() % 2 + 1) * 2;
		}
		else
			num++;
	}
}


//拷贝当前地图
static void CopyMap(PTSqure pSqure)
{
	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < N; j++)
		{
			pSqure->gcmap[i][j] = pSqure->gmap[i][j];
		}
	}
}


//移动 合并
static void Move(PTSqure pSqure)
{
	//移动
	for (int i = 0; i < N; i++)
	{
		//默认无效
		int index = -1;
		for (int j = 0; j < N; j++)
		{

			if (index != -1 && pSqure->gmap[i][j] == pSqure->gmap[i][index])
			{
				pSqure->gmap[i][index] += pSqure->gmap[i][j];
				pSqure->gmap[i][j] = 0;
			}
			else if (pSqure->gmap[i][j] != 0)
			{
				index = j;
			}
		}
	}
	//合并
	for (int i = 0; i < N; i++)
	{
		int p = 100;
		for (int j = 0; j < N; j++)
		{
			for (int t = 0; i < N; t++)
			{
				if (pSqure->gmap[i][t] == 0)
				{
					p = t;
					break;
				}
			}
			if (p == 100)
			{
				break;
			}
			if (p < j && pSqure->gmap[i][j] != 0)
			{
				pSqure->gmap[i][p] = pSqure->gmap[i][j];
				pSqure->gmap[i][j] = 0;
			}

		}

	}
}


//判断地图石头改变
static int JudgeMapChange(PTSqure pSqure)
{
	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < N; j++)
		{
			if (pSqure->gmap[i][j] != pSqure->gcmap[i][j])
			{
				//地图已经改变
				return 1;
			}
		}
	}
	return 0;
}

//左移动
static void Left(PTSqure pSqure)
{
	//移动前拷贝地图
	CopyMap(pSqure);
	//移动
	Move(pSqure);
	//移动后比较是否改变
	pSqure->bchange = JudgeMapChange(pSqure);
}

//生成新的随机数
static void AddNums(PTSqure pSqure)
{
	if (pSqure->bfull)
	{
		int xx = rand() % 4;
		int yy = rand() % 4;
		while (pSqure->gmap[xx][yy] != 0)
		{
			xx = rand() % 4;
			yy = rand() % 4;
		}
		int bflag = rand() % 3;
		if (bflag == 0)
			pSqure->gmap[xx][yy] = 4;
		else
			pSqure->gmap[xx][yy] = 2;
	}
}


//矩阵旋转
static void SqureRotation(PTSqure pSqure)
{
	int squre[N][N] = { 0 };
	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < N; j++)
		{
			int x = j;
			int y = N - i - 1;
			squre[x][y] = pSqure->gmap[i][j];
		}
	}
	memcpy(pSqure->gmap, squre, sizeof(int) * N * N);
}

//判断是否为满
static int JudgeFull(PTSqure pSqure)
{
	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < N; j++)
		{
			if (pSqure->gmap[i][j] == 0)
			{
				//返回1 表示未满
				return 1;
			}
		}
	}
	return 0;
}

//判断是否失败
static int JudgeFail(PTSqure pSqure)
{//1未满  0表示满

		//判断每个数右边和下边的还能不能继续合并
	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < N - 1; j++)
		{
			if (pSqure->gmap[i][j] == pSqure->gmap[i][j + 1])  //判断右边的
			{
				// 1表示未失败
				return 1;
			}
			else if (pSqure->gmap[j][i] == pSqure->gmap[j + 1][i]) //判断下面的
			{
				return 1;
			}

		}

	}
	return 0;
}

//最大分数
static void MostScore(PTSqure pSqure)
{
	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < N; j++)
		{
			if (pSqure->gmap[i][j] > pSqure->mostScore)
			{
				pSqure->mostScore = pSqure->gmap[i][j];
			}
		}
	}
}


//记录历史记录
static void WriteHistory(PTSqure pSqure)
{
	pSqure->start++;
	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < N; j++)
			pSqure->hismap[pSqure->start % pSqure->len][i][j] = pSqure->gmap[i][j];
		if (pSqure->start - pSqure->end == pSqure->len)
		{
			pSqure->end++;
		}
	}

}


//回退
static void BackHistory(PTSqure pSqure)
{
	if (pSqure->start >= pSqure->end)
	{
		for (int i = 0; i < N; i++)
		{
			for (int j = 0; j < N; j++)
			{
				pSqure->gmap[i][j] = pSqure->hismap[pSqure->start % pSqure->len][i][j];

			}
		}
		pSqure->start--;
	}
}


//玩家squre死去
static void GameSqureOver(PTSqure pSqure)
{
	float score = ((float)(pSqure->movetime) / (float)(pSqure->start + 1)) * ((float)(pSqure->mostScore));
	printf("\033[21;22H\033[31m玩家Squre无法移动,游戏结束\033[0m");
	printf("\033[22;22H\033[31m玩家Squre得分为=>\033[33m%.4f\033[0m", score);
}

static void GameBlockOver(PTSqure pBlock)
{
	float score = ((float)(pBlock->movetime) / (float)(pBlock->start + 1)) * ((float)(pBlock->mostScore));
	printf("\033[21;62H\033[31m玩家Squre无法移动,游戏结束\033[0m");
	printf("\033[22;62H\033[31m玩家Squre得分为=>\033[33m%.4f\033[0m", score);
}


//写文件
static void FileWrite(PTSqure pSqure)
{
	FILE* pfile = fopen("TheSqure2048.bin", "wb");
	if (pfile == NULL)
	{
		printf("文件打开失败");
		return;
	}
	fwrite(pSqure, 1, sizeof(TSqure), pfile);
	printf("\033[20;22H二进制存档成功!");
	Sleep(1000);
	printf("\033[20;22H                   ");
	fclose(pfile);

}
//读文件
static void FileRead(PTSqure pSqure)
{
	FILE* pfile = fopen("TheSqure2048.bin", "rb");
	if (pfile == NULL)
	{
		printf("文件打开失败");
		return;
	}
	FreeSqure(pSqure);
	fread(pSqure, 1, sizeof(TSqure), pfile);
	printf("\033[20;22H                        ");
	printf("\033[21;22H                        ");
	printf("\033[22;22H                        ");
	printf("\033[23;22H                        ");
	printf("\033[24;22H                        ");
	fclose(pfile);
}


static void FileBlockWrite(PTSqure pSqure)
{
	FILE* pfile = fopen("TheBlock2048.bin", "wb");
	if (pfile == NULL)
	{
		printf("文件打开失败");
		return;
	}
	fwrite(pSqure, 1, sizeof(TSqure), pfile);
	printf("\033[20;26H二进制存档成功!");
	Sleep(1000);
	printf("\033[20;62H                   ");
	fclose(pfile);

}

static void FileBlockRead(PTSqure pSqure)
{
	FILE* pfile = fopen("TheBlock2048.bin", "rb");
	if (pfile == NULL)
	{
		printf("文件打开失败");
		return;
	}
	FreeSqure(pSqure);
	fread(pSqure, 1, sizeof(TSqure), pfile);
	printf("\033[20;62H                        ");
	printf("\033[21;62H                        ");
	printf("\033[22;62H                        ");
	printf("\033[23;62H                        ");
	printf("\033[24;62H                        ");
	fclose(pfile);
}



static void Console(PTSqure pSqure)
{
	if (!pSqure->bstop)
	{
		for (int i = 0; i < N; i++)
		{
			if (pSqure->rtime == i)
			{
				Left(pSqure);
			}
			SqureRotation(pSqure);
		}
		MostScore(pSqure);
		WriteHistory(pSqure);
		pSqure->bfull = JudgeFull(pSqure);
		if (pSqure->bchange)
		{
			pSqure->movetime++;
			AddNums(pSqure);
		}
		pSqure->bover = JudgeFail(pSqure);
		//如果游失败 则暂停游戏

	}
}







int main81300()
{
	srand((unsigned)time(NULL));
	printf("\033[?25l");
	PTSqure pSqure = malloc(sizeof(TSqure));
	PTSqure pBlock = malloc(sizeof(TSqure));

	InitSqure(&pSqure);
	InitSqure(&pBlock);

	InitMap(pSqure);
	InitMap(pBlock);

	PrintSqure(pSqure);
	PrintBlock(pBlock);
	while (1)
	{
		int bflag = -2;
		char c = _getch();
		//p控制
		switch (c)
		{
		case 'w':
			pSqure->rtime = 3;
			bflag = 0;
			break;
		case 'a':
			pSqure->rtime = 0;
			bflag = 0;
			break;
		case 's':
			pSqure->rtime = 1;
			bflag = 0;
			break;
		case 'd':
			pSqure->rtime = 2;
			bflag = 0;
			break;
		case '1':
			pSqure->bstop = !pSqure->bstop;  //默认为0
			PrintSqure(pSqure);
			break;
		case '2':
			if (pSqure->bstop)
			{
				BackHistory(pSqure);
				PrintSqure(pSqure);
				break;
			}
			else
			{
				printf("\033[20;22H请暂停游戏再回退!");
				Sleep(1500);
				printf("\033[20;22H                   ");
				break;
			}
			break;
		case '3':
			if (pSqure->bstop)
			{
				FileWrite(pSqure);
				break;
			}
			else
			{
				printf("\033[20;22H请暂停游戏再存档!");
				Sleep(1500);
				printf("\033[20;22H                   ");
				break;
			}
			break;
		case '4':
			FileRead(pSqure);
			PrintSqure(pSqure);
			break;
		case 'i':
			pBlock->rtime = 3;
			bflag = 1;
			break;
		case 'j':
			pBlock->rtime = 0;
			bflag = 1;
			break;
		case 'k':
			pBlock->rtime = 1;
			bflag = 1;
			break;
		case 'l':
			pBlock->rtime = 2;
			bflag = 1;
			break;
		case '6':
			pBlock->bstop = !pBlock->bstop;  //默认为0
			PrintBlock(pBlock);
			break;
		case '7':
			if (pBlock->bstop)
			{
				BackHistory(pBlock);
				PrintBlock(pBlock);
				break;
			}
			else
			{
				printf("\033[20;62H请暂停游戏再回退!");
				Sleep(1500);
				printf("\033[20;62H                   ");
				break;
			}
			break;
		case '8':
			if (pBlock->bstop)
			{
				FileBlockWrite(pBlock);
				break;
			}
			else
			{
				printf("\033[20;62H请暂停游戏再存档!");
				Sleep(1500);
				printf("\033[20;62H                   ");
				break;
			}
			break;
		case '9':
			FileBlockRead(pBlock);
			break;
		default:
			break;
		}


		switch (bflag)
		{
		case 0:
		{
			Console(pSqure);
			if (!pSqure->bover)
			{
				pSqure->bstop = 1;
				GameSqureOver(pSqure);
			}
			PrintSqure(pSqure);
		}
		break;
		case 1:
		{
			Console(pBlock);
			if (!pBlock->bover)
			{
				pBlock->bstop = 1;
				GameBlockOver(pSqure);
			}
			PrintBlock(pBlock);
		}
		break;
		default:
			break;
		}

	}
	return 0;
}
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-01 11:44:21  更:2021-09-01 11:46:03 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/27 21:14:39-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计