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

1. 풀이 접근
ㆍ 현재 바라보는 방향으로 이동 (8:상, 6:우, 4:좌, 2:하)
※ 아직 좌표는 업데이트하기 전! 앞으로 향할 위치에 대해서 다른 변수를 이용해 저장
ㆍ 지도(범위 안에 있는지) 체크 ==> flag1
ㆍ 뱀이 너무 길어서 몸끼리 부딛쳤는지 확인 ==> flag2
ㆍ 조건문 확인
1) flag1 == true && flag2 == true
- 머리가 있는 위치에 사과가 있는지 확인 == flag3
* 사과가 있으면 사과 위치에 길이 1 추가
* 사과 없으면 사과 위치에 길이 1 추가하고, 맨뒤를 하나 자름
2) flag1 == false || flag2 == false
- 반복 종료 결과 출력
ㆍ 입력 확인 (커맨드에 따라 방향 전환해줘야 하는지 확인)
1) 방향 전환 해야 함
- 방향 전환 실시
2) 방향 전환 안해도 됨
- 방향 전환 안함
ㆍ 다시 처음으로 돌아감
2. 소스코드
github.com/Choi-JinYeong/Solve_Alg/tree/master/Solve_Algs/src/Git_BJ_3190
Choi-JinYeong/Solve_Alg
알고리즘 풀이. Contribute to Choi-JinYeong/Solve_Alg development by creating an account on GitHub.
github.com
package Git_BJ_3190;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
public class Main {
static class Point {
int x, y;
Point(int x, int y) {
this.x = x;
this.y = y;
}
}
static class Apple {
int x;
int y;
int isUsed;
Apple(int x, int y, int isUsed) {
this.x = x;
this.y = y;
this.isUsed = 0;
}
}
static class s_cmd {
int delay; // 시작시간 기준
char curve;
s_cmd(int d, char c) {
this.delay = d;
this.curve = c;
}
}
public static int N, K;
public static int map[][];
public static int cmap[][];
public static ArrayList<Point> snake;
public static ArrayList<Apple> apples;
public static ArrayList<s_cmd> s_cmds;
public static int CurrentDirection; // 2,4,6,8
public static int tempx, tempy;
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
CurrentDirection = 6;
N = Integer.parseInt(br.readLine());
K = Integer.parseInt(br.readLine());
snake = new ArrayList<>();
apples = new ArrayList<>();
s_cmds = new ArrayList<>();
for (int i = 0; i < K; i++) {
String s = br.readLine();
int x = Integer.parseInt(s.split(" ")[1]);
int y = Integer.parseInt(s.split(" ")[0]);
apples.add(new Apple(x, y, 0));
}
int t = Integer.parseInt(br.readLine());
for (int i = 0; i < t; i++) {
String s = br.readLine();
int x = Integer.parseInt(s.split(" ")[0]);
char y = s.split(" ")[1].charAt(0);
s_cmds.add(new s_cmd(x, y));
}
snake.add(new Point(1, 1));
solve();
System.out.println(currentTime);
}
// 이동 -> 머리만 먼저 앞으로 이동
// * 사과 없음 : 한칸씩 머리쪽으로 따라서 이동 -> 맨 마지막 칸이 비워져야 함
// * 사과 있음 : 현재 위치에 추가 ( index 1에 add )
// 업데이트는 전좌표 값 기준으로 차이를 계산해서 어디 방향으로 움직여야 하는지 도출
public static int currentTime;
public static int s_cmd_idx;
public static void solve() {
currentTime = 0;
while (true) {
currentTime++;
move();
boolean check1 = isINmap(snake.get(0).x, snake.get(0).y);
boolean check2 = isNotComplictWithBody();
if (check1 == true && check2 == true) {
boolean check3 = checkApple();
updateBody(check3);
} else {
break;
}
//checkSnakeStatus();
boolean check = checkChangeDirection();
if (check == true) {
changeDirection();
} else {
}
}
}
public static void changeDirection() {
// L 이 왼쪽 D가 오른쪽
switch (CurrentDirection) {
case 2: // 하
if (s_cmds.get(s_cmd_idx).curve == 'L') {
CurrentDirection = 6;
} else {
CurrentDirection = 4;
}
break;
case 4: // 좌
if (s_cmds.get(s_cmd_idx).curve == 'L') {
CurrentDirection = 2;
} else {
CurrentDirection = 8;
}
break;
case 6: // 우
if (s_cmds.get(s_cmd_idx).curve == 'L') {
CurrentDirection = 8;
} else {
CurrentDirection = 2;
}
break;
case 8: // 상
if (s_cmds.get(s_cmd_idx).curve == 'L') {
CurrentDirection = 4;
} else {
CurrentDirection = 6;
}
break;
}
}
public static boolean checkChangeDirection() {
for (int i = 0; i < s_cmds.size(); i++) {
s_cmd s = s_cmds.get(i);
if (s.delay == currentTime) {
s_cmd_idx = i;
return true;
}
}
return false;
}
// 업데이트는 전좌표 값 기준으로 차이를 계산해서 어디 방향으로 움직여야 하는지 도출
public static void move() {
tempx = snake.get(0).x;
tempy = snake.get(0).y;
switch (CurrentDirection) {
case 2: // 하
snake.get(0).y++;
break;
case 4: // 좌
snake.get(0).x--;
break;
case 6: // 우
snake.get(0).x++;
break;
case 8: // 상
snake.get(0).y--;
break;
}
}
public static boolean checkApple() {
int sx = snake.get(0).x;
int sy = snake.get(0).y;
// 사과 있을 경우
for (int i = 0; i < apples.size(); i++) {
int ax = apples.get(i).x;
int ay = apples.get(i).y;
int isused = apples.get(i).isUsed;
if (ax == sx && ay == sy && isused == 0) {
apples.get(i).isUsed = 1;
return true;
}
}
return false;
}
public static void updateBody(boolean check) {
if (check == true) { // 사과 있음
snake.add(1, new Point(tempx, tempy));
} else { // 사과 없음
if (snake.size() >= 2) {
snake.add(1, new Point(tempx, tempy));
snake.remove(snake.size()-1);
}
}
}
public static void checkSnakeStatus() {
for (int i = 0; i < snake.size(); i++) {
//System.out.print(snake.get(i).x + "," + snake.get(i).y + " ");
}
//System.out.println();
for (int i = 0; i < apples.size(); i++) {
//System.out.print(apples.get(i).x + "," + apples.get(i).y + " " + apples.get(i).isUsed + " / ");
}
//System.out.println();
}
public static boolean isINmap(int x, int y) {
if (x < 1 || x > N || y < 1 || y > N)
return false;
else
return true;
}
public static boolean isNotComplictWithBody() {
for (int i = 0; i < snake.size(); i++) {
for (int j = 0; j < snake.size(); j++) {
if (i != j)
if (snake.get(i).x == snake.get(j).x && snake.get(i).y == snake.get(j).y) {
checkSnakeStatus();
return false;
}
}
}
return true;
}
}
3. 맺음말
ㆍ 체감난이도 : 보통
ㆍ 사과를 먹었을 때와 먹지 않았을 때만 잘 구별해서 처리하면 됨.
ㆍ 더욱 좋은 풀이방법이나 보완할 수 있는 부분, 또는 문제가 될 수 있는 부분들은 알려주시면 감사하겠습니다.
'IT > 알고리즘 풀이' 카테고리의 다른 글
[SWEA] [자바] 1949. 등산로 조성 (0) | 2021.04.04 |
---|---|
[SWEA] [자바] 5656. 벽돌 깨기 (0) | 2021.04.03 |
[백준] [자바] 17144번 : 미세먼지 안녕! (0) | 2021.03.29 |
[백준] [자바] 16236번 : 아기 상어 (0) | 2021.03.26 |
[백준] [자바] 10250번 : ACM 호텔 (0) | 2021.03.26 |
댓글