본문 바로가기
책갈피

C언어 뜬다는 생키 나와

강동원빈 |2012.08.04 16:04
조회 205 |추천 0

/* Name: blockInfo.h ver 1.0
 * Content: 각종 블록 정보
 * Implementation: YSW
 *
 * Last modified 2008/01/01
 */

#ifndef __BLOCK_INFO_H_
#define __BLOCK_INFO_H_

#define NUM_OF_BLOCK_MODEL   7
char blockModel[][4][4] =
{
    /* 첫 번째 블록
         ■
         ■■■     */
    {
        {0, 0, 0, 0},
        {1, 0, 0, 0},
        {1, 1, 1, 0},
        {0, 0, 0, 0} },  
    {
        {0, 1, 0, 0},
        {0, 1, 0, 0},
        {1, 1, 0, 0},
        {0, 0, 0, 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, 1, 0},
        {1, 1, 1, 0},
        {0, 0, 0, 0} },  
    {
        {0, 0, 0, 0},
        {0, 1, 1, 0},
        {0, 0, 1, 0},
        {0, 0, 1, 0} },   
    {
        {0, 0, 0, 0},
        {0, 1, 1, 1},
        {0, 1, 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},
        {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, 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, 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, 1, 0, 0},
        {1, 1, 0, 0},
        {1, 0, 0, 0},
        {0, 0, 0, 0} },
    {  
        {0, 0, 0, 0},
        {1, 1, 0, 0},
        {0, 1, 1, 0},
        {0, 0, 0, 0} },  
    {
        {0, 1, 0, 0},
        {1, 1, 0, 0},
        {1, 0, 0, 0},
        {0, 0, 0, 0} },
};

#endif

/* end of file */

/* Name: blockStageControl.c ver 1.2
 * Content: 블록, 게임화면 컨트롤 함수들의 정의
 * Implementation: YSW
 *
 * Last modified 2008/01/01
 */

#include <time.h>
#include "common.h"
#include "point.h"
#include "blockInfo.h"
#include "keyCurControl.h"

#define  GBOARD_WIDTH    10
#define  GBOARD_HEIGHT   20

#define  GBOARD_ORIGIN_X  4
#define  GBOARD_ORIGIN_Y  2

static int gameBoardInfo[GBOARD_HEIGHT+1][GBOARD_WIDTH+2]={0,};

static int currentBlockModel;
static int curPosX, curPosY;
static int rotateSte;

/* 함    수: void InitNewBlockPos(int x, int y)
 * 기    능: 블록의 첫 위치 지정
 * 반    환: void
 *
 */
void InitNewBlockPos(int x, int y)
{
    if(x<0 || y<0)
        return;
  
    curPosX=x;
    curPosY=y;

    SetCurrentCursorPos(x, y);
}

/* 함    수: void ChooseBlock(void)
 * 기    능: 출력할 블록을 무작위 선택
 * 반    환: void
 *
 */
void ChooseBlock(void)
{
    srand((unsigned int)time(NULL));
   
    currentBlockModel = (rand() % NUM_OF_BLOCK_MODEL) * 4;
}

/* 함    수: int GetCurrentBlockIdx(void)
 * 기    능: 현재 출력해야 하는 블록의 index 정보 반환
 * 반    환: int
 *
 */
int GetCurrentBlockIdx(void)
{
    return currentBlockModel + rotateSte;
}

/* 함    수: void ShowBlock(char blockInfo[][4])
 * 기    능: 전달된 인자를 참조하여 블록 출력
 * 반    환: void
 *
 */
void ShowBlock(char blockInfo[][4])
{
    int y, x;
    point curPos=GetCurrentCursorPos();

    for(y=0; y<4; y++)
    {
        for(x=0; x<4; x++)
        {
            SetCurrentCursorPos(curPos.x+x*2, curPos.y+y);
           
            if(blockInfo[y][x] == 1)
                printf("■");
        }
    }
    SetCurrentCursorPos(curPos.x, curPos.y);
}

/* 함    수: void DeleteBlock(char blockInfo[][4])
 * 기    능: 현재 위치에 출력된 블록 삭제
 * 반    환: void
 *
 */
