[Block 클래스의 Class Diagram]


이동중인 블럭을 나타내는 Block 클래스에 대해서 살펴보겠습니다. Block.h 와 Block.c 에서 변경된 부분 위주로 설명드릴 예정입니다. 먼저, 추가, 삭제, 변경 이력에 대해서 말씀드리겠습니다.


[Block.h 버전 비교]


16 라인 (추가)


[Block.c 버전 비교 (1)]


8, 14, 16 라인 (변경)

41 ~ 48 라인 (추가)


[Block.c 버전 비교 (2)]


90 라인 (추가)

114 라인 (변경)


[Block.c 버전 비교 (3)]


114 라인 (변경)

140 라인 (변경)

145 ~ 149 라인 (추가)




이제는, 위에서 언급한 부분들을 분석해 보겠습니다.


[Block.h]

#ifndef _BLOCK_H
#define _BLOCK_H

typedef struct _point{
	int x;
	int y;
}Point;

#define POSITIONS_SIZE 4

typedef struct _block{
	Point positions[POSITIONS_SIZE][POSITIONS_SIZE];
	int current;
	int next;
	int direction;
	int color;
}Block;

Block Block_Make(int isFirst, Block block);
Block Block_Move(Block block, int direction);
Point* Block_GetPositions(Block block);
void Block_PrintNext(Block block, int x, int y);

#endif


16 라인 (추가)

현재 블럭의 색상을 열거형 상수로 관리하기 위해 int 형 변수 color 의 선언부를 추가했습니다.


[Block.c]

#include <time.h>
#include <windows.h>
#include <stdio.h>
#include "Block.h"
#include "Util.h"
#include "Constant.h"

#define BLOCK_EXAMPLES_SIZE 7

const static Point blockExamples[BLOCK_EXAMPLES_SIZE][POSITIONS_SIZE][POSITIONS_SIZE] = {
	//ㅁㅁㅁㅁ
	{
		{ { 0, 5 }, { 0, 6 }, { 0, 7 }, { 0, 8 } },
		{ { -1, 6 }, { 0, 6 }, { 1, 6 }, { 2, 6 } },
		{ { 0, 5 }, { 0, 6 }, { 0, 7 }, { 0, 8 } },
		{ { -1, 6 }, { 0, 6 }, { 1, 6 }, { 2, 6 } }
	},
	//    ㅁ
	//ㅁㅁㅁ
	{
		{ { 0, 8 }, { 1, 6 }, { 1, 7 }, { 1, 8 } },
		{ { -1, 7 }, { 0, 7 }, { 1, 7 }, { 1, 8 } },
		{ { 0, 6 }, { 0, 7 }, { 0, 8 }, { 1, 6 } },
		{ { -1, 6 }, { -1, 7 }, { 0, 7 }, { 1, 7 } }
	},
	//  ㅁㅁ
	//ㅁㅁ
	{
		{ { 0, 7 }, { 0, 8 }, { 1, 6 }, { 1, 7 } },
		{ { -1, 6 }, { 0, 6 }, { 0, 7 }, { 1, 7 } },
		{ { 0, 7 }, { 0, 8 }, { 1, 6 }, { 1, 7 } },
		{ { -1, 6 }, { 0, 6 }, { 0, 7 }, { 1, 7 } }
	},
	//ㅁㅁ
	//  ㅁㅁ
	{
		{ { 0, 6 }, { 0, 7 }, { 1, 7 }, { 1, 8 } },
		{ { -1, 8 }, { 0, 8 }, { 0, 7 }, { 1, 7 } },
		{ { 0, 6 }, { 0, 7 }, { 1, 7 }, { 1, 8 } },
		{ { -1, 8 }, { 0, 8 }, { 0, 7 }, { 1, 7 } }
	},
	//  ㅁ
	//ㅁㅁㅁ
	{
		{ { 0, 7 }, { 1, 6 }, { 1, 7 }, { 1, 8 } },
		{ { -1, 7 }, { 0, 7 }, { 0, 8 }, { 1, 7 } },
		{ { 0, 6 }, { 0, 7 }, { 0, 8 }, { 1, 7 } },
		{ { -1, 7 }, { 0, 6 }, { 0, 7 }, { 1, 7 } }
	},
	//ㅁ
	//ㅁㅁㅁ
	{
		{ { 0, 6 }, { 1, 6 }, { 1, 7 }, { 1, 8 } },
		{ { -1, 8 }, { -1, 7 }, { 0, 7 }, { 1, 7 } },
		{ { 0, 6 }, { 0, 7 }, { 0, 8 }, { 1, 8 } },
		{ { -1, 7 }, { 0, 7 }, { 1, 7 }, { 1, 6 } }
	},
	//ㅁㅁ
	//ㅁㅁ
	{
		{ { 0, 6 }, { 0, 7 }, { 1, 6 }, { 1, 7 } },
		{ { 0, 6 }, { 0, 7 }, { 1, 6 }, { 1, 7 } },
		{ { 0, 6 }, { 0, 7 }, { 1, 6 }, { 1, 7 } },
		{ { 0, 6 }, { 0, 7 }, { 1, 6 }, { 1, 7 } }
	}
};

static Block _Block_MoveToDown(Block block);
static Block _Block_MoveToLeft(Block block);
static Block _Block_MoveToRight(Block block);
static Block _Block_RotateRight(Block block);

Block Block_Make(int isFirst, Block block){
	int i;
	int j;
	srand((unsigned int)time(NULL));
	if (isFirst){
		block.current = rand() % BLOCK_EXAMPLES_SIZE;
	}
	else{
		block.current = block.next;
	}
	for (i = 0; i < POSITIONS_SIZE; i++){
		for (j = 0; j < POSITIONS_SIZE; j++){
			block.positions[i][j] = blockExamples[block.current][i][j];
		}
	}
	block.next = rand() % BLOCK_EXAMPLES_SIZE;
	block.direction = UP;
	block.color = rand() % (FONT_COLOR_SIZE - 2) + 2;
	return block;
}

