C语言实现N阶的2048小游戏
程序员文章站
2024-03-19 16:51:04
...
内存是一条铺满板砖的街道。不存在二维结构。生活中处处有二维结构。为了让计算机解决更多的问题。将物理上的内存中的一维数组划分为逻辑上的二维数组。请参考《C和指针》。p[i] = *(p+i),那么p[-i] = *(p-i);前者是指针向后滑动i个元素。后者是向前滑动i个元素。则p[i][j] = *(*(p+i)+j) ;本次用到了p[i][-j] = *(*(p+i)-j);表示的意思是指针数组中的第i号元素所指的数组取其从首地址开始向前滑动j个元素。指针不一定指的就是每个元素的首地址,也可指向当前数组中的一个元素,然后通过滑动读写其他元素。这样就解决2048只有4阶的局限性。指针数组中的每个元素指向一维数组中的某个部分,然后通过滑动从而改变一维数组的元素,主函数所给的数组大小由宏定义决定,通过更改宏的值达到更改N阶游戏的目的。如下所示
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<conio.h>
#include<malloc.h>
#define LEN 5 //宏定义 表示N阶
void random_number (int *p, int n)//返回一个在0到n之间的随机数
{
int x;
srand((unsigned)time(NULL));//随机函数
x = rand()%n; //产生0~n之间的随机数
if (x == 0)
{
x = 4;
}
else
{
x = 2;
} // 随机出现4和2;出现4的概率n分之一。其他概率为出现2的概率.
while (1)
{
srand((unsigned)time(NULL));
int a = rand()%(n*n) ; //产生一个0~n*n之间的下标
if (p[a] == 0) //如果该数组元素为0,将4或者2赋值给该元素
{
p[a] = x;
break;
}
}
}
bool Left (int *p,int n)//左操作函数
{
int *arr = (int *)malloc(n*n*sizeof(int));//定义同样长度的数组保存当前数组的元素。
for (int i=0; i<n*n; i++)
{
arr[i] = p[i];
}
int **pp = (int **)malloc(n*sizeof(int));//定义二维指针,后边即可当做指针数组使用
for (int i=0; i<n; i++)
{
pp[i] = (p+n*i);//指向
}
for (int i=0; i<n; i++)//遍历数组 使得等值的数相加
{
for (int j=0; j<n-1; j++)
{
for (int k=j+1; k<n; k++)
{
if (pp[i][k] == 0)
{
continue;
}
if (pp[i][j] != pp[i][k])
{
break;
}
pp[i][j] += pp[i][k];
pp[i][k] = 0;
break;
}
}
}
for (int i=0; i<n; i++)//遍历数组,让不为0 的数移位
{
for (int j=0; j<n-1; j++)
{
if ((pp[i])[j] == 0)
{
for (int k = j+1; k<n; k++)
{
if ((pp[i])[k] != 0)
{
int temp;
temp = (pp[i])[k];
(pp[i])[k] = (pp[i])[j];
(pp[i])[j] = temp;
break;
}
}
}
}
}
free(pp);//释放申请的内存
for (int i=0; i<n*n;)//判断玩家的操作是否有效,判断是否出现新的随机数
{
if (arr[i] == p[i])
{
i++;
continue;
}
return true;
}
return false;
}
bool Right(int *p,int n)
{
int *arr = (int *)malloc(n*n*sizeof(int ));
for (int i=0; i<n*n; i++)
{
arr[i] = p[i];
}
int **pp = (int **)malloc(n*sizeof(int));
for (int i=0; i<n; i++)
{
pp[i] = (p+n*i+n);
}
for (int i=0; i<n; i++)//遍历数组 使得等值的数相加
{
for (int j=1; j<n+1; j++)
{
for (int k=j+1; k<n+1; k++ )
{
if ((pp[i])[-k] == 0)
{
continue;
}
if (pp[i][-k] != pp[i][-j])
{
break;
}
pp[i][-j] += pp[i][-k];
pp[i][-k] = 0;
break;
}
}
}
for (int i=0; i<n; i++)//遍历数组,让不为0的数移位
{
for (int j=1; j<n+1; j++)
{
if (pp[i][-j] == 0)
{
for (int k=j+1; k<n+1; k++)
{
if ((pp[i])[-k] != 0)
{
int temp;
temp = (pp[i])[-k];
(pp[i])[-k] = (pp[i])[-j];
(pp[i])[-j] = temp;
break;
}
}
}
}
}
free(pp);
for (int i=0; i<n*n;)
{
if (arr[i] == p[i])
{
i++;
continue;
}
return true;
}
return false;
}
bool Up(int *p,int n)
{
int *arr = (int *)malloc(n*n*sizeof(int ));
for (int i=0; i<n*n; i++)
{
arr[i] = p[i];
}
int **pp = (int **)malloc(n*sizeof(int));
for (int i=0; i<n; i++)
{
pp[i] = p+i;
}
for (int i=0; i<n; i++)
{
for (int j=0; j<n*(n-1); j+=n)
{
for (int k=j+n; k<n*n; k+=n)
{
if (pp[i][k] == 0)
{
continue;
}
if (pp[i][k] != pp[i][j])
{
break;
}
pp[i][j] += pp[i][k];
pp[i][k] = 0;
break;
}
}
}
for (int i=0; i<n; i++)
{
for (int j=0; j<n*(n-1); j+=n)
{
if ((pp[i])[j] == 0)
{
for (int k=j+n; k<n*n; k+=n)
{
if ((pp[i])[k] != 0)
{
int temp;
temp = (pp[i])[k];
(pp[i])[k] = (pp[i])[j];
(pp[i])[j] = temp;
break;
}
}
}
}
}
free(pp);
for (int i=0; i<n*n;)
{
if (arr[i] == p[i])
{
i++;
continue;
}
return true;
}
return false;
}
bool Down(int *p,int n)
{
int *arr = (int *)malloc(n*n*sizeof(int ));
for (int i=0; i<n*n; i++)
{
arr[i] = p[i];
}
int **pp = (int **)malloc(n*sizeof(int));
p = p+n*n;
for (int i=n-1; i>-1; i--)
{
pp[i] = p-(n-i);
}
for (int i=n-1; i>-1; i--)
{
for (int j=0; j<n*(n-1); j+=n)
{
for (int k=j+n; k<n*n; k+=n )
{
if (pp[i][-k] == 0)
{
continue;
}
if (pp[i][-j] != pp[i][-k])
{
break;
}
pp[i][-j] += pp[i][-k];
pp[i][-k] = 0;
break;
}
}
}
for (int i=n-1; i>-1; i--)
{
for (int j=0; j<n*(n-1); j+=n)
{
if ((pp[i])[-j] == 0)
{
for (int k=j+n; k<n*n; k+=n)
{
if ((pp[i])[-k] != 0)
{
int temp;
temp = (pp[i])[-k];
(pp[i])[-k] = (pp[i])[-j];
pp[i][-j] = temp;
break;
}
}
}
}
}
free(pp);
for (int i=0; i<n*n;)
{
if (arr[i] == p[i])
{
i++;
continue;
}
return true;
}
return false;
}
bool Game_over(int *p, int n)
{
for (int i=0; i<n*n; i++)
{
if (p[i] == 0 || p[i] == 2048)
{
return false;
}
}
int **pp = (int **)malloc(n*sizeof(int));
for (int i=0; i<n; i++)
{
pp[i] = (p+n*i);
}
for (int i=0; i<n; i++)
{
for (int j=0; j<n-1; j++)
{
for (int k=j+1; k<n;k++)
{
if (pp[i][j] != pp[i][k])
{
break;
}
free(pp);
return false;
}
}
}
for (int i=0; i<n; i++)
{
pp[i] = p+i;
}
for (int i=0; i<n; i++)
{
for (int j=0; j<n*(n-1); j+=n )
{
for (int k=j+n; j<n*n; j++)
{
if (pp[i][j] != pp[i][k])
{
break;
}
free(pp);
return false;
}
}
}
return true;
}
bool Win (int *p, int n)
{
for (int i=0; i<n*n; i++)
{
if (p[i] == 2048)
{
return true;
}
}
return false;
}
void Show(int *p, int n)
{
for (int i=0; i<n; i++)
{
for (int j=0; j<n; j++)
{
printf("%4d ",p[i*n+j]);
}
printf("\n");
printf("\n");
}
}
int main()
{
int arr[LEN*LEN] = {}; //定义一个n*n的一维数组,初始化为全0。并当做二维数组使用。
char key;
random_number (arr, LEN);//调用随机函数给数组赋值
random_number (arr, LEN);
Show(arr,LEN);//输出数组
while (1)//从键盘获取上下左右操作键值。调用相应的函数
{
while (key = getch())
{
key = getch();
switch(key)
{
case 72: if (Up(arr,LEN))
random_number (arr, LEN);//如果操作有效,产生新的随机值。
break;
case 80: if (Down(arr,LEN))
random_number (arr, LEN);
break;
case 75: if (Left(arr,LEN))
random_number (arr, LEN);
break;
case 77: if (Right(arr,LEN))
random_number (arr, LEN);
default :break;
}
break;
}
system("CLS");//清屏
Show(arr,LEN);//再次输出数组
if (Game_over(arr,LEN))//判断输了
{
printf("game over,you lose\n");
break;
}
if (Win(arr,LEN))
{
printf("game over,you win\n");//判断获胜
break;
}
}
return 0;
}