보드(게임판) 구성
앞에서 만든 7가지의 벽돌들이 놀 수 있는 Board(게임판)을 만들어 보겠습니다.
필요한 속성과 메소드는 다음과 같습니다.
속성
설명
COneBlock m_iBoard[BOARD_Y_SIZE+1][BOARD_X_SIZE+2]
Board 의 데이터
CClientDC *m_pDC;
출력디바이스
CShape *m_Shape;
움직이는 벽돌 포인터
CPoint m_ptOffsetDisplay;
보드의 출력 옵셋
BOOL m_bGameStart;
게임이 시작되었는가
CShapeArray m_arrayShape;
벽돌을 array로 관리
메소드는 다음과 같습니다.
메소드
설명
BOOL IsGameEnd();
게임이 끝났는지 확인
BOOL BlockDrop();
벽돌을 마지막 까지 내림
void RemoveLineDirect(int _line);
_line 번째 줄을 제거
void RemoveLine();
삭제할 수 있는 줄을 제거
void Refresh(BOOL bShape=TRUE);
화면 갱신
void NewShape();
새로운 벽돌 생성
void NewGame();
새로운 게임 시작
void MergeNowBlock();
벽돌를 보드에 포함
BOOL BlockRotate();
벽돌 회전
BOOL BlockMoveRight();
벽돌 우측 이동
BOOL BlockMoveLeft();
벽돌 좌측 이동
BOOL BlockMoveDown();
벽돌 아래로 한 칸 이동
BOOL IsOverlap(CShape s);
겹치는지 체크
void SetShape(CShape *_shape);
벽돌 설정
void SetOffsetDisplay(CPoint _pt);
화면 출력 옵셋 설정
void DrawOneBlock(int y,int x,int iSize,CClientDC *pDC, COLORREF crRGB, COLORREF crLine=RGB(255,255,255)) ;
벽돌 그리기
void DrawBoard(BOOL bShape=TRUE);
벽돌 그리기
void SetPDC(CClientDC *dc);
출력 디바이스 설정
Board.h
typedef CTypedPtrArray<CObArray, CShape*> CShapeArray;
class CBoard : public CObject
{
public:
BOOL IsGameEnd();
BOOL BlockDrop();
void RemoveLineDirect(int _line);
void RemoveLine();
void Refresh(BOOL bShape=TRUE);
void NewShape();
void NewGame();
void MergeNowBlock();
BOOL BlockRotate();
BOOL BlockMoveRight();
BOOL BlockMoveLeft();
BOOL BlockMoveDown();
BOOL IsOverlap(CShape s);
void SetShape(CShape *_shape);
void SetOffsetDisplay(CPoint _pt);
void DrawOneBlock(int y,int x,int iSize,CClientDC *pDC, COLORREF crRGB, COLORREF crLine=RGB(255,255,255)) ;
void DrawBoard(BOOL bShape=TRUE);
void SetPDC(CClientDC *dc);
CShapeArray m_arrayShape; // 벽돌들을 array로 관리
CClientDC *m_pDC;
COneBlock m_iBoard[BOARD_Y_SIZE+1][BOARD_X_SIZE+2];
CShape *m_Shape;
CPoint m_ptOffsetDisplay; // 보드의 옵셋
BOOL m_bGameStart;
CBoard();
virtual ~CBoard();
};
Board.cpp
CBoard::CBoard()
{
m_Shape = NULL;
m_bGameStart = false;
m_ptOffsetDisplay = CPoint(0,0);
// 랜덤 벽돌을 위한 함수
srand( (unsigned)time( NULL ) );
m_arrayShape.Add(new CShape1());
m_arrayShape.Add(new CShape2());
m_arrayShape.Add(new CShape3());
m_arrayShape.Add(new CShape4());
m_arrayShape.Add(new CShape5());
m_arrayShape.Add(new CShape6());
m_arrayShape.Add(new CShape7());
NewGame();
}
CBoard::~CBoard()
{
if(m_Shape)
{
delete m_Shape;
m_Shape = NULL;
}
}
void CBoard::SetPDC(CClientDC *dc)
{
m_pDC = dc;
m_Shape->SetPDC(dc);
}
void CBoard::DrawBoard(BOOL bShape)
{
int tempY;
for(tempY = 0;tempY<BOARD_Y_SIZE+1;tempY++){
for(int tempX=0; tempX<BOARD_X_SIZE+2; tempX++)
{
if(0 != m_iBoard[tempY][tempX].m_iValue){
DrawOneBlock((m_ptOffsetDisplay.y+tempY),m_ptOffsetDisplay.x+tempX,ONE_BLOCK_SIZE,m_pDC,RGB(200,200,200));
}
}
}
if(m_Shape)
{
m_Shape->SetPDC(m_pDC);
m_Shape->DrawBlock();
}
}
void CBoard::DrawOneBlock(int y,int x,int iSize,CClientDC *pDC, COLORREF crRGB, COLORREF crLine)
{
pDC->FillSolidRect((x)*iSize, (y)*iSize, iSize, iSize, crRGB);
pDC->Draw3dRect((x)*iSize, (y)*iSize, iSize, iSize, crLine,crLine);
}
void CBoard::SetOffsetDisplay(CPoint _pt)
{
this->m_ptOffsetDisplay = _pt;
m_Shape->SetOffsetDisplay(_pt);
}
void CBoard::SetShape(CShape *_shape)
{
this->m_Shape = _shape;
}
void CBoard::NewGame()
{
int tempY;
int tempX;
for(tempY = 0;tempY<BOARD_Y_SIZE+1;tempY++){
for(tempX=0; tempX<BOARD_X_SIZE+2; tempX++)
{
m_iBoard[tempY][tempX].m_iValue = 0;
}
}
// 보드의 좌측 벽
for(int i=0;i<BOARD_Y_SIZE;i++){
m_iBoard[i][0].m_iValue=50;
}
// 보드의 우측 벽
for( i=0;i<BOARD_Y_SIZE;i++){
m_iBoard[i][BOARD_X_SIZE+1].m_iValue=50;
}
// 보드의 하단 벽
for( i=0;i<BOARD_X_SIZE+2;i++){
m_iBoard[BOARD_Y_SIZE][i].m_iValue=50;
}
NewShape();
}
BOOL CBoard::BlockMoveDown()
{
CShape s;
s.Copy(m_Shape);
s.m_ptPosition.y++;
if(IsOverlap(s))
{
// LOGOUT(” 겹친다.”);
MergeNowBlock();
RemoveLine();
NewShape();
Refresh();
return FALSE;
}
else
{
// LOGOUT(” 안 겹친다.”);
m_Shape->MoveDown();
return TRUE;
}
}
BOOL CBoard::BlockMoveLeft()
{
CShape s;
s.Copy(m_Shape);
s.m_ptPosition.x–;
if(IsOverlap(s))
{
return FALSE;
}
else
{
m_Shape->MoveLeft();
return TRUE;
}
}
BOOL CBoard::BlockMoveRight()
{
CShape s;
s.Copy(m_Shape);
s.m_ptPosition.x++;
if(IsOverlap(s))
{
return FALSE;
}
else
{
m_Shape->MoveRight();
return TRUE;
}
}
BOOL CBoard::BlockRotate()
{
CShape s;
s.Copy(m_Shape);
s.ChangeRotate();
if(IsOverlap(s))
{
return FALSE;
}
else
{
m_Shape->RotateCCW();
return TRUE;
}
}
BOOL CBoard::BlockDrop()
{
while(BlockMoveDown())
{
}
return true;
}
BOOL CBoard::IsOverlap(CShape s)
{
for (int iTemp = 0;iTemp<4;iTemp++)
{
COneBlock b =s.GetOneBlock(s.GetRotate(),iTemp);
int x = s.m_ptPosition.x + b.iPosX;
int y = s.m_ptPosition.y+ b.iPosY;
if(0 != m_iBoard[y][x].m_iValue){
return TRUE;
}
}
return FALSE;}
void CBoard::MergeNowBlock()
{
for (int iTemp = 0;iTemp<4;iTemp++)
{
COneBlock b =m_Shape->GetOneBlock(m_Shape->GetRotate(),iTemp);
int x = m_Shape->m_ptPosition.x + b.iPosX;
int y = m_Shape->m_ptPosition.y+ b.iPosY;
m_iBoard[y][x].m_iValue = 50;
}
}
void CBoard::RemoveLine()
{
int p[4];//
m_Shape->GetY(p);
for (int iTemp = 0;iTemp<4;iTemp++)
{
int iLineY = p[iTemp];
if (-1 != iLineY)
{
BOOL bGoodOneLine = TRUE;
for (int iTempBlockX = 0;iTempBlockX<BOARD_X_SIZE+2;iTempBlockX++)
{
if(0 == m_iBoard[iLineY][iTempBlockX].m_iValue ){ // 한칸이라도 빈칸이 있으면.
bGoodOneLine = FALSE;
}
}
if(TRUE == bGoodOneLine){
RemoveLineDirect(iLineY);
for(int iTempLine = 0;iTempLine<4;iTempLine++)
{
if(-1 !=p[iTempLine] && p[iTempLine]<iLineY)
{
p[iTempLine]++;
}
}
p[iTemp] = -1;
}
}
}
}
void CBoard::NewShape()
{
int iShape = rand()%m_arrayShape.GetSize();
m_Shape = m_arrayShape.GetAt(iShape);
m_Shape->m_ptPosition = CPoint(4,0);
m_Shape->SetOffsetDisplay(m_ptOffsetDisplay);
}
void CBoard::Refresh(BOOL bShape)
{
int tempY;
for(tempY = 0;tempY<BOARD_Y_SIZE+1;tempY++){
for(int tempX=0; tempX<BOARD_X_SIZE+2; tempX++)
{
DrawOneBlock((m_ptOffsetDisplay.y+tempY),m_ptOffsetDisplay.x+tempX,ONE_BLOCK_SIZE,m_pDC,RGB(0xc0,0xc0,0xc0),RGB(0xc0,0xc0,0xc0));
}
}
DrawBoard(bShape);
}
void CBoard::RemoveLineDirect(int _line)
{
while(_line >1)
{
LOGOUT(“_line:%d”,_line);
for(int j=1;j<BOARD_X_SIZE+1;j++){
m_iBoard[_line][j] =m_iBoard[_line-1][j] ;
m_iBoard[_line-1][j].m_iValue = 0;
}
_line– ;
}
Refresh(FALSE);
}
BOOL CBoard::IsGameEnd()
{
for(int tempY = 0;tempY<2 ;tempY++){
for(int tempX=3; tempX<7; tempX++)
{
if(0 != m_iBoard[tempY][tempX].m_iValue){
return TRUE;
}
}
}
return FALSE;
}