Block Block_Move(Block block, int direction){
	switch (direction){
	case LEFT:
		return _Block_MoveToLeft(block);
	case RIGHT:
		return _Block_MoveToRight(block);
	case DOWN:
		return _Block_MoveToDown(block);
	case UP:
		return _Block_RotateRight(block);
	}
	return _Block_MoveToDown(block);
}

Point* Block_GetPositions(Block block){
	return block.positions[block.direction];
}

void Block_PrintNext(Block block, int x, int y){
	CursorUtil_GotoXY(x, y);
	printf("[Next block]\n");
	x += 3;
	y += 2;
	CursorUtil_GotoXY(x, y++);
	switch (block.next){
	case 0:
		printf("■■■■");
		CursorUtil_GotoXY(x, y++);
		printf("        ");
		break;
	case 1:
		printf("      ■");
		CursorUtil_GotoXY(x, y++);
		printf("  ■■■");
		break;
	case 2:
		printf("    ■■");
		CursorUtil_GotoXY(x, y++);
		printf("  ■■  ");
		break;
	case 3:
		printf("  ■■  ");
		CursorUtil_GotoXY(x, y++);
		printf("    ■■");
		break;
	case 4:
		printf("  ■   ");
		CursorUtil_GotoXY(x, y++);
		printf("■■■  ");
		break;
	case 5:
		printf("■      ");
		CursorUtil_GotoXY(x, y++);
		printf("■■■  ");
		break;
	case 6:
		printf("  ■■  ");
		CursorUtil_GotoXY(x, y++);
		printf("  ■■  ");
		break;
	}
}

static Block _Block_MoveToDown(Block block){
	int i;
	int j;
	for (i = 0; i < POSITIONS_SIZE; i++){
		for (j = 0; j < POSITIONS_SIZE; j++){
			block.positions[i][j].x++;
		}
	}
	return block;
}

static Block _Block_MoveToLeft(Block block){
	int i;
	int j;
	for (i = 0; i < POSITIONS_SIZE; i++){
		for (j = 0; j < POSITIONS_SIZE; j++){
			block.positions[i][j].y--;
		}
	}
	return block;
}

static Block _Block_MoveToRight(Block block){
	int i;
	int j;
	for (i = 0; i < POSITIONS_SIZE; i++){
		for (j = 0; j < POSITIONS_SIZE; j++){
			block.positions[i][j].y++;
		}
	}
	return block;
}

static Block _Block_RotateRight(Block block){
	block.direction = (block.direction + 1) % POSITIONS_SIZE;
	return block;
}


8, 14, 16 라인 (변경)

테트리스의 원래 블럭 타입은 총 7 개 입니다. 하지만, 블럭 타입 한 개가 누락되어 지금까지 총 6 개로 진행해 왔습니다. 따라서, 나머지 테트리스 블럭 타입을 하나 더 추가하기 위해서, 먼저, 8 라인의 BLOCK_EXAMPLES_SIZE 를 6 에서 7 로 변경하였습니다. 그리고, 14, 16 라인에서는, 블럭 타입 1 (가장 긴 모양의 블럭) 의 시작 위치를 한 칸 위에서 밑으로 내린 것입니다. 이것을 조정한 이유는, 이 타입의 블럭이 생성되고 나서, 바로 회전 키 (위 방향의 키) 를 사용자가 누르더라도, 시작 위치가 (0, 6) 가 되기 때문입니다. (블럭의 생성 위치에 한 칸 밑으로 내려온 위치가 실제 처음으로 화면에 보이는 위치입니다. 따라서, 기존에는, 회전을 하면, (-1, 6) 이 되어, 테트리스 판 배열의 위치 중에서 -1 번째 index 를 참조하려고 하기 때문에 오류가 났습니다. 안전상의 이유로, 긴 모양의 블럭만 시작 위치 중에서, 회전을 홀수번 한 모양 (위 아래로 긴 모양) 의 시작 위치들만 모두 한 칸씩 내리게 되었습니다.)


41 ~ 48 라인 (추가)

실제로 추가한 블럭 타입입니다. 각각의 시작 위치를 좌표에 찍어보면, 아래와 같은 모양의 블럭인 것을 확인할 수 있습니다.


ㅁㅁㅁ


90 라인 (추가)

block 구조체의 color 변수에 rand 함수를 활용하여, 블럭의 색상을 랜덤하게 생성하여 대입합니다. FONT_COLOR_SIZE 상수가 15 이기 때문에, 실제로 color 변수에 저장되는 정수값의 범위는 최소 2 에서 최대 15 까지가 됩니다. 이 부분에서, 사실 제가 오타를 내서, 원래 의도한 바는, 검정색 (= 0) 을 제외하고, 1 부터 15 까지 대입하려고 했는데, 오타를 쳐서 2 부터 15 까지 대입하게 되었습니다. 그래서, 원래 의도한 소스 코드는


block.color = rand() % (FONT_COLOR_SIZE - 1) + 1;


이 되어, 1 부터 15 까지 랜덤 정수를 생성하여 color 변수에 대입하는 형태로 바뀌어야 할 것입니다. (향후에 고치도록 하겠습니다.)


114 라인 (변경)

다음 블럭 출력 제목 UI 를 좀 더 보기 좋게 변경하였습니다.


140 라인 (변경)

145 ~ 149 라인 (추가)

추가된 블럭 타입을 다음 블럭 추가하는 함수에 추가하였습니다.


by kkikkodev 2015. 8. 21. 00:52