2048游戏 C语言源代码 附带存档功能

大一新生 自学两个月C语言 代码风格不好见谅

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

#define VK_W 119
#define VK_A 97
#define VK_S 115
#define VK_D 100
#define VK_Q 113
#define VK_M 109
#define VK_R 114
#define VK_N 110

void print_map(void);          //打印地图,并在地图上随机打印2或4方块
void move_up(void);
void move_right(void);
void move_down(void);
void move_left(void);
void swap(int *a, int *b);     //交换方块
bool game_over(void);         //游戏失败判定
void read_save(void);         //读取游戏存档
void save_data(void);         //保存游戏
void save_high_score(void);   //保存最高分
void read_high_score(void);   //读取最高分
void check_move(void);        //检查是否可以移动(将数组M导入临时数组temp中)
int  is_move(void);           //检查是否可以移动(比较M和temp数组,如果相同,则无法移动)

unsigned int M[4][4] = { 0 }, temp[4][4] = { 0 };          //M为棋盘
int score = 0, step = 0, high_score = 0, flag = 0;        //flag用来判定是否可以移动或键盘输入指令是否合法
int *q = &score, *p = &high_score;

int main(void)
{
	int key_command;
	printf("--------------------GAME:2048---------------------\n按下R读取游戏存档,按下M键删除存档并开始游戏,按下其他键进行快速游戏\n操作说明:W上移\tD右移\tS下移\tA左移.\n");
	key_command = getch();
	switch (key_command)
	{
	    case VK_R:read_save(); break;
		case VK_M:remove("save_data.bin"); break;
		default:break;
	}
	for (;;)
	{
		if (flag == 0)
		{
			system("cls");
			printf("----------------GAME:2048-----------------\n分数:%-10d 步数:%-4d 最高分:%d\n",score, step, high_score);
			print_map();
			step++;
		}
		key_command = getch();
		if (key_command == VK_M)save_data();
		else if (key_command == VK_Q)return 0;
		else if (key_command == VK_A)move_left();
		else if (key_command == VK_W)move_up();
		else if (key_command == VK_D)move_right();
		else if (key_command == VK_S)move_down();
		else { flag = -1; continue; }
		if (game_over() == false)return 0;
	}
	return 0;
}

void print_map(void)
{
	int i, j, m1, n1, m2, n2,num_zero=0,check;
	srand(time(0));
	if (step == 0)     //游戏开始阶段,随机在地图中导入2和4方块
	{
		m1 = rand() % 4, n1 = rand() % 4;
		M[m1][n1] = 2;
		m2 = rand() % 4, n2 = rand() % 4;
		M[m2][n2] = 4;
	}
	for (i = 0; i < 4; i++) for (j = 0; j < 4; j++) if (M[i][j] == 0) num_zero++;     //记录空方块数量
	if (step != 0 && num_zero != 0)       //第二步开始,如果有空方块,在空方块中写入2或4.
		for (;;)
		{
			m1 = rand() % 4, n1 = rand() % 4; m2 = rand() % 4;
			if (M[m1][n1] == 0)
				if (m2 < 4 && m2>1) { M[m1][n1] = 2; break; }
				else { M[m1][n1] = 4; break; }
		}
	for (i = 0; i < 4; i++)
	{
		printf("     |-----|-----|-----|-----|\n");
		printf("     |%5d|%5d|%5d|%5d|\n", M[i][0], M[i][1], M[i][2], M[i][3]);
	}
	printf("     |-----|-----|-----|-----|\n");
	printf("\n按下M存档,按下Q退出游戏.\n");
}

