需要用到EasyX图形库
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include<assert.h>
#include <conio.h>
#include <windows.h>
#include<graphics.h>
#include<string.h>
#define ROW 4 /* 行数 */
#define COL ROW /* 列数 */
#define KEY_UP 72 /* 方向键'上'的扫描码码值 */
#define KEY_DOWN 80 /* 方向键'下'的扫描码码值 */
#define KEY_LEFT 75 /* 方向键'左'的扫描码码值 */
#define KEY_RIGHT 77 /* 方向键'右'的扫描码码值 */
#define BLANK 0 /* 空白区域的数字 */
int g_seed = 0; /* 修改随机数种子 */
//产生新的数字
bool GetNum(int(*arr)[COL])
{
srand((unsigned int)time(NULL) + g_seed);
g_seed++;
int row = rand() % ROW;
int col = rand() % COL;
int ran = 2;//ran用来确认随机数为2或4
if (rand() % 5 == 0)
{
ran = 4;
}
while (arr[row][col] != 0)//当前格子不等于0
{
col++;
if (col == COL)
{
row = (row + 1) % ROW;
col = 0;
}
}
if (arr[row][col] == 0)
{
arr[row][col] = ran;
return true;
}
else
return false;
}
//显示界面
void Show(int(*arr)[COL])
{
system("CLS");//清除屏幕数据
绘图窗口初始化
//initgraph(640, 640);
读取图片至绘图窗口
//loadimage(NULL, _T("C:\\Users\\86166\\Desktop\\微信图片_20230524161021.jpg"), 640, 640);
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
printf("%d\t", arr[i][j]);
}
printf("\n\n");
}
/*_getch();
closegraph();*/
}
//向左合并和移动函数
//有合并或移动数据返回true,否则返回false
bool MergeLeft(int(*arr)[COL])
{
for (int i = 0; i < 4; i++)
{
//如果出现连续三个相同,先合并靠里面的,也就是说先合并最左边的,所以从左向右循环
//如果后两个合并后与前一个相同,不会继续和前一个合并
for (int j = 0; j < 3; j++)
{//合并
if (((*(arr + i))[j] == (*(arr + i))[j + 1]) && (*(arr + i))[j + 1] != 0)
{
(*(arr + i))[j] *= 2;
(*(arr + i))[j + 1] = 0;
}
else if (j < 2 && (*(arr + i))[j] == (*(arr + i))[j + 2] && (*(arr + i))[j + 1] == 0)
{//解决出现2 0 2 0->4 0 0 0的问题和0 2 0 2->0 4 0 0的问题
(*(arr + i))[j] *= 2;
(*(arr + i))[j + 2] = 0;
}
else if (j == 0 && (*(arr + i))[j] == (*(arr + i))[j + 3] && (*(arr + i))[j + 1] == 0 && (*(arr + i))[j + 2] == 0)
{//解决出现2 0 0 2->4 0 0 0的问题
(*(arr + i))[j] *= 2;
(*(arr + i))[j + 3] = 0;
}
/*else
{
break;
}*/
}
for (int j = 2; j >= 0; j--)
{//平移
if ((*(arr + i))[j] == 0 && (*(arr + i))[j + 1] != 0)
{
for (int k = j; k < 3; k++)
{
(*(arr + i))[k] = (*(arr + i))[k + 1];
}
(*(arr + i))[3] = 0;
}
}
}
return true;
}
//向上合并函数
bool MergeUp(int(*arr)[COL])
{
for (int j = 0; j < 4; j++)
{
//如果出现连续三个相同,先合并靠里面的,也会是说先合并最左边的,所以从左向右循环
//如果后两个合并后与前一个相同,不会继续和前一个合并
for (int i = 0; i < 3; i++)
{//合并
if ((*(arr + i))[j] == (*(arr + i + 1))[j] && (*(arr + i + 1))[j] != 0)
{
(*(arr + i))[j] *= 2;
(*(arr + i + 1))[j] = 0;
}
else if (i < 2 && (*(arr + i))[j] == (*(arr + i + 2))[j] && (*(arr + i + 1))[j] == 0)
{//解决出现2 0 2 0->4 0 0 0的问题和0 2 0 2->0 4 0 0的问题
(*(arr + i))[j] *= 2;
(*(arr + i + 2))[j] = 0;
}
else if (i == 0 && (*(arr + i))[j] == (*(arr + i + 3))[j] && (*(arr + i + 1))[j] == 0 && (*(arr + i + 2))[j] == 0)
{//解决出现2 0 0 2->4 0 0 0的问题
(*(arr + i))[j] *= 2;
(*(arr + i + 3))[j] = 0;
}
}
for (int i = 2; i >= 0; i--)
{//平移
if ((*(arr + i))[j] == 0 && (*(arr + i + 1))[j] != 0)
{
for (int k = i; k < 3; k++)
{
(*(arr + k))[j] = (*(arr + k + 1))[j];
}
(*arr + 3)[j] = 0;
}
}
}
return true;
}
bool MergeRight(int(*arr)[COL])
{
for (int i = 0; i < 4; i++)
{
//如果出现连续三个相同,先合并靠里面的,也会是说先合并最左边的,所以从左向右循环
//如果后两个合并后与前一个相同,不会继续和前一个合并
for (int j = 3; j > 0; j--)
{//合并
if (((*(arr + i))[j] == (*(arr + i))[j - 1]) && (*(arr + i))[j - 1] != 0)
{
(*(arr + i))[j] *= 2;
(*(arr + i))[j - 1] = 0;
}
else if (j > 1 && (*(arr + i))[j] == (*(arr + i))[j - 2] && (*(arr + i))[j - 1] == 0)
{//解决出现2 0 2 0->4 0 0 0的问题和0 2 0 2->0 4 0 0的问题
(*(arr + i))[j] *= 2;
(*(arr + i))[j - 2] = 0;
}
else if (j == 3 && (*(arr + i))[j] == (*(arr + i))[j - 3] && (*(arr + i))[j - 1] == 0 && (*(arr + i))[j - 2] == 0)
{//解决出现2 0 0 2->4 0 0 0的问题
(*(arr + i))[j] *= 2;
(*(arr + i))[j - 3] = 0;
}
/*else
{
break;
}*/
}
for (int j = 1; j <= 3; j++)
{//平移
if ((*(arr + i))[j] == 0 && (*(arr + i))[j - 1] != 0)
{
for (int k = j; k > 0; k--)
{
(*(arr + i))[k] = (*(arr + i))[k - 1];
}
(*(arr + i))[0] = 0;
}
}
}
return true;
}
//向下合并函数
bool MergeDown(int(*arr)[COL])
{
for (int j = 0; j < 4; j++)
{
//如果出现连续三个相同,先合并靠里面的,也会是说先合并最左边的,所以从左向右循环
//如果后两个合并后与前一个相同,不会继续和前一个合并
for (int i = 3; i > 0; i--)
{//合并
if ((*(arr + i))[j] == (*(arr + i - 1))[j] && (*(arr + i - 1))[j] != 0)
{
(*(arr + i))[j] *= 2;
(*(arr + i - 1))[j] = 0;
}
else if (i > 1 && (*(arr + i))[j] == (*(arr + i - 2))[j] && (*(arr + i - 1))[j] == 0)
{//解决出现2 0 2 0->4 0 0 0的问题和0 2 0 2->0 4 0 0的问题
(*(arr + i))[j] *= 2;
(*(arr + i - 2))[j] = 0;
}
else if (i == 3 && (*(arr + i))[j] == (*(arr + i - 3))[j] && (*(arr + i - 1))[j] == 0 && (*(arr + i - 2))[j] == 0)
{//解决出现2 0 0 2->4 0 0 0的问题
(*(arr + i))[j] *= 2;
(*(arr + i - 3))[j] = 0;
}
}
for (int i = 1; i < 4; i++)
{//平移
if ((*(arr + i))[j] == 0 && (*(arr + i - 1))[j] != 0)
{
for (int k = i; k > 0; k--)
{
(*(arr + k))[j] = (*(arr + k - 1))[j];
}
(*arr)[j] = 0;
}
}
}
return true;
}
//根据方向键合并相应的数字
//arr:保存数据的数组,dirce :方向值
bool MergeNum(int(*arr)[COL], int dirce)
{
bool flg = false;
switch (dirce)
{
case 1:
flg = MergeLeft(arr);//向左合并
break;
case 2:
flg = MergeUp(arr);//向上合并
break;
case 3:
flg = MergeRight(arr);//向右合并
break;
case 4:
flg = MergeDown(arr);//向下合并
break;
default:
break;
}
return flg;
}
// 获得方向键键值函数
int GetButton()
{
int ch;//保存从键盘读取的值
while (1)
{
if (_kbhit())//有击键发生
{
ch = _getch();//获取键盘值,不需要回车
if (ch == 0xE0)//确定是方向键
{
ch = _getch();
if (ch == KEY_LEFT)
return 1;
else if (ch == KEY_UP)
return 2;
else if (ch == KEY_RIGHT)
return 3;
else if (ch == KEY_DOWN)
return 4;
else
return 0;
}
}
}
ExMessage m;
while (peekmessage(&m, EX_KEY))
{
if (m.message == WM_KEYDOWN)
{
switch (m.vkcode)
{
case VK_LEFT:
return 1;
case VK_UP:
return 2;
case VK_RIGHT:
return 3;
case VK_DOWN:
return 4;
}
}
}
return 0;
}
//判断游戏是否结束函数
bool IsGameover(int(*arr)[COL])
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
if ((*arr + i)[j] == 0)
{
return false;
}
else if (((*(arr + i))[j] == (*(arr + i))[j + 1] && j < 3) || ((*(arr + i))[j] == (*(arr + i + 1))[j] && i < 3))
{
return false;
}
}
}
return true;
}
//运行游戏
void Run(int(*arr)[COL])
{
int direc; /* 保存方向值 */
while (1)
{
direc = GetButton();//获得方向键键值
//printf("%d\n", direc);//用于测试
if (!MergeNum(arr, direc)) //合并和移动数据
{
continue;
}
if (!GetNum(arr)) /* 游戏结束 */
{
return;
}
Show(arr);
if (IsGameover(arr)) //游戏是否结束
{
return;
}
}
}
//开始游戏
void Start(int(*arr)[COL])
{
for (int i = 0; i < 2; i++) /* 开始界面必须有两个数字 */
{
GetNum(arr);
}
Show(arr);
}
int main()
{
int arr[ROW][COL] = { 0 };
Start(arr);
Run(arr);
printf("Game over!\n");
return 0;
}