좀 길긴해 ;; 그리고 테트리스야
뭐 어떻게말하면 좋을진모르겠지만
열심히 공부해서 테트리스 만드려하는데
책보면서 공부해서 대충 틀은 다잡아놨거든?
그런데 사람들 테트리스보면 다음 도형나오고 점수나오고 점수 1000점 하면 레벨오르고그런거있짢아
어떻게 하는지좀알려줫으면 좋겠어
대충 다음 도형같은건 프린트폼 쓰면되는것같고
점수는 체크라인에가서 줄없어지면 카운트 변수에 1씩올리고 하면되고 
레벨은 솔직히 잘모르겠어 ㅠ

좀알려줬으면 감사감사

#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <time.h>
#include <windows.h>



int count=0;

// x,y 두개의 좌표가 필요하니깐 벽돌 하나 모양을 정의하려면 8바이트가 필요하지?
// 그래서 도형하나의 공간인 4행 4열 위치를 지정해야해

char form[7][4][8] =
{
        { {1,0,1,1,1,2,1,3}, {0,1,1,1,2,1,3,1} , {1,0,1,1,1,2,1,3} , {0,1,1,1,2,1,3,1} },
        { {1,1,2,1,1,2,2,2}, {1,1,2,1,1,2,2,2}, {1,1,2,1,1,2,2,2}, {1,1,2,1,1,2,2,2} },
        { {2,1,0,2,1,2,1,1}, {1,0,1,1,2,1,2,2}, {2,1,0,2,1,2,1,1}, {1,0,1,1,2,1,2,2} },
        { {0,1,1,1,1,2,2,2}, {2,0,2,1,1,1,1,2}, {0,1,1,1,1,2,2,2}, {2,0,2,1,1,1,1,2} },
        { {1,0,1,1,1,2,2,2}, {0,1,1,1,2,1,0,2}, {1,0,2,0,2,1,2,2}, {2,1,2,2,1,2,0,2} },
        { {2,0,2,1,2,2,1,2}, {0,1,0,2,1,2,2,2}, {1,0,2,0,1,1,1,2}, {0,1,1,1,2,1,2,2} },
        { {0,1,1,1,2,1,1,2} , {2,0,2,1,2,2,1,1}, {1,1,1,2,0,2,2,2} , {1,0,1,1,1,2,2,1} },
};
// 여긴 테트리스 보드판 만드는거야
int tetris[21][12];

//블록 종류를 나타내는거야

int form_kind;

// 블록 회전형태

int rotate_kind;

// 화면상의 좌표 !
int screen_x, screen_y;

// 화면 위치 지정하는함수야

void CurrentXY(int x, int y)
{
        COORD Location;
        X =x;
        Y =y;

        SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), Location);
}


// 화면 커서없내는 거야

void CursorOff(void)
{

        CONSOLE_CURSOR_INFO Information;

        Information.dwSize=1;
        Information.bVisible=FALSE;

        SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &Information);
}

// 화면 커서 나타내게 하는거야 ㅇ

void CursorOn(void)

{

        CONSOLE_CURSOR_INFO Information;

        Information.dwSize=20;
        Information.bVisible=TRUE;

        SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &Information);
}

// 도형 하나를 출력하는거야

void Print_form()
{

        int i;

        for(i=0; i<4; i++)
        {

                // 화면 위치 지정하는거야
                CurrentXY(30+ (screen_x+form[form_kind][rotate_kind][i*2])*2, screen_y + form[form_kind][rotate_kind][i*2+1]);

                //착지하지 않은 도형을 1로 지정하는거야 그래서 tetris 배열에 저장하는거지

                tetris[screen_y+form[form_kind][rotate_kind][i*2+1]] [screen_x+form[form_kind][rotate_kind][i*2] ] = 1;

                // 도형을 화면에 출력하는거임

                printf("□");
        }
}

// 도형 하나 삭제하는거야 