void DeleteBlock(char blockInfo[][4])
{
    int y, x;
    point curPos=GetCurrentCursorPos();
   
    for(y=0; y<4; y++)
    {
        for(x=0; x<4; x++)
        {
            SetCurrentCursorPos(curPos.x+x*2, curPos.y+y);
           
            if(blockInfo[y][x] == 1)
                printf("  ");
        }
    }
    SetCurrentCursorPos(curPos.x, curPos.y);
}

/* 함    수: int DetectCollision(int posX, int posY, char blockModel[][4])
 * 기    능: 블록의 이동 및 회전 가능 여부 판단
 * 반    환: 이동 및 회전 가능시 1 반환
 *
 */
int DetectCollision(int posX, int posY, char blockModel[][4])
{
    int x, y;

    /* gameBoardInfo 배열의 좌표로 변경 */
    int arrX= (posX-GBOARD_ORIGIN_X)/2;
    int arrY= posY-GBOARD_ORIGIN_Y;

    /* 충돌 검사 */
    for(x=0; x<4; x++)
    {
        for(y=0; y<4; y++)
        {
            /* Short Circuit eva1uation에 의해 배열 일부만 검사 */
            if(blockModel[y][x]==1 && gameBoardInfo[arrY+y][arrX+x]==1)
                return 0;
        }
    }
   
    return 1;
}

/* 함    수: int BlockDown(void)
 * 기    능: 모니터에 그려진 블록을 아래로 한 칸 내림
 * 반    환: 성공 시 1, 실패 시 0
 *
 */
int BlockDown(void)
{
    if(!DetectCollision(curPosX, curPosY+1, blockModel[GetCurrentBlockIdx()]))
        return 0;

    DeleteBlock(blockModel[GetCurrentBlockIdx()]);
    curPosY+=1;
   
    SetCurrentCursorPos(curPosX, curPosY);
    ShowBlock(blockModel[GetCurrentBlockIdx()]);

    return 1;
}

/* 함    수: void ShiftLeft(void)
 * 기    능: 블록을 왼쪽으로 한 칸 이동
 * 반    환: void
 *
 */
void ShiftLeft(void)
{
    if(!DetectCollision(curPosX-2, curPosY, blockModel[GetCurrentBlockIdx()]))
      return;
 
    DeleteBlock(blockModel[GetCurrentBlockIdx()]);
    curPosX-=2;
   
    SetCurrentCursorPos(curPosX, curPosY);
    ShowBlock(blockModel[GetCurrentBlockIdx()]);
}

/* 함    수: void ShiftRight(void)
 * 기    능: 블록을 오른쪽으로 한 칸 이동
 * 반    환: void
 *
 */
void ShiftRight(void)
{
    if(!DetectCollision(curPosX+2, curPosY, blockModel[GetCurrentBlockIdx()]))
        return;
 
    DeleteBlock(blockModel[GetCurrentBlockIdx()]);
    curPosX+=2;
   
    SetCurrentCursorPos(curPosX, curPosY);
    ShowBlock(blockModel[GetCurrentBlockIdx()]);
}

/* 함    수: void RotateBlock(void)
 * 기    능: 블록을 90도 회전
 * 반    환: void
 *
 */
void RotateBlock(void)
{
    int nextRotSte;
    int beforeRotSte=rotateSte;  // 복원을 위한 정보
   
    DeleteBlock(blockModel[GetCurrentBlockIdx()]);

    nextRotSte=rotateSte+1;
    nextRotSte%=4;
    rotateSte=nextRotSte;

    if(!DetectCollision(curPosX, curPosY, blockModel[GetCurrentBlockIdx()]))
    {
        rotateSte=beforeRotSte;
        return;
    }
   
    SetCurrentCursorPos(curPosX, curPosY);
    ShowBlock(blockModel[GetCurrentBlockIdx()]);
}

/* 함    수: void DrawGameBoard(void)
 * 기    능: 게임 판의 경계 면을 그린다.
 * 반    환: void
 *
 */
