본문 바로가기

뭐라도 만들어보자!!( 프로젝트 )/C, C++ 프로젝트

1-3 C/C++ Console 테트리스를 만들어보자!!(Class : Block)

반응형

앞서 예고한 데로 3개의 클래스에 대해서 글 3개에 걸쳐서 설명하고자 합니다.

 

Block이라는 클래스는 1칸짜리 블록에 대해서 정의한 것입니다. 차후에 TetrisBlock 클래스에서 4개의 Block 인스턴스를 생성하고 관리하게 될 것입니다.

 

다음은 Block Class의 정의입니다. 변화가 반영된 nowState와 그 이전 상태인 prevState를 눈여겨 볼필요가 있습니다. 전 상태의 블록은 지우고, 현재 상태의 블록을 출력한다면 사용자에게는 블록이 이동하는 것처럼 느껴질 것입니다.

 

/*
struct dotPos{
	int posX;
    int posY;
    bool whetherStacked;
};

sturct ableToMove{
	bool ableToFall;
    bool ableToMoveLeft;
    bool ableToMoveRight;
};
*/

class Block {
private:
	dotPos nowState;
	dotPos prevState;
	ableToMove nowMovableState;
public:
	Block(int X=0, int Y=0) {
		this->nowState = {X, Y, FALSE};
		this->prevState = {X, Y, FALSE};
		this->nowMovableState = {TRUE, TRUE, TRUE};
	}
	void blockDefaultFall(void);
	void blockPlayerControllLeft(bool left);
	void blockPlayerControllRight(bool right);
	void blockPlayerControllDown(bool down);
	void blockCollisionCheck(std::list<dotPos>& stackedBlock);
	bool blockRightCollisionCheck(std::list<dotPos>& stackedBlock);
	bool blockLeftCollisionCheck(std::list<dotPos>& stackedBlock);
	bool blockDownCollisionCheck(std::list<dotPos>& stackedBlock);
	dotPos getBlockNowState();
	dotPos getBlockPrevState();
	ableToMove getNowMovableState();
	void updateNowMovableStateLeft(bool);
	void updateNowMovableStateRight(bool);
	void updateNowMovableStateDown(bool);
	void updateWhetherStacked(bool);
	void updateBlockPos(int x, int y);
	void updateBlockPrevPos(int x, int y);
};

메서드에 대한 설명은 다음과 같습니다. 

  1. void blockDefaultFall(void) : 블록의 기본적인 낙하
  2. void blockPlayerControllLeft(bool left) : 사용자의 키조작에 따라서 왼쪽으로 움직임
  3. void blockPlayerControllRight(bool right) : 사용자의 키조작에 따라서 오른쪽으로 움직임
  4. void blockPlayerControllDown(bool down) : 사용자의 키조작에 따라서 아래쪽으로 움직임
  5. void blockCollisionCheck(std::list& stackedBlock) : 블록의 좌, 우, 아래방향으로의 충돌 확인(받는 것은 차후 StackedBlock State에서 반환된 경계 블록이다)
  6. bool blockRightCollisionCheck(std::list& stackedBlock) : 블록의 오른쪽 충돌 확인(받는 것은 차후 StackedBlock State에서 반환된 경계 블록이다)
  7. bool blockLeftCollisionCheck(std::list& stackedBlock) : 블록의 왼쪽 충돌 확인(받는 것은 차후 StackedBlock State에서 반환된 경계 블록이다)
  8. bool blockDownCollisionCheck(std::list& stackedBlock) : 블록의 아랫쪽 충돌 확인 및 현재 블록 상태의 확정(추락하지 못하는 블록은 더이상 위치가 변하지 않음)
  9. dotPos getBlockNowState() : 위치가 변한 블록의 위치 반환
  10. dotPos getBlockPrevState() : 변화 전 블록의 위치 반환
  11. ableToMove getNowMovableState() : 블록의 이동 가능한 상태 반환
  12. void updateNowMovableStateLeft(bool) : 블록의 이동가능 상태 임의조작(왼쪽 방향)
  13. void updateNowMovableStateRight(bool) : 블록의 이동가능 상태 임의조작(오른쪽 방향)
  14. void updateNowMovableStateDown(bool) : 블록의 이동가능 상태 임의조작(아래 방향)
  15. void updateWhetherStacked(bool) : 블록의 위치 확정 여부 확인
  16. void updateBlockPos(int x, int y) : 블록의 위치 조정
  17. void updateBlockPrevPos(int x, int y) : 블록의 전 위치 조정

Block 클래스의 주요 기능은 위치 조작과 위치 조작 전 충돌 상태 확인입니다. 이 기능들을 하는 메서드들을 보고 설명하도록 하겠습니다.

 

// 오른 쪽 방향으로 충돌 확인
bool Block::blockRightCollisionCheck(std::list<dotPos>& stackedBlock) {
	list<dotPos>::iterator iter = stackedBlock.begin();
	for (;iter != stackedBlock.end(); iter++) 
	{
		if (iter->posY == nowState.posY) {
			if (iter->posX - nowState.posX == 1)
				return FALSE;
		}
	}
	return TRUE;
}

 

쉽게 말하자면 stackedBlock이라는 list를 참고하여 블록의 오른 쪽에 쌓인 블록이 있는 지 체크하고, 하나라도 있으면 false 값을 그렇지 않으면 true 값을 반환합니다. stackedBlock list는 차후에 다룰 StackedBlockState 클래스에서 반환될 경계 list 입니다. 그런가 보다 하고 넘어가 주세요 !! 왼쪽 방향과 아랫쪽 방향에 대한 충돌도 같은 구조입니다. 

 

다음은 전체 충돌 상태를 업데이트하는 메서드 입니다.

 

//전체 블록 충돌 상태 체크
void Block::blockCollisionCheck(std::list<dotPos>& stackedBlock) {
	this->nowMovableState.ableToFall = blockDownCollisionCheck(stackedBlock);
	this->nowMovableState.ableToMoveLeft = blockLeftCollisionCheck(stackedBlock);
	this->nowMovableState.ableToMoveRight = blockRightCollisionCheck(stackedBlock);
	if (nowMovableState.ableToFall == false) { 
		nowMovableState = { false, false, false };
		nowState.whetherStacked = true;
	}
}

 

블록의 움직임을 정의하는 nowMovableState에 각각 방향으로의 충돌 상태를 저장합니다. 단 아랫 방향으로의 충돌 상태가 false인 경우 nowMovableState에 모두 false값을 반환하고 nowState.whetherStacked에 true 값을 반환합니다. 만약 더이상 낙하를 하지 못하는 상태가 되었다면 하나의 블록에 대해서 이미 그 위치가 확정 되었기 때문입니다.

 

다음은 블록의 이동에 대한 메서드 예시입니다.

 

//블록의 기본 낙하입니다
void Block::blockDefaultFall() {
	if (nowMovableState.ableToFall) {
		this->prevState = this->nowState;
		this->nowState.posY += 1;
	}
}

 

전 상태를 지우고 변화된 상태를 출력하면 블록이 이동하는 것처럼 보일 것입니다. 그리 복잡할 것은 없습니다.

 

클래스 Block은 TetrisBlock을 구성하기 위한 일종의 부품입니다. Block을 조립하여 TetrisBlock을 만들 것입니다.

 

다음은 TetrisBlock Class에 대해서 설명하겠습니다!!

 

 

반응형