티스토리 뷰
[JAVA] 백준 #1986 체스 오답 기록 / If 조건문 | 와 || 의 차이 / & 와 && 의 차이
YouJungJang 2023. 11. 18. 20:49백준 #1986 체스
🔒 문제 설명
n×m 크기의 체스 판과, 상대팀의 Queen, Knight, Pawn의 위치가 주어져 있을 때, 안전한 칸이 몇 칸인지 세는 프로그램을 작성하시오. (안전한 칸이란 말은 그곳에 자신의 말이 있어도 잡힐 가능성이 없다는 것이다.)
참고로 Queen은 가로, 세로, 대각선으로 갈 수 있는 만큼 최대한 많이 이동을 할 수 있는데 만약 그 중간에 장애물이 있다면 이동을 할 수 없다. 그리고 Knight는 2 ×3 직사각형을 그렸을 때, 반대쪽 꼭짓점으로 이동을 할 수 있다. 아래 그림과 같은 8칸이 이에 해당한다.
이때 Knight는 중간에 장애물이 있더라도 이동을 할 수 있다. 그리고 Pawn은 상대팀의 말은 잡을 수 없다고 하자(즉, 장애물의 역할만 한다는 것이다).
예를 들어 다음과 같이 말이 배치가 되어 있다면 진하게 표시된 부분이 안전한 칸이 될 것이다. (K : Knight, Q : Queen, P : Pawn)
⌨️ 입력
첫째 줄에는 체스 판의 크기 n과 m이 주어진다. (1 ≤ n, m ≤ 1000) 그리고 둘째 줄에는 Queen의 개수와 그 개수만큼의 Queen의 위치가 입력된다. 그리고 마찬가지로 셋째 줄에는 Knight의 개수와 위치, 넷째 줄에는 Pawn의 개수와 위치가 입력된다. 즉 둘째 줄, 셋째 줄, 넷째 줄은 k, r1, c1, r2, c2,..., rk, ck 이 빈칸을 사이에 두고 주어진다는 것이다. 여기서 ri는 i번째 말의 행 위치, ci는 i번째 말의 열 위치를 의미한다. 한 칸에는 하나의 말만 놓인다고 가정한다. Knight, Queen, Pawn의 개수는 각각 100을 넘지 않는 음이 아닌 정수이다.
🖥️ 출력
첫째 줄에 n×m 체스판에 안전한 칸이 몇 칸인지 출력하시오.
♟️오답 기록
얼마 전부터 재미를 붙인 체스가 코딩 문제 중에 있어서 신나서 클릭해서 도전해 봤는데 고려할 케이스가 너무 많아서 골치 아팠다. 그래도 포기하지 않고 열심히 구현했는데... '틀렸습니다'.. 다음에 꼭 다시 시도하고자 해당 오답 코드를 기록한다.
우선 폰의 위치에 따라 퀸의 이동 경로가 달라지기 때문에 처음 퀸의 좌표를 입력받자마자 보드에 이동 경로를 표시해서는 안된다. 그러므로 일단 ArrayList에 퀸의 좌표를 저장한다.
두 번째 나이트의 경우에는 장애물이 있어도 뛰어넘을 수 있으므로 입력받자마자 바로 이동 경로를 표시한다. 나이트 본인의 위치에는 '2', 이동할 수 있는 위치에는 '1'을 저장했다.
폰의 경우 장애물의 역할만 하고 움직일 수 없으므로 본인의 위치에만 '2'를 표시한다.
이제 모든 말이 올라왔으니 퀸이 움직일 차례다. 퀸은 총 8가지 방향으로 움직일 수 있다. 각 경우마다 while문 안에 if문을 사용해서 코드를 구현했는데 (1) 현재 좌표가 보드의 범위를 벗어나거나 (2) 현재 위치에 다른 말이 있을 때 break 한다. 여기서 오랜만에 조건문에 대해 복습했다. 바로 "조건문에서 | 와 ||의 차이"
조건문에서 '|'와 '||'의 차이 혹은 '&'와 '&&'의 차이
✅ '|' 하나 사용한 경우
if( 조건 1 | 조건 2 )
조건 1이 True여도 조건 2가 True인지 False인지 검사한다.
✅'||' 두 개 사용한 경우
if( 조건 1 || 조건 2 )
조건 1이 True -> 조건 2는 검사하지 않는다. -> 조건 2 안 봐도 조건문 자체가 True로 판명남
조건 1이 False -> 조건 2를 검사한다.
마찬가지로 && 연산자일 경우
✅ '&' 하나 사용한 경우
if( 조건 1 & 조건 2 )
조건 1이 False여도 조건 2가 True인지 False인지 검사한다.
✅'&&' 두 개 사용한 경우
if( 조건 1 && 조건 2 )
조건 1이 False -> 조건 2는 검사하지 않는다. -> 조건 2 안 봐도 조건문 자체가 이미 False로 판명 남
조건 1이 True -> 조건 2를 검사한다.
우선 위에서 (2) 번 조건을 작성할 때, board(i)(j)==2 이런 식으로 조건이 작성되는데 만약 i, j 둘 중 하나라도 인덱스 범위를 벗어났다면 바로 Index Out Of Range 에러가 발생할 것이다. 이때, if문에 '||'로 인덱스 체크 조건을 앞에 함께 써주면 인덱스 범위에 해당하는 것에 한해서 board 접근을 할 것이다.
🔎 나의 코드 (오답)
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
Scanner in = new Scanner(System.in);
// 체스판 가로 세로
int n = in.nextInt();
int m = in.nextInt();
int[][] board = new int[n][m];
// Queen 좌표 입력
int q= in.nextInt();
ArrayList<ArrayList<Integer>> queen = new ArrayList<>();
for(int i = 0; i < q; i++){
ArrayList<Integer> location = new ArrayList<>();
int x = in.nextInt()-1;
int y = in.nextInt()-1;
location.add(x);
location.add(y);
queen.add(location);
board[x][y]=2;
}
// Knight 좌표 입력 / 보드에 나이트 위험 구역 표시
int k= in.nextInt();
for(int i = 0; i < k; i++){
int x = in.nextInt()-1;
int y = in.nextInt()-1;
board[x][y]=2;
if(x-1>-1 && y-2>-1) board[x-1][y-2]=1;
if(x-2>-1 && y-1>-1) board[x-2][y-1]=1;
if(x-2>-1 && y+1<m) board[x-2][y+1]=1;
if(x-1>-1 && y+2<m) board[x-1][y+2]=1;
if(x+1<n && y+2<m) board[x+1][y+2]=1;
if(x+2<n && y+1<m) board[x+2][y+1]=1;
if(x+2<n && y-1>-1) board[x+2][y-1]=1;
if(x+1<n && y-2>-1) board[x+1][y-2]=1;
}
// Pawn 좌표 입력 / pawn 위치 표시
int p= in.nextInt();
for(int i = 0; i < p; i++){
int x = in.nextInt()-1;
int y = in.nextInt()-1;
board[x][y] = 2;
}
for(int i = 0; i < q; i++){
int x = queen.get(i).get(0);
int y = queen.get(i).get(1);
//[1] 12시 방향 탐색
int tmp = x;
while(true){
tmp--;
if(tmp == -1 || board[tmp][y] == 2) break;
else board[tmp][y] = 1;
}
//[2] 6시 방향 탐색
tmp = x;
while(true){
tmp++;
if(tmp == n || board[tmp][y] == 2) break;
else board[tmp][y] = 1;
}
//[3] 3시 방향 탐색
tmp = y;
while(true){
tmp++;
if(tmp == m || board[x][tmp] == 2) break;
else board[x][tmp] = 1;
}
//[4] 9시 방향 탐색
tmp = y;
while(true){
tmp--;
if(tmp == -1 || board[x][tmp] == 2) break;
else board[x][tmp] = 1;
}
//[5] 1~2시 방향 대각선 탐색
int tmpx = x;
int tmpy = y;
while(true){
tmpx--;
tmpy++;
if(tmpx == -1 || tmpy ==m || board[tmpx][tmpy] == 2) break;
else board[tmpx][tmpy] = 1;
}
//[6] 4~5시 방향 대각선 탐색
tmpx = x;
tmpy = y;
while(true){
tmpx++;
tmpy++;
if(tmpx == n || tmpy ==m || board[tmpx][tmpy] == 2) break;
else board[tmpx][tmpy] = 1;
}
//[7] 7~8시 방향 대각선 탐색
tmpx = x;
tmpy = y;
while(true){
tmpx++;
tmpy--;
if(tmpx == n || tmpy == -1 || board[tmpx][tmpy] == 2) break;
else board[tmpx][tmpy] = 1;
}
//[8] 10~11시 방향 대각선 탐색
tmpx = x;
tmpy = y;
while(true){
tmpx--;
tmpy--;
if(tmpx == -1 || tmpy == -1 || board[tmpx][tmpy] == 2) break;
else board[tmpx][tmpy] = 1;
}
}
int safe_zone = 0;
//보드판 출력
for(int i = 0; i<n; i++){
for(int j = 0; j<m; j++){
if(board[i][j]==0) safe_zone++;
////
System.out.print(board[i][j]+" ");
}
////
System.out.println();
}
System.out.println("safe: "+safe_zone);
}
}
'Study > 오답 기록' 카테고리의 다른 글
[JAVA] 백준 #5582 공통 부분 문자열: 시간 초과 오답 기록 | 해결 (0) | 2023.11.17 |
---|