본문 바로가기
코딩/문제풀이-백준

백준 1694 - FEN 체스 (C++)

by 남대현 2021. 7. 15.
반응형

문제

해결 방법

입력값을 기준으로 먼저 체스판의 배치를 배열에 넣어준 뒤, 체스판을 순회하며 해당 자리에 기물이 있다면 그 기물이 갈 수 있는 모든 경로의 좌표를 체크한다. 이를 끝까지 반복하고, 체크되지 않은 좌표의 갯수를 더해 출력한다.

아쉬웠던 점

상하좌우/대각/나이트 이동 코드가 한 45줄 가량 나왔는데 더 줄일 수 있을 것 같다... 더럽다. 또한, 체스판의 크기만큼 반복을 돌리는데 입력할때, 입력을 기반으로 경로 파악할때, 빈칸 체크할때 총 세번이나 돌아간다.

쓰면서 생각났는데 O를 X로 바꿀때(경로 체크할때) + 체스 기물 갯수 하면 마지막에 체크되지 않은 좌표를 찾기위해 순회하는 일은 없어도 됐다... 의미없는 반복이 한번 더 들어갔다.

코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
 
bool Chess_Check(string _Board[][8], int _x, int _y)
{
    if (_x > 7 || _x < 0 || _y > 7 || _y < 0return true;
    if (_Board[_x][_y] != "X" && _Board[_x][_y] != "O")
        return true;
    _Board[_x][_y] = "O";
    return false;
}
 
void UDLR(string _Board[][8], int _x, int _y, int IsK = false)
{
    for (int i = _x + 1; i < 8++i)
        if (Chess_Check(_Board, i, _y) || IsK) break;
    for (int i = _x - 1; i > -1--i)
        if (Chess_Check(_Board, i, _y) || IsK) break;
    for (int i = _y + 1; i < 8++i)
        if (Chess_Check(_Board, _x, i) || IsK) break;
    for (int i = _y - 1; i > -1--i)
        if (Chess_Check(_Board, _x, i) || IsK) break;
}
 
void Diagonal(string _Board[][8], int _x, int _y, int _Size, bool IsK = false//
{
    if (_Size == 8 || _Size == -1)
   {
        for (int i = _y + 1; i < 8++i)
            if (Chess_Check(_Board, _x - (i - _y), i) || IsK) break;
        for (int i = _y - 1; i > -1--i)
            if (Chess_Check(_Board, _x + (i - _y), i) || IsK) break;
    }
    if (_Size == 8 || _Size == 1)
    {
        for (int i = _y - 1; i > -1--i)
            if (Chess_Check(_Board, _x - (i - _y), i) || IsK) break;
        for (int i = _y + 1; i < 8++i)
            if (Chess_Check(_Board, _x + (i - _y), i) || IsK) break;
    }
}
 
void Knight(string _Board[][8], int _x, int _y)
{
    for (int i = -1; i < 2; i += 2)
        for (int j = -2; j < 3; j += 4)
        {
            Chess_Check(_Board, _x + j, _y + i);
            Chess_Check(_Board, _x + i, _y + j);
        }
}
 
void Chess(string& _Str)
{
    string Board[8][8];
    for (int i = 0; i < 8++i)
        for (int j = 0; j < 8++j)
            Board[i][j] = "X";
    int x = 0, y = 0, ans = 0;
    for (auto i : _Str) //1. Board에 체스 기물 배치
   {
        //숫자라면
        if (i >= 48 && i <= 57)
            y += i - 49//-48(char to int) -1(증감)
        //영어라면
        else if (i != 47)
            Board[x][y] = i;
        y++;
        //줄바꿈
        if (y != 8)
            continue;
        x++;
        y = -1;
    }
 
    for (int i = 0; i < 8++i) //2. Board 순회하며 기물 만나면 이동 가능 경로를 체크함
        for (int j = 0; j < 8++j)
        {
            //영어라면
            if (Board[i][j] != "O" && Board[i][j] != "X")
            {
                if (Board[i][j] == "b" || Board[i][j] == "B" || Board[i][j] == "q" || Board[i][j] == "Q")
                    Diagonal(Board, i, j, 8);
                if (Board[i][j] == "r" || Board[i][j] == "R" || Board[i][j] == "q" || Board[i][j] == "Q")
                    UDLR(Board, i, j);
                else if (Board[i][j] == "k" || Board[i][j] == "K")
                {
                    UDLR(Board, i, j, true);
                    Diagonal(Board, i, j, 8true);
                }
                else if (Board[i][j] == "p")
                    Diagonal(Board, i, j, 1true);
                else if (Board[i][j] == "P")
                    Diagonal(Board, i, j, -1true);
                else if (Board[i][j] == "n" || Board[i][j] == "N")
                    Knight(Board, i, j);
            }
        }
 
    for (int i = 0; i < 8++i) //3. board 순회하며 X만나면(경로 체크에 안걸렸다면)답에 1 더해줌.
        for (int j = 0; j < 8++j)
            if (Board[i][j] == "X")
                ans++;
    cout << ans << "\n";
}
 
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
 
    string Str;
    while (cin >> Str)
        Chess(Str);
}
cs

8x8 배열 Board 선언 -> Board에 체스 기물 배치 -> Board 순회하며 기물 만나면 이동 가능 경로를 체크 -> board 순회하며 X만나면(경로 체크에 안걸렸다면)답에 1 더해줌. 마지막 과정은 확실히 있을 필요가 없다.

 

잡설 : 이 문제 코드 풀이는 내가 처음이다 ㅎ

반응형

댓글