테트리스
#include < stdio.h >

#include < stdlib.h >

#include < time.h >

#include < conio.h >

#include < windows.h >

#include < mmsystem.h >

#pragma comment(lib, "winmm.lib")

# define true 1

# define false 0

# define bool int

# define BOARD_WIDTH 10

# define BOARD_HEIGHT 20

# define BOARD_X 4

# define BOARD_Y 2

# define DELAY 100

enum ControlKeys

{

  UP = 72,

    DOWN = 80,

    LEFT = 75,

    RIGHT = 77,

    SPACE = 32

};

static int score = 0; //게임점수

static int level = 1; //게임레벨

static int speed = 180; // 블럭이 떨어지는 속도

int board[BOARD_HEIGHT + 1][BOARD_WIDTH + 2] = {
  0,
};

// 7개의 블럭 생성

int blocks[28][4][4] =

  {

    // ■■■■

    {

      {
        0,
        1,
        0,
        0
      },

      {
        0,
        1,
        0,
        0
      },

      {
        0,
        1,
        0,
        0
      },

      {
        0,
        1,
        0,
        0
      }

    },

    {

      {
        0,
        0,
        0,
        0
      },

      {
        0,
        0,
        0,
        0
      },

      {
        1,
        1,
        1,
        1
      },

      {
        0,
        0,
        0,
        0
      }

    },

    {

      {
        0,
        1,
        0,
        0
      },

      {
        0,
        1,
        0,
        0
      },

      {
        0,
        1,
        0,
        0
      },

      {
        0,
        1,
        0,
        0
      }

    },

    {

      {
        0,
        0,
        0,
        0
      },

      {
        0,
        0,
        0,
        0
      },

      {
        1,
        1,
        1,
        1
      },

      {
        0,
        0,
        0,
        0
      }

    },

    // ■■

    // ■■

    {

      {
        1,
        1,
        0,
        0
      },

      {
        1,
        1,
        0,
        0
      },

      {
        0,
        0,
        0,
        0
      },

      {
        0,
        0,
        0,
        0
      }

    },

    {

      {
        1,
        1,
        0,
        0
      },

      {
        1,
        1,
        0,
        0
      },

      {
        0,
        0,
        0,
        0
      },

      {
        0,
        0,
        0,
        0
      }

    },

    {

      {
        1,
        1,
        0,
        0
      },

      {
        1,
        1,
        0,
        0
      },

      {
        0,
        0,
        0,
        0
      },

      {
        0,
        0,
        0,
        0
      }

    },

    {

      {
        1,
        1,
        0,
        0
      },

      {
        1,
        1,
        0,
        0
      },

      {
        0,
        0,
        0,
        0
      },

      {
        0,
        0,
        0,
        0
      }

    },

    // ■

    // ■■■

    {

      {
        0,
        0,
        0,
        0
      },

      {
        0,
        1,
        0,
        0
      },

      {
        1,
        1,
        1,
        0
      },

      {
        0,
        0,
        0,
        0
      }

    },

    {

      {
        0,
        0,
        0,
        0
      },

      {
        0,
        1,
        0,
        0
      },

      {
        1,
        1,
        0,
        0
      },

      {
        0,
        1,
        0,
        0
      }

    },

    {

      {
        0,
        0,
        0,
        0
      },

      {
        0,
        0,
        0,
        0
      },

      {
        1,
        1,
        1,
        0
      },

      {
        0,
        1,
        0,
        0
      }

    },

    {

      {
        0,
        0,
        0,
        0
      },

      {
        0,
        1,
        0,
        0
      },

      {
        0,
        1,
        1,
        0
      },

      {
        0,
        1,
        0,
        0
      }

    },

    // ■

    // ■■■

    {

      {
        0,
        0,
        0,
        0
      },

      {
        0,
        0,
        1,
        0
      },

      {
        1,
        1,
        1,
        0
      },

      {
        0,
        0,
        0,
        0
      }

    },

    {

      {
        0,
        1,
        1,
        0
      },

      {
        0,
        0,
        1,
        0
      },

      {
        0,
        0,
        1,
        0
      },

      {
        0,
        0,
        0,
        0
      }

    },

    {

      {
        1,
        1,
        1,
        0
      },

      {
        1,
        0,
        0,
        0
      },

      {
        0,
        0,
        0,
        0
      },

      {
        0,
        0,
        0,
        0
      }

    },

    {

      {
        1,
        0,
        0,
        0
      },

      {
        1,
        0,
        0,
        0
      },

      {
        1,
        1,
        0,
        0
      },

      {
        0,
        0,
        0,
        0
      }

    },

    // ■

    // ■■■

    {

      {
        0,
        0,
        0,
        0
      },

      {
        1,
        0,
        0,
        0
      },

      {
        1,
        1,
        1,
        0
      },

      {
        0,
        0,
        0,
        0
      }

    },

    {

      {
        0,
        0,
        1,
        0
      },

      {
        0,
        0,
        1,
        0
      },

      {
        0,
        1,
        1,
        0
      },

      {
        0,
        0,
        0,
        0
      }

    },

    {

      {
        1,
        1,
        1,
        0
      },

      {
        0,
        0,
        1,
        0
      },

      {
        0,
        0,
        0,
        0
      },

      {
        0,
        0,
        0,
        0
      }

    },

    {

      {
        1,
        1,
        0,
        0
      },

      {
        1,
        0,
        0,
        0
      },

      {
        1,
        0,
        0,
        0
      },

      {
        0,
        0,
        0,
        0
      }

    },

    // ■■

    // ■■

    {

      {
        0,
        0,
        0,
        0
      },

      {
        0,
        1,
        1,
        0
      },

      {
        1,
        1,
        0,
        0
      },

      {
        0,
        0,
        0,
        0
      }

    },

    {

      {
        0,
        1,
        0,
        0
      },

      {
        0,
        1,
        1,
        0
      },

      {
        0,
        0,
        1,
        0
      },

      {
        0,
        0,
        0,
        0
      }

    },

    {

      {
        0,
        0,
        0,
        0
      },

      {
        0,
        1,
        1,
        0
      },

      {
        1,
        1,
        0,
        0
      },

      {
        0,
        0,
        0,
        0
      }

    },

    {

      {
        0,
        1,
        0,
        0
      },

      {
        0,
        1,
        1,
        0
      },

      {
        0,
        0,
        1,
        0
      },

      {
        0,
        0,
        0,
        0
      }

    },

    // ■■

    // ■■

    {

      {
        0,
        0,
        0,
        0
      },

      {
        1,
        1,
        0,
        0
      },

      {
        0,
        1,
        1,
        0
      },

      {
        0,
        0,
        0,
        0
      }

    },

    {

      {
        0,
        0,
        1,
        0
      },

      {
        0,
        1,
        1,
        0
      },

      {
        0,
        1,
        0,
        0
      },

      {
        0,
        0,
        0,
        0
      }

    },

    {

      {
        0,
        0,
        0,
        0
      },

      {
        1,
        1,
        0,
        0
      },

      {
        0,
        1,
        1,
        0
      },

      {
        0,
        0,
        0,
        0
      }

    },

    {

      {
        0,
        0,
        1,
        0
      },

      {
        0,
        1,
        1,
        0
      },

      {
        0,
        1,
        0,
        0
      },

      {
        0,
        0,
        0,
        0
      }

    },

  }; // 블럭생성 완료