void Delete_form()
{

        int i;

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

        {

                // 화면 위치 지정하는거임

                CurrentXY(30+(screen_x+form[form_kind][rotate_kind][i*2]) *2, screen_y+form[form_kind][rotate_kind][i*2+1]);

                //도형이 없다는걸 0으로 tetris 배열에 저장하는거야 !

                tetris [ screen_y + form[form_kind][rotate_kind][i*2+1]] [ screen_x + form[form_kind][rotate_kind][i*2] ] = 0;

                // 화면의 도형 삭제 !!!!!
                
                printf(" ");

        }
}


// 보드판 초기위치를 어디다 할껀지 설정하고 테두리 만드는거야

void Initial()
{
        int i,j;

        for(i=0; i<21; i++)
        {

                for(j=0; j<12; j++)
                {   //외벽을 의미하는 3을 저장하는거야 
                        if (i==20 || j==0 || j==11)
                                tetris[i][j] = 3;
                        else // 빈 도형을 의미하는 0을 저장해
                                tetris[i][j] = 0;
                }
        }

        for(i=0; i<21; i++)
        {   // 아래로 출력 !

                CurrentXY(30,i);
                printf("│");
                CurrentXY(52,i);
                printf("│");

        }

        CurrentXY(30,20);

        printf("└");
        for (j=1; j<11;j++)
        {     // 옆으로 출력

                CurrentXY(30 + j*2, 20);
                printf("─");
        }

        CurrentXY(52,20);
        printf("┘");
}

// 위치에 도형이나 테두리가 있는지 체크하는거야

int Check_board(int location_x, int location_y)
{
        int i, temp=0;

        for(i=0; i<4; i++)
        {

                // 현재 위치에 있는 도형 정보를 읽는거야

                temp = tetris[ location_y + form[form_kind][rotate_kind][i*2+1]] [ location_x + form[form_kind][rotate_kind][i*2] ];


                // 아까 도형이있으면 1저장한댔짢아? 그거야

                if ( temp > 1)
                        return TRUE;
        }

        return FALSE;
}

// 현재 보드판 상황의 도형들을 출력

void Print_data()

{

        int i,j;

        for(i=0; i <20; i++)
                for (j=1; j <11; j++)
                        // 착지한 도형이면

                        if (tetris[i][j] == 2)
                        {

                                CurrentXY(30 + j*2, i);
                                printf("□");
                        }
                        else
                        {
                                CurrentXY(30 + j*2, i);
                                printf(" ");
                        }
}

// 보드판 데이터를 한줄 아래로 이동 !!

void Move_data(int row)

{

        int i,j;

        // 삭제 대상의 윗줄부터 최상위 라인까지를 한줄 아래로 이동 !!


        for ( i=row - 1; i >=0; i--)

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

                        tetris[i+1][j] = tetris[i][j];
}

// 한줄찼는지 체크하는거야 그리고 나 이제 졸리다 ㅠ 새벽샜어

int Check_line2 (int row)
{

        int chk=0;
        int j;

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

                chk += tetris[row][j];

        // 착지한 도형을 의미하는 2가 열개모이면 줄이찬거야 

        if (chk==20) return TRUE;
        else return FALSE;
}


// 없앨줄있는지 체크

void Check_line()

{
        int rst;

        int i;

        for(i=screen_y; i<screen_y + 4; i++)
        {

                // 한줄 찼는지 점검 !
                rst =Check_line2(i);
                
                // 한줄이 찼으면 삭제할 줄을 없애는거야

                if (rst==TRUE)
                {

                        Move_data(i);
                        Print_data();
                        i--;
                }
        }
}

// 착지 완료된 도형의 데이터를 보드판에 기입해 ㅠㅠ 졸려

void Write_board()
{

        int i;

        for(i=0; i<4; i++)
        {

                tetris[ screen_y + form[form_kind][rotate_kind][i *2 +1]] [ screen_x + form[form_kind][rotate_kind][i*2]] =2;
        }
}

// 도형을 아래로 이동하게하는거야 

