/*
-----------------------------------------------------------------------------------
프로그램을 작성하는 첫 단계는 이 프로그램이 사용할 자료 구조를 설계하는 것이다.
표현하고자 하는 정보를 가장 효율적으로 저장하고 관리할 수 있는 자료 구조를 선택해야
알고리즘이 간단해지고 구조가 튼튼해진다. 반면 자료 구조를 잘못 선택하면 알고리즘이
복잡해지고 구조가 지저분해져서 오류가 많아지고 확장하기도 어려워진다.
소스를 분석하는 첫 단계는 프로그램 전반에 걸쳐 영향력을 행사하는 전역 변수를
분석하는 것이며 전역 변수가 적을수록 분석하기 쉬워진다.
짝찾기 게임의 게임판은 4*4의 칸(전부 16개)에 숫자들이 숨어 있으므로 각 칸에
어떤 숫자가 숨겨져 있는지를 저장해야 한다. 게임판이 4*4의 평면으로 이루어져
있고 각 칸에는 정수형 숫자가 저장되므로 필요한 자료 구조는 가로 세로 크기가
모두 4인 2차 정수형 배열이다. 모든 숫자는 일단 ?로 표시되며 짝을 찾으면
더 이상 ?가 아닌 숫자를 보여 주어야 한다. 그래서 각 칸의 상태, 즉 아직도
꼭꼭 숨어 있는지, 아니면 사용자에게 이미 들켰는지를 기억할 공간이 필요하다.
모든 칸이 이 정보를 유지해야 하며 각 칸의 상태는 둘 중 하나이므로 BOOL형의
2차 배열이면 된다. 그래서 이 프로그램은 두 개의 전역 배열을 선언하고 있다.
-----------------------------------------------------------------------------------
arFlip 배열은 각 칸의 현재 상태를 기억하는데 사용자가 찾은 칸은 TRUE가 되고
아직 찾지 못한 칸은 FALSE값을 가진다. 게임 시작 직후에는 모든 칸이 아직 숨어
있는 상태이므로 arFlip 배열의 모든 요소는 FALSE로 초기화되어야 한다.
그래서 게임 시작 직후 이 두 배열은 다음과 같이 초기화될 것이다.
arNum
01|02|03|04
-----------
05|06|07|08
-----------
09|10|11|12
-----------
13|14|15|16
arFlip
T|F|T|T
-------
T|F|T|T
-------
T|F|T|T
-------
T|F|T|T
*/
#include <Turboc.h>
//
// 키보드 아스키 코드 값
//
#define LEFT 75
#define RIGHT 77
#define UP 72
#define DOWN 80
#define ESC 27
#define IDX(x,y) ((y)*4+(x)) // 2차원 카테고리를 1차원 형태로 변경해준다.
#define DELAYTIME 5000
// 00 : 0
// 01 : 1
// 02 : 2
// 03 : 3
// 10 : 4
// 11 : 5
// 12 : 6
// 13 : 7
// 20 : 8
// 21 : 9
// 22 : 10
// 23 : 11
int arNum[4][4];
BOOL arFlip[4][4];
int nx,ny;
int open1,open2;
int count;
int remain;
void InitGame();
void DrawScreen(BOOL bHint);
void main()
{
int ch;
randomize();
InitGame();
for (;;)
{
gotoxy(nx*5+2,ny*3+2); // 포인터 이동
ch=getch(); // 문자 캐릭터 하나 받기
if (ch == 0xE0)
{
ch=getch();
switch (ch)
{
case LEFT:
if (nx > 0) nx--;
break;
case RIGHT:
if (nx < 3) nx++;
break;
case UP:
if (ny > 0) ny--;
break;
case DOWN:
if (ny < 3) ny++;
break;
}
}
else
{
switch (ch)
{
case ESC: exit(0); break;
case ' ': // spacebar
if (arFlip[nx][ny] == FALSE && open1 != IDX(nx,ny))
{
if (open1 == -1)
{
open1=IDX(nx,ny);
}
else
{
count++;
if (arNum[open1%4][open1/4] == arNum[nx][ny])
{
putch('\a'); // BEEP
arFlip[open1%4][open1/4]=TRUE;
arFlip[nx][ny]=TRUE;
remain-=2;
if (remain == 0)
{
DrawScreen(FALSE);
gotoxy(26,22);puts("축하합니다. 다시 시작합니다.");
delay(DELAYTIME);
InitGame();
}
}
else
{
open2=IDX(nx,ny);
DrawScreen(FALSE);
delay(1000);
}
open1=open2=-1;
}
DrawScreen(FALSE);
}
break;
}
}
}
}
void InitGame()
{
int i,j;
int x,y;
nx=ny=0; // 전역변수
open1=open2=-1;
count=0;
remain=16;
//
// 변수 초기화
//
for (i=0;i<4;i++)
{
for (j=0;j<4;j++)
{
arNum[i][j]=0;
arFlip[i][j]=FALSE;
}
}
for (i=1;i<=8;i++) // 1~8 까지
{
for (j=0;j<2;j++) // 같은 숫자가 2개
{
do
{
x=random(4); // range 0~4
y=random(4);
}
while (arNum[x][y] != 0); // 해당 2차원 배열 내에 없을때
arNum[x][y]=i;
}
}
DrawScreen(TRUE); // 힌트
delay(DELAYTIME);
clrscr();
DrawScreen(FALSE);
}
void DrawScreen(BOOL bHint)
{
int x,y;
for (x=0;x<4;x++)
{
for (y=0;y<4;y++)
{
gotoxy(x*5+2,y*3+2);
if (bHint == TRUE || arFlip[x][y])
{
gotoxy(wherex()-1,wherey());
printf("[%d]",arNum[x][y]);
}
else if (open1 == IDX(x,y) || open2 == IDX(x,y))
{
printf("%d",arNum[x][y]);
}
else
{
printf("?");
}
}
}
gotoxy(30,2);puts("짝 맞추기 게임 Ver 1.0");
gotoxy(30,4);puts("커서키:이동. 공백:뒤집기. Esc:종료");
gotoxy(30,6);printf("총 시도 회수 : %d",count);
gotoxy(30,8);printf("아직 못 찾은 것 : %d ",remain);
}
-----------------------------------------------------------------------------------
프로그램을 작성하는 첫 단계는 이 프로그램이 사용할 자료 구조를 설계하는 것이다.
표현하고자 하는 정보를 가장 효율적으로 저장하고 관리할 수 있는 자료 구조를 선택해야
알고리즘이 간단해지고 구조가 튼튼해진다. 반면 자료 구조를 잘못 선택하면 알고리즘이
복잡해지고 구조가 지저분해져서 오류가 많아지고 확장하기도 어려워진다.
소스를 분석하는 첫 단계는 프로그램 전반에 걸쳐 영향력을 행사하는 전역 변수를
분석하는 것이며 전역 변수가 적을수록 분석하기 쉬워진다.
짝찾기 게임의 게임판은 4*4의 칸(전부 16개)에 숫자들이 숨어 있으므로 각 칸에
어떤 숫자가 숨겨져 있는지를 저장해야 한다. 게임판이 4*4의 평면으로 이루어져
있고 각 칸에는 정수형 숫자가 저장되므로 필요한 자료 구조는 가로 세로 크기가
모두 4인 2차 정수형 배열이다. 모든 숫자는 일단 ?로 표시되며 짝을 찾으면
더 이상 ?가 아닌 숫자를 보여 주어야 한다. 그래서 각 칸의 상태, 즉 아직도
꼭꼭 숨어 있는지, 아니면 사용자에게 이미 들켰는지를 기억할 공간이 필요하다.
모든 칸이 이 정보를 유지해야 하며 각 칸의 상태는 둘 중 하나이므로 BOOL형의
2차 배열이면 된다. 그래서 이 프로그램은 두 개의 전역 배열을 선언하고 있다.
-----------------------------------------------------------------------------------
arFlip 배열은 각 칸의 현재 상태를 기억하는데 사용자가 찾은 칸은 TRUE가 되고
아직 찾지 못한 칸은 FALSE값을 가진다. 게임 시작 직후에는 모든 칸이 아직 숨어
있는 상태이므로 arFlip 배열의 모든 요소는 FALSE로 초기화되어야 한다.
그래서 게임 시작 직후 이 두 배열은 다음과 같이 초기화될 것이다.
arNum
01|02|03|04
-----------
05|06|07|08
-----------
09|10|11|12
-----------
13|14|15|16
arFlip
T|F|T|T
-------
T|F|T|T
-------
T|F|T|T
-------
T|F|T|T
*/
#include <Turboc.h>
//
// 키보드 아스키 코드 값
//
#define LEFT 75
#define RIGHT 77
#define UP 72
#define DOWN 80
#define ESC 27
#define IDX(x,y) ((y)*4+(x)) // 2차원 카테고리를 1차원 형태로 변경해준다.
#define DELAYTIME 5000
// 00 : 0
// 01 : 1
// 02 : 2
// 03 : 3
// 10 : 4
// 11 : 5
// 12 : 6
// 13 : 7
// 20 : 8
// 21 : 9
// 22 : 10
// 23 : 11
int arNum[4][4];
BOOL arFlip[4][4];
int nx,ny;
int open1,open2;
int count;
int remain;
void InitGame();
void DrawScreen(BOOL bHint);
void main()
{
int ch;
randomize();
InitGame();
for (;;)
{
gotoxy(nx*5+2,ny*3+2); // 포인터 이동
ch=getch(); // 문자 캐릭터 하나 받기
if (ch == 0xE0)
{
ch=getch();
switch (ch)
{
case LEFT:
if (nx > 0) nx--;
break;
case RIGHT:
if (nx < 3) nx++;
break;
case UP:
if (ny > 0) ny--;
break;
case DOWN:
if (ny < 3) ny++;
break;
}
}
else
{
switch (ch)
{
case ESC: exit(0); break;
case ' ': // spacebar
if (arFlip[nx][ny] == FALSE && open1 != IDX(nx,ny))
{
if (open1 == -1)
{
open1=IDX(nx,ny);
}
else
{
count++;
if (arNum[open1%4][open1/4] == arNum[nx][ny])
{
putch('\a'); // BEEP
arFlip[open1%4][open1/4]=TRUE;
arFlip[nx][ny]=TRUE;
remain-=2;
if (remain == 0)
{
DrawScreen(FALSE);
gotoxy(26,22);puts("축하합니다. 다시 시작합니다.");
delay(DELAYTIME);
InitGame();
}
}
else
{
open2=IDX(nx,ny);
DrawScreen(FALSE);
delay(1000);
}
open1=open2=-1;
}
DrawScreen(FALSE);
}
break;
}
}
}
}
void InitGame()
{
int i,j;
int x,y;
nx=ny=0; // 전역변수
open1=open2=-1;
count=0;
remain=16;
//
// 변수 초기화
//
for (i=0;i<4;i++)
{
for (j=0;j<4;j++)
{
arNum[i][j]=0;
arFlip[i][j]=FALSE;
}
}
for (i=1;i<=8;i++) // 1~8 까지
{
for (j=0;j<2;j++) // 같은 숫자가 2개
{
do
{
x=random(4); // range 0~4
y=random(4);
}
while (arNum[x][y] != 0); // 해당 2차원 배열 내에 없을때
arNum[x][y]=i;
}
}
DrawScreen(TRUE); // 힌트
delay(DELAYTIME);
clrscr();
DrawScreen(FALSE);
}
void DrawScreen(BOOL bHint)
{
int x,y;
for (x=0;x<4;x++)
{
for (y=0;y<4;y++)
{
gotoxy(x*5+2,y*3+2);
if (bHint == TRUE || arFlip[x][y])
{
gotoxy(wherex()-1,wherey());
printf("[%d]",arNum[x][y]);
}
else if (open1 == IDX(x,y) || open2 == IDX(x,y))
{
printf("%d",arNum[x][y]);
}
else
{
printf("?");
}
}
}
gotoxy(30,2);puts("짝 맞추기 게임 Ver 1.0");
gotoxy(30,4);puts("커서키:이동. 공백:뒤집기. Esc:종료");
gotoxy(30,6);printf("총 시도 회수 : %d",count);
gotoxy(30,8);printf("아직 못 찾은 것 : %d ",remain);
}
'Native > C' 카테고리의 다른 글
file lock (파일 사용시 다른 엑서스 불가능 하게 하기) (0) | 2013.10.02 |
---|---|
file lock (파일 사용시 다른 엑서스 불가능 하게 하기) (0) | 2013.10.02 |
내일을 구하는 예제 (0) | 2013.10.02 |
md5 (0) | 2013.10.02 |
3-2.입출력 (0) | 2013.10.02 |