一个2048游戏

写代码容易,构思难啊。为了写这还专门玩了玩2048小游戏,将里面的步骤分解,变成一个一个的函数,才慢慢写完这个小游戏。写加上改代码,测差不多4个多晚上啊。
先说自己遇到的一些问题:

    最大的一个问题便是getchar();当输入一个字符时,它会接收回车键,导致程序多跑一边。
1.使用了 fflush(stdin)用了清空缓存区但不知道为什莫不管用。

2.想了一个笨办法:ch=getchar(); getchar()
    或是:scanf("%c\\n", &ch);
反正是搞定了。

查的相关的知识点:

1.产生一定范围的随机数:

C语言的获取随机数的函数为rand(), 可以获得一个非负整数的随机数。要调用rand需要引用头文件 stdlib.h
要让随机数限定在一个范围,可以采用模除加加法的方式。
要产生随机数r, 其范围为 m<=r<=n,可以使用如下公式:
rand()%(n-m+1)+m
其原理为,对于任意数,
0<=rand()%(n-m+1)<=n-m
于是
0+m<=rand()%(n-m+1)+m<=n-m+m

m<=rand()%(n-m+1)+m<=n

2. exit() 是电脑函数
exit()通常是用在 子程序 中用来终结程序用的,使用后程序自动结束,跳回操作系统。 exit(0) 表示程序正常退出,exit⑴/exit(-1)表示程序异常退出。

3。getchar()
如用户在按回车之前输入了不止一个字符,其他字符会保留在键盘缓存区中,等待后续getchar调用读取.也就是说,后续的getchar调用不会等待用户按键,而直接读取缓冲区中的字符,直到缓冲区中的字符读完为后,才等待用户按键.
具体代码:

#define _CRT_SECURE_NO_DEPRECATE
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define OK 1
#define ERRORY 0


int times = 0;
int pane[9][9];
typedef struct Head
{
	int order;
	int data1;
	int data2;
	struct Head *next;
}Pane_number, *Pane;


//功能函数
void grid();//打印4*4格子
void init_pane();//初始化二维数组
void move_up();//格子向上移动
void move_down();//格子向下移动
void move_left();//向左移动
void move_right();//向右移动
Pane ergodic_gane(Pane head);//遍历所有的格子存在链表里
void delete_other(Pane head);//删除除过表头以外的链表节点
void new_number(Pane head);//移动一次产生一个新数
int judge_end(Pane head);//判断是否结束
int score();//显示分数
void select();//方向选择;
void play(Pane head);
void menu(Pane head);//界面初始化

//函数实现


//打印4*4格子
void grid()
{
	int i = 0, j = 0, k = 0;
	for (k = 0; k<21; k++)
	{
		printf("*");
	}
	printf("\n");
	for (i = 0; i<4; i++)
	{
		for (j = 0; j<4; j++)
		{
			printf("*    ");
		}
		printf("*\n");

		for (j = 0; j<4; j++)
		{
			if (pane[i][j] == 0)
			{
				printf("*    ");

			}
			else
			{
				if (pane[i][j] < 10)
				{
					printf("*%d   ", pane[i][j]);
				}
				if (pane[i][j] >= 10 && pane[i][j] < 100)
				{
					printf("*%d  ", pane[i][j]);
				}
				if (pane[i][j] >= 100 && pane[i][j] < 1000)
				{
					printf("*%d ", pane[i][j]);
				}
				if (pane[i][j] >= 1000)
				{
					printf("%d", pane[i][j]);
				}
			}
		}
		printf("*\n");

		for (k = 0; k<21; k++)
		{
			printf("*");
		}
		printf("\n");
	}
}

//初始化二维数组
void init_pane()
{
	int i = 0, j = 0;
	for (i = 0; i<4; i++)
	{
		for (j = 0; j<4; j++)
		{
			pane[i][j] = 0;
		}
	}
	srand(time(NULL));
	i = rand() % 4;
	j = rand() % 4;
	if (i == 0 || i == 2)
	{
		pane[i][j] = 2;
	}
	else
	{
		pane[i][j] = 4;
	}
}

