글
[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 라인 (추가)
추가된 블럭 타입을 다음 블럭 추가하는 함수에 추가하였습니다.
'1.2) 프로젝트 > 테트리스' 카테고리의 다른 글
테트리스 ver 0.5 (1) - 실행 결과 & 프로젝트 개요 (0) | 2016.02.23 |
---|---|
테트리스 ver 0.4 (1) - 실행 결과 & 프로젝트 개요 (6) | 2015.08.21 |
테트리스 ver 0.3 (9) - 개발 완료 / 후기 (0) | 2015.08.21 |
테트리스 ver 0.3 (8) - 소스코드 구현 (Main) (0) | 2015.08.21 |
테트리스 ver 0.3 (7) - 소스코드 구현 (TetrisManager) (0) | 2015.08.21 |
테트리스 ver 0.3 (5) - 소스코드 구현 (Util) (0) | 2015.08.21 |
테트리스 ver 0.3 (4) - 소스코드 변경 내역 (0) | 2015.08.20 |
테트리스 ver 0.3 (3) - 프로그램 설계 (Use Case, Class, Sequence) (0) | 2015.08.20 |
테트리스 ver 0.3 (2) - 요구사항 분석 (0) | 2015.08.20 |
테트리스 ver 0.3 (1) - 실행 결과 & 프로젝트 개요 (10) | 2015.06.17 |
RECENT COMMENT