void DrawGameBoard(void)
{
    int x, y;

    /* 시각적인 부분 처리 */
    for(y=0; y<=GBOARD_HEIGHT; y++)
    {
        SetCurrentCursorPos(GBOARD_ORIGIN_X, GBOARD_ORIGIN_Y+y);

        if(y==GBOARD_HEIGHT)
            printf("┗");
        else
            printf("┃");
    }
   
    for(y=0; y<=GBOARD_HEIGHT; y++)
    {
        SetCurrentCursorPos(GBOARD_ORIGIN_X+(GBOARD_WIDTH+1)*2, GBOARD_ORIGIN_Y+y);

        if(y==GBOARD_HEIGHT)
            printf("┛");
        else
            printf("┃");
    }
   
    for(x=1; x<GBOARD_WIDTH+1; x++)
    {
        SetCurrentCursorPos(GBOARD_ORIGIN_X+x*2, GBOARD_ORIGIN_Y+GBOARD_HEIGHT);
        printf("━");
    }

    SetCurrentCursorPos(0, 0); 

    /* 데이터 부분 처리 */
    for(y=0; y<GBOARD_HEIGHT; y++)
    {
        gameBoardInfo[y][0]=1;
        gameBoardInfo[y][GBOARD_WIDTH+1]=1;
    }
   
    for(x=0; x<GBOARD_WIDTH+2; x++)
    {
        gameBoardInfo[GBOARD_HEIGHT][x]=1;
    }
}

/* 함    수: void AddCurrentBlockInfoToBoard(void)
 * 기    능: 배열에 현재 블록의 정보를 추가한다.
 * 반    환: void
 *
 */
void AddCurrentBlockInfoToBoard(void)
{
    int x, y;

    int arrCurX;
    int arrCurY;
   
    for(y=0; y<4; y++)
    {
        for(x=0; x<4; x++)
        {
            /* 커서 위치 정보를 배열 index 정보로 변경 */
            arrCurX=(curPosX-GBOARD_ORIGIN_X)/2;
            arrCurY=curPosY-GBOARD_ORIGIN_Y;

            if(blockModel[GetCurrentBlockIdx()][y][x]==1)
                gameBoardInfo[arrCurY+y][arrCurX+x]=1;
        }
    }
}

/* 함    수: int IsGameOver(void)
 * 기    능: 게임이 종료되었는지 확인하는 함수
 * 반    환: 게임 종료 시 1 반환
 *
 */
int IsGameOver(void)
{
    if(!DetectCollision(curPosX, curPosY, blockModel[GetCurrentBlockIdx()]))
        return 1;
    else
        return 0; 
}

/* end of file */

/* Name: blockStageControl.h ver 1.2
 * Content: 블록, 게임화면 컨트롤 함수들의 선언
 * Implementation: YSW
 *
 * Last modified 2008/01/01
 */

#ifndef __BLOCK_STAGE_H_
#define __BLOCK_STAGE_H_

void InitNewBlockPos(int x, int y);
void ChooseBlock(void);
int GetCurrentBlockIdx(void);
void ShowBlock(char blockInfo[][4]);
void DeleteBlock(char blockInfo[][4]);
int BlockDown(void);
void ShiftLeft(void);
void ShiftRight(void);
void RotateBlock(void);

void AddCurrentBlockInfoToBoard(void);
void DrawGameBoard(void);
int IsGameOver(void);

#endif

/* Name: common.h  ver 1.0
 * Content: 공통 ANSI 표준 헤더.
 * Implementation: YSW
 *
 * Last modified 2008/01/01
 */

#ifndef __COMMOM_H__
#define __COMMON_H__

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#endif
/* end of file */

/* Name: keyCurControl.c  ver 1.1
 * Content: 커서, 키보드 컨트롤 함수들의 정의
 * Implementation: YSW
 *
 * Last modified 2008/01/01
 */

#include <conio.h>
#include <windows.h>
#include "point.h"
#include "blockStageControl.h"

#define KEY_SENSITIVE        100
#define SYS_DELAY              20

#define LEFT 75
#define RIGHT 77
#define UP 72
#define DOWN 80

static int keyDelayRate;   // 값이 클수록 속도 증가

/* 함    수: void RemoveCursor(void)
 * 기    능: 깜빡 거리는 커서의 제거
 * 반    환: void
 *
 */