//格子向上移动
void move_up()
{
	//遍历每个格子,合并相同的数字
	int k = 0, i = 0, j = 0;
	for (i = 0; i<4; i++)
	{
		for (j = 0; j<4; j++)
		{
			if (pane[j][i] == 0)
				;
			else
			{
				for (k = j + 1; k<4; k++)
				{
					if (pane[k][i] == 0)
						;
					else
					{
						if (pane[j][i] == pane[k][i])
						{
							pane[j][i] = pane[j][i] * 2;
							pane[k][i] = 0;
							break;
						}

					}
				}
			}
		}
	}
	//向上来移动格子,使得其没有空格
	for (i = 0; i<4; i++)
	{
		for (j = 0; j<4; j++)
		{
			if (pane[j][i] == 0)
			{
				for (k = j + 1; k<4; k++)
				{
					if (pane[k][i] == 0)
						;
					else
					{
						pane[j][i] = pane[k][i];
						pane[k][i] = 0;
						break;
					}
				}

			}
		}
	}
}

//格子向下移动
void move_down()
{
	//遍历每个格子,合并相同的数字
	int k = 0, i = 0, j = 0;
	for (i = 3; i >= 0; i--)
	{
		for (j = 3; j >= 0; j--)
		{
			if (pane[j][i] == 0)
				;
			else
			{
				for (k = j - 1; k >= 0; k--)
				{
					if (pane[k][i] == 0)
						;
					else
					{
						if (pane[k][i] == pane[j][i])
						{
							pane[j][i] = pane[j][i] * 2;
							pane[k][i] = 0;
							break;
						}

					}
				}
			}
		}
	}
	//向下来移动格子,使得其没有空格
	for (i = 3; i >= 0; i--)
	{
		for (j = 3; j >= 0; j--)
		{
			if (pane[j][i] == 0)
			{
				for (k = j - 1; k >= 0; k--)
				{
					if (pane[k][i] == 0)
						;
					else
					{
						pane[j][i] = pane[k][i];
						pane[k][i] = 0;
						break;
					}
				}

			}
		}
	}

}

//向左移动
void move_left()
{
	//遍历每个格子,合并相同的数字
	int k = 0, i = 0, j = 0;
	for (i = 0; i<4; i++)
	{
		for (j = 0; j<4; j++)
		{
			if (pane[i][j] == 0)
				;
			else
			{
				for (k = j + 1; k<4; k++)
				{
					if (pane[i][k] == 0)
						;
					else
					{
						if (pane[i][k] == pane[i][k])
						{
							pane[i][j] = pane[i][j] * 2;
							pane[i][k] = 0;
							break;
						}

					}
				}
			}
		}
	}
	//向左来移动格子,使得其没有空格
	for (i = 0; i<4; i++)
	{
		for (j = 0; j<4; j++)
		{
			if (pane[i][j] == 0)
			{
				for (k = j + 1; k<4; k++)
				{
					if (pane[i][k] == 0)
						;
					else
					{
						pane[i][j] = pane[i][k];
						pane[i][k] = 0;
						break;
					}
				}

			}
		}
	}
}

//向右移动
void move_right()
{
	//遍历每个格子,合并相同的数字
	int k = 0, i = 0, j = 0;
	for (i = 3; i >= 0; i--)
	{
		for (j = 3; j >= 0; j--)
		{
			if (pane[i][j] == 0)
				;
			else
			{
				for (k = j - 1; k >= 0; k--)
				{
					if (pane[i][k] == 0)
						;
					else
					{
						if (pane[i][k] == pane[i][j])
						{
							pane[i][j] = pane[i][j] * 2;
							pane[i][k] = 0;
							break;
						}

					}
				}
			}
		}
	}
	//向右来移动格子,使得其没有空格
	for (i = 3; i >= 0; i--)
	{
		for (j = 3; j >= 0; j--)
		{
			if (pane[i][j] == 0)
			{
				for (k = j - 1; k >= 0; k--)
				{
					if (pane[i][k] == 0)
						;
					else
					{
						pane[i][j] = pane[i][k];
						pane[i][k] = 0;
						break;
					}
				}

			}
		}
	}

}

