ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [백준] 뱀 (3190번) Swift
    알고리즘 2021. 10. 9. 17:28

    문제 내용

    뱀이 1초에 한칸씩 이동을 하는데 벽이나 자신의 몸통에 부딪히면 게임이 종료된다.

    뱀은 매 초마다 이동을 하는데 다음과 같은 규칙을 따른다.

    • 먼저 뱀은 몸길이를 늘려 머리를 다음칸에 위치시킨다.
    • 만약 이동한 칸에 사과가 있다면, 그 칸에 있던 사과가 없어지고 꼬리는 움직이지 않는다.
    • 만약 이동한 칸에 사과가 없다면, 몸길이를 줄여서 꼬리가 위치한 칸을 비워준다. 즉, 몸길이는 변하지 않는다.

    초기 뱀의 길이는 1이고, 오른쪽을 향한다.


    전체 코드

    // 1. n 값
    let n = Int(readLine()!)!
    // 2. k 값
    let k = Int(readLine()!)!
    // 3. 현재 전체 상태를 저장하기 위한 배열 (지도)
    var location: [[Int]] = Array(repeating: Array(repeating: 0, count: n), count: n)
    // 4. snake 의 위치를 저장하기 위한 배열
    // queue 형태로 사용하기 위해 snakeIndex 도 생성하였음
    var snake: [(x: Int, y: Int)] = []
    var snakeIndex = 0
    // 5. 현재 방향 (초기 값은 오른쪽)
    var direction: Direction = .right
    // 6. 시간 값
    var time = 0
    // 7. 끝까지 가기 전에 종료되었는지 저장하기 위한 값
    var breaked = false
    
    // 8. 초기 0,0 위치에서 뱀이 시작함
    // 뱀의 값을 -1로 설정함
    location[0][0] = -1
    snake.append((0, 0))
    
    // 9. 사과 값 저장
    for _ in 0..<k {
        let apple = readLine()!.split { $0 == " " }.map { Int(String($0))! }
        // location 에 1로 표현하였음
        location[apple[0] - 1][apple[1] - 1] = 1
    }
    
    // 10. l 값
    let l = Int(readLine()!)!
    
    outer: for _ in 0..<l {
        let info = readLine()!.split{ $0 == " " }
        
        // 11. time 부터 info[0] 까지 진행함
        for _ in time..<Int(info[0])! {
            // 12. 만약 generate 가 false 라면 (진행 도중에 벽이나 뱀의 몸에 부딪혀서 종료되었으면)
            if !generate() {
                // 13. 도중에 종료되었다고 체크하고 반복문 종료
                breaked = true
                break outer
            }
        }
        // 15. 방향 변경에 대한 함수
        convertDirection("\(info[1])")
    }
    
    // 16. 만약 도중에 종료되지 않았다면
    // 종료될때까지 진행함
    while !breaked {
        if !generate() {
            break
        }
    }
    
    // 17. 결과 출력
    print(time)
    
    // 18. 방향 변경에 대한 함수
    func convertDirection(_ order: String) {
        // 19. L 은 왼쪽으로 90 도 회전
        if order == "L" {
            switch direction {
            case .up:
                direction = .left
            case .down:
                direction = .right
            case .left:
                direction = .down
            case .right:
                direction = .up
            }
        // 20. 나머지는 오른쪽으로 90도 회전
        } else {
            switch direction {
            case .up:
                direction = .right
            case .down:
                direction = .left
            case .left:
                direction = .up
            case .right:
                direction = .down
            }
        }
    }
    
    // 21. 뱀이 이동하는 함수
    func generate() -> Bool {
        // 22. 먼저 시간을 + 1 함
        time += 1
        // 23. 뱀의 머리의 위치를 얻음
        let last = snake.last!
        // 24. 뱀의 머리가 갈 위치가 사과인지 저장하기 위한 값
        var isApple = false
        
        switch direction {
        case .up:
            // 25. 만약 벽의 위치 (index 를 넘어감) 거나 뱀의 몸 (값이 -1) 이라면
            // false 를 리턴하고 종료
            if last.x - 1 < 0 || location[last.x - 1][last.y] == -1 {
                return false
            }
            // 26. 만약 그 위치 값이 사과 (값이 1) 이라면
            if location[last.x - 1][last.y] == 1 {
                // 사과라고 체크함
                isApple = true
            }
            // 27. snake 에 머리 위치를 갱신함
            snake.append((last.x - 1, last.y))
            // 28. location 에 snake 위치 갱신
            location[last.x - 1][last.y] = -1
        case .down:
            if last.x + 1 == n || location[last.x + 1][last.y] == -1 {
                return false
            }
            if location[last.x + 1][last.y] == 1 {
                isApple = true
            }
            snake.append((last.x + 1, last.y))
            location[last.x + 1][last.y] = -1
            
        case .left:
            if last.y - 1 < 0 || location[last.x][last.y - 1] == -1 {
                return false
            }
            if location[last.x][last.y - 1] == 1 {
                isApple = true
            }
            snake.append((last.x, last.y - 1))
            location[last.x][last.y - 1] = -1
        case .right:
            if last.y + 1 == n || location[last.x][last.y + 1] == -1 {
                return false
            }
            if location[last.x][last.y + 1] == 1 {
                isApple = true
            }
            snake.append((last.x, last.y + 1))
            location[last.x][last.y + 1] = -1
        }
        
        // 29. 만약 사과가 아니라면
        if !isApple {
            // 30. 꼬리 제거함
            location[snake[snakeIndex].x][snake[snakeIndex].y] = 0
            // 31. queue 형식이므로 snakeIndex 를 + 1 해줌
            snakeIndex += 1
        }
        
        return true
    }
    
    enum Direction {
        case up
        case down
        case left
        case right
    }

    결론

    time 에 대해 조금 헷갈렸다.

    8 D

    10 D

    11 D

    13 L

    이런 식으로 몇 초 후의 값이 들어오면

    8 초 후에 방향 변경, 10 초 후에 방향 변경 ...

    이건 줄 알았는데

     

    8초에 변경, 10초에 변경이다.

     

    출처 : 백준 뱀

    http://www.acmicpc.net/problem/3190 

     

    3190번: 뱀

     'Dummy' 라는 도스게임이 있다. 이 게임에는 뱀이 나와서 기어다니는데, 사과를 먹으면 뱀 길이가 늘어난다. 뱀이 이리저리 기어다니다가 벽 또는 자기자신의 몸과 부딪히면 게임이 끝난다. 게임

    www.acmicpc.net

     

Designed by Tistory.