#include<stdio.h>
#include<stdlib.h>
#include<Windows.h>
#include<string.h>
#include<conio.h> //为了读取方向键
#include<time.h> //为了生成随机数
#define N 4
int Map[4][4];
//这是为了显示该游戏棋盘
/*主要是由八个函数完成基本功能,第一个ShowMap,主要是显示游戏的期盼格子
第二个isGameOver判断游戏是否结束,棋盘全部占满,且上下左右没有可以合并的值,则游戏失败;反之出现2048则游戏成功
第三个随机数字函数,主要是借用随机种子函数来为合并之后空出来的位置随机生成一个数字
第四个上移函数,主要是针对同列非同行的相同数字,合并之后需要补位
第五个下移函数,主要是针对同列非同行的相同数字,合并之后需要补位,下移到底
第六个左移函数,主要是针对同行非同列的相同数字,合并之后需要补位,左移到底
第七个右移函数,主要是针对同行非同列的相同数字,合并之后需要补位,右移到底
第八个函数,是通过ascll码值从键盘读取上下左右键
*/
void ShowMap()
{
printf("\t欢迎来到2048\n");
printf("\t游戏界面如下:\n");
for( int i = 0; i < N; i++)
{
for( int j = 0; j < N; j++)
{
printf("%6d", Map[i][j] );
}
printf("\n");
printf("\n");
}
}
int isGameOver() //判断是否游戏结束
{
int flag = 1;
int i, j;
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++)
if (!Map[i][j])
{
flag = 0;
}
//如果没有空位但是有相邻相同的数也可以继续
if (flag == 1)
{
for (i = 0; i < 4; i++)
{
for (j = 0; j < 4; j++)
{
if (i != 0 && Map[i][j] == Map[i - 1][j])
flag = 0;
if (i != 3 && Map[i][j] == Map[i + 1][j])
flag = 0;
if (j != 0 && Map[i][j] == Map[i][j - 1])
flag = 0;
if (j != 3 && Map[i][j] == Map[i][j + 1])
flag = 0;
}
}
}
if (flag == 1)
{
printf("游戏结束");
}
return flag;
}
void RandNum()
{
//判断游戏是否结束了
isGameOver();
srand(time(NULL));
//判断坐标一个随机的位置
int i = rand() % 4;
int j = rand() % 4;
int data = 2;
if (rand() % 5 == 0)
{
data = 4;
}
while(Map[i][j] != 0) //当该下标已经有值
{
//产生随机的数字
j++;
if(j == 4)
{
i = (i+1) % 4;
j = 0;
}
}
Map[i][j] = data;
}
int MoveUp()
{
int tmp = 0; //记录是否发生移动
for( int j = 0; j < N; j++)
{
//移动
for( int i = 1; i < N; i++)
{
//同列非同行 上移
if (Map[i][j] && !Map[i-1][j])
{
Map[i-1][j] = Map[i][j];
Map[i][j] = 0;
//上移到底
if( i > 1)
{
i -= 2;
tmp = 1;
}
}
}
//合并数字
for( int i = 1; i < N; i++)
{
if(Map[i][j] == Map[i-1][j])
{
Map[i-1][j] = 2 * Map[i][j];
Map[i][j] = 0;
tmp = 1;
}
}
//移动之后又需要补空位
for( int i = 1; i < N; i++)
{
//同列非同行 上移
if (Map[i][j] && !Map[i-1][j])
{
Map[i-1][j] = Map[i][j];
Map[i][j] = 0;
//上移到底
if( i > 1)
{
i -= 2;
tmp = 1;
}
}
}
}
return tmp;
}
int MoveDown()
{
int tmp = 0;
for( int j = 0; j < N; j++)
{
//移动
for( int i = 2; i >= 0; i--)
{
//同列非同行 下移
if (Map[i][j] && !Map[i+1][j])
{
Map[i+1][j] = Map[i][j];
Map[i][j] = 0;
//上移到底
if( i < 2)
{
i += 2;
tmp = 1;
}
}
}
//合并数字
for( int i = 2; i >= 0; i--)
{
if(Map[i][j] == Map[i+1][j])
{
Map[i+1][j] = 2 * Map[i][j];
Map[i][j] = 0;
tmp = 1;
}
}
//移动之后又需要补空位
for( int i = 2; i >= 0; i--)
{
//同列非同行 下移
if (Map[i][j] && !Map[i+1][j])
{
Map[i+1][j] = Map[i][j];
Map[i][j] = 0;
//上移到底
if( i < 2)
{
i += 2;
tmp = 1;
}
}
}
}
return tmp;
}
int MoveLeft()
{
int tmp = 0;
for( int i = 0; i < N; i++)
{
//同行 左移
for( int j = 1; j < N; j++)
{
if(Map[i][j] && !Map[i][j-1] )
{
Map[i][j-1] = Map[i][j];
Map[i][j] = 0;
if(j > 1)
{
j -= 2;
tmp = 1;
}
}
}
//合并数字
for( int j = 1; j < N; j++)
{
if(Map[i][j] == Map[i][j-1])
{
Map[i][j-1] = 2 * Map[i][j];
Map[i][j] = 0;
tmp = 1;
}
}
//合并数字以后再次移动
for( int j = 0; j < N; j++)
{
if(Map[i][j] && !Map[i][j-1] )
{
Map[i][j-1] = Map[i][j];
Map[i][j] = 0;
if(j > 1)
{
j -= 2;
tmp = 1;
}
}
}
}
return tmp;
}
int MoveRight()
{
int tmp = 0;
for( int i = 0; i < N; i++)
{
//同行 右移
for( int j = 2; j >= 0; j--)
{
if(Map[i][j] && !Map[i][j+1] )
{
Map[i][j+1] = Map[i][j];
Map[i][j] = 0;
if(j < 2)
{
j += 2;
tmp = 1;
}
}
}
//合并数字
for( int j = 2; j >= 0; j--)
{
if(Map[i][j] == Map[i][j+1])
{
Map[i][j+1] = 2 * Map[i][j];
Map[i][j] = 0;
tmp = 1;
}
}
//合并数字以后再次移动
for( int j = 2; j >= 0; j--)
{
if(Map[i][j] && !Map[i][j+1] )
{
Map[i][j+1] = Map[i][j];
Map[i][j] = 0;
if(j < 2)
{
j += 2;
tmp = 1;
}
}
}
}
return tmp;
}
void keyboard()
{
int ch = getch();
switch (ch)
{
case 72://向上
if (MoveUp())
{
RandNum();
system("cls");
ShowMap();
}
break;
case 75:
if (MoveLeft())
{
RandNum();
system("cls");
ShowMap();
}
break;
case 77:
if (MoveRight())
{
RandNum();
system("cls");
ShowMap();
}
break;
case 80: // down
if (MoveDown())
{
RandNum();
system("cls");
ShowMap();
}
break;
default:
break;
}
}