//产生一个新数
void new_number(Pane head)
{
	int i = 0, k = 0;
	Pane sign, re;
	sign = ergodic_gane(head);
	re = ergodic_gane(head);
	//随机选择一个空格子,赋值给2
	srand(time(NULL));
	k = rand() % sign->order + 1;
	//printf("空个数:%d\n", re->order);
	//printf("被选择的格子:%d\n", k);
	for (i = 0; i <= re->order; i++)
	{
		sign = sign->next;
		if (sign->order == k)
		{
			pane[sign->data1][sign->data2] = 2;
			//printf("坐标是:%d  %d\n", sign->data1, sign->data2);
		}
	}

}

//显示分数
int score()
{
	int i = 0, j = 0, total = 0;
	for (i = 0; i<4; i++)
	{
		for (j = 0; j<4; j++)
		{
			if (pane[i][j] != 0)
				total = pane[i][j] + total;
		}
	}
	printf("The score: %d\n", total);
	return (0);
}

//遍历所有的格子将信息存在链表里
Pane ergodic_gane(Pane head)
{
	int i = 0, j = 0, sum = 0;
	//现遍历所有的格子
	for (i = 0; i<4; i++)
	{
		for (j = 0; j<4; j++)
		{
			if (pane[i][j] == 0)
			{
				Pane p = (Pane)malloc(sizeof(Pane_number));
				p->data1 = i;
				p->data2 = j;
				sum = sum++;
				p->order = sum;

				p->next = head->next;
				head->next = p;
			}
		}

	}
	if (head->next == NULL)
	{
		head->order = 0;
	}
	else
	{
		head->order = head->next->order;
	}
	return (head);
}

//删除除过表头以外的链表节点
void delete_other(Pane head)
{
	Pane p, q;
	p = head->next;
	if (head->next == NULL)
		;
	else
	{
		q = p->next;
		free(p);
		p = q;
	}
	head->order = 0;
	head->next = 0;
}

//判断是否结束
int judge_end(Pane head)
{
	int i = 0, j = 0, k = 0;
	Pane mm;
	mm = ergodic_gane(head);
	for (i = 0; i<4; i++)
	{
		for (j = 0; j<4; j++)
		{
			if (pane[i][j] == 2048)
				k = 1;
		}
	}
	//printf("判断已调用\n");
	if (mm->order == 0 || k == 1)
		return ERRORY;
	else
		return OK;
}

//选择移动方向
void select()
{
	char ch = 0;
	//fflush(stdin);
	printf("Please import control key !\n");
	scanf("%c\\n", &ch); //接收了回车键,消除回车键的影响

	if (ch <= 'z' && ch >= 'a')
		ch -= 32;
	while (ch != 'A' && ch != 'D' && ch != 'S' && ch != 'W' && ch != 'Q')
	{
		printf("caution!   caution! \n");
		printf("please enter again !\n");
		scanf("%c\\n", &ch);
		if (ch <= 'z' && ch >= 'a')
			ch -= 32;
	}

	switch (ch)
	{
	case 'A':	move_left(); break;
	case 'D':	move_right(); break;
	case 'S':   move_down(); break;
	case 'W':   move_up(); break;
	case 'Q':   exit(0);
	default: break;
	}
}

void play(Pane head)
{
	new_number(head);
	score();
	grid();
	delete_other(head);
}

//界面初始化
void menu(Pane head)
{
	system("color 05");
	printf("****************************\n");
	printf("          2048            \n\n");
	printf("Control by:\n"
		" w/s/a/d or W/S/A/D\n");
	printf("press q or Q quit game!\n");
	printf("****************************\n");
	printf("Press any key to continue . . .\n");
	getchar();
	system("cls");
	init_pane();
	new_number(head);
	grid();
	system("pause");
}

int main()
{
	Pane head;
	head = (Pane)malloc(sizeof(Pane_number));
	head->next = NULL;

	menu(head);

	while (judge_end(head))
	{
		select();
		system("cls");
		play(head);
	}
	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值