본문으로 건너뛰기

23.05.08.

Today I learned

  • 컴공실

컴공실

tetris project First week

CheckToMove, DrawChange, AddBlockToField, DeleteLine함수 구현하기

int CheckToMove(char f[HEIGHT][WIDTH],int currentBlock,int blockRotate, int blockY, int blockX){
int i, j;
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
if (block[currentBlock][blockRotate][i][j] == 1) {
//블럭이 field를 벗어나는지 check
if (i + blockY >= HEIGHT || i + blockY < 0) return 0;
if (j + blockX >= WIDTH || j + blockX < 0)return 0;
//이미 field위에 블럭이 있는지 check
if (f[i + blockY][j + blockX]) return 0;
}
}
}
return 1;
}
void DrawChange(char f[HEIGHT][WIDTH],int command,int currentBlock,int blockRotate, int blockY, int blockX){
int i, j;
switch (command) {
case KEY_UP:
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++) {
if (block[currentBlock][(blockRotate+3)%4][i][j] && (i + blockY >= 0)) {
//block을 삭제해주는 경우, drawblock에서 '.'을 찍는 것이 아니라 ncurses.h의 move,printw사용
//drawblock 같은경우 attron을 사용해 effect를 준다
//ncurses.h를 사용하는 이유는, 이미 출력이 완료된 행으로 올라가 수정을 해야하기 때문
move(i + blockY + 1, j + blockX + 1);
printw(".");
}
}
break;
case KEY_DOWN:
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++) {
if (block[currentBlock][blockRotate][i][j] && (i + blockY - 1 >= 0)) {
move(i + blockY, j + blockX + 1);
printw(".");
}
}
break;
case KEY_RIGHT:
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++) {
if (block[currentBlock][blockRotate][i][j] && (i + blockY >= 0)) {
move(i + blockY + 1, j + blockX);
printw(".");
}
}
break;
case KEY_LEFT:
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++) {
if (block[currentBlock][blockRotate][i][j] && (i + blockY >= 0)) {
move(i + blockY + 1, j + blockX + 2);
printw(".");
}
}
break;
default:
break;
}
DrawField();
DrawBlockWithFeatures(blockY, blockX, currentBlock, blockRotate);
move(HEIGHT, WIDTH + 10);
}
void BlockDown(int sig){
timed_out = 0;
if (CheckToMove(field, nextBlock[0], blockRotate, blockY + 1, blockX)) {
blockY++;
}
else if (blockY == -1)
gameOver = 1;
else {
AddBlockToField(field, nextBlock[0], blockRotate, blockY, blockX);
score += DeleteLine(field);
nextBlock[0] = nextBlock[1];
nextBlock[1] = rand() % 7;
DrawNextBlock(nextBlock);
DrawField();
blockY = -1;
blockX = WIDTH / 2 - 2;
blockRotate = 0;
PrintScore(score);
DrawField();
}
DrawChange(field, KEY_DOWN, nextBlock[0], blockRotate, blockY, blockX);
}
int DeleteLine(char f[HEIGHT][WIDTH]){
int flag;
int count = 0;
int i,j,k;
//위에서부터 검사한다
for (i = HEIGHT - 1; i >= 0; i--) {
flag = 0;
for (j = 0; j < WIDTH; j++) {
if (!f[i][j]) {
flag = 1;
break;
}
}
//모든 칸이 채워져 있으면 실행
if (!flag) {
for (j = i; j > 0; j--) {
if (j == 0) {
for (k = 0; k < WIDTH; k++)
f[j][k] = 0;
}
else {
for (k = 0; k < WIDTH; k++)
f[j][k] = f[j - 1][k];
}
}
i++;
count++;
}
}

return count * count * 100;
}
시간복잡도 O(HEIGHT^2)

그림자 구현, 점수계산 수정, nextBlock 2개 그리기

void DrawShadow(int y, int x, int blockID,int blockRotate){
int i;
for (i = 0; i < HEIGHT - 1; i++) {
//움직일 수 없을 때까지 체크, 움직일 수 없다면 y-1칸에 그림자 그리기
if (!CheckToMove(field, blockID, blockRotate, i, x)) {
DrawBlock(i-1, x, blockID, blockRotate, '/');
break;
}
}
}

void DrawBlockWithFeatures(int y, int x, int blockID, int blockRotate) {
//기존 DrawBlock자레에 DrawBlockWithFeatures를 써넣어 그림자도 같이 그릴 수 있도록 설계
DrawBlock(y, x, blockID, blockRotate, ' ');
DrawShadow(y, x, blockID, blockRotate);
}
//next 블럭을 하나 더 그려야 하므로 score 밑으로 내리고, nextBlock[2]그리기
void PrintScore(int score){
move(17,WIDTH+11);
//printw("%8d",score);
}

void DrawNextBlock(int *nextBlock){
// int i, j;
// for( i = 0; i < 4; i++ ){
// move(4+i,WIDTH+13);
// for( j = 0; j < 4; j++ ){
// if( block[nextBlock[1]][0][i][j] == 1 ){
// attron(A_REVERSE);
// printw(" ");
// attroff(A_REVERSE);
// }
// else printw(" ");
// }
// }
for (i = 0; i < 4; i++) {
move(10 + i, WIDTH + 13);
for (j = 0; j < 4; j++) {
if (block[nextBlock[2]][0][i][j] == 1) {
attron(A_REVERSE);
printw(" ");
attroff(A_REVERSE);
}
else printw(" ");
}
}
}

void DrawOutline(){
int i,j;
// DrawBox(0,0,HEIGHT,WIDTH);

// move(2,WIDTH+10);
// printw("NEXT BLOCK");
// DrawBox(3,WIDTH+10,4,8);
DrawBox(9, WIDTH + 10, 4, 8);

move(15,WIDTH+10);
// printw("SCORE");
DrawBox(16,WIDTH+10,1,8);
}
시간복잡도 O(1)
void AddBlockToField(char f[HEIGHT][WIDTH],int currentBlock,int blockRotate, int blockY, int blockX){
// int i, j;
int touched = 0;
// for (i = 0; i < 4; i++) {
// for (j = 0; j < 4; j++) {
// if (block[currentBlock][blockRotate][i][j]) {
// if (0 <= i + blockY && i + blockY < HEIGHT && 0 <= j + blockX && j + blockX < WIDTH) {
//도형에 닿거나, 테트리스 필드의 바닥에 도달하면 touch++;
if (f[i + blockY + 1][j + blockX] == 1 || i + blockY + 1 == HEIGHT) touched++;
// f[i + blockY][j + blockX] = 1;
// }
// }
// }
// }
//score에 점수를 추가한다
score += touched * 10;
}
시간복잡도 O(1)