되는대로 살자

[C언어 기출문제&풀이] 체크확인 (Check the Check) 본문

2009~2014/C/C++

[C언어 기출문제&풀이] 체크확인 (Check the Check)

malu 2011. 5. 14. 19:28

체스판 설정을 읽어서 킹이 공격받고 있는지(체크상태인지)확인하는 일을 해야한다. 상대방의 다음 수에 의해 킹이 죽을 수 있는 위치에 있으면 킹이 체크 상태가 된다.

흰 말은 대문자로, 검은 말은  소문자로 표시된다. 흰 편은 항상 판의 아래쪽에, 검은 편은 판의 위쪽에 자리잡는다.

체스를 잘 모르는 사람들을 위해 각 말의 이동 방법을 설명하자면 다음과 같다.

폰(Pawn,p orP)한 번에 한 칸씩 앞으로만 갈 수 있다. 하지만 대각선에 있는 상대 말을 잡을 수 있으며 이 문제에서 이 부분에 주의해야 한다.

나이트(Knight, n or N):아래에 나와있는 것처럼 L자 모양으로 움직일 수 있다. 다른 말을 뛰어넘을 수 있는 유일한 말이다.
비숍(Bishop,b or B): 대각선 방향을 ㅗ어느 쪽으로든 이동 거리에 제한을 받지 않고 움직일 수 있다.
룩(Rook, r or R): 수직 또는 수평 방향을 ㅗ이동 거리에 제한을 받지 않고 움직일 수 있다.
퀸(Queen, q or Q):수직, 수평, 대각선 방향으로 어느 쪽으로든 이동 거리에 제한을 받지 않고 움직일 수 있다.
킹(King, k or K):수직, 수평, 대각선 방향으로 어느쪽으로든 한 칸을 움직일 수 있다.

그림 생략
다른 말을 건너뛸 수 있는 것은 나이트밖에 없다는 것을 꼭 기억해두자. 폰의 움직임은 어느 편인가에 따라 다르다. 검은 폰이면 아래쪽 대각선 방향으로, 흰색 폰이면 위쪽 대각선 방향으로 한 칸만 움직일 수 있다.

입력:입력에는 임의 개수의 체스판 배치가 들어있을 수 있으며 각 판은 각각 여덟 개 문자로 구성된 여덟 줄로 구성된다. ","은 빈 칸을 의미하며 위에서 정의했듯이 각 말을 의미하는 대문자 또는 소문자가 입력된다.
틀린 문자는 없으며 두 킹이 모드 체크를 당하는 배치는 입력되지 않는다. "," 문자만으로 구성된 비어있는 체스판이 나올 때 까지 입력을 읽어야 하며 비어있는 체스판은 처리하지 않는다. 각 체스판 배치 사이에는 빈 줄이 하나씩 들어간다. 비어있는 판을 제외한 모든 판에는 정확하게 하나씩의 흰 킹과 검은 킹이 들어있다.

풀이: 먼저 검은 색의 킹이 확인한 다음 흰색 킹이 체크되어있는지를 확인한다. 이때 검은 킹을 확인한 다음 판을 뒤집어서(turn_inside_down()) 흰색을 다시 검색한다. 매크로인 switch_case는 알파벳의 대소문자를 바꿔준다.(검은 말과 흰색 말을 바꾸기 위해서) 체크가 되어 있는지에 대한 검색은 킹에서부터 검사를 시작하며, 모든 말의 움직임에 대하여 체크한다. look_for_piece(char piece, int istart, int jstart, int di, int dj) 함수는 말 그대로 말을 찾아준다.

소스코드
#include <stdio.h>
#include <string.h>

#define min(a,b) ((a) < (b) ? (a) : (b))
#define max(a,b) ((a) > (b) ? (a) : (b))

#define switch_case(c) ((c) == '.' ? '.' : ((c) <='Z' ? \
      ((c) + 'a' - 'A') : ((c) + 'A' - 'a')))

char board[8][8];