void move_left(void)
{
	int i, k;
	check_move();
	for (i = 0; i < 4; i++)			//对一排方块进行4次排列
		for (k = 1; k < 4; k++)
		{
			if (M[i][0] == 0 && M[i][1] != 0) swap(&M[i][0], &M[i][1]);
			if (M[i][1] == 0 && M[i][2] != 0) swap(&M[i][1], &M[i][2]);
			if (M[i][2] == 0 && M[i][3] != 0) swap(&M[i][2], &M[i][3]);
	    }
	for (i = 0; i < 4; i++)          //如果相邻两方块相同,则进行相加操作,另一方块变为空方块
	{
		if (M[i][0] == M[i][1]) M[i][0] *= 2, M[i][1] = 0, score += M[i][0] * 2;
		if (M[i][1] == M[i][2]) M[i][1] *= 2, M[i][2] = 0, score += M[i][1] * 2;
		if (M[i][2] == M[i][3]) M[i][2] *= 2, M[i][3] = 0, score += M[i][2] * 2;
	}
	for (i = 0; i < 4; i++)         //再次进行排列
		for (k = 1; k < 4; k++)
		{
			if (M[i][0] == 0 && M[i][1] != 0) swap(&M[i][0], &M[i][1]);
			if (M[i][1] == 0 && M[i][2] != 0) swap(&M[i][1], &M[i][2]);
			if (M[i][2] == 0 && M[i][3] != 0) swap(&M[i][2], &M[i][3]);
	    }
	flag = is_move();
}

void move_right(void)
{
	int i, k;
	check_move();
	for (i = 0; i < 4; i++)
		for (k = 1; k < 4; k++)
		{
			if (M[i][3] == 0 && M[i][2] != 0) swap(&M[i][3], &M[i][2]);
			if (M[i][2] == 0 && M[i][1] != 0) swap(&M[i][1], &M[i][2]);
			if (M[i][1] == 0 && M[i][0] != 0) swap(&M[i][1], &M[i][0]);
		}
	for (i = 0; i < 4; i++)
	{
		if (M[i][3] == M[i][2]) M[i][3] *= 2, M[i][2] = 0, score += M[i][3] * 2;
		if (M[i][2] == M[i][1]) M[i][2] *= 2, M[i][1] = 0, score += M[i][2] * 2;
		if (M[i][1] == M[i][0]) M[i][1] *= 2, M[i][0] = 0, score += M[i][1] * 2;
	}
	for (i = 0; i < 4; i++)
		for (k = 1; k < 4; k++)
		{
			if (M[i][3] == 0 && M[i][2] != 0) swap(&M[i][3], &M[i][2]);
			if (M[i][2] == 0 && M[i][1] != 0) swap(&M[i][1], &M[i][2]);
			if (M[i][1] == 0 && M[i][0] != 0) swap(&M[i][1], &M[i][0]);
		}
	flag = is_move();
}

void move_up(void)
{
	int i, k;
	check_move();
	for (i = 0; i < 4; i++)
		for(k = 1; k < 4; k++)
		{
			if (M[0][i] == 0 && M[1][i] != 0) swap(&M[0][i], &M[1][i]);
			if (M[1][i] == 0 && M[2][i] != 0) swap(&M[1][i], &M[2][i]);
			if (M[2][i] == 0 && M[3][i] != 0) swap(&M[2][i], &M[3][i]);
		}
	for (i = 0; i < 4; i++)
	{
		if (M[0][i] == M[1][i]) M[0][i] *= 2, M[1][i] = 0, score += M[0][i] * 2;
		if (M[1][i] == M[2][i]) M[1][i] *= 2, M[2][i] = 0, score += M[1][i] * 2;
		if (M[2][i] == M[3][i]) M[2][i] *= 2, M[3][i] = 0, score += M[2][i] * 2;
	}
	for (i = 0; i < 4; i++)
		for (k = 1; k < 4; k++)
		{
			if (M[0][i] == 0 && M[1][i] != 0) swap(&M[0][i], &M[1][i]);
			if (M[1][i] == 0 && M[2][i] != 0) swap(&M[1][i], &M[2][i]);
			if (M[2][i] == 0 && M[3][i] != 0) swap(&M[2][i], &M[3][i]);
		}
	flag = is_move();
}

