/*
---------------------2048------------------------
*/
/*
实现思路:
是否有数据? 数据如何存放
整数 4*4 int short long ...
int 4*4的数组
数组一般搭配循环
如果两个相同元素 会进行合并 分支
不断进行游戏 (函数)
---->按键-->一轮合并-->判断输赢--->按键
1. 按键 按上下左右 都要移动 生成一个新的数字
2. 移动过程中相同的数字碰到了会进行合并成一个更大的数字
3. 移动之后会判断输赢 如果合成了比2048更大的数字 游戏结束
4. 如果游戏最后无法移动(已经满了并且没法移动)
游戏刚刚开始时候的状态 --->两个数字 任意位置 2和4中的一个
任意位置 随机数
srand((unsigned)time(NULL));
rand()//用求余控制范围
*/
//头文件
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<string.h>
#include<conio.h>
#include<easyx.h>
//全局变量
//函数声明
void play(int map[][4]);
void drawMap(int map[][4]);//函数声明和函数定义记得写一样
int win(int map[][4]);
void newNum(int map[][4]);
//主函数
int main() //主函数 程序的入口
{
initgraph(400,400);//窗口大小
settextcolor(LIGHTBLUE);
settextstyle(40, 0, "黑体");
int map[4][4];//数组 下标从0开始算
//先把数组全部赋值为0 给数组 循环
memset(map, 0, sizeof(int)* 4 * 4);//初始化一块内存
srand((unsigned)time(NULL));
int x, y;
for (int i = 0; i < 2; )
{
x = rand() % 4;
y = rand() % 4;
//if (map[x][y] == 0)
if (0 == map[x][y])
{
++i;//每次找到新位置 i加1 不然i就不加 确保找到两个新位置
map[x][y] = rand() % 2 * 2 + 2;//随机的2或者4
//if (rand() % 10 == 0) map[x][y] = 2;
//else map[x][y] = 4;
//控制概率 10%生成2 90%生成一个4
/*switch (rand() % 10)
{
case 0:
case 1:
case 2:
case 3:
case 4:
map[x][y] = 2; break;
case 5:
case 6:
case 7:
case 8:
case 9:
map[x][y] = 4; break;
}*/
}
}
while (1)
{
drawMap(map);
play(map);
switch (win(map))
{
case 0://赢
//弹窗
return 0;
break;
case -1:
return 0;
break;
case 1:
break;
case 2:
//newNum(map);
break;
default:
break;
}
}
/*for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 4; ++j)
{
printf("%d\t", map[i][j]);
}
printf("\n");
}*/
getchar();
closegraph();
return 0;
}
//函数定义
//获取用户的一个按键 根据按键 执行往上或者往下移动(需要数组) 需要参数
//如果可以移动 就生成一个新的数字
//这里没有需要结果的必要 所以可以不用返回值
void play(int map[][4]) //kbhit 用户按一下 操作一下 贪吃蛇 用户按也会走 不按也会走
{
int len;//表示一行或者一列的元素的个数
switch (_getch())
{
case 'W':
case 'w'://上
case 72:
for (int y = 0; y < 4; ++y)//四列
{
len = 4;//每一行默认四个元素
//先把0往右移动
for (int i = 0; i < len-1; ++i)
{
if (map[i][y] == 0)
{
for (int j = i; j < 3; ++j)
{
map[j][y] = map[j+1][y];
}
map[3][y] = 0;
len--;//出现一个0 那么len--一次
--i;
}
}
//合并操作
for (int i = 0; i < len-1; ++i)
{
if (map[i][y] == 0) break;
if (map[i][y] == map[i+1][y])//合并
{
map[i][y] *= 2;
for (int j = i + 1; j < 3; ++j)
{
map[j][y] = map[j+1][y];
}
map[3][y] = 0;
}
}
}
newNum(map);
break;
case 'A':
case 'a'://左
case 75:
for (int x = 0; x < 4; ++x)//四行
{
len = 4;//每一行默认四个元素
//先把0往右移动
for (int i = 0; i < len-1; ++i)
{
if (map[x][i] == 0)
{
for (int j = i; j < 3; ++j)
{
map[x][j] = map[x][j + 1];
}
map[x][3] = 0;
len--;//出现一个0 那么len--一次
--i;
}
}
//合并操作
for (int i = 0; i < len-1; ++i)
{
if (map[x][i] == 0) break;
if (map[x][i] == map[x][i + 1])//合并
{
map[x][i] *= 2;
for (int j = i + 1; j < 3; ++j)
{
map[x][j] = map[x][j + 1];
}
map[x][3] = 0;
}
}
}
newNum(map);
break;
case 'S':
case 's'://往下
case 80:
for (int y = 0; y < 4; ++y)//四列
{
len = 0;
//先把0往上移动
for (int i = 3; i >len; --i)
{
if (map[i][y] == 0)
{
for (int j = i; j >0; --j)//或者j>=1
{
map[j][y] = map[j-1][y];
}
map[0][y] = 0;
len++;
i++;
}
}
//合并操作
for (int i = 3; i >0; --i)
{
if (map[i][y] == 0) break;
if (map[i][y] == map[i-1][y])//合并
{
map[i][y] *= 2;
for (int j = i - 1; j >0; --j)
{
map[j][y] = map[j-1][y];
}
map[0][y] = 0;
}
}
}
newNum(map);
break;
case 'D':
case 'd'://往右
case 77:
for (int x = 0; x < 4; ++x)//四行
{
len = 0;//这里表示0的个数
//先把0往左移动
//找到一个0 len++
for (int i = 3; i >len; --i)
{
if (map[x][i] == 0)
{
for (int j = i; j >0; --j)//或者j>=1
{
map[x][j] = map[x][j - 1];
}
map[x][0] = 0;
len++;
++i;//如果有移动 i的位置先不变 ..这里++ 循环有一个--
}
}
//合并操作
for (int i = 3; i >len; --i)
{
if (map[x][i] == 0) break;
if (map[x][i] == map[x][i - 1])//合并
{
map[x][i] *= 2;
for (int j = i - 1; j >0; --j)
{
map[x][j] = map[x][j - 1];
}
map[x][0] = 0;
}
}
}
newNum(map);
break;
default: break;
}
}
///判断是否输赢
///输 全满并且不可合并 -1
///如果是赢 看看里面有没有数字大于等于2048就行 0
///否则看是不是 满 1
//没有满 2
int win(int map[][4])
{
int num = 0;//记录0的个数
int flag = 0;//如果存在一组可以合并的元素 那么flag置为1
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 4; ++j)
{
if (map[i][j] >= 2048) return 0;//赢
if (map[i][j] == 0) num++;//记录0的个数
if (j + 1 < 4 && map[i][j] == map[i][j + 1]) flag = 1;//右边是不是一样
if (i + 1 < 4 && map[i][j] == map[i + 1][j]) flag = 1;//下方是不是一样
}
}
if (num == 0 && flag == 0) return -1;//满了并且不能合并 输
if (num == 0) return 1;//满了 但是可以合并
return 2;
}
//随机生成一个新数字的函数
void newNum(int map[][4])
{
//随机位置生成一个随机的2或者4
int x, y;
do
{
x = rand() % 4;
y = rand() % 4;
} while (map[x][y] != 0);//不是0就继续找
map[x][y] = rand() % 2 * 2 + 2;//随机赋值2或者4
}
//图形库的画图函数
void drawMap(int map[][4])
{
//这个全部元素都是数字 图形库 outtextxy 输出字符或者是一个字符串
//需要改多字节字符集
char arr[20];
BeginBatchDraw();//开始批量绘图,为了效果更好看
cleardevice();
for (int i = 1; i <= 3; ++i)
{
line(100 * i, 0, 100 * i, 400);//竖线
line(0, 100 * i, 400, 100 * i);//横线
}
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 4; ++j)
{
sprintf(arr, "%d", map[i][j]); //将数字写入字符串
outtextxy(j*100+20, i*100+30, arr);//指定位置输出字符串
}
}
EndBatchDraw();//结束批量绘图
}
void fun(int arr[])//元素有4个
{
int size;//表示
for (int i = 0; i < 4; ++i)
{
if (arr[i] == 0)
{
for (int j = i; j < 4-1; ++j)
{
arr[j] = arr[j + 1];//后面的元素往前移动 j+1<4
}
arr[3] = 0;//最后一个元素赋值为0
}
}
for (int i = 0; i < 3; ++i)
{
if (arr[i] == 0) break;//表明后面已经没有元素了 直接结束
if (arr[i] == arr[i + 1])//这个元素和后面的元素相等 合并
{
arr[i] *= 2;//合并 这里变成两倍
arr[i + 1] = 0;
for (int j = i + 1; j < 3; ++j)//后面的元素补上来 最后一个变成0
{
arr[j] = arr[j + 1];
}
arr[3] = 0;
}
}
}
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!