void RemoveCursor(void)
{
    CONSOLE_CURSOR_INFO curInfo;
    GetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE),&curInfo);
    curInfo.bVisible=0;
    SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE),&curInfo);
}

/* 함    수: point GetCurrentCursorPos(void)
 * 기    능: 현재 커서 위치 정보를 담은 구조체 변수 반환
 * 반    환: point
 *
 */
point GetCurrentCursorPos(void)
{
    point curPoint;
    CONSOLE_SCREEN_BUFFER_INFO curInfo;
   
    GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &curInfo);
    curPoint.x=curInfo.dwCursorPosition.X;
    curPoint.y=curInfo.dwCursorPosition.Y;
   
    return curPoint;
}

/* 함    수: void SetCurrentCursorPos(int x, int y)
 * 기    능: 커서 위치를 설정
 * 반    환: void
 *
 */
void SetCurrentCursorPos(int x, int y)
{
    COORD pos={x, y};
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
}

/* 함    수: void ProcessKeyInput(void)
 * 기    능: 키 입력 처리
 * 반    환: void
 *
 */
void ProcessKeyInput(void)
{
    int i;
    int key;

    for(i=0; i<KEY_SENSITIVE; i++)
    {
        if(_kbhit() != 0)
        {
            key = _getch();
                        
            switch(key)
            {
            case LEFT:
               ShiftLeft();
                break;
                
            case RIGHT:
                ShiftRight();
                break;
           
            case UP:
                RotateBlock();    
            }
        }
   
        if(i % keyDelayRate == 0)
            Sleep(SYS_DELAY);
    }
}

/* 함    수: void InitKeyDelayRate(int rate)
 * 기    능: 속도 조절, 값이 클수록 속도 증가
 * 반    환: void
 *
 */
void InitKeyDelayRate(int rate)
{
    if(rate<1)
        return;
   
    keyDelayRate=rate;
}

/* end of file */

/* Name: keyCurControl.h  ver 1.1
 * Content: 커서, 키보드 컨트롤 함수들의 정의
 * Implementation: YSW
 *
 * Last modified 2008/01/01
 */

#ifndef __KEY_CURSOR_H_
#define __KEY_CURSOR_H_

#include "point.h"

void RemoveCursor(void);
point GetCurrentCursorPos(void);
void SetCurrentCursorPos(int x, int y);
void ProcessKeyInput(void);
void InitKeyDelayRate(int rate);

#endif
/* end of file */

/* Name: point.h  ver 1.0
 * Content: 커서 위치 정보 표현을 위한 구조체
 * Implementation: YSW
 *
 * Last modified 2008/01/01
 */

#ifndef __POINT_H_
#define __POINT_H_

typedef struct __point
{
    int x;
    int y;
} point;

#endif
/* Name: tetrisMain.c  ver 1.2
 * Content: main 함수의 정의
 * Implementation: YSW
 *
 * Last modified 2008/01/01
 */
#include <Windows.h>
#include "common.h"
#include "keyCurControl.h"
#include "blockStageControl.h"

#define START_CURPOS_X         (5*2)
#define START_CURPOS_Y         (0)

int main(void)
{
    /* 게임 속도 설정 */
    InitKeyDelayRate(10);

    /* 커서 깜빡임 제거 */
    RemoveCursor();

    /* 게임 보드 그리기 */
    DrawGameBoard();
   
    /* 반복적으로 새로운 블록의 등장 */
    while(1)
    {
        /* 새 블록의 등장위치 설정 */
        InitNewBlockPos(START_CURPOS_X, START_CURPOS_Y);
       
        /* 블록 선택 */
        ChooseBlock();
       
        /* 게임 종료 확인 */
        if(IsGameOver())
            break;
        
        /* 내리는 작업 시작 */
        while(1)
        {
            /* 블록을 아래로 한 칸 이동 */
            if(BlockDown()==0) // 블록 이동 실패 시
            {
                AddCurrentBlockInfoToBoard();
                break;
            }
           
            /* 게이머 키 입력 처리 */
            ProcessKeyInput();
        }
    }
   
    SetCurrentCursorPos(10, 10);
    puts("GAME OVER ^^");
   
    return 0;
}

/* end of file */

추천수0
반대수0

공감많은 뉴스 연예

더보기

뉴스 플러스