int Go_down()
{

        int chk2;

        // 한줄ㅇ ㅏ래로 이동 가능한지 점검한다 !

        chk2 = Check_board(screen_x, screen_y + 1);

        // 이동 가능하지않으면

        if (chk2==TRUE)
        {

                // 보드판에 2를 저장해

                Write_board();

                // 채워진 줄이 존재하는 점검해바

                Check_line();

                return TRUE;
        }

        // 도형을 아래로 내려
        Delete_form();
        screen_y++;
        Print_form();

        return FALSE;
}

// 키값에 따른처리해 이거 키 이벤트야 알지 ?

int Select(void)

{

        int chk1;
        int prev_rotate;
        int new_rotate;
        int rtn_value;

        if(GetAsyncKeyState(VK_LEFT))
        {

                //왼쪽누르면 
                chk1= Check_board(screen_x-1, screen_y);

                // 이동할 위치가 빈곳이면

                if (chk1 ==FALSE)

                {

                        // 기존에있는 도형을 삭제하고 새 위치에 출력하는거야!
                        Delete_form();
                        screen_x--;
                        Print_form();
                        return TRUE;
                }
        }

        if(GetAsyncKeyState(VK_RIGHT))
        {
                // 오른쪽 누르면

                chk1 = Check_board(screen_x+1, screen_y);

                // 이동할 위치가 빈곳이면

                if(chk1 ==FALSE)
                {

                        // 기존 위치의 도형 삭제하고 새 위치에 출력

                        Delete_form();

                        screen_x++;

                        Print_form();

                        return TRUE;
                }
        }

        if(GetAsyncKeyState(VK_UP))
        {
                // 위 입력하면 도형을 바꿔

                prev_rotate = rotate_kind;

                // 도형 모양을 바꿈

                if(rotate_kind ==3) rotate_kind = 0;

                else rotate_kind++;

                new_rotate = rotate_kind;

                // 새로운 도형이 출력 ㅏ가능한지 점검해봐

                chk1 = Check_board(screen_x, screen_y);
                // 가능하면 전 도형 삭제하고 새도형 출력해

                if(chk1==FALSE)
                {

                rotate_kind = prev_rotate;
                Delete_form();

                rotate_kind = new_rotate;
                Print_form();
                return TRUE;
                }
                else
                {
                        rotate_kind = prev_rotate;
                }
        }

        if(GetAsyncKeyState(VK_SPACE))
        {
                // 도형을 한줄 밑으로 출력하는 Go_down 을 연속 호출해서 밑으로 쭉내리는거지

                while ( !Go_down());
                return FALSE;
        }

        rtn_value = Go_down();

        if (rtn_value==TRUE) return FALSE;
        else return TRUE;
}

// 시간 지연 처리 하는곳이야

void Timing(void)
{

        DWORD   thisTickCount;
        static DWORD  lastTickCount = 0;
        DWORD   delay = 100;                // 딜레이 이부분 수정하면속도를 늦추거나 빠르게할수있음


        //클럭 틱을 얻어 온다.

        thisTickCount = GetTickCount();

        while(1)
        {
                // 클럭틱의 횟수를 비교한다 .

                if((thisTickCount - lastTickCount) > delay)
                {
                        // 정해진 횟수의 틱 카운트면 최과해

                        lastTickCount = thisTickCount;
                        return;

                }

                thisTickCount = GetTickCount();
        }
}


void main()

{

        int chk, chk2;

        // 커서 안보이게하기!

        CursorOff();

        Initial();

        do {

                // 화면 좌표 초기값

                screen_y = 0;
                screen_x = 4;

                // 도형 종류 및 회전형태 지정

                form_kind = rand() % 7;
                rotate_kind = 0;

                Print_form();

                chk = Check_board(screen_x, screen_y);
                chk2 = Check_board(screen_x, screen_y+1);

                // 처음 위치가 아니라면 저장 하고 종료

                if ( chk==FALSE && chk2==TRUE)
                {

                        Write_board();
                        Check_line();

                        break;

                }
                // 처음위치라면 저장라고 종료해

                else 
                        if(chk ==TRUE && chk2==TRUE)
                                break;

                do {
                        Timing();
                }
                while(Select());

        }

        while(1);

        // 커서 다시 나타내자

        CursorOn();

}