ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [백준 4577] 소코반
    C 프로그래밍/BOJ 2022. 11. 27. 17:13
    728x90

    https://www.acmicpc.net/problem/4577

     

    4577번: 소코반

    소코반은 1982년에 일본에서 만들어진 게임으로, 일본어로 창고지기라는 뜻이다. 이 게임은 캐릭터를 이용해 창고 안에 있는 박스를 모두 목표점으로 옮기는 게임이다. 목표점의 수와 박스의 수

    www.acmicpc.net

    #include <cstdio>
    #include <cstring>
    #include <queue>
    #include <vector>
    int R, C;
    char board[15 + 2][15 + 2];
    char cmd[50 + 2];
    int wx, wy;
    
    std::queue<char> Q;
    
    struct _st
    {
    	int x, y;
    };
    
    std::vector <_st> V;
    
    void input()
    {
    	// init
    	memset(board, '0', sizeof(board));
    	memset(cmd, '0', sizeof(cmd));
    	wx = wy = 0;
    	Q = {};
    	V.clear();
    
    
    	for (int i = 0; i < R; i++) {
    		scanf("%s", &board[i]);
    		for (int j = 0; j < C; j++) {
    			if (board[i][j] == 'w') {
    				wx = i;
    				wy = j;
    				board[i][j] = '.';
    			}
    			else if (board[i][j] == 'W') {
    				wx = i;
    				wy = j;
    				V.push_back({ i, j });
    				board[i][j] = '.';
    			}
    			else if (board[i][j] == '+') {
    				V.push_back({ i, j });
    				board[i][j] = '.';
    			}
    			else if (board[i][j] == 'B') {
    				V.push_back({ i, j });
    			}
    		}
    	}
    	scanf("%s", &cmd);
    	for (int i = 0;; i++) {
    		if (cmd[i] == '\0') break;
    		Q.push(cmd[i]);
    	}
    }
    
    
    bool chk_end()
    {
    	int plus = 0;
    	for (_st v : V) {
    		if (board[v.x][v.y] != 'b' && board[v.x][v.y] != 'B') {
    			plus++;
    		}
    	}
    
    	if (plus == 0) return true;
    	return false;
    }
    
    
    
    void simulation()
    {
    	// dir
    	// 0상 1우 2좌 3하
    	int dir_x[4] = { -1, 0, 0, 1 };
    	int dir_y[4] = { 0, 1, -1, 0 };
    
    	int x = wx;
    	int y = wy;
    
    	while (!Q.empty()) {
    		char dir = Q.front();
    		Q.pop();
    
    		// 모든 박스를 목표점으로 이동시킨 경우 게임은 끝난다 .
    		if(chk_end()) return;
    
    		int ndir = -1;
    		if (dir == 'U') ndir = 0;
    		else if (dir == 'R') ndir = 1;
    		else if (dir == 'L') ndir = 2;
    		else if (dir == 'D') ndir = 3;
    
    		int nx = x + dir_x[ndir];
    		int ny = y + dir_y[ndir];
    
    		// 빈공간일때 
    		if (board[nx][ny] == '.') {
    			board[x][y] = '.';
    			board[nx][ny] = 'w';
    			x = nx; y = ny;
    			continue;
    		}
    		// 박스가 있을 때 
    		else if (board[nx][ny] == 'b' || board[nx][ny] == 'B') {
    			// 이동할 수 있는 경우 
    			int bx = nx + dir_x[ndir];
    			int by = ny + dir_y[ndir];
    			if (board[bx][by] == '.' ) {
    				board[nx][ny] = '.';
    				board[bx][by] = 'b';
    
    				// 사람도 이동 
    				board[x][y] = '.';
    				board[nx][ny] = 'w';
    				x = nx; y = ny; 
    				continue;
    			}
    			else continue;
    		}
    		else if (board[nx][ny] == '#') continue;
    	}
    }
    
    
    
    
    void output(int tc)
    {
    	int plus = 0;
    	for (_st v : V) {
    		if (board[v.x][v.y] == 'b' || board[v.x][v.y] == 'B') {
    			board[v.x][v.y] = 'B';
    		}
    		else if (board[v.x][v.y] == 'w' || board[v.x][v.y] == 'W') {
    			board[v.x][v.y] = 'W';
    			plus++;
    		}
    		else {
    			board[v.x][v.y] = '+';
    			plus++;
    		}
    	}
    
    	if (plus == 0) printf("Game %d: complete", tc);
    	else printf("Game %d: incomplete", tc);
    	std::cout << std::endl;
    
    	for (int i = 0; i < R; i++) {
    		for (int j = 0; j < C; j++) {
    			printf("%c", board[i][j]);
    		}
    		std::cout << std::endl;
    	}
    }
    
    
    int main()
    {
    	for (int t = 1;; t++){
    		scanf("%d %d", &R, &C);
    		if (R == 0 && C == 0) return 0;
    		input();
    		simulation();
    		output(t);	
    	}
    }

    고려하지 못했던 것

    1. 게임이 끝난 후에 입력되는 키는 모두 무시된다. 

    2. 입력 시 +위치에 캐릭터(W)나 박스(B)가 있을 수 있다. 

     

    728x90

    'C 프로그래밍 > BOJ' 카테고리의 다른 글

    [백준 13460] 구슬탈출 2  (0) 2022.11.27
    [백준 20926] 얼음미로  (0) 2022.11.27
    [백준 2307] 도로검문  (0) 2022.11.24
    [백준 10282] 해킹  (0) 2022.11.24
    [백준 1238] 파티  (0) 2022.11.23

    댓글

Designed by Tistory.