XTU-OJ 1239-2048

题目描述

2048是大家非常喜欢的一款小游戏,给定一个2048的局面,和下一步的指令,请计算出变化后的局面。 2048的游戏规则如下:

  • 游戏是一个4×4的格子
  • 玩家可以使用上、下、左、右控制数字方格滑动,
  • 每滑动一次,所有的数字方块都会往滑动的方向靠拢,相同数字的方块在靠拢、相撞时会相加。
  • 不断的叠加最终拼凑出2048这个数字就算成功
  • 每次滑动后,会在某个空白格子中出现随机的2或者4,如果不存在空白格子,则游戏结束。

输入

第一行是一个整数K,表示样例的个数。 每个样例的前4行,每行4个整数,如果整数为0表示空白格子,其他为数字。 每个样例的第5行,是指令,指令为"LEFT","DOWN","RIGHT","UP",依次表示滑动的方向。

输出

输出每个样例的结果,每个样例后输出一个空行。

样例输入

3
2 2 0 0
2 0 2 0
2 0 0 2
0 0 2 2
LEFT
2 0 2 0
2 2 2 2
0 2 0 2
4 2 2 0
LEFT
2 4 2 2
0 2 2 0
0 4 4 4
0 0 0 2
LEFT

样例输出

4 0 0 0
4 0 0 0
4 0 0 0
4 0 0 0

4 0 0 0
4 4 0 0
4 0 0 0
4 4 0 0

2 4 4 0
4 0 0 0
8 4 0 0
2 0 0 0

解题思路:这题又是一道大模拟,2048应该都玩过,具体步骤没什么多说的,就讲讲如何更新执行完指令后的结果。其实简单来说就两步。

1:按指令的方向,把 相同的数加在一起(加的数*2,被加的数置0)。比如左滑:2 2 2 2 —> 4 0 4 0 ; 2 0 0 2 —> 4 0 0 0 ; 2 0 2 1—> 4 0 0 1; 2 0 4 8 —> 2 0 4 8。

2:把非0的数,按指令的方向移动,把0放在 相反方向。 比如:2 2 2 2 —> 4 0 4 0 —> 4 4 0 0 ;2 0 2 1—> 4 0 0 1 —> 4 1 0 0;2 0 4 8 —> 2 0 4 8 —> 2 4 8 0。

执行完这两步,也就是完成了一次2048指令了。具体请看代码。

AC代码:

#include <stdio.h>

char ins[7];
int game[7][7];
int tag1,tag2,flag;
void swap(int &x,int &y){           // 交换函数
    int t;
    t = x, x = y, y = t;
}

void exchange1(int i)       // 左滑
{
    tag1 = tag2 = -1, flag = true;      // tag1存下标,tag2存数值
    for (int j = 1; j <= 4; j ++)       // 把可以合并的数合并起来
    {
        if (game[i][j] == 0) continue;  // 如果是0,跳过
        if (game[i][j] != tag2)         // 两个数不一样,更新。 比如 1 2 0 2, j = 2时, 2和1不一样,更新记录2
            {tag1 = j, tag2 = game[i][j]; continue;}
        if (game[i][j] == tag2)         // 两个数相同,相加。(接上)j = 4时,2 与前面的2相同,相加。 
        {
            game[i][tag1] *= 2, game[i][j] = 0;
            tag1 = tag2 = -1;           // 2048规则是一次指令中,对相同的数只加一次。比如
        }                               // 2 2 2 0 , 只会加成 4 2 0 0 ,不好成 6 0 0 0 
    }
    while (flag)                        // 把 >0的数,向左填充。
    {
        flag = false;   // 默认都向左填充好了,不要移位了。
        for (int j = 1; j < 4; j ++)   
            if (game[i][j] == 0 && game[i][j+1] != 0)  // 如果前一位是0,后一位非0,把非0数左移。
                swap(game[i][j], game[i][j+1]), flag = true; //移过一次就重新记 true。
    }   // 如果最后flag 还是 false,说明该轮没用移动过数,那么说明已经排好了,跳出循环。
}

void exchange2(int i)
{
    tag1 = tag2 = -1, flag = true;
    for (int j = 4; j >= 1; j --)
    {
        if (game[i][j] == 0) continue;
        if (game[i][j] != tag2)
            {tag1 = j, tag2 = game[i][j]; continue;}
        if (game[i][j] == tag2)
        {
            game[i][tag1] *= 2, game[i][j] = 0;
            tag1 = tag2 = -1;
        }
    }
    while (flag)
    {
        flag = false;
        for (int j = 4; j > 1; j --)
            if (game[i][j] == 0 && game[i][j-1] != 0)
                swap(game[i][j], game[i][j-1]), flag = true;
    }
}

void exchange3(int i)
{
    tag1 = tag2 = -1, flag = true;
    for (int j = 4; j >= 1; j --)
    {
        if (game[j][i] == 0) continue;
        if (game[j][i] != tag2)
            tag1 = j, tag2 = game[j][i];
        else if (game[j][i] == tag2)
        {
            game[tag1][i] *= 2, game[j][i] = 0;
            tag1 = tag2 = -1;
        }
    }
    while (flag)
    {
        flag = false;
        for (int j = 4; j > 1; j --)
            if (game[j][i] == 0 && game[j-1][i] != 0)
                swap(game[j][i], game[j-1][i]), flag = true;
    }
}
void exchange4(int i)
{
    tag1 = tag2 = -1, flag = true;
    for (int j = 1; j <= 4; j ++)
    {
        if (game[j][i] == 0) continue;
        if (game[j][i] != tag2)
            tag1 = j, tag2 = game[j][i];
        else if (game[j][i] == tag2)
        {
            game[tag1][i] *= 2, game[j][i] = 0;
            tag1 = tag2 = -1;
        }
    }
    while (flag)
    {
        flag = false;
        for (int j = 1; j < 4; j ++)
            if (game[j][i] == 0 && game[j+1][i] != 0)
                swap(game[j][i], game[j+1][i]), flag = true;
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    while ( T --)
    {
        for (int i = 1; i <= 4; i ++)
            for (int j = 1; j <= 4; j ++)
                scanf("%d",&game[i][j]);
        scanf("%s",ins);
        if  (ins[0] == 'L')                     // 按指令操作
            for (int i = 1; i <= 4; i ++)
                exchange1(i);
        else if (ins[0] == 'R')
            for (int i = 1; i <= 4; i ++)
                exchange2(i);
        else if (ins[0] == 'D')
            for (int i = 1; i <= 4; i ++)
                exchange3(i);
        else
            for (int i = 1; i <= 4; i ++)
                exchange4(i);

        for (int i = 1; i <= 4; i ++)           // 输出
        {
            for (int j = 1; j <= 3; j ++)
                printf("%d ",game[i][j]);
            printf("%d\n",game[i][4]);
        }
        puts("");
    }
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值