일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- 참조은요양병원
- IT
- 반복문
- Backdoor
- 리눅스
- c언어
- 제어문
- 수학영재원
- 배열
- For문
- 리눅스 명령어
- 프로그래밍
- if문
- 정보과학
- 자료구조
- 풀이&소스코드저작권:왕유승
- DBMS
- 백도어
- C
- 독서 감상문
- 정보올림피아드
- 정보영재원
- 알고리즘
- 다중반복문
- 독후감
- Linux
- 문제출저:www.dovelet.com
- API
- C++
- 영재교육원
- Today
- Total
되는대로 살자
뿌요뿌요 소스코드 본문
와 오늘 진짜 대박 뿌요뿌요 소스코드를 찾았다 !!!
분석은 내일 하도록 하겠음 (주석 너무 잘달아 놔서 할 게 없을지도? ㅋ )
#include <Turboc.h>
#define LEFT_KEY 75
#define RIGHT_KEY 77
#define UP_KEY 72
#define DOWN_KEY 80
#define STOP_KEY 27 // ESC
#define START_KEY 115 // S
#define QUIT_KEY 113 // Q
#define MAP_START_X 5
#define MAP_START_Y 1
#define BOARD_WIDTH 10
#define BOARD_HEIGHT 20
#define COUNT_OF_BRICK 2
#define BRICK_COUNT_OF_CLEAR 4
#define NUM_OF_DIRECTION_TO_CHECK 4
#define HIT_COUNT_FOR_LEVEL_UP 20 // 게임 등급 상승을 위한 Brick clear회수: 4개 1회 4개 초과
#define MAX_LEVEL_COUNT 20 // 최대 게임 등급
#define AUTO_SCROLL_INTERVAL 2 // Brick를 자동으로 아래로 움직이기 위한 시간
#define BRICK_CLEAR_INTERVAL 50 // Brick한개를 지울때 지연시간
#define MAX_HIT_COUNT 99000
#define INIT_GAME 0
#define WAITING_GAME_MODE_SELECTION 1
#define START_GAME 2
#define INITIAL_TO_START_GAME 3
#define RUNNING_GAME 4
#define STOP_GAME 5
#define QUIT_PROGRAM 6
#define NEW_BRICK_MODE 1
#define BRICK_OPERATING_MODE 2
void DrawScreen();
void DisplayLevelAndBrickClearCount();
void ProcessKeyAtMenu();
BOOL ProcessKeyAtGame();
void PrintCurrentBrick(BOOL Show);
int GetAround(int x,int y,int r);
BOOL MoveDown();
void DownOneBrick(int x, int y,int block);
void ClearOneBrick(int x, int y);
void ClearConnectedBrick();
int BrickConnectionStatus(int x, int y, int CheckBoard);
int BlockedBrickProgress(int x, int y);
void DisplayGameOverMessage(int mode);
struct Point {
int x,y;
};
// 해당 정점을 중심으로하 4 방향
Point Shape[NUM_OF_DIRECTION_TO_CHECK] = {{0,1},{-1,0},{0,-1},{1,0}};
enum { EMPTY, WALL, BRICK};
char *arTile[]={". ","□","★","●","◈","♠"};
int Board[BOARD_WIDTH+2][BOARD_HEIGHT+2];
int Pos_X,Pos_Y;
int CurrentBrick[COUNT_OF_BRICK],AliveBrick[COUNT_OF_BRICK];
int RotationId;
int Column_Height[BOARD_WIDTH];
int BrickConnectedTable[BOARD_WIDTH+2][BOARD_HEIGHT+2];
int CurrentLevel,BrickClearCountChanged;
long BrickClearCount;
int RunningMode,OldRunningMode,BrickMode;
void main()
{
int i,x,y;
int OldLevel,OldBrickClearCount;
int AutoScrollTimer,AutoScrollCount;
srand((time(NULL)));
setcursortype(NOCURSOR);
randomize();
clrscr();
///////////////////////////////////////////////////////////
// 변수 초기화
///////////////////////////////////////////////////////////
RunningMode = OldRunningMode = INIT_GAME;
WAITING_GAME_MODE_SELECTION;
while (true)
{
if (RunningMode == QUIT_PROGRAM)
break;
// S키를 이용해서 게임을 시작했을 때 초기화 루틴
if ((RunningMode == INITIAL_TO_START_GAME) || (RunningMode == INIT_GAME))
{
// 초기화(. ) & 벽만들기(□)
for (x=0;x<BOARD_WIDTH+2;x++)
{
// 열별 block의 수 초기화
Column_Height[x] = 0;
// 2는 벽
for (y=0;y<BOARD_HEIGHT+2;y++) // 2는 벽
Board[x][y] = (y==0 || y==BOARD_HEIGHT+1 || x==0 || x==BOARD_WIDTH+1) ? WALL:EMPTY;
}
// Level and 히트 수 초기화
CurrentLevel = 1;
BrickClearCount = 0;
// Level이 올라가면 delay가 짧아져서 빨라짐
AutoScrollCount = (MAX_LEVEL_COUNT - CurrentLevel) * AUTO_SCROLL_INTERVAL;
AutoScrollTimer = AutoScrollCount;
// 새 게임시작할때는 새 brick만들기로시작한다.
BrickMode = NEW_BRICK_MODE;
DrawScreen();
DisplayGameOverMessage(false);
if (RunningMode == INIT_GAME)
RunningMode = WAITING_GAME_MODE_SELECTION;
else if (RunningMode == INITIAL_TO_START_GAME)
RunningMode = RUNNING_GAME;
}
// BRICK을 움직일수 없는 조건이면 새 BRICK생성모드가 됨
// S나 Q,ESC키를 누르면 게임시작, 게임종료, 게임중지 등이 됨
// Key를 조작하여 회전,아래로 떨어뜨리기 등이 됨
if ((RunningMode == RUNNING_GAME) && (BrickMode == BRICK_OPERATING_MODE))
ProcessKeyAtGame();
else
ProcessKeyAtMenu();
if (RunningMode == RUNNING_GAME)
{
// BRICK생성모드(생성된 Brick이 바닥에 닿았을 때
if (BrickMode == NEW_BRICK_MODE)
{
for (i=0;i<COUNT_OF_BRICK;i++)
{
// 생성될 벽돌 지정
CurrentBrick[i] = rand() % 4 + 2; //2: EMPTY & WALL 제외
// 다른 brick과 닿으면 false로 변함
// false가 되면 더이상 움직일 수 없음
AliveBrick[i] = true;
}
// 벽돌의 현재 위치 초기화(생성 위치)
Pos_X = BOARD_WIDTH/2;
Pos_Y = 1;
// 수평, 수직 구분
// 추가된 Brick의 중심 brick에 대한 상대 좌표
RotationId = rand() % 2;
PrintCurrentBrick(TRUE);
//BRICK생성하고 조작모드로 변경시킴
BrickMode = BRICK_OPERATING_MODE;
}
// BRICK 조작 모드
if (BrickMode == BRICK_OPERATING_MODE)
{
OldLevel = CurrentLevel;
OldBrickClearCount = BrickClearCount;
// 1씩 감소시켜 0이되면 자동 Scroll down
if (--AutoScrollTimer == 0)
{
AutoScrollTimer = AutoScrollCount;
if (MoveDown())
BrickMode = NEW_BRICK_MODE;
}
CurrentLevel = BrickClearCount/HIT_COUNT_FOR_LEVEL_UP + 1;
if (CurrentLevel >= MAX_LEVEL_COUNT)
CurrentLevel = MAX_LEVEL_COUNT-1;
CurrentLevel = 2;
AutoScrollCount = (MAX_LEVEL_COUNT - CurrentLevel) * AUTO_SCROLL_INTERVAL;
if ((CurrentLevel != OldLevel) || BrickClearCountChanged)
{
DisplayLevelAndBrickClearCount();
BrickClearCountChanged = false;
// Level이 올라가면 delay가 짧아져서 빨라짐
AutoScrollCount = (MAX_LEVEL_COUNT - CurrentLevel) * AUTO_SCROLL_INTERVAL;
}
}
}
delay(10);
}
setcursortype(NORMALCURSOR);
}
void DrawScreen()
{
int x,y;
char String[256];
for (x=0;x<BOARD_WIDTH+2;x++)
{
for (y=0;y<BOARD_HEIGHT+2;y++)
{
gotoxy(MAP_START_X+x*2,MAP_START_Y+y);
puts(arTile[Board[x][y]]);
}
}
gotoxy(50,3);puts("뿌요뿌요 Ver 1.0");
gotoxy(50,5);puts("S:시작 Esc:중지 Q: 종료");
gotoxy(50,7);puts("좌우:이동, 위:회전, 아래:내림");
gotoxy(50,8);puts("공백:전부 내림");
sprintf(String,"Level:%02d/%02d",CurrentLevel,MAX_LEVEL_COUNT);
gotoxy(50,12);puts(String);
sprintf(String,"Hit Count:%05ld",BrickClearCount);
gotoxy(50,13);puts(String);
}
void DisplayLevelAndBrickClearCount()
{
char String[256];
sprintf(String,"%02d/%02d",CurrentLevel,MAX_LEVEL_COUNT);
gotoxy(56,12);puts(String);
sprintf(String,"%05ld",BrickClearCount);
gotoxy(60,13);puts(String);
}
void DisplayGameOverMessage(int mode)
{
gotoxy(50,15);
if (mode)
puts("G A M E O V E R");
else
puts(" ");
}
BOOL ProcessKeyAtGame()
{
int InputKey,tRotationId;
if (kbhit())
{
InputKey = getch();
if ((InputKey == 0xE0 || InputKey == 0))
{
InputKey = getch();
switch (InputKey)
{
case LEFT_KEY:
if (GetAround(Pos_X-1,Pos_Y,RotationId) == EMPTY)
{
PrintCurrentBrick(FALSE);
Pos_X--;
PrintCurrentBrick(TRUE);
}
break;
case RIGHT_KEY:
if (GetAround(Pos_X+1,Pos_Y,RotationId) == EMPTY)
{
PrintCurrentBrick(FALSE);
Pos_X++;
PrintCurrentBrick(TRUE);
}
break;
// Rotation
case UP_KEY:
tRotationId=(RotationId == 3 ? 0:RotationId+1);
if (GetAround(Pos_X,Pos_Y,tRotationId) == EMPTY)
{
PrintCurrentBrick(FALSE);
RotationId=tRotationId;
PrintCurrentBrick(TRUE);
}
break;
case DOWN_KEY:
if (MoveDown())
BrickMode = NEW_BRICK_MODE;
break;
}
}
else
{
switch (InputKey)
{
case STOP_KEY:
DisplayGameOverMessage(true);
RunningMode = WAITING_GAME_MODE_SELECTION;
break;
case ' ':
while(MoveDown()==FALSE) {;}
BrickMode = NEW_BRICK_MODE;
break;
}
}
}
return FALSE;
}
void ProcessKeyAtMenu()
{
int InputKey;
if (kbhit())
{
InputKey = getch();
switch (InputKey)
{
case START_KEY:
if (RunningMode == WAITING_GAME_MODE_SELECTION)
RunningMode = INITIAL_TO_START_GAME;
break;
case QUIT_KEY:
RunningMode = QUIT_PROGRAM;
break;
}
}
}
// True: Brick을 현재 위치에 표시
// False: Brick이 표시되었던 이전 위치를 EMPTY로 지움
void PrintCurrentBrick(BOOL Show)
{
// 현재 출력 위치로 이동
gotoxy(MAP_START_X+Pos_X*2,MAP_START_Y+Pos_Y);
puts(arTile[Show ? CurrentBrick[0]:EMPTY]);
gotoxy(MAP_START_X+(Pos_X+Shape[RotationId].x)*2,
MAP_START_Y+Pos_Y+Shape[RotationId].y);
puts(arTile[Show ? CurrentBrick[1]:EMPTY]);
}
int GetAround(int x,int y,int r)
{
int i,MaxBlockValue;
Point BrickPosition[COUNT_OF_BRICK];
for (i=0;i<COUNT_OF_BRICK;i++)
{
// 중심점에 있는 Brick
if (i==0)
{
BrickPosition[i].x = x;
BrickPosition[i].y = y;
}
// 상대 좌표에 있는 Brick
else
{
BrickPosition[i].x = x+Shape[r].x;
BrickPosition[i].y = y+Shape[r].y;
}
}
MaxBlockValue = EMPTY;
for (i=0;i<COUNT_OF_BRICK;i++)
{
// 이미 처리된 brick은 제외함
if (AliveBrick[i] == false)
continue;
if (Board[BrickPosition[i].x][BrickPosition[i].y] > MaxBlockValue)
MaxBlockValue = Board[BrickPosition[i].x][BrickPosition[i].y];
}
return(MaxBlockValue);
}
BOOL MoveDown()
{
if(GetAround(Pos_X,Pos_Y+1,RotationId) == EMPTY)
{
PrintCurrentBrick(FALSE);
Pos_Y++;
PrintCurrentBrick(TRUE);
return FALSE;
}
else
{
// BRICK이 천장에 닿으면 게임 Over
if (Pos_Y == 1)
{
DisplayGameOverMessage(true);
RunningMode = WAITING_GAME_MODE_SELECTION;
}
else
{
// 중심점 이외의 brick이 아래에 위치한 경우
if (Shape[RotationId].y <= 0)
{
DownOneBrick(Pos_X,Pos_Y,CurrentBrick[0]);
DownOneBrick(Pos_X+Shape[RotationId].x,Pos_Y+Shape[RotationId].y,CurrentBrick[1]);
}
else
{
DownOneBrick(Pos_X+Shape[RotationId].x,Pos_Y+Shape[RotationId].y,CurrentBrick[1]);
DownOneBrick(Pos_X,Pos_Y,CurrentBrick[0]);
}
ClearConnectedBrick();
}
}
return TRUE;
}
void DownOneBrick(int x, int y,int block)
{
int Scan_Y;
for (Scan_Y=y;Scan_Y < BOARD_HEIGHT+1;Scan_Y++)
{
if (Board[x][Scan_Y+1] >= WALL)
{
Board[x][Scan_Y] = block;
break;
}
else
{
gotoxy(MAP_START_X+x*2,MAP_START_Y+Scan_Y);
puts(arTile[EMPTY]);
gotoxy(MAP_START_X+x*2,MAP_START_Y+Scan_Y+1);
puts(arTile[block]);
}
}
}
void ClearOneBrick(int x, int y)
{
int scan_y;
for (scan_y = y;scan_y > 0;scan_y--) // Wall은 제외
{
if ((Board[x][scan_y-1] == WALL) || (Board[x][scan_y] == EMPTY))
break;
gotoxy(MAP_START_X+x*2,MAP_START_Y+scan_y);
puts(arTile[Board[x][scan_y-1]]);
Board[x][scan_y] = Board[x][scan_y-1];
delay(BRICK_CLEAR_INTERVAL);
}
}
int BrickConnectionStatus(int x, int y, int CheckBoard)
{
int Dir,BrickConnectedCount;
BrickConnectedCount = 0;
if ((Board[x][y] == CheckBoard) && BrickConnectedTable[x][y])
{
// 현 점에서 4방향으로 검색
for (Dir=0;Dir < NUM_OF_DIRECTION_TO_CHECK;Dir++)
{
if ((Board[x+Shape[Dir].x][y+Shape[Dir].y] == CheckBoard) &&
(BrickConnectedTable[x+Shape[Dir].x][y+Shape[Dir].y] == false))
{
// 신규로 연결 검사된 pixel만 계산
BrickConnectedCount++;
BrickConnectedTable[x+Shape[Dir].x][y+Shape[Dir].y] = true;
}
}
}
return(BrickConnectedCount);
}
void ClearConnectedBrick()
{
int i,j,scan_x,scan_y,MaxY,LineHeightCheckNeeded;
int Brick_Count_At_Column;
int BlockClearProgressed;
LineHeightCheckNeeded = true;
while (true)
{
if (LineHeightCheckNeeded)
{
for (i = 0;i < BOARD_WIDTH+2;i++)
{
Brick_Count_At_Column = 0;
for (j = BOARD_HEIGHT;j >= 0;j--)
{
BrickConnectedTable[i][j] = false;
if (Board[i][j] >= BRICK)
Brick_Count_At_Column++;
}
Column_Height[i] = Brick_Count_At_Column;
}
LineHeightCheckNeeded = false;
scan_x = 1;
scan_y = 1;
}
BlockClearProgressed = false;
if (Board[scan_x][scan_y] >= BRICK)
BlockClearProgressed = BlockedBrickProgress(scan_x,scan_y);
if (BlockClearProgressed)
LineHeightCheckNeeded = true;
else
{
scan_x++;
if (scan_x > BOARD_WIDTH+1)
{
scan_x = 1;
scan_y++;
if (scan_y > BOARD_HEIGHT+2)
break;
}
}
}
}
int BlockedBrickProgress(int scan_x, int scan_y)
{
int i,j,x,y,AllCount=0;
int CheckBoard,BrickConnectedCountInLine;
int temp_x,temp_y;
int BrickConnectedCount,BlockClearedStatus,BrickCountInBlock;
for (x = 0;x < BOARD_WIDTH+2;x++)
for (y = 0;y < BOARD_HEIGHT + 2;y++)
BrickConnectedTable[x][y] = false;
BrickConnectedTable[scan_x][scan_y] = true;
BlockClearedStatus = false;
CheckBoard = Board[scan_x][scan_y];
temp_y = scan_y;
// 라인별 Scan수행
while(true)
{
BrickConnectedCountInLine = 0;
// 우측 방향 SCAN
for (temp_x = scan_x;temp_x < BOARD_WIDTH+2;temp_x++)
{
BrickConnectedCount = BrickConnectionStatus(temp_x,temp_y,CheckBoard);
BrickConnectedCountInLine += BrickConnectedCount;
}
// 좌측 방향 SCAN
for (temp_x = scan_x-1;temp_x >= 0;temp_x--)
{
BrickConnectedCount = BrickConnectionStatus(temp_x,temp_y,CheckBoard);
BrickConnectedCountInLine += BrickConnectedCount;
}
if (BrickConnectedCountInLine == 0)
break;
// 다음행 검색 실행을 위한 라인 증가
temp_y++;
if (temp_y >= BOARD_HEIGHT+2)
break;
}
// 화면 전체에서 연결된 보드의 수 계산
BrickCountInBlock = 0;
for (y = 0; y < BOARD_HEIGHT+1;y++)
for (x = 0;x < BOARD_WIDTH+2;x++)
if (BrickConnectedTable[x][y])
BrickCountInBlock++;
if (BrickCountInBlock >= BRICK_COUNT_OF_CLEAR)
{
// 기본 4개 삭제되면 hit 1증가
BrickClearCount = BrickClearCount + 1;
// 4개보다 많이 삭제하면 combo수만큼 hit수 증가
if (BrickCountInBlock > BRICK_COUNT_OF_CLEAR)
BrickClearCount += (BrickCountInBlock - BRICK_COUNT_OF_CLEAR);
if (MAX_HIT_COUNT <= BrickClearCount)
BrickClearCount = MAX_HIT_COUNT;
BrickClearCountChanged = true;
}
// BRICK 제거 수행
if (BrickCountInBlock >= BRICK_COUNT_OF_CLEAR)
{
BlockClearedStatus = true;
for (j = 0; j < BOARD_HEIGHT+2;j++)
for (i = 0;i < BOARD_WIDTH+2;i++)
{
// BRICK Delete
if (BrickConnectedTable[i][j])
ClearOneBrick(i,j);
}
}
return(BlockClearedStatus);
}
'2009~2014 > C/C++' 카테고리의 다른 글
[C언어 프로젝트] 미니게임 모음 숫자-스피드산술 (0) | 2010.11.05 |
---|---|
[C언어 기출문제&풀이] 모듈러 인버스 (0) | 2010.11.05 |
[C언어 기출문제&풀이] 오버랩 (0) | 2010.11.04 |
[C언어 기출문제&풀이] 제출 (0) | 2010.11.04 |
[C언어 기출문제&풀이] what is n, Daddy? (0) | 2010.11.04 |