// 커서를 나타내거나 숨김

void CursorVisible(bool blnCursorVisible) // Console.CursorVisible = false;

{

  CONSOLE_CURSOR_INFO cursorInfo;

  GetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), & cursorInfo);

  cursorInfo.bVisible = blnCursorVisible;

  SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), & cursorInfo);

}

// 커서위치를 설정

void SetCursorPosition(int cursorLeft, int cursorTop) //
Console.SetCursorPosition(posX, posY);

{

  int posX = cursorLeft;

  int posY = cursorTop;

  COORD pos = {
    posX,
    posY
  };

  SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);

}

// 커서의 현재 위치좌표 얻기

COORD GetCursorPosition(void)

{

  COORD cursor;

  CONSOLE_SCREEN_BUFFER_INFO cursorInfo;

  GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), & cursorInfo);

  cursor.X = cursorInfo.dwCursorPosition.X;

  cursor.Y = cursorInfo.dwCursorPosition.Y;

  return cursor;

}

//시작 화면 및 콘솔 초기화

void ConsoleInit()

{

  // 콘솔 초기화 및 시작 화면 구성 영역

  printf("C Language Tetris Game\n\n");

  printf("Made by. ReverserHW\n\n");

  printf("=================================== \n");

  printf(":: 조작키 :: \n");

  printf("[→] 블록을 오른쪽으로 이동 \n");

  printf("[←] 블록을 왼쪽으로 이동 \n");

  printf("[↑] 블록을 왼쪽으로 회전하기 \n");

  printf("[↓] 블록을 아래로 1칸 내리기 \n");

  printf("[Space] 아래로 떨어뜨리기 \n");

  printf(" \n");

  printf("아무키나 누르면 시작됩니다. \n");

  printf("=================================== \n");

  getch();

  system("cls");

  CursorVisible(false);

  SetCursorPosition(0, 0);

}

// 게임판 그리기

void DrawField(void)

