글
[TetrisManager 클래스의 Class Diagram]
테트리스의 전반적인 로직 부분을 담당하는 클래스인 TetrisManager 에 대해서 살펴볼 차례입니다. TetrisManager.h 와 TetrisManager.c 를 분석하겠습니다.
[TetrisManager.h]
#ifndef _BOARD_H #define _BOARD_H #include "Block.h" enum GameStatus{ PLAYING, END }; #define BOARD_ROW_SIZE 20 #define BOARD_COL_SIZE 14 typedef struct _tetrisManager{ char board[BOARD_ROW_SIZE][BOARD_COL_SIZE]; Block block; int deletedLineCount; int speedLevel; }TetrisManager; void TetrisManager_Init(TetrisManager* tetrisManager, int speedLevel); int TetrisManager_CheckValidPosition(TetrisManager* tetrisManager, int direction); void TetrisManager_ChangeBoardByDirection(TetrisManager* tetrisManager, int direction); void TetrisManager_ChangeBoardByAuto(TetrisManager* tetrisManager); void TetrisManager_ProcessDirectDown(TetrisManager* tetrisManager); void TetrisManager_ProcessDeletingLines(TetrisManager* tetrisManager); int TetrisManager_IsReachedToBottom(TetrisManager* tetrisManager); int TetrisManager_ProcessReachedCase(TetrisManager* tetrisManager); void TetrisManager_Sleep(TetrisManager* tetrisManager); void TetrisManager_Print(TetrisManager* tetrisManager); #endif
1 ~ 2, 31 라인
헤더파일을 중복 포함되게 하지 않기 위한 guard 입니다.
4 라인
본 헤더파일에서 필요한 헤더파일을 include 합니다.
6 ~ 8 라인
GameStatus 열거형 상수를 정의합니다. 이는 게임 상태에 대한 내용들이 있는데, PLAYING (게임을 끝내지 않고, 계속 진행함) 과 END (게임 종료) 가 정의되어 있습니다.
10 ~ 11 라인
테트리스판의 가로 행의 개수와, 세로 열의 개수를 매크로 상수로 정의합니다.
13 ~ 18 라인
TetrisManager 구조체를 정의합니다. 멤버로는, 2 차원 배열인 board (테트리스 판) 이 있고, block (현재, 다음 블럭) 이 정의되어 있습니다. 또, deletedLineCount (삭제한 줄 수) 와 speedLevel (블럭이 떨어지는 속도 레벨) 이 있습니다.
20 ~ 29 라인
TetrisManager.c 에서 정의될 함수의 선언부입니다.
[TetrisManager.c]
#include <stdio.h> #include <string.h> #include <windows.h> #include "TetrisManager.h" #include "Util.h" #include "Constant.h" #define INITIAL_SPEED 500 #define SPEED_LEVEL_OFFSET 100 #define LEVELP_UP_CONDITION 3 #define STATUS_POSITION_X_TO_PRINT 40 #define STATUS_POSITION_Y_TO_PRINT 6 static void _TetrisManager_ClearBoard(TetrisManager* tetrisManager); static void _TetrisManager_ChangeBoardByStatus(TetrisManager* tetrisManager, int status); static void _TetrisManager_UpSpeedLevel(TetrisManager* tetrisManager); static void _TetrisManager_SearchLineIndexesToDelete(TetrisManager* tetrisManager, int* indexes, int* count); static void _TetrisManager_DeleteLines(TetrisManager* tetrisManager, int* indexes, int count); void TetrisManager_Init(TetrisManager* tetrisManager, int speedLevel){ Block block; block.current = -1; memset(tetrisManager->board, 0, sizeof(char)* BOARD_ROW_SIZE * BOARD_COL_SIZE); _TetrisManager_ClearBoard(tetrisManager); tetrisManager->block = Block_Make(True, block); tetrisManager->deletedLineCount = 0; tetrisManager->speedLevel = speedLevel; } int TetrisManager_CheckValidPosition(TetrisManager* tetrisManager, int direction){ Block temp = Block_Move(tetrisManager->block, direction); int i; for (i = 0; i < POSITIONS_SIZE; i++){ int x = Block_GetPositions(temp)[i].x; int y = Block_GetPositions(temp)[i].y; if (tetrisManager->board[x][y] != EMPTY && tetrisManager->board[x][y] != MOVING_BLOCK){ return tetrisManager->board[x][y]; } } return EMPTY; } void TetrisManager_ChangeBoardByDirection(TetrisManager* tetrisManager, int direction){ int tempDirection = DOWN; int tempCheckResult = EMPTY; _TetrisManager_ClearBoard(tetrisManager); int checkResult = TetrisManager_CheckValidPosition(tetrisManager, direction); if (checkResult == EMPTY){ tetrisManager->block = Block_Move(tetrisManager->block, direction); } else{ if (direction == UP){ switch (checkResult){ case TOP_WALL: tempDirection = DOWN; tempCheckResult = TOP_WALL; break; case RIGHT_WALL: tempDirection = LEFT; tempCheckResult = RIGHT_WALL; break; case LEFT_WALL: tempDirection = RIGHT; tempCheckResult = LEFT_WALL; break; } do{ tetrisManager->block = Block_Move(tetrisManager->block, tempDirection); } while (TetrisManager_CheckValidPosition(tetrisManager, direction) == tempCheckResult); tetrisManager->block = Block_Move(tetrisManager->block, direction); } else{ if (direction == RIGHT && checkResult == RIGHT_WALL || direction == LEFT && checkResult == LEFT_WALL || direction == RIGHT && checkResult == FIXED_BLOCK || direction == LEFT && checkResult == FIXED_BLOCK){ TetrisManager_Sleep(tetrisManager); tetrisManager->block = Block_Move(tetrisManager->block, DOWN); } } } _TetrisManager_ChangeBoardByStatus(tetrisManager, MOVING_BLOCK); } void TetrisManager_ChangeBoardByAuto(TetrisManager* tetrisManager){ TetrisManager_ChangeBoardByDirection(tetrisManager, DOWN); } void TetrisManager_ProcessDirectDown(TetrisManager* tetrisManager){ while (!TetrisManager_IsReachedToBottom(tetrisManager)){ TetrisManager_ChangeBoardByDirection(tetrisManager, DOWN); } } void TetrisManager_ProcessDeletingLines(TetrisManager* tetrisManager){ int indexes[BOARD_ROW_SIZE]; int count; int i; _TetrisManager_SearchLineIndexesToDelete(tetrisManager, indexes, &count); if (count > 0){ _TetrisManager_DeleteLines(tetrisManager, indexes, count); for (i = tetrisManager->speedLevel; i <= tetrisManager->deletedLineCount / LEVELP_UP_CONDITION; i++){ _TetrisManager_UpSpeedLevel(tetrisManager); } } } int TetrisManager_IsReachedToBottom(TetrisManager* tetrisManager){ int i; for (i = 0; i < POSITIONS_SIZE; i++){ int x = Block_GetPositions(tetrisManager->block)[i].x; int y = Block_GetPositions(tetrisManager->block)[i].y; if (tetrisManager->board[x + 1][y] != EMPTY && tetrisManager->board[x + 1][y] != MOVING_BLOCK){ return True; } } return False; } int TetrisManager_ProcessReachedCase(TetrisManager* tetrisManager){ _TetrisManager_ChangeBoardByStatus(tetrisManager, FIXED_BLOCK); tetrisManager->block = Block_Make(False, tetrisManager->block); if (TetrisManager_IsReachedToBottom(tetrisManager)){ return END; } else{ return PLAYING; } } void TetrisManager_Sleep(TetrisManager* tetrisManager){ int i; DWORD milliSecond = INITIAL_SPEED; for (i = MIN_SPEED_LEVEL; i < tetrisManager->speedLevel; i++){ if (i < MAX_SPEED_LEVEL / 2){ milliSecond -= SPEED_LEVEL_OFFSET; } else{ milliSecond -= (SPEED_LEVEL_OFFSET / 5); } } Sleep(milliSecond); } void TetrisManager_Print(TetrisManager* tetrisManager){ int i; int j; CursorUtil_GotoXY(0, 0); for (i = 0; i < BOARD_ROW_SIZE; i++){ for (j = 0; j < BOARD_COL_SIZE; j++){ switch (tetrisManager->board[i][j]){ case LEFT_TOP_EDGE: printf("┎"); break; case RIGHT_TOP_EDGE: printf("┒"); break; case LEFT_BOTTOM_EDGE: printf("┖"); break; case RIGHT_BOTTOM_EDGE: printf("┚"); break; case EMPTY: printf(" "); break; case MOVING_BLOCK: printf("■"); break; case FIXED_BLOCK: printf("▧"); break; case LEFT_WALL: case RIGHT_WALL: printf("|"); break; case TOP_WALL: case BOTTOM_WALL: printf("―"); break; } } printf("\n"); } CursorUtil_GotoXY(STATUS_POSITION_X_TO_PRINT, STATUS_POSITION_Y_TO_PRINT); printf("***** Tetris *****\n"); CursorUtil_GotoXY(STATUS_POSITION_X_TO_PRINT, STATUS_POSITION_Y_TO_PRINT + 1); printf("Current speed level : %d level\n", tetrisManager->speedLevel); CursorUtil_GotoXY(STATUS_POSITION_X_TO_PRINT, STATUS_POSITION_Y_TO_PRINT + 2); printf("Deleted lines : %d lines", tetrisManager->deletedLineCount); Block_PrintNext(tetrisManager->block, STATUS_POSITION_X_TO_PRINT, STATUS_POSITION_Y_TO_PRINT + 4); CursorUtil_Hide(); } static void _TetrisManager_ClearBoard(TetrisManager* tetrisManager){ int i; int j; for (i = 0; i < BOARD_ROW_SIZE; i++){ tetrisManager->board[i][0] = LEFT_WALL; tetrisManager->board[i][BOARD_COL_SIZE - 1] = RIGHT_WALL; } for (i = 0; i < BOARD_COL_SIZE; i++){ tetrisManager->board[0][i] = TOP_WALL; tetrisManager->board[BOARD_ROW_SIZE - 1][i] = BOTTOM_WALL; } for (i = 1; i < BOARD_ROW_SIZE - 1; i++){ for (j = 1; j < BOARD_COL_SIZE - 1; j++){ if (tetrisManager->board[i][j] != FIXED_BLOCK){ tetrisManager->board[i][j] = EMPTY; } } } tetrisManager->board[0][0] = LEFT_TOP_EDGE; tetrisManager->board[0][BOARD_COL_SIZE - 1] = RIGHT_TOP_EDGE; tetrisManager->board[BOARD_ROW_SIZE - 1][0] = LEFT_BOTTOM_EDGE; tetrisManager->board[BOARD_ROW_SIZE - 1][BOARD_COL_SIZE - 1] = RIGHT_BOTTOM_EDGE; } static void _TetrisManager_ChangeBoardByStatus(TetrisManager* tetrisManager, int status){ int i; for (i = 0; i < POSITIONS_SIZE; i++){ int x = Block_GetPositions(tetrisManager->block)[i].x; int y = Block_GetPositions(tetrisManager->block)[i].y; tetrisManager->board[x][y] = status; } } static void _TetrisManager_UpSpeedLevel(TetrisManager* tetrisManager){ if (tetrisManager->speedLevel < MAX_SPEED_LEVEL){ tetrisManager->speedLevel++; } } static void _TetrisManager_SearchLineIndexesToDelete(TetrisManager* tetrisManager, int* indexes, int* count){ int i; int j; int toDelete; memset(indexes, -1, sizeof(int)* (BOARD_ROW_SIZE - 2)); *count = 0; for (i = 1; i < BOARD_ROW_SIZE - 1; i++){ toDelete = True; for (j = 1; j < BOARD_COL_SIZE - 1; j++){ if (tetrisManager->board[i][j] != FIXED_BLOCK){ toDelete = False; break; } } if (toDelete){ indexes[(*count)++] = i; } } } static void _TetrisManager_DeleteLines(TetrisManager* tetrisManager, int* indexes, int count){ int i; int j; int k = BOARD_ROW_SIZE - 2; int toDelete; char temp[BOARD_ROW_SIZE][BOARD_COL_SIZE] = { EMPTY }; for (i = BOARD_ROW_SIZE - 2; i > 0; i--){ toDelete = False; for (j = 0; j < BOARD_COL_SIZE; j++){ if (i == indexes[j]){ toDelete = True; break; } } if (!toDelete){ for (j = 0; j < BOARD_COL_SIZE; j++){ temp[k][j] = tetrisManager->board[i][j]; } k--; } } for (i = 1; i < BOARD_ROW_SIZE - 1; i++){ for (j = 1; j < BOARD_COL_SIZE - 1; j++){ tetrisManager->board[i][j] = temp[i][j]; } } tetrisManager->deletedLineCount += count; }
1 ~ 6 라인
필요한 헤더파일들을 include 합니다.
8 라인
초기 시작 스피드를 매크로 상수로 정의합니다.
9 라인
속도 레벨이 하나씩 증가할수록 벌어질 offset 을 매크로 상수로 정의합니다.
10 라인
라인을 몇 줄 지워야 속도 레벨이 1 증가하는지 (3 줄 삭제시 1 레벨 증가) 매크로 상수로 정의합니다.
11 ~ 12 라인
게임의 전반적인 상태를 출력할 위치의 좌표 (x, y) 를 매크로 상수로 정의합니다.
14 ~ 18 라인
현재 소스 파일 내부에서만 사용될 static 함수들의 선언부입니다.
20 라인
TetrisManager_Init 함수의 정의부입니다. 매개변수로 tetrisManager 와 speedLevel (사용자가 입력한 속도 레벨) 이 넘어옵니다. 이 함수는, Tetris 가 시작되면 처음 불리며, tetrisManager 의 멤버 변수들을 초기화 하는 역할을 합니다.
21 ~ 22 라인
Block 을 하나 생성하고, current 를 -1 로 초기화합니다. (아직 현재 블럭을 안 설정한 상태라서)
23 라인
memset 함수를 호출하여 tetrisManager 의 board 를 0 으로 초기화합니다.
(변수 or 배열을 특정 값으로 한번에 초기화하기 참고)
http://kkikkodev.tistory.com/50
24 라인
_TetrisManager_ClearBoard 함수를 호출하여 tetrisManager 의 board 를 초기 상태를 설정합니다. (외부 벽과 같은)
25 라인
Block_Make 함수를 처음 호출하여 블럭을 생성하여 tetrisManager->block 에 저장합니다.
26 ~ 27 라인
tetrisManager 의 deletedLineCount 를 0 으로 speedLevel 을 사용자로부터 입력 받은 speedLevel 로 초기화합니다.
30 라인
TetrisManager_CheckValidPosition 함수의 정의부입니다. 매개변수로 tetrisManager 와 direction (방향) 을 전달받습니다. 이 함수는 전달받은 방향으로 block 을 임시로 이동 or 회전시켜보고 그 블럭 상태가 유효한지 아닌지를 반환합니다.
31 라인
tetrisManager->block 과 direction 을 매개변수로 넘기면서 Block_Move 를 호출하여 얻은 block 값을 임시 temp 에 저장합니다.
33 ~ 40 라인
temp 의 4 개의 상자의 x, y 좌표를 각각 얻어와서 그 좌표에 해당하는 tetrisManager->board 가 EMPTY (빈 곳) 가 아니고, MOVING_BLOCK (움직이는 현재 블럭) 도 아닌 경우에는 그 상태를 반환하고 (유효하지 않다는 의미), 모두 이 두 가지 경우에만 해당되면, EMPTY 를 반환합니다. (유효하다는 의미)
43 라인
TetrisManager_ChangeBoardByDirection 함수의 정의부 입니다. 매개변수들로는 tetrisManager 와 direction (방향) 을 전달받고 있습니다. 이 함수는 방향에 해당하는 처리에 대해서 블럭을 이동 혹은 회전시키고, 그에 따른 테트리스 판의 상태도 변경하는 작업을 합니다.
44 ~ 45 라인
회전시에 벽에 부딪혀 유효하지 않은 상태가 되었을 때도, 한 칸 밀려 나오면서 회전은 가능해야 하기 때문에, 이를 위한 임시 방향과 임시 유효 상태 체크 결과 변수를 선언합니다.
46 라인
처리를 하기 전에 먼저, _TetrisManager_ClearBoard 함수를 호출하여 테트리스 판의 상태들을 정리합니다.
47 라인
TetrisManager_CheckValidPosition 함수를 호출하여 해당 direction 에 해당하는 블럭의 다음 위치가 유효한지를 구하여 checkResult 에 저장합니다.
48 ~ 50 라인
만약 그 다음 위치가 유효하다면, Block_Move 함수를 호출하여 실제로 블럭을 direction 으로 이동 혹은 회전합니다.
52 ~ 70 라인
checkResult 가 유효하지 않은 경우의 처리입니다. 회전을 제외한 왼쪽, 오른쪽, 아래쪽으로의 이동은 움직이면 안되지만, 회전의 경우에는 벽을 만나더라도, 회전을 하면서 한 칸 밀려나와야 합니다. 따라서, checkResult 의 결과를 토대로 TOP_WALL 이면 tempDirection 을 아래로, RIGHT_WALL 이면, tempDirection 을 왼쪽으로, LEFT_WALL 이면 tempDirection 을 오른쪽으로 지정한 뒤, Block_Move 함수에 tempDirection 을 넘기면서 block 을 벽의 반대 방향으로 밀려 나오게 합니다. (회전이 가능할 정도로) 그 다음에 실제로 direction 을 넘기면서 Block_Move 를 호출하여 블럭을 회전시킵니다.
즉, 쉽게 말하면, 회전의 경우에는, 벽을 만나더라도 회전이 가능해야 하기 때문에, 벽의 반대쪽으로 밀려 나와서, 회전을 해야 한다는 것입니다.
72 ~ 79 라인
checkResult 가 유효하지 않은 경우이지만, 회전이 아닌 경우의 처리입니다. 방향은 오른쪽인데, 오른쪽 벽 혹은 굳어진 블럭에 막혀 있거나, 방향은 왼쪽인데 왼쪽 벽 혹은 굳어진 블럭에 막혀 있는 경우에는, 해당 방향으로 이동은 못하되, 밑으로 일정 시간 지난 후에 자동으로 내려와야 하기 때문에, TetrisManager_Sleep 함수를 호출하여 지연시킨 뒤, Block_Move 함수를 호출하면서 DOWN 방향을 넘겨 블럭을 자동으로 한 칸 내려오게 합니다. (즉, 이동 못하게 되었을 때, 가만히 그 위치에 머물러 있지 않도록 방지하기 위함입니다.)
82 라인
_TetrisManager_ChangeBoardByStatus 함수를 호출하면서, MOVING_BLOCK 을 넘겨서 tetrisManager 의 board 에서 새로 바뀐 블럭의 위치를 재설정합니다.
85 라인
TetrisManager_ChangeBoardByAuto 함수의 정의부입니다. 매개변수로 tetrisManager 를 받아서 자동으로 블럭을 한 칸 내려가게 하는 역할을 합니다.
86 라인
TetrisManager_ChangeBoardByDirection 함수에 DOWN 을 매개변수로 넘겨서 한 칸 밑으로 블럭을 내려가게 합니다.
89 라인
TetrisManager_ProcessDirectDown 함수의 정의부입니다. 매개변수로 tetrisManager 를 받아서 스페이스바를 눌렀을 시 처리 (블럭을 내려갈 수 있을 때까지 한꺼번에 내리기) 를 합니다.
90 ~ 91 라인
TetrisManager_IsReachedToBottom 함수를 호출하여 블럭이 더 이상 밑으로 이동할 수 있는지 체크를 해, 이동 가능하면, 계속해서, TetrisManager_ChangeBoardByDirection 함수를 호출하면서, 매개변수로 DOWN 을 넘겨 밑으로 블럭을 한 칸씩 내립니다. 즉, 밑으로 내릴 수 있을 때까지 계속해서 블럭을 밑으로 내리는 것입니다.
95 라인
TetrisManger_ProcessDeletingLines 함수의 정의부입니다. 매개변수로 tetrisManger 를 받아서, 삭제할 라인을 찾아서 삭제하고 테트리스 판을 갱신하는 역할을 합니다.
96 ~ 97 라인
삭제할 라인의 위치를 저장할 정수 배열과 개수를 선언합니다.
99 라인
_TetrisManager_SearchLineIndexesToDelete 함수를 호출하여, 삭제할 라인의 위치를 찾아서 indexes 배열에 저장하고, count 에는 그 라인의 총 수를 저장합니다.
100 ~ 105 라인
만약, 삭제할 줄 수가 있다면, _TetrisManager_DeleteLines 함수를 호출하여 해당하는 위치의 라인들을 삭제합니다. 그리고, 지운 줄의 총 수가 3 의 배수가 되면, _TetrisManager_UpSpeedLevel 함수를 호출하여 속도 레벨을 1 증가 시킵니다.
108 라인
TetrisManager_IsReachedToBottom 함수의 정의부입니다. 매개변수로 tetrisManager 를 받아서, 현재 이동중인 블럭이 밑으로 이동할 수 있는지 체크하여 그 결과를 참 / 거짓으로 반환하는 역할을 합니다.
110 ~ 117 라인
현재 이동중인 block 의 4 개의 상자의 좌표를 받아와서 그 좌표의 바로 밑이 EMPTY 가 아니고, MOVING_BLOCK 이 아니면 True (밑으로 더 이상 이동할 수 없다는 의미) 를 반환하고, 이것이 아니면 False (밑에 블럭이 닿지 않았음을 의미) 를 반환합니다.
120 라인
TetrisManger_ProcessReachedCase 함수의 정의부입니다. 이 함수에서는 블럭이 밑에 닿았을 때 (아래 벽 혹은 굳어진 블럭에 닿았을 때) 현재 이동중인 블럭을 굳어지게 하고, 새 블럭을 생성하는 등의 처리를 합니다.
121 라인
_TetrisManager_ChangeBoardByStatus 함수를 호춣하며 FIXED_BLOCK 매개변수를 넘겨서 현재 블럭에 해당하는 위치를 테트리스판에서 FIXED_BLOCK 으로 변경합니다.
122 라인
Block_Make 함수를 호출하여 (매개변수로 False 를 넘기는 이유는, 처음 불리는 것이 아닌 2 번째 이후부터 불리는 것이라는 것을 구분해주기 위함입니다.) 새 블럭을 생성합니다.
123 ~ 128 라인
TetrisManager_IsReachedToBottom 함수를 호출하여 새로 생성한 블럭이 더 이상 밑으로 갈 수 있는지 체크를 하여 갈 수 없으면 END (게임 종료) 를 반환하고, 갈 수 있으면 PLAYING (게임 계속 진행) 을 반환합니다.
131 라인
TetrisManager_Sleep 함수의 정의부입니다. 매개변수로 tetrisManager 를 전달받아서, 속도 레벨에 해당하는 만큼 프로그램을 지연시키는 역할을 합니다.
133 ~ 141 라인
milliSecond 변수에 INITIAL_SPEED 를 넣고, 최소 속도 레벨부터 현재 속도 레벨까지 반복하면서, 최대 속도 레벨 / 2 까지는 milliSecond 에서 SPEED_LEVEL_OFFSET 만큼 빼고, 그 이후에는, SPEED_LEVEL_OFFSET / 5 를 빼면서, 점점 블럭이 내려오는 속도인 milliSecond 를 줄여줍니다.
142 라인
Sleep 함수를 호출하면서 위에서 만든 milliSecond 를 매개변수로 넘겨서 프로그램을 지연시킵니다. 지연 후에 블럭이 자동으로 내려오게 됩니다.
(1 초에 한 번씩 데이터 출력하기 참고)
http://kkikkodev.tistory.com/66
145 라인
TetrisManager_Print 함수의 정의부입니다. 매개변수로 tetrisManager 를 받아서, 테트리스 판을 출력하고, 게임 상태를 출력하는 역할을 합니다.
148 ~ 184 라인
CursorUtil_GotoXY 로 (0,0) 위치로 커서를 이동시킨 후에, tetrisManager->board 배열을 반복하면서, boardType 에 따라 해당하는 문자열을 화면에 출력합니다.
(콘솔 커서 좌표 이동하기 참고)
http://kkikkodev.tistory.com/26
185 ~ 192 라인
테트리스의 속도 레벨과 현재까지 삭제한 총 줄 수를 출력하고, Block_PrintNext 함수를 호출하여 다음 나올 블럭을 화면에 출력한 뒤, CursorUtil_Hide 함수를 호출하여 커서를 숨깁니다.
(콘솔 커서 숨기기 & 두께 조절하기 참고)
http://kkikkodev.tistory.com/27
195 라인
_TetrisManager_ClearBoard 함수의 정의부입니다. 매개변수로 tetrisManger 를 전달받아서 테트리스 판을 초기화하는 역할을 합니다.
198 ~ 201 라인
테트리스판의 왼쪽 벽과 오른쪽 벽을 재설정합니다.
202 ~ 205 라인
테트리스판의 위쪽 벽과 아래쪽 벽을 재설정합니다.
206 ~ 212 라인
테트리스 판의 안쪽에서 굳어진 블럭 빼고 모두 빈 공간으로 재설정합니다.
213 ~ 216 라인
테트리스 판의 4 모서리를 재설정합니다.
219 라인
_TetrisManager_ChangeBoardByStatus 함수의 정의부입니다. 매개변수로는 tetrisManager 와 status (테트리스 판에서 블럭의 위치에 해당하는 좌표를 변경할 상태) 를 받아서, 해당 status 로 블럭의 위치를 테트리스판에서 변경하는 역할을 합니다.
221 ~ 225 라인
block 의 4 좌표를 돌면서 입력받은 status 로 변경해 줍니다.
228 라인
_TetrisManager_UpSpeedLevel 함수의 정의부입니다. 매개변수로 tetrisManager 를 받아서 속도레벨을 1 증가 시키는 역할을 합니다.
229 ~ 231 라인
속도 레벨이 최대 속도 레벨보다 작은 경우에만 1 증가 시킵니다.
234 라인
_TetrisManager_SearchLineIndexesToDelete 함수의 정의부입니다. 매개변수로 tetrisManager 와 indexes (삭제할 라인의 위치들을 담을 배열), count (삭제할 라인의 총 개수) 를 전달받아서, 테트리스 판 중에서 삭제할 라인의 위치를 찾는 역할을 하고 있습니다.
238 ~ 239 라인
indexes 배열에 memset 함수를 통해 -1 로 모두 초기화합니다. 그리고 count 에 0 을 저장합니다.
(변수 or 배열을 특정 값으로 한번에 초기화하기 참고)
http://kkikkodev.tistory.com/50
240 ~ 251 라인
테트리스 판을 모두 돌면서 가로 한 줄이 모두 FIXED_BLOCK 인 경우를 찾아서 그 위치를 indexes 에 저장하고, 그 때마다 count 를 1 씩 증가합니다.
254 라인
_TetrisManager_DeleteLines 함수의 정의부입니다. 매개변수로 tetrisManager 와 indexes (삭제할 라인의 위치가 담긴 배열), count (삭제할 라인의 총 개수) 를 전달받아서 삭제할 라인을 지우는 역할을 합니다.
259 라인
라인 삭제를 하기 위해서 임시로 삭제된 테트리스판을 저장할 임시 판을 선언합니다.
260 ~ 274 라인
테트리스판을 돌면서 indexes 에 해당하는 줄을 제외한 모든 줄을 임시 판에 저장합니다.
275 ~ 279 라인
다시 임시 판을 기존의 판에 복사합니다.
280 라인
tetrisManager 의 deletedLineCount 를 count 만큼 증가시킵니다.
'1.2) 프로젝트 > 테트리스' 카테고리의 다른 글
테트리스 ver 0.2 (2) - 요구사항 분석 (0) | 2015.06.12 |
---|---|
테트리스 ver 0.2 (1) - 실행 결과 & 프로젝트 개요 (0) | 2015.06.12 |
테트리스 ver 0.1 (10) - 개발 완료 / 후기 (0) | 2015.06.12 |
테트리스 ver 0.1 (9) - 소스코드 구현 (Main) (0) | 2015.06.12 |
테트리스 ver 0.1 (8) - 소스코드 구현 (TetrisView) (0) | 2015.06.12 |
테트리스 ver 0.1 (6) - 소스코드 구현 (Block) (0) | 2015.06.12 |
테트리스 ver 0.1 (5) - 소스코드 구현 (Util) (0) | 2015.06.12 |
테트리스 ver 0.1 (4) - 소스코드 구현 (Constant) (0) | 2015.06.12 |
테트리스 ver 0.1 (3) - 프로그램 설계 (Use Case, Class, Sequence) (0) | 2015.06.12 |
테트리스 ver 0.1 (2) - 요구사항 분석 (0) | 2015.06.12 |
RECENT COMMENT