백준 3190번 뱀 Kotlin 구현해 보기
```
백준 3190번 뱀 Kotlin 구현해 보기
```
배워갈 내용
- 백준 3190번 뱀 풀이
문제 링크
https://www.acmicpc.net/problem/3190
문제 설명
백준 3190번 뱀은
난이도 골드등급의 문제로서
보드의 크기 N (2 ≤ N ≤ 100)과 사과의 개수 K (0 ≤ K ≤ 100)가 주어집니다.
다음 K개의 줄에는 사과의 위치가 주어지며, 각 위치는 행과 열로 표시됩니다.
맨 위 왼쪽 (1행 1열)에는 사과가 없습니다.
뱀의 방향 변환 횟수 L (1 ≤ L ≤ 100)이 주어집니다.
다음 L개의 줄에는 뱀의 방향 변환 정보가 주어지며, 정수 X와 문자 C로 이루어져 있습니다.
X는 게임 시작 시간으로부터 경과한 시간을 나타내며,
C가 'L'이면 왼쪽으로 90도 회전, 'D'이면 오른쪽으로 90도 회전을 의미합니다.
X는 10,000 이하의 양의 정수이며, 방향 전환 정보는 X가 증가하는 순서로 주어집니다.
게임이 몇 초에 끝나는지 출력하면 됩니다
30분 정도 위에 링크를 방문하셔서 풀어보시고
안 풀리시는 경우에만 아래 해답을 봐주시면 감사하겠습니다.
코드 설명
입력을 받고
정해진 조건에 맞춰서 계산을 해서 출력해 주면 되는
문제입니다.
요즘에는 주석이나 설명 없이 코드로 설명하고자 노력 중입니다
만약 코드가 이해가 안 가시면 댓글 부탁드립니다
Deque를 이용해서
새로 이동할 공간에
사과가 있으면
Push만 하고
빈 공간이면 Push Pull을 하고
뱀의 몸이나 꼬리 혹은 맵 밖이면 종료를 하였습니다
코드
fun main() {
val inputDto = getInput()
print(solution(inputDto))
}
data class Position(
val x: Int,
val y: Int,
)
data class SnakeDirectionCmd(
val seconds: Int,
val rotate: Rotation,
)
enum class Rotation(val value: Char) {
LEFT('L'),
RIGHT('D')
}
enum class MapItem(val v: Char) {
EMPTY('0'),
SNAKE('S'),
APPLE('A')
}
enum class Direction(val v: Int) {
RIGHT(0),
LEFT(1),
DOWN(2),
UP(3),
}
fun getInput(): InputDto {
val boardSize = readLine()!!.toInt()
val appleCount = readLine()!!.toInt()
val applePostList = (1..appleCount).map {
val (y, x) = readLine()!!.split(" ").map(String::toInt)
Position(x, y)
}.toMutableList()
val cmdCount = readLine()!!.toInt()
val cmdList = List(cmdCount) {
val (seconds, chDir) = readLine()!!.split(" ")
val direction = when (chDir) {
"D" -> Rotation.RIGHT
"L" -> Rotation.LEFT
else -> {
throw Error("direction should be D or L")
}
}
SnakeDirectionCmd(seconds.toInt(), direction)
}.toMutableList()
return InputDto(boardSize, applePostList, cmdList)
}
data class InputDto(
val boardSize: Int,
val applePostList: MutableList<Position>,
val cmdList: MutableList<SnakeDirectionCmd>
) {
private var dy = intArrayOf(0, 0, 1, -1)
private var dx = intArrayOf(1, -1, 0, 0)
private fun calculateTurnDirection(currentDirection: Direction, rotation: Rotation): Direction {
return when (rotation) {
Rotation.LEFT -> when (currentDirection) {
Direction.DOWN -> Direction.RIGHT
Direction.UP -> Direction.LEFT
Direction.RIGHT -> Direction.UP
Direction.LEFT -> Direction.DOWN
}
Rotation.RIGHT -> when (currentDirection) {
Direction.DOWN -> Direction.LEFT
Direction.UP -> Direction.RIGHT
Direction.RIGHT -> Direction.DOWN
Direction.LEFT -> Direction.UP
}
}
}
private fun isOutOfBounds(x: Int, y: Int): Boolean {
return x < 0 || y < 0 || x >= boardSize || y >= boardSize
}
private fun initGameMap(): Array<CharArray> {
val gameMap = Array(boardSize) {
CharArray(boardSize) {
MapItem.EMPTY.v
}
}
// fill in apple pos
for (i in 0 until applePostList.size) {
val ax = applePostList[i].x - 1
val ay = applePostList[i].y - 1
gameMap[ay][ax] = MapItem.APPLE.v
}
return gameMap
}
fun findGameEndTimeSeconds(): Int {
var curX = 0
var curY = 0
var currentDirection = Direction.RIGHT
var time = 0
var cmdIdx = 0
val gameMap = initGameMap()
val q = ArrayDeque<Position>()
q.add(Position(curX, curY))
while (true) {
time++
val newX = curX + dx[currentDirection.v]
val newY = curY + dy[currentDirection.v]
if (isOutOfBounds(newX, newY)) {
break
}
when (gameMap[newY][newX]) {
MapItem.SNAKE.v -> break
MapItem.EMPTY.v -> {
val pos = q.removeFirst()
gameMap[pos.y][pos.x] = MapItem.EMPTY.v
gameMap[newY][newX] = MapItem.SNAKE.v
q.add(Position(newX, newY))
}
MapItem.APPLE.v -> {
gameMap[newY][newX] = MapItem.SNAKE.v
q.add(Position(newX, newY))
}
}
if (cmdIdx < cmdList.size && time == cmdList[cmdIdx].seconds) {
currentDirection = calculateTurnDirection(currentDirection, cmdList[cmdIdx].rotate)
cmdIdx++
}
curX = newX
curY = newY
}
return time
}
}
fun solution(dto: InputDto): Int {
return dto.findGameEndTimeSeconds()
}
// https://codemasterkimc.tistory.com/
읽어주셔서 감사합니다
무엇인가 얻어가셨기를 바라며
오늘도 즐거운 코딩 하시길 바랍니다 ~ :)