{

  int x, y;

  //중앙 보드 라인

  for (x = 1; x <= BOARD_WIDTH + 1; x++)

  {

    board[BOARD_HEIGHT][x] = 1; //board 배열 중앙 1인식

    SetCursorPosition((BOARD_X) + x * 2, BOARD_Y + BOARD_HEIGHT); //콘솔좌표

    printf("━");

  }

  //왼쪽 보드 라인

  for (y = 0; y < BOARD_HEIGHT + 1; y++)

  {

    board[y][0] = 1; //board 배열 왼쪽 1인식

    SetCursorPosition(BOARD_X, BOARD_Y + y);

    if (y == BOARD_HEIGHT)

      printf("┗");

    else

      printf("┃");

  }

  //오른쪽 보드 라인

  for (y = 0; y < BOARD_HEIGHT + 1; y++)

  {

    board[y][BOARD_WIDTH + 1] = 1; //board 배열 오른쪽 1인식

    SetCursorPosition(BOARD_X + (BOARD_WIDTH + 2) * 2, BOARD_Y + y);

    if (y == BOARD_HEIGHT)

      printf("┛");

    else

      printf("┃");

  }

  //모서리값 변경

  board[20][0] = 1;

  board[20][11] = 1;

  puts(" ");

}

// 점수판 출력

void ShowScore(void)

{

  SetCursorPosition(40, 3);

  printf("C언어 콘솔 테스리스");

  SetCursorPosition(40, 5);

  printf("레벨: %d\n", level);

  SetCursorPosition(40, 7);

  printf("점수: %d\n", score);

}

// 사용 가능 위치 체크

// 특정 위치에 블록이 들어갈 수 있는지 아닌지를 체크

// 들어갈 수 있으면 true, 없으면 false 반환

bool CanPositionedAt(int rotation, int move1, int move2)

{

  int x, y;

  int arrX, arrY; // 배열좌표저장

  COORD pos = GetCursorPosition();

  arrX = pos.X + move1;

  arrY = pos.Y + move2;

  arrX = (arrX / 2) - 2;

  arrY = arrY - BOARD_Y;

  for (y = 0; y < 4; y++)

  {

    for (x = 0; x < 4; x++)

    {

      if ((blocks[rotation][y][x] == 1) && board[arrY + y][arrX + x] == 1)

        return false; //보드와 벽돌 겹침

    }

  }

  return true; //겹치지 않음

}

// 현재 위치에 블록 출력

void WriteBlock(int rotation)

{

  int i, j;

  COORD cursor = GetCursorPosition();

  if (CanPositionedAt(rotation, 0, 0) == true)

  {

    //콘솔창위치 설정, 배열값에서 1은 ■출력, 0은 출력없음

    for (i = 0; i < 4; i++) // 행 반복

    {

      for (j = 0; j < 4; j++) // 열 반복

      {

        SetCursorPosition(cursor.X + (j * 2), cursor.Y + i);

        if (blocks[rotation][i][j] == 1)

        {

          printf("■");

        }

      }

    }

    SetCursorPosition(cursor.X, cursor.Y);

  }

}

// 블록 보드판에서 1인식

void BoardInit(int n, int move1, int move2)

{

  COORD pos = GetCursorPosition();

  int arrX = pos.X + move1; //콘솔좌표 열

  int arrY = pos.Y + move2; //콘솔좌표 행

  int x, y;

  /*커서위치정보->배열위치정보 변경*/

  arrX = arrX / 2 - 2; //콘솔좌표->배열 열 변환값

  arrY = arrY - 2; //콘솔좌표->배열 행 변환값

  //보드판에서 블록 이동시 1인식

  for (y = 0; y < 4; y++)

  {

    for (x = 0; x < 4; x++)

    {

      if (blocks[n][y][x] == 1)

      {

        board[arrY + y][arrX + x] = 1;

      }

    }

  }

}

// 배열,블록 옮김

void Stepper(int column)

{

  int y, x;

  // board배열 값 행 다운

  for (y = column; y >= 0; y--)

  {

    for (x = 1; x <= 10; x++)

    {

      board[y][x] = board[y - 1][x];

    }

  }

  // board배열 0행에 0삽입

  for (x = 1; x <= 10; x++)

    board[0][x] = 0;

  // board배열 1값 전체 출력

  for (y = 1; y <= 19; y++)

  {

    for (x = 1; x <= 10; x++)

    {

      SetCursorPosition((BOARD_X) + x * 2 + 1, y + BOARD_Y);

      if (board[y][x] == 1)

        printf("■");

      else

        printf(" ");

    }

  }

}

//[ 레벨 스코어 계산

void CountScore(void)

{

  score += 10;

  if (score % 50 == 0)

  {

    level += 1;

    speed -= 10; // 레벨 1증가시, 10 밀리초씩 빨라짐

  }

  ShowScore();

}

//[12]

// 1~10까지 행의 열 전체가 1로되면 블록사라짐. 사라지면 Stepper함수 실행

