#pragma once
#ifndef _chessman_
#define _chessman_
#include <vector>
using namespace std;
#define MAX_WIDTH 8
#define MAX_HEIGHT 8
typedef struct tag_point{
// 화면상의 좌표를 표현하는 구조체.
public:
int x;
int y;
// POINT의 초기값은 -1, -1이다.
// 체스판 위에 존재하지 않는 좌표.
tag_point()
{
x = -1;
y = -1;
}
// 현포인트에서 이동할 좌표를 계산해서 반환.
tag_point MovePoint(int pX, int pY) const{
tag_point t;
t.x = x + pX;
t.y = y + pY;
return t;
}
// 움직일 좌표의 유효성 검사. 체스판 범위를 벗어나면 false
bool CheckPoint(int pX, int pY) const{
return ((x+pX >= 0) && (x+pX < MAX_WIDTH) && (y+pY >= 0) && (y+pY < MAX_HEIGHT));
}
bool isZero(void) const {
// 초기값이 -1, -1 이면
return ((x == -1) && (y == -1));
}
}POINT;
#define VRANGE vector<POINT> // 한방향의 가상 이동 거리
#define VRANGE8 vector<VRANGE> // 8방향의 가상 이동거리
class VirtualRange{
// 체스말이 현위치에서 움직일 방향의 포인터들을 찾아낸다. VRANGE로 반환
// 다른 체스말에 의해 이동이 막히는 것은 보드에서 처리
// 직선,대각선만 찾아내며, 나이트는 이 클래스를 사용할수 없다.
public:
VirtualRange(){}
~VirtualRange(){}
public:
// 방향 정의.
enum DIRECTION{
D_TOP = 1,
D_TOP_RIGHT,
D_RIGHT,
D_BOT_RIGHT,
D_BOT,
D_BOT_LEFT,
D_LEFT,
D_TOP_LEFT
};
// 코딩의 편의를 위한 매크로.
#define D_RIGHT_TOP D_TOP_RIGHT
#define D_RIGHT_BOT D_BOT_RIGHT
#define D_LEFT_TOP D_TOP_LEFT
#define D_LEFT_BOT D_BOT_LEFT
enum RANGE{
R_ONE = 1,
R_FULL
};
// 외부에서는 이것만 호출하여 좌표를 찾아온다.
void GetRange(VRANGE8 * retRange, const POINT & origin, const DIRECTION & dir, const RANGE & r) const {
VRANGE range;
range = this->Get(origin, dir, r);
if ( range.size() > 0 )
retRange->push_back(range);
}
private:
// 동작 분리자.
VRANGE Get(const POINT & origin, const DIRECTION & dir, const RANGE & r) const {
VRANGE retRange;
if ( r == VirtualRange::R_ONE )
{
POINT ret = this->GetOne(origin, dir);
if ( !ret.isZero() )
retRange.push_back(ret);
}
else if ( r == VirtualRange::R_FULL )
{
this->GetMore(&retRange, origin, dir);
}
return retRange;
}
// 한칸씩 움직이는거 좌표찾기.
POINT GetOne(POINT origin, DIRECTION dir) const {
POINT ret;
switch(dir)
{
case D_TOP:
if (origin.CheckPoint(0, -1))
ret = origin.MovePoint(0, -1);
break;
case D_TOP_RIGHT:
if (origin.CheckPoint(1, -1))
ret = origin.MovePoint(1, -1);
break;
case D_RIGHT:
if (origin.CheckPoint(1, 0))
ret = origin.MovePoint(1, 0);
break;
case D_BOT_RIGHT:
if (origin.CheckPoint(1, 1))
ret = origin.MovePoint(1, 1);
break;
case D_BOT:
if (origin.CheckPoint(0, 1))
ret = origin.MovePoint(0, 1);
break;
case D_BOT_LEFT:
if (origin.CheckPoint(-1, 1))
ret = origin.MovePoint(-1, 1);
break;
case D_LEFT:
if (origin.CheckPoint(-1, 0))
ret = origin.MovePoint(-1, 0);
break;
case D_TOP_LEFT:
if (origin.CheckPoint(-1, -1))
ret = origin.MovePoint(-1, -1);
break;
}
return ret;
}
// 멀리가는 것들 좌표 찾기. 재귀호출.
void GetMore(VRANGE* retRange, POINT origin, DIRECTION dir) const {
POINT ret;
switch(dir)
{
case D_TOP:
if (origin.CheckPoint(0, -1))
ret = origin.MovePoint(0, -1);
break;
case D_TOP_RIGHT:
if (origin.CheckPoint(1, -1))
ret = origin.MovePoint(1, -1);
break;
case D_RIGHT:
if (origin.CheckPoint(1, 0))
ret = origin.MovePoint(1, 0);
break;
case D_BOT_RIGHT:
if (origin.CheckPoint(1, 1))
ret = origin.MovePoint(1, 1);
break;
case D_BOT:
if (origin.CheckPoint(0, 1))
ret = origin.MovePoint(0, 1);
break;
case D_BOT_LEFT:
if (origin.CheckPoint(-1, 1))
ret = origin.MovePoint(-1, 1);
break;
case D_LEFT:
if (origin.CheckPoint(-1, 0))
ret = origin.MovePoint(-1, 0);
break;
case D_TOP_LEFT:
if (origin.CheckPoint(-1, -1))
ret = origin.MovePoint(-1, -1);
break;
}
if ( !ret.isZero() )
{
retRange->push_back(ret);
this->GetMore(retRange, ret, dir);
}
}
};
// VritualRange를 줄여쓰기 위해 VR로 매크로 선언
#define VR VirtualRange
class chessman{
// 단순한 움직일 위치만 찾는다.
public:
enum MAN_COLOR{
_BLACK_ = 1,
_WHITE_,
_NULL_
};
chessman(void){}
chessman(const chessman::MAN_COLOR & color, const POINT & point, const char & Name)
{
this->mColor = color;
this->mPoint = point;
this->manName = Name;
}
~chessman(void){}
public:
MAN_COLOR mColor;
POINT mPoint;
char manName;
virtual VRANGE8 GetRange(void) const = 0;
};
#define CM chessman
class Pawn:public chessman{
// 폰은 전방 대각선 한칸만 알면 된다.
// 흑백에 따라 전방은 반전된다.
public:
Pawn(){}
~Pawn(){}
Pawn(const CM::MAN_COLOR & color, const POINT & point, const char & Name )
{
this->mColor = color;
this->mPoint = point;
this->manName = Name;
}
virtual VRANGE8 GetRange(void) const{
VRANGE8 retRange;
if (this->mColor == chessman::_BLACK_)
{
VR().GetRange(&retRange, this->mPoint, VR::D_LEFT_BOT, VR::R_ONE);
VR().GetRange(&retRange, this->mPoint, VR::D_RIGHT_BOT, VR::R_ONE);
}
else if (this->mColor == chessman::_WHITE_)
{
VR().GetRange(&retRange, this->mPoint, VR::D_LEFT_TOP, VR::R_ONE);
VR().GetRange(&retRange, this->mPoint, VR::D_RIGHT_TOP, VR::R_ONE);
}
return retRange;
}
};
class Rook: public chessman{
public:
Rook(){}
~Rook(){}
Rook(const CM::MAN_COLOR & color, const POINT & point, const char & Name)
{
this->mColor = color;
this->mPoint = point;
this->manName = Name;
}
// 룩은 흑백 상관 없이 4방향 직선만 알면 된다.
virtual VRANGE8 GetRange(void) const{
VRANGE8 retRange;
VR().GetRange(&retRange, this->mPoint, VR::D_TOP, VR::R_FULL);
VR().GetRange(&retRange, this->mPoint, VR::D_RIGHT, VR::R_FULL);
VR().GetRange(&retRange, this->mPoint, VR::D_LEFT, VR::R_FULL);
VR().GetRange(&retRange, this->mPoint, VR::D_BOT, VR::R_FULL);
return retRange;
}
};
class Bishop: public chessman{
public:
Bishop(){}
~Bishop(){}
Bishop(const CM::MAN_COLOR & color, const POINT & point, const char & Name)
{
this->mColor = color;
this->mPoint = point;
this->manName = Name;
}
// 폰은 흑백 상관 없이 대각선 방향의 직선만 알면된다.
virtual VRANGE8 GetRange(void) const {
VRANGE8 retRange;
VR().GetRange(&retRange, this->mPoint, VR::D_BOT_LEFT, VR::R_FULL);
VR().GetRange(&retRange, this->mPoint, VR::D_BOT_RIGHT, VR::R_FULL);
VR().GetRange(&retRange, this->mPoint, VR::D_TOP_LEFT, VR::R_FULL);
VR().GetRange(&retRange, this->mPoint, VR::D_TOP_RIGHT, VR::R_FULL);
return retRange;
}
};
class Queen: public chessman{
public:
Queen(){}
~Queen(){}
Queen(const CM::MAN_COLOR & color, const POINT & point, const char & Name)
{
this->mColor = color;
this->mPoint = point;
this->manName = Name;
}
// 퀸은 비숍과 룩을 합친것과 같다.
virtual VRANGE8 GetRange(void) const {
VRANGE8 retRange;
VR().GetRange(&retRange, this->mPoint, VR::D_TOP, VR::R_FULL);
VR().GetRange(&retRange, this->mPoint, VR::D_RIGHT, VR::R_FULL);
VR().GetRange(&retRange, this->mPoint, VR::D_LEFT, VR::R_FULL);
VR().GetRange(&retRange, this->mPoint, VR::D_BOT, VR::R_FULL);
VR().GetRange(&retRange, this->mPoint, VR::D_BOT_LEFT, VR::R_FULL);
VR().GetRange(&retRange, this->mPoint, VR::D_BOT_RIGHT, VR::R_FULL);
VR().GetRange(&retRange, this->mPoint, VR::D_TOP_LEFT, VR::R_FULL);
VR().GetRange(&retRange, this->mPoint, VR::D_TOP_RIGHT, VR::R_FULL);
return retRange;
}
};
class King: public chessman{
public:
King(){}
~King(){}
King(const CM::MAN_COLOR & color, const POINT & point, const char & Name)
{
this->mColor = color;
this->mPoint = point;
this->manName = Name;
}
// 킹은 퀸과 비슷하지만 한칸씩 움직인다.
virtual VRANGE8 GetRange(void) const {
VRANGE8 retRange;
VR().GetRange(&retRange, this->mPoint, VR::D_TOP, VR::R_ONE);
VR().GetRange(&retRange, this->mPoint, VR::D_RIGHT, VR::R_ONE);
VR().GetRange(&retRange, this->mPoint, VR::D_LEFT, VR::R_ONE);
VR().GetRange(&retRange, this->mPoint, VR::D_BOT, VR::R_ONE);
VR().GetRange(&retRange, this->mPoint, VR::D_BOT_LEFT, VR::R_ONE);
VR().GetRange(&retRange, this->mPoint, VR::D_BOT_RIGHT, VR::R_ONE);
VR().GetRange(&retRange, this->mPoint, VR::D_TOP_LEFT, VR::R_ONE);
VR().GetRange(&retRange, this->mPoint, VR::D_TOP_RIGHT, VR::R_ONE);
return retRange;
}
};
class Knight: public chessman{
public:
Knight(){}
~Knight(){}
Knight(const CM::MAN_COLOR & color, const POINT & point, const char & Name)
{
this->mColor = color;
this->mPoint = point;
this->manName = Name;
}
// 나이트는 8방향 ㄴ자로 움직인다. 나이트는 특별하다.
virtual VRANGE8 GetRange(void) const {
VRANGE8 retRange;
this->GetVRange(&retRange, -2, -1);
this->GetVRange(&retRange, -2, 1);
this->GetVRange(&retRange, 2, -1);
this->GetVRange(&retRange, 2, 1);
this->GetVRange(&retRange, -1, 2);
this->GetVRange(&retRange, 1, 2);
this->GetVRange(&retRange, -1, -2);
this->GetVRange(&retRange, 1, -2);
return retRange;
}
private:
void GetVRange(VRANGE8* retRange, int x, int y) const {
VRANGE range;
POINT point;
if (this->mPoint.CheckPoint(x, y))
{
point = this->mPoint.MovePoint(x, y);
if ( !point.isZero() )
{
range.push_back(point);
retRange->push_back(range);
}
}
}
};
class NullSpace: public chessman{
public:
NullSpace(){}
~NullSpace(){}
NullSpace(const CM::MAN_COLOR & color, const POINT & point, const char & Name)
{
this->mColor = color;
this->mPoint = point;
this->manName = Name;
}
// 체스말이 없는곳.
virtual VRANGE8 GetRange(void) const {
VRANGE8 retRange;
return retRange;
}
};
#endif