hihoCoder_推箱子

一.题目

题目1 : 推箱子

时间限制:10000ms

单点时限:1000ms

内存限制:256MB

描述

推箱子是一款经典游戏。如图所示,灰色格子代表不能通过区域,蓝色方格是箱子,黑色圆形代表玩家,含有圆点的格子代表目标点。

规定以下规则:

1、一局游戏中只会有一个箱子,一个玩家和一个目标点。

2、通过方向键控制玩家移动。

3、图中的灰色格子代表墙壁,玩家与箱子都不能通过。

4、推到墙壁的箱子,就无法再将箱子推离墙壁,因为玩家无法到达箱子靠墙壁的一侧去推箱子。也就是说箱子只能以“被推”的方式被移动,不是以“被拉”的方式被移动。但如果玩家将箱子推至墙壁后,垂直墙壁的两侧没有阻碍物,则玩家可以朝这两个不同的方向推移箱子。如果箱子进入角落,就没有办法再推动这个箱子了。

5、玩家是不能走出场景的。玩家推着箱子到达场景边缘,如果继续点击使玩家和箱子向墙壁前进的方向键,箱子和人都会保持不动。玩家的前进方向上如果有墙壁,也是不能前进的。但是这些点击都视为合理的输入。

6、箱子一旦到达目标点,就不能再移动了。但这时,玩家仍然可以在场景内自由行动。如果继续尝试推箱子,那么玩家将会和箱子一起保持在原地不动。

现在,给出一种方向键的点击方案,请判断,这种方案是否能使箱子最终停在目标点上。为了方便表示,我们以0代表空白格子,以4代表不能通过区域,以1代表玩家,以3代表箱子,以2代表目标点。

输入

第一行数据包含三个整数,N,M,S。其中,N(0 < N <= 100)代表格子的宽度,M(0 < M <= 100)代表格子的高度,S(0 < S <= 200)代表测试点的个数。

接下来的M行,每行都会有N个字符,描述当前的盘面。

接下来的S行,每行都代表一个测试点。每行都以一个整数T(0 < T <= 10000)开头,接下来是一个空格和T个字符。这T个字符仅由d,u,l,r这四个字母组成,分别代表了敲击向下,向上,向左,向右的方向键。

输出

对于每个测试点,输出最后箱子是否在目标点上。如果是,输出YES,如果不是,则输出NO。

样例输入
5 4 3
00000
13000
00200
00000
4 rurd
6 urdldr
6 rrrurd
样例输出
YES
YES
NO

二.解题技巧

这道题主要就是考虑各种边界条件的问题,并没有包含过多的算法。

三.实现代码

#include <iostream>
#include <vector>

using namespace std;

class Box
{
private:
    vector<vector<char> > Board;
    unsigned char Width;
    unsigned char Height;
    unsigned char X;
    unsigned char Y;
    bool IsSucceed;

public:

    // constructor
    Box(int N, int M);
    Box(const Box& Origin);

    void BuildBoard();
    void MoveUp();
    void MoveDown();
    void MoveLeft();
    void MoveRight();

    void Move(const char& SingleMove);
    bool Move(const vector<char> &Moves);

    void Print();

};

Box::Box(int N, int M) : Board(), Width(N), Height(M), X(255), Y(255), IsSucceed(false)
{

}

Box::Box(const Box& Origin):Board(Origin.Board), Width(Origin.Width),
         Height(Origin.Height), X(Origin.X), Y(Origin.Y), IsSucceed(Origin.IsSucceed)
{

}

void Box::BuildBoard()
{
    for (int IndexOfRows = 0; IndexOfRows < Height; IndexOfRows++)
    {
        vector<char> Row;

        for (int IndexOfCols = 0; IndexOfCols < Width; IndexOfCols++)
        {
            char InputChar = 0;
            cin >> InputChar;
            InputChar = InputChar - '0';

            if (InputChar == 1)
            {
                X = IndexOfCols;
                Y = IndexOfRows;
            }

            Row.push_back(InputChar);
        }

        Board.push_back(Row);

    }
}