void RemoveLine(void)

{

  int i;

  int x, y;

  int z = 0;

  // 19행부터 시작해서 1행까지 반복

  for (y = 19; y >= 1; y--)

  {

    //행기준으로 4번 반복

    for (z = 0; z < 4; z++)

    {

      i = 0;

      //1열부터 10열까지 증가

      for (x = 1; x < 11; x++)

      {

        //행기준

        if (board[y][x] == 1)

        {

          i++;

          //1이 10개면 행 블록 삭제

          if (i == 10)

          {

            for (x = 1; x < 11; x++)

            {

              SetCursorPosition((x + 2) * 2, y + 2);

              printf(" ");

            }

            //행 기준으로 블록 내리기

            CountScore();

            Stepper(y);

          }

        }

      }

    }

  }

}

// 현재 블록 클리어

void ClearBlock(int rotation, int move1, int move2)

{

  int x, y;

  COORD cursor = GetCursorPosition();

  if (CanPositionedAt(rotation, move1, move2) == true)

  {

    for (y = 0; y < 4; y++)

    {

      for (x = 0; x < 4; x++)

      {

        SetCursorPosition(cursor.X + (x * 2), cursor.Y + y);

        if (blocks[rotation][y][x] == 1)

          printf(" ");

      }

    }

    SetCursorPosition(cursor.X + move1, cursor.Y + move2);

  }

}

// 게임 시작

void StartGame(void)

{

  int n; // 블록종류를 결정하는 변수

  int kb; // 키보드 값

  int c = 2;

  srand((unsigned) time(0)); // rand() 함수로 랜덤값을 주기 위해서 초기값 부여

  PlaySound(TEXT("tetris.wav"), NULL, SND_ASYNC | SND_LOOP);

  // 게임 시작~끝

  while (1)

  {

    //블록 생성 위치 좌표(13, 2)에서 시작

    SetCursorPosition(13, 2);

    n = rand() % 7; // 0~27까지의 인덱스 생성 : 블록 종류 결정

    n = n * 4; // 각 블록의 첫번째 블록(0, 4, 8, 12, 16, 20, 24)을 기준으로 출력 그리고 방향키로 변환할 수
    있도록

    if (level == 30) // 레벨이 30 에 도달하면 게임 끝

    {

      SetCursorPosition(40, 15);

      printf("Game Clear");

      getchar();

      exit(1);

    }

    if (CanPositionedAt(n, 0, 0) == false)

      break; //게임 끝

    // 블록 한개 위~밑 이동

    while (1)

    {

      int ww = 0;

      int k = 0;

      // 블록 아래로 이동

      while (!_kbhit())

      {

        //블록 쇼

        WriteBlock(n);

        //딜레이 타임

        Sleep(DELAY + speed);

        //아래이동시 1있는지 확인

        if (CanPositionedAt(n, 0, 1) == false)

        {

          ww = 1;

          BoardInit(n, 0, 0); //보드 벽돌 배열 1추가

          RemoveLine();

          break;

        }

        ClearBlock(n, 0, 1); //board배열 +1행

      }

      // CanPositionedAt함수에서 배열값 1발견시 중지

      if (ww == 1)

        break;

      kb = _getch();

      // 방향키

      switch (kb)

      {

      case LEFT:

        ClearBlock(n, -2, 0);

        WriteBlock(n);

        break;

      case RIGHT:

        ClearBlock(n, 2, 0);

        WriteBlock(n);

        break;

      case UP:

        // 첫수를구한다.

        k = n / 4;

        k *= 4;

        // 다음수가 끝수이하인가?

        if ((n + 1) <= (k + 3))

        {

          k = n + 1;

        }

        if (CanPositionedAt(k, 0, 0) == true)

        {

          ClearBlock(n, 0, 0);

          n = k;

          WriteBlock(n);

          break;

        }

        break;

      case DOWN:

        ClearBlock(n, 0, 2);

        break;

      case SPACE: // 아래로 뚝 떨어지는 로직

        while (1)

        {

          ClearBlock(n, 0, 1);

          if (CanPositionedAt(n, 0, 1) == false)

          {

            WriteBlock(n);

            BoardInit(n, 0, 0);

            break;

          }

        }

      default:
        break;

      } // end switch

    } // end while(블록)

  } // end while(게임)

}

// 게임 종료 화면

void EndGame()

{

  SetCursorPosition(40, 15);

  printf("Game Over");

  getch(); // 입력 대기

  system("cls");

}

// 메인 함수

int main()

{

  ConsoleInit(); // 시작 화면

  DrawField(); // 게임 영역 출력

  ShowScore(); // 점수판 출력

  StartGame(); // 게임 시작

  EndGame(); // 게임 종료 화면

}

About Me

Related Posts

What do you think?