본문 바로가기

알고리즘/SW Expert Academy

[모의 SW 역량테스트] 5650. 핀볼 게임

반응형

[모의 SW 역량테스트] 핀볼 게임


1. 이해하기

  • 게임판 위에서는 작은 핀볼 하나가 상, 하, 좌, 우 중 한 방향으로 움직인다.
  • 핀볼은 블록이나 웜홀 또는 블랙홀을 만나지 않는 한 현재 방향을 유지하며 움직인다.
  • 핀볼이 블록의 수평면이나 수직면을 만날 경우 방향을 바꿔 반대 방향으로 돌아오고, 경사면을 만날 경우에는 직각으로 진행 방향이 꺾이게 된다.
  • 핀볼은 벽을 만날 경우에도 반대 방향으로 돌아온다.
  • 웜홀에 빠지면 동일한 숫자를 가진 다른 반대편 웜홀로 빠져 나오게 되며 진행방향은 그대로 유지된다.
  • 핀볼이 블랙홀을 만나면, 핀볼이 사라지게 되어 게임은 끝난다.
  • 게임은 핀볼이 출발 위치로 돌아오거나, 블랙홀에 빠질 때 끝나게 된다.
  • 점수는 벽이나 블록에 부딪힌 횟수가 된다.
  • 게임에서 얻을 수 있는 점수의 최댓값을 구하는 문제.
  • 완전탐색+시뮬레이션 문제이다.

 

2. 구현하기

  • 구슬의 이동방향으로 움직이고 그때의 상황을 체크한다.

    void move(int sx, int sy) {
        ball.p.x+=dx[ball.dir]; ball.p.y+=dy[ball.dir];
        check_location(sx,sy);
    }
  • 상황별로 알맞게 핀볼의 상태를 바꿔준다.

    • 벽이나 블록에 부딪히면 점수를 증가한다.
    • 각 맵의 상태에 맞게 핀볼의 상태를 바꿔준다.
    • 웜홀에 들어갔을때, 다음 웜홀을 구하는 조건식을 잘 짜야한다.
    bool out_of_bound() {
        return ball.p.x < 0 or ball.p.x >= N or ball.p.y < 0 or ball.p.y >= N;
    }
    
    void check_location(int sx, int sy) {
        if(out_of_bound()) {
            if(ball.dir == 0) ball.dir = 1;
            else if(ball.dir == 1) ball.dir = 0;
            else if(ball.dir == 2) ball.dir = 3;
            else if(ball.dir == 3) ball.dir = 2;
            ball.score++;
        } else if(map[ball.p.x][ball.p.y] == 1) {
            if(ball.dir == 0) ball.dir = 1;
            else if(ball.dir == 1) ball.dir = 3;
            else if(ball.dir == 2) ball.dir = 0;
            else if(ball.dir == 3) ball.dir = 2;
            ball.score++;
        } else if(map[ball.p.x][ball.p.y] == 2) {
            if(ball.dir == 0) ball.dir = 3;
            else if(ball.dir == 1) ball.dir = 0;
            else if(ball.dir == 2) ball.dir = 1;
            else if(ball.dir == 3) ball.dir = 2;
            ball.score++;
        } else if(map[ball.p.x][ball.p.y] == 3) {
            if(ball.dir == 0) ball.dir = 2;
            else if(ball.dir == 1) ball.dir = 0;
            else if(ball.dir == 2) ball.dir = 3;
            else if(ball.dir == 3) ball.dir = 1;
            ball.score++;
        } else if(map[ball.p.x][ball.p.y] == 4) {
            if(ball.dir == 0) ball.dir = 1;
            else if(ball.dir == 1) ball.dir = 2;
            else if(ball.dir == 2) ball.dir = 3;
            else if(ball.dir == 3) ball.dir = 0;
            ball.score++;
        } else if(map[ball.p.x][ball.p.y] == 5) {
            if(ball.dir == 0) ball.dir = 1;
            else if(ball.dir == 1) ball.dir = 0;
            else if(ball.dir == 2) ball.dir = 3;
            else if(ball.dir == 3) ball.dir = 2;
            ball.score++;
        } else if(6 <= map[ball.p.x][ball.p.y] and map[ball.p.x][ball.p.y] <= 10) {
            int num = map[ball.p.x][ball.p.y]-6;
            int nx,ny;
            for(int i = 0; i < 2; i++) {
                if(hole[num][i].x != ball.p.x or hole[num][i].y != ball.p.y) {
                    nx = hole[num][i].x; ny = hole[num][i].y;
                    break;
                }
            }
            ball.p.x = nx; ball.p.y = ny;
        } else if(map[ball.p.x][ball.p.y] == -1) ball.p.x = ball.p.y = -1;
        else if(sx == ball.p.x and sy == ball.p.y) ball.p.x = ball.p.y = -1;
    }
  • 맵의 비어있는 부분에 핀볼을 4가지 방향으로 모두 넣어보면서 게임에서 얻을 수 있는 점수의 최댓값을 구한다.

    int solve() {
        int ret = 0;
        for(int i = 0; i < N; i++) {
            for(int j = 0; j < N; j++) {
                if(map[i][j] != 0) continue;
                for(int d = 0; d < 4; d++) {
                    ball.p = {i,j}; ball.dir = d; ball.score = 0;
                    while(1) {
                        if(ball.p.x == -1 and ball.p.y == -1) break;
                        move(i,j);
                    }
                    ret = max(ret,ball.score);
                }
            }
        }
        return ret;
    }

 