void Box::MoveUp()
{
    if (Y < 1)
    {
        return;
    }

    int NextY = Y - 1;

    // The upper is the box in the right point
    if (Board[NextY][X] == 5)
    {
        IsSucceed = true;
        return;
    }

    // The upper is box
    if (Board[NextY][X] == 3 )
    {
        if (Y == 1)
        {
            return;
        }

        // the upper of the box is the wall
        if (Board[NextY - 1][X] == 4)
        {
            return;
        }

        // updating
        Board[NextY - 1][X] += 3;
        Board[NextY][X] = 1;
        if (Board[Y][X] != 2)
        {
            Board[Y][X] = 0;
        }
        Y = NextY;

        if (Board[NextY - 1][X] == 5)
        {
            IsSucceed = true;
        }

        return;
    }

    // the upper is wall
    if (Board[NextY][X] == 4)
    {
        return;
    }

    // the upper is  zero
    if (Board[NextY][X] == 0)
    {
        if (Board[Y][X] != 2)
        {
            Board[Y][X] = 0;
        }

        Board[NextY][X] = 1;
        Y = NextY;

        return;
    }

    if (Board[NextY][X] == 2)
    {
        Board[Y][X] = 0;
        Y = NextY;
        return;
    }
}

void Box::MoveDown()
{
    if (Y  > (Height - 2))
    {
        return;
    }

    int NextY = Y + 1;

    // The upper is the box in the right point
    if (Board[NextY][X] == 5)
    {
        IsSucceed = true;
        return;
    }

    // The upper is box
    if (Board[NextY][X] == 3 )
    {
        if (Y == (Height - 2))
        {
            return;
        }

        // the upper of the box is the wall
        if (Board[NextY + 1][X] == 4)
        {
            return;
        }

        // updating
        Board[NextY + 1][X] += 3;
        Board[NextY][X] = 1;
        if (Board[Y][X] != 2)
        {
            Board[Y][X] = 0;
        }
        Y = NextY;

        if (Board[NextY + 1][X] == 5)
        {
            IsSucceed = true;
        }

        return;
    }

    // the upper is wall
    if (Board[NextY][X] == 4)
    {
        return;
    }

    // the upper is  zero
    if (Board[NextY][X] == 0)
    {
        if (Board[Y][X] != 2)
        {
            Board[Y][X] = 0;
        }

        Board[NextY][X] = 1;
        Y = NextY;

        return;
    }

    if (Board[NextY][X] == 2)
    {
        Board[Y][X] = 0;
        Y = NextY;
        return;
    }
}

void Box::MoveLeft()
{
    if (X < 1)
    {
        return;
    }

    int NextX = X - 1;

    // The upper is the box in the right point
    if (Board[Y][NextX] == 5)
    {
        IsSucceed = true;
        return;
    }

    // The upper is box
    if (Board[Y][NextX] == 3 )
    {
        if (X == 1)
        {
            return;
        }

        // the upper of the box is the wall
        if (Board[Y][NextX - 1] == 4)
        {
            return;
        }

        // updating
        Board[Y][NextX - 1] += 3;
        Board[Y][NextX] = 1;
        if (Board[Y][X] != 2)
        {
            Board[Y][X] = 0;
        }
        X = NextX;

        if (Board[Y][NextX - 1] == 5)
        {
            IsSucceed = true;
        }

        return;
    }

    // the upper is wall
    if (Board[Y][NextX] == 4)
    {
        return;
    }

    // the upper is  zero
    if (Board[Y][NextX] == 0)
    {
        if (Board[Y][X] != 2)
        {
            Board[Y][X] = 0;
        }

        Board[Y][NextX] = 1;
        X = NextX;

        return;
    }

    if (Board[Y][NextX] == 2)
    {
        Board[Y][X] = 0;
        X = NextX;
        return;
    }
}

void Box::MoveRight()
{
    if (X > (Width - 2))
    {
        return;
    }

    int NextX = X + 1;

    // The upper is the box in the right point
    if (Board[Y][NextX] == 5)
    {
        IsSucceed = true;
        return;
    }

    // The upper is box
    if (Board[Y][NextX] == 3 )
    {
        if (X == (Width - 2))
        {
            return;
        }

        // the upper of the box is the wall
        if (Board[Y][NextX + 1] == 4)
        {
            return;
        }

        // updating
        Board[Y][NextX + 1] += 3;
        Board[Y][NextX] = 1;
        if (Board[Y][X] != 2)
        {
            Board[Y][X] = 0;
        }
        X = NextX;

        if (Board[Y][NextX + 1] == 5)
        {
            IsSucceed = true;
        }

        return;
    }

    // the upper is wall
    if (Board[Y][NextX] == 4)
    {
        return;
    }

    // the upper is  zero
    if (Board[Y][NextX] == 0)
    {
        if (Board[Y][X] != 2)
        {
            Board[Y][X] = 0;
        }

        Board[Y][NextX] = 1;
        X = NextX;

        return;
    }

    if (Board[Y][NextX] == 2)
    {
        Board[Y][X] = 0;
        X = NextX;
        return;
    }
}

void Box::Move(const char &SingleMove)
{
    //Print();

    switch(SingleMove)
    {
    case 'u':
        MoveUp();
        break;

    case 'd':
        MoveDown();
        break;

    case 'l':
        MoveLeft();
        break;

    case 'r':
        MoveRight();
        break;

    default:
        break;
    }

    //cout << "X is " << X << endl;
    //cout << "Y is " << Y << endl;
    //Print();
}

bool Box::Move(const vector<char> &Moves)
{

    const int SIZE = Moves.size();

    for (int Index = 0; Index < SIZE; Index++)
    {
        Move(Moves[Index]);

        if (IsSucceed)
        {
            return true;
        }

    }
    return false;
}

void Box::Print()
{
    const int SIZE = Board.size();

    for (int RowIndex = 0; RowIndex < SIZE; RowIndex++)
    {
        vector<char> Row = Board[RowIndex];

        int COLS = Row.size();

        for (int ColIndex = 0; ColIndex < COLS; ColIndex++)
        {
            char Tmp = Row[ColIndex] + '0';
            cout << Tmp;
        }

        cout << endl;

    }
}

int main()
{
    int N = 0, M = 0;
    int S = 0;

    cin >> N >> M >> S;
    Box Box_1(N, M);
    Box_1.BuildBoard();

    while (S--)
    {
        Box Box_Tmp(Box_1);

        int Number = 0;
        vector<char> Moves;
        cin >> Number;
        while(Number--)
        {
            char SinlgeMove = '0';
            cin >> SinlgeMove;
            Moves.push_back(SinlgeMove);
        }

        if (Box_Tmp.Move(Moves))
        {
            cout << "YES" << endl;
        }
        else
        {
            cout << "NO" << endl;
        }

    }

    return 0;
}

四.体会

这道题全在考虑边界条件和写代码速度上面了,并没有太多需要思考的算法问题。

版权所有,欢迎转载,转载请注明出处,谢谢

时间: 2024-10-25 17:03:06

hihoCoder_推箱子的相关文章

致佳音: 推箱子游戏自动求解算法设计(一)

本来酷爱音乐, 老衲也想谱一曲<献给爱丽丝>之类, 通俗又有境界的曲子, 奈何没有那个水平, 也不是一个程序员做的勾当,于是就有了本文. 希望莲花妹妹跟着思路走,能遗忘那些太多的忧伤-- 本文分以下四个小节: 一.平面寻路算法(Alpha Star) 二.闭合图形填充算法(扫描线种子填充) 三.推箱子求解 四.执行效率的优化 日本人有个程序叫Sokuban Automatic Solver,文件名是sokoban722.exe我附带在资源里面 不过日本人的东西没有开源,我们也不知道它里面的花花

致佳音: 推箱子游戏自动求解算法设计(二)

这一个小节我们说一说传说中的A×算法,其实之前也上传过类似的小件件,这里我们就去剖析一下它 毕竟在游戏程序,我们要从一点移动到另一点,并得到最短路程的轨迹,类似这种算法还有好几种,执行效率都差不多,不过大多不能得到轨迹 首先,从一点移动到另一点,最快就是直接走过去了,就像小男生爱上小女生,最好的办法就是直接走到她面前说:我爱你 不过理想状态,几乎是没有的,弯路那是必然的经过,有曲线,其实更美-- 那么弯路该怎么走呢,是不是先去背景看下毛主席,再去三亚晒个太阳,再回来告诉她外面的世界好美,不,不,

12月28日 二维数组的应用:第一个小游戏(推箱子)

小游戏:******推箱子******** static void Main(string[] args) { int i, j; int[,] a = new int[10, 10]                  //二维数组的定义           类型[,] 数组名 = new  类型 [行数, 列数] {赋值}:   或单个赋值 a[i,j]=1; { {1,1,1,1,1,1,1,1,1,1}, {1,0,0,0,0,0,0,0,0,1}, {1,0,2,0,0,8,0,0,0,

搜索 [HDU 1254] 推箱子

推箱子 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 5343    Accepted Submission(s): 1503 Problem Description 推箱子是一个很经典的游戏.今天我们来玩一个简单版本.在一个M*N的房间里有一个箱子和一个搬运工,搬运工的工作就是把箱子推到指定的位置,注意,搬运工只能推箱子而不能拉箱子

C语言版推箱子

推箱子源代码初步: 1 #include<stdio.h> 2 #include<conio.h> 3 #include<stdlib.h> 4 #define boolean int 5 #define true 1 6 #define false 0 7 8 #define ROWS 10 9 //之所以定义为11,是因为字符串的尾部的\0 10 #define COLUMNS 11 11 12 //根据程序定义或者文件读入来构建地图,然后把他绘制到屏幕上 13 v

java版 推箱子,俄罗斯方块,诗歌默写,坦克!由瑶哥特改造哦!

其实我发现自己用java还真的写了好多小游戏了,一起刚刚开始学java的时候听学长说,写个俄罗斯方块要看一本搬砖厚的书, 刚开始还不信,不过现在信了,javaSe学完是要有本搬砖候的书了! 这个好像也是大一写的吧,具体时间都记不得了. 这个游戏还是改良了一下咯,我添加了个魔鬼的角色在里面, 魔鬼可以退箱子,而且魔鬼不能碰到你,碰到你,你就over了 .比以前的推箱子好玩些.我自己也经常玩玩. 懒得把自己写的一些java写游戏一个一个发文章了一次性吧,总之如果要代码找我QQ就好了935090232

推箱子(嵌套搜索,bfs中有dfs)

推箱子 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 6416    Accepted Submission(s): 1834 Problem Description 推箱子是一个很经典的游戏.今天我们来玩一个简单版本.在一个M*N的房间里有一个箱子和一个搬运工,搬运工的工作就是把箱子推到指定的位置,注意,搬运工只能推箱子而不能拉箱子,

专业实训题目需求分析(3D推箱子)

业务需求:    游戏提供主菜单让玩家进行游戏设置.帮助说明,推箱子的小人可以前后左右转动,箱子可以被上下左右的推动,要有关卡设置,障碍物设置,游戏提供背景音乐的功能,要实现3D效果. 面向的用户类型:会使用手机软件的人 用户需求:可以对游戏进行设置,可以上下左右的推箱子,移动小人,要有关卡的转换,有个美好的体验. 软件需求:用户可以对游戏进行设置,用户通过移动小人来改变箱子的位置,游戏每关的关卡都要不一样,有独特的地图,给用户一个美好的体验.

hdu1254推箱子

推箱子 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6089    Accepted Submission(s): 1743 Problem Description 推箱子是一个很经典的游戏.今天我们来玩一个简单版本.在一个M*N的房间里有一个箱子和一个搬运工,搬运工的工作就是把箱子推到指定的位置,注意,搬运工只能推箱子而不能拉箱子