#include <stdio.h>
#include <vector>
using namespace std;
#define DIM_SIZE (8 + 2 + 2)
#define LINE_SIZE 8
#define DELTA ((DIM_SIZE - LINE_SIZE) / 2)
enum ChessType_t
{
BLACK = 0,
WHITE
};
class Chess
{
public:
typedef Chess* ChessPtr;
typedef ChessPtr ChessCol[DIM_SIZE][DIM_SIZE];
Chess(int row, int col, ChessType_t type) : m_Row(row), m_Col(col), m_type(type)
{
}
virtual ~Chess()
{
}
virtual bool Check(ChessCol& chessCol) = 0;
ChessType_t GetType() { return m_type; }
protected:
virtual bool IsKing() { return false; }
bool DoCheck(ChessCol& chessCol, int row, int col, bool& blocked)
{
blocked = false;
ChessPtr& pChess = chessCol[row][col];
if (!pChess)
return false;
blocked = true;
if ((pChess->m_type != m_type) && (pChess->IsKing()))
return true;
return false;
}
protected:
int m_Row, m_Col;
ChessType_t m_type;
};
class P : public Chess // Soldier
{
public:
P(int row, int col, ChessType_t type) : Chess(row, col, type)
{
}
virtual bool Check(ChessCol& chessCol)
{
bool dummy;
if (BLACK == m_type)
return (DoCheck(chessCol, m_Row + 1, m_Col - 1, dummy) || DoCheck(chessCol, m_Row + 1, m_Col + 1, dummy));
return (DoCheck(chessCol, m_Row - 1, m_Col - 1, dummy) || DoCheck(chessCol, m_Row - 1, m_Col + 1, dummy));
}
};
class N : public Chess // Horse
{
public:
N(int row, int col, ChessType_t type) : Chess(row, col, type)
{
}
virtual bool Check(ChessCol& chessCol)
{
bool dummy;
return (DoCheck(chessCol, m_Row - 1, m_Col - 2, dummy) ||
DoCheck(chessCol, m_Row - 1, m_Col + 2, dummy) ||
DoCheck(chessCol, m_Row - 2, m_Col - 1, dummy) ||
DoCheck(chessCol, m_Row - 2, m_Col + 1, dummy) ||
DoCheck(chessCol, m_Row + 1, m_Col - 2, dummy) ||
DoCheck(chessCol, m_Row + 1, m_Col + 2, dummy) ||
DoCheck(chessCol, m_Row + 2, m_Col - 1, dummy) ||
DoCheck(chessCol, m_Row + 2, m_Col + 1, dummy));
}
};
class B : virtual public Chess // Elephant
{
public:
B(int row, int col, ChessType_t type) : Chess(row, col, type)
{
}
virtual bool Check(ChessCol& chessCol)
{
// Left Upper
bool blocked = false;
int curRow = m_Row - 1, curCol = m_Col - 1;
while(!blocked)
{
if ((curRow < DELTA) || (curCol < DELTA))
break;
if (DoCheck(chessCol, curRow, curCol, blocked))
return true;
--curRow;
--curCol;
}
// Right Upper
blocked = false;
curRow = m_Row - 1;
curCol = m_Col + 1;
while(!blocked)
{
if ((curRow < DELTA) || (curCol >= (DELTA + LINE_SIZE)))
break;
if (DoCheck(chessCol, curRow, curCol, blocked))
return true;
--curRow;
++curCol;
}
// Left Below
blocked = false;
curRow = m_Row + 1;
curCol = m_Col - 1;
while(!blocked)
{
if ((curRow >= (DELTA + LINE_SIZE)) || (curCol < DELTA))
break;
if (DoCheck(chessCol, curRow, curCol, blocked))
return true;
++curRow;
--curCol;
}
// Right Below
blocked = false;
curRow = m_Row + 1;
curCol = m_Col + 1;
while(!blocked)
{
if ((curRow >= (DELTA + LINE_SIZE)) || (curCol >= (DELTA + LINE_SIZE)))
break;
if (DoCheck(chessCol, curRow, curCol, blocked))
return true;
++curRow;
++curCol;
}
return false;
}
};
class R : virtual public Chess // Car
{
public:
R(int row, int col, ChessType_t type) : Chess(row, col, type)
{
}
virtual bool Check(ChessCol& chessCol)
{
// Left
bool blocked = false;
int curCol = m_Col - 1;
while(!blocked)
{
if (curCol < DELTA)
break;
if (DoCheck(chessCol, m_Row, curCol, blocked))
return true;
--curCol;
}
// Right
blocked = false;
curCol = m_Col + 1;
while(!blocked)
{
if (curCol >= (DELTA + LINE_SIZE))
break;
if (DoCheck(chessCol, m_Row, curCol, blocked))
return true;
++curCol;
}
// Upper
blocked = false;
int curRow = m_Row - 1;
while(!blocked)
{
if (curRow < DELTA)
break;
if (DoCheck(chessCol, curRow, m_Col, blocked))
return true;
--curRow;
}
// Below
blocked = false;
curRow = m_Row + 1;
while(!blocked)
{
if (curRow >= (DELTA + LINE_SIZE))
break;
if (DoCheck(chessCol, curRow, m_Col, blocked))
return true;
++curRow;
}
return false;
}
};
class Q : public B, public R // Queen
{
public:
Q(int row, int col, ChessType_t type) : Chess(row, col, type), B(row, col, type), R(row, col, type)
{
}
virtual bool Check(ChessCol& chessCol)
{
return (B::Check(chessCol) || R::Check(chessCol));
}
};
class K : public Chess
{
public:
K(int row, int col, ChessType_t type) : Chess(row, col, type)
{
}
virtual bool Check(ChessCol& chessCol)
{
bool dummy;
for (int i = m_Col - 1; i <= m_Col + 1; ++i)
{
if (DoCheck(chessCol, m_Row - 1, i, dummy)) // Upper
return true;
if (DoCheck(chessCol, m_Row + 1, i, dummy)) // Below
return true;
}
// Left & Right
return (DoCheck(chessCol, m_Row, m_Col - 1, dummy) ||
DoCheck(chessCol, m_Row, m_Col + 1, dummy));
}
virtual bool IsKing() { return true; }
};
class ChessPanel
{
public:
ChessPanel(int index) : m_ValidChessCnt(0), m_Index(index)
{
for(int i = 0; i < DIM_SIZE; ++i)
{
for(int j = 0; j < DIM_SIZE; ++j)
{
m_ChessCol[i][j] = NULL;
}
}
}
~ChessPanel()
{
for(int i = 0; i < DIM_SIZE; ++i)
{
for(int j = 0; j < DIM_SIZE; ++j)
{
if (m_ChessCol[i][j])
delete m_ChessCol[i][j];
}
}
}
void Input(char* pLine, int lineNo)
{
int cnt = 0;
for (int i = 0; i < LINE_SIZE; ++i)
{
int row = DELTA + lineNo, col = DELTA + i;
Chess::ChessPtr& pChess = m_ChessCol[row][col];
switch(pLine[i])
{
case 'p':
pChess = new P(row, col, BLACK);
++cnt;
break;
case 'P':
pChess = new P(row, col, WHITE);
++cnt;
break;
case 'n':
pChess = new N(row, col, BLACK);
++cnt;
break;
case 'N':
pChess = new N(row, col, WHITE);
++cnt;
break;
case 'b':
pChess = new B(row, col, BLACK);
++cnt;
break;
case 'B':
pChess = new B(row, col, WHITE);
++cnt;
break;
case 'r':
pChess = new R(row, col, BLACK);
++cnt;
break;
case 'R':
pChess = new R(row, col, WHITE);
++cnt;
break;
case 'q':
pChess = new Q(row, col, BLACK);
++cnt;
break;
case 'Q':
pChess = new Q(row, col, WHITE);
++cnt;
break;
case 'k':
pChess = new K(row, col, BLACK);
++cnt;
break;
case 'K':
pChess = new K(row, col, WHITE);
++cnt;
break;
default:
pChess = NULL;
break;
}
}
m_ValidChessCnt += cnt;
}
bool IsValid()
{
return (m_ValidChessCnt > 0);
}
void Check()
{
for (int i = DELTA; i < (DELTA + LINE_SIZE); ++i)
{
for (int j = DELTA; j < (DELTA + LINE_SIZE); ++j)
{
if (!m_ChessCol[i][j])
continue;
if (!m_ChessCol[i][j]->Check(m_ChessCol))
continue;
if (BLACK == m_ChessCol[i][j]->GetType())
{
printf("Game #%d: white king is in check.\n", m_Index);
return;
}
printf("Game #%d: black king is in check.\n", m_Index);
return;
}
}
printf("Game #%d: no king is in check.\n", m_Index);
}
private:
Chess::ChessCol m_ChessCol;
int m_ValidChessCnt;
int m_Index;
};
void Input(vector<ChessPanel*>& chessPanelCol)
{
char buf[DIM_SIZE];
int index = 1;
while(true)
{
ChessPanel* pPanel = new ChessPanel(index);
for (int i = 0; i < LINE_SIZE; ++i)
{
fgets(buf, DIM_SIZE, stdin);
pPanel->Input(buf, i);
}
if (pPanel->IsValid())
{
fgets(buf, DIM_SIZE, stdin); // Consume the empty line.
++index;
chessPanelCol.push_back(pPanel);
continue;
}
delete pPanel;
return;
}
}
void Check(vector<ChessPanel*>& chessPanelCol)
{
for (size_t i = 0; i < chessPanelCol.size(); ++i)
{
chessPanelCol[i]->Check();
}
}
void Clear(vector<ChessPanel*>& chessPanelCol)
{
for (size_t i = 0; i < chessPanelCol.size(); ++i)
{
delete chessPanelCol[i];
}
chessPanelCol.clear();
}
int main(int argc, char* argv[])
{
vector<ChessPanel*> chessPanelCol;
Input(chessPanelCol);
Check(chessPanelCol);
Clear(chessPanelCol);
return 0;
}