3. 전체 코드

#include <iostream>
#include <vector>
using namespace std;
struct Point{
    int x,y;
};
struct Ball{
    Point p;
    int dir,score;
} ball;
int map[100][100];
vector<Point> hole[5];
int dx[] = {-1,1,0,0};
int dy[] = {0,0,-1,1};
int N;

bool out_of_bound() {
    return ball.p.x < 0 or ball.p.x >= N or ball.p.y < 0 or ball.p.y >= N;
}

void check_location(int sx, int sy) {
    if(out_of_bound()) {
        if(ball.dir == 0) ball.dir = 1;
        else if(ball.dir == 1) ball.dir = 0;
        else if(ball.dir == 2) ball.dir = 3;
        else if(ball.dir == 3) ball.dir = 2;
        ball.score++;
    } else if(map[ball.p.x][ball.p.y] == 1) {
        if(ball.dir == 0) ball.dir = 1;
        else if(ball.dir == 1) ball.dir = 3;
        else if(ball.dir == 2) ball.dir = 0;
        else if(ball.dir == 3) ball.dir = 2;
        ball.score++;
    } else if(map[ball.p.x][ball.p.y] == 2) {
        if(ball.dir == 0) ball.dir = 3;
        else if(ball.dir == 1) ball.dir = 0;
        else if(ball.dir == 2) ball.dir = 1;
        else if(ball.dir == 3) ball.dir = 2;
        ball.score++;
    } else if(map[ball.p.x][ball.p.y] == 3) {
        if(ball.dir == 0) ball.dir = 2;
        else if(ball.dir == 1) ball.dir = 0;
        else if(ball.dir == 2) ball.dir = 3;
        else if(ball.dir == 3) ball.dir = 1;
        ball.score++;
    } else if(map[ball.p.x][ball.p.y] == 4) {
        if(ball.dir == 0) ball.dir = 1;
        else if(ball.dir == 1) ball.dir = 2;
        else if(ball.dir == 2) ball.dir = 3;
        else if(ball.dir == 3) ball.dir = 0;
        ball.score++;
    } else if(map[ball.p.x][ball.p.y] == 5) {
        if(ball.dir == 0) ball.dir = 1;
        else if(ball.dir == 1) ball.dir = 0;
        else if(ball.dir == 2) ball.dir = 3;
        else if(ball.dir == 3) ball.dir = 2;
        ball.score++;
    } else if(6 <= map[ball.p.x][ball.p.y] and map[ball.p.x][ball.p.y] <= 10) {
        int num = map[ball.p.x][ball.p.y]-6;
        int nx,ny;
        for(int i = 0; i < 2; i++) {
            if(hole[num][i].x != ball.p.x or hole[num][i].y != ball.p.y) {
                nx = hole[num][i].x; ny = hole[num][i].y;
                break;
            }
        }
        ball.p.x = nx; ball.p.y = ny;
    } else if(map[ball.p.x][ball.p.y] == -1) ball.p.x = ball.p.y = -1;
    else if(sx == ball.p.x and sy == ball.p.y) ball.p.x = ball.p.y = -1;
}

void move(int sx, int sy) {
    ball.p.x+=dx[ball.dir]; ball.p.y+=dy[ball.dir];
    check_location(sx,sy);
}

int solve() {
    int ret = 0;
    for(int i = 0; i < N; i++) {
        for(int j = 0; j < N; j++) {
            if(map[i][j] != 0) continue;
            for(int d = 0; d < 4; d++) {
                ball.p = {i,j}; ball.dir = d; ball.score = 0;
                while(1) {
                    if(ball.p.x == -1 and ball.p.y == -1) break;
                    move(i,j);
                }
                ret = max(ret,ball.score);
            }
        }
    }
    return ret;
}

void input() {
    for(int i = 0; i < 5; i++) hole[i].clear();
    cin >> N;
    for(int i = 0; i < N; i++) {
        for(int j = 0; j < N; j++) {
            cin >> map[i][j];
            if(6 <= map[i][j] and map[i][j] <= 10) {
                hole[map[i][j]-6].push_back({i,j});
            }
        }
    }
}

int main() {
    int T;
    cin >> T;
    for(int t = 1; t <= T; t++) {
        input();
        cout << '#' << t << ' ' << solve() << '\n';
    }
    return 0;
}