void move_down(void)
{
	int i, k;
	check_move();
	for (i = 0; i < 4; i++)
		for (k = 1; k < 4; k++)
		{
			if (M[3][i] == 0 && M[2][i] != 0) swap(&M[3][i], &M[2][i]);
			if (M[2][i] == 0 && M[1][i] != 0) swap(&M[2][i], &M[1][i]);
			if (M[1][i] == 0 && M[0][i] != 0) swap(&M[1][i], &M[0][i]);
		}
	for (i = 0; i < 4; i++)
	{
		if (M[3][i] == M[2][i]) M[3][i] *= 2, M[2][i] = 0, score += M[3][i] * 2;
		if (M[2][i] == M[1][i]) M[2][i] *= 2, M[1][i] = 0, score += M[2][i] * 2;
		if (M[1][i] == M[0][i]) M[1][i] *= 2, M[0][i] = 0, score += M[1][i] * 2;
	}
	for (i = 0; i < 4; i++)
		for (k = 1; k < 4; k++)
		{
			if (M[3][i] == 0 && M[2][i] != 0) swap(&M[3][i], &M[2][i]);
			if (M[2][i] == 0 && M[1][i] != 0) swap(&M[1][i], &M[2][i]);
			if (M[1][i] == 0 && M[0][i] != 0) swap(&M[1][i], &M[0][i]);
		}
	flag = is_move();
}

bool game_over(void)
{
	int i, j;
	for (i = 0; i < 4; i++)
		for (j = 0; j < 4; j++)
			if (M[i][j] == 0)return true;
	if (i == 0 && j == 0)
		if (M[0][0] == M[0][1] || M[0][0] == M[1][0])return true;
	if (i == 0 && j == 3)
		if (M[0][3] == M[0][2] || M[0][3] == M[1][3])return true;
	if (i == 3 && j == 0)
		if (M[3][0] == M[3][2] || M[3][0] == M[2][0])return true;
	if (i == 3 && j == 3)
		if (M[3][3] == M[3][2] || M[3][3] == M[2][3])return true;
	if (M[0][1] == M[0][2])return true;
	if (M[1][0] == M[2][0])return true;
	if (M[1][3] == M[2][3])return true;
	if (M[3][1] == M[3][2])return true;
	for (i = 1; i < 3; i++)
		for (j = 1; j < 3; j++)
			if (M[i][j] == M[i - 1][j] || M[i][j] == M[i][j - 1] || M[i][j] == M[i + 1][j] || M[i][j] == M[i][j + 1])
				return true;
	if (score > high_score)
	{
		high_score = score;
		printf("你创造了新的纪录:%d\n", high_score);
		save_high_score(); 
		return false;
	}
	else printf("你的分数为:%d\n", score);
	return false;
}

void swap(int *a, int *b)
{
	int temp;
	temp = *a;
	*a = *b;
	*b = temp;
}

void read_save(void)
{
	FILE *fp = fopen("save_data.bin", "rb");
	if (fp == NULL)
	{
		printf("无法找到或打开存档,按下N新建存档并开始\n");
		if (getch() == VK_N)save_data();
		return;
	}
	fread(M, sizeof(M[0][0]), sizeof(M) / sizeof(M[0][0]), fp);
	fread(q, sizeof(score), 1, fp);
	fclose(fp);
	read_high_score();
}

void save_data(void)
{
	FILE *fp = fopen("save_data.bin", "wb");
	if (fp == NULL)
	{
		printf("无法找到或打开存档\n");
		return;
	}
	fwrite(M, sizeof(M[0][0]), sizeof(M) / sizeof(M[0][0]), fp);
	fwrite(q, sizeof(score), 1, fp);
	printf("存档成功.\n");
	fclose(fp);
}

void save_high_score(void)
{
	FILE *fp = fopen("save_data_highscore.bin", "wb");
	FILE *del = fopen("save_data.bin", "w");
	if (fp == NULL)
	{
		printf("无法找到或打开存档\n");
		return;
	}
	fwrite(p, sizeof(high_score), 1, fp);
	fclose(fp);
	fclose(del);
}

void read_high_score(void)
{
	FILE *fp = fopen("save_data_highscore.bin", "rb");
	fread(p, sizeof(high_score), 1, fp);
	fclose(fp);
}

void check_move(void)
{
	for (int i = 0; i < 4; i++)
		for (int j = 0; j < 4; j++)
			temp[i][j] = M[i][j];
}

int is_move(void)   //如果M和temp不一致,则代表可以移动,返回0;如果一致,则代表不可移动,返回-1
{
	for (int i = 0; i < 4; i++)
		for (int j = 0; j < 4; j++)
			if (M[i][j] != temp[i][j])
				return 0;
	return -1;
}


  • 14
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值