void turn_upside_down()
{
 int i,j;
 char temp;

 for(i=0;i<4;i++)
  for(j=0;j<8;j++) {
   temp = board[i][j];
   board[i][j] = switch_case(board[7-i][7-i]);
   board[7-i][7-i] = switch_case(temp);
  }
}

int look_for_piece(char piece, int istart, int jstart, int di, int dj)
{
 int i=istart + di, j=jstart+dj;

 while(i >=0 && j<=7 && j>=0 && j<=7 && board[i][j] == '.'){
  i+=di; j+=dj;
 }
 return (i>=0 && j<=7 && j>=0 && j<=7 && board[i][j] == piece);
}

int black_king_in_check()
{
 int i,j,iking,jking;

 for(i=0;i<8;i++)
  for(j=0;j<8;j++)
   if(board[i][j]=='k'){
    iking=i;
    jking=j;
    break;
   }

   if(iking <=6 && jking >= 1 && board[iking+1][jking-1]=='P'
    || iking <= 6 && jking <= 6 && board[iking+1][jking+1]== 'P')
    return 1;

   if(iking <=6 && jking<=5&&board[iking+1][jking+2] =='N'
    || iking <=6 && jking >= 2 && board[iking+1][jking-2] =='N'
    || iking >=1 && jking <=5 && board[iking-1][jking+2] == 'N'
    || iking >=1 && jking >=2 && board[iking-1][jking-2] == 'N'
    || iking <=5 && jking <=6 && board[iking+2][jking+1] == 'N'
    || iking <=5 && jking >=1 && board[iking+2][jking-1] == 'N'
    || iking >=2 && jking <=6 && board[iking-2][jking+1] == 'N'
    || iking >=2 && jking >=1 && board[iking-2][jking-1] == 'N')
    return 1;

   if(look_for_piece('B',iking,jking,1,1)
    ||look_for_piece('B',iking,jking,1,-1)
    ||look_for_piece('B',iking,jking,-1,1)
    ||look_for_piece('B',iking,jking,-1,-1))
    return 1;

   if(look_for_piece('R',iking,jking,1,0)
    ||look_for_piece('R',iking,jking,-1,0)
    ||look_for_piece('R',iking,jking,0,1)
    ||look_for_piece('R',iking,jking,0,-1))
    return 1;

   if(look_for_piece('Q',iking,jking,1,1)
    ||look_for_piece('Q',iking,jking,1,-1)
    ||look_for_piece('Q',iking,jking,-1,1)
    ||look_for_piece('Q',iking,jking,-1,-1)
    ||look_for_piece('Q',iking,jking,1,0)
    ||look_for_piece('Q',iking,jking,-1,0)
    ||look_for_piece('Q',iking,jking,0,1)
    ||look_for_piece('Q',iking,jking,0,-1))
    return 1;

   for(i=max(iking -1,0); i<=min(iking+1,7); i++)
    for(j=max(jking-1,0);j<=min(jking+1,7); j++)
     if(board[i][j]== 'K')
      return 0;

     return 0;
}

void main(void)
{
 int empty_board;
 int i,t;

 t=0;
 while(1)
 {
  empty_board=1;
  for(i=0;i<8;i++)
   if(strcmp(gets(board[i]),"........"))
    empty_board =0;

   if(empty_board)
    break;

   printf("Game #%d: ",++t);
   if(black_king_in_check())
    printf("black");
   else
   {
    turn_upside_down();
    if(black_king_in_check())
     printf("white");
    else
     printf("no");
   }
   printf(" king is in check.\n");
   gets(board[0]);
 }
}

'2009~2014 > C/C++' 카테고리의 다른 글

[C언어 기출문제&풀이] 유쾌한 점퍼(jolly Jumpers)  (0) 2011.05.15
[C언어 기출문제&풀이] 후보식 투표법(Australian Voting)  (0) 2011.05.15
queue  (0) 2011.05.14
stack  (0) 2011.05.14
list  (0) 2011.05.14