/* mine.c: 지뢰찾기 소스 파�(TUI)
종류: win32 console program
언어: C
ì œìž‘ìž�: 윤종하
ì œìž‘ 시작ì�¼: 2010ë…„ 12ì›” 24ì�¼
1차 종료�: 2010년 12월 29�*/
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<conio.h>
#include<windows.h>
#define TRUE 1
#define FALSE 0
//#define NO_STATE 3
typedef struct cell//1개 셀� �함� ��터� 구조체
{
int iIsRevealed;
int iIsMine;
int iNumOfMine;//주변� 있는 지뢰� 개수
int iIsUnknown;
int iIsFined;
}CELL;
COORD* make_mine_map(CELL** map,COORD size,int iNumOfMine);
void print_map(CELL** map,COORD size,int iNumOfMine,int iCurrentFindedMine);
int click_cell(CELL** map,COORD size,int *iNumOfLeftCell);
void one_right_click_cell(CELL** map,COORD size,COORD *cPosOfMine,int iNumOfMine,int *iFindedRealMine);
void double_right_click_cell(CELL** map,COORD size);
void find_mine(CELL** map,COORD size,COORD pos,int *iNumOfLeftCell);
void count_time(int iSecond);
void print_one_cell(CELL** map,int xpos,int ypos,int mine);
COORD coord_input(COORD size);
void initialize_cell(CELL *input);
int search_mine(int iNumOfMine,COORD* real_mine_cell,COORD target_cell);
int main(int argc,char* argv[])
{
CELL **map;
COORD size;
COORD *cPosOfMine;
int iNumOfMine,iCurrentFindedMine=0,iNumOfLeftCell,iIsAlive=TRUE,tempX,tempY,iFindedRealMine=0,i,j;
time_t tStartTime,tEndTime;
char cSelect;
/*ê±� 멋있으ë�¼ê³ 한 시작화면*/
for(i=0;i<5;i++) printf("*****************************************************************************\n");
printf("********** **********\n");
printf("********** **********\n");
printf("********** **********\n");
printf("********** 지뢰찾기 **********\n");
printf("********** **********\n");
printf("********** **********\n");
printf("********** **********\n");
printf("********** **********\n");
printf("********** í�¬ë¦¬ìŠ¤ë§ˆìŠ¤ì—� í• ê±° 없어서 만듦*********\n");
for(i=0;i<5;i++) printf("\*****************************************************************************\n");
/*map 작성 시작*/
if(argc==4){//argument로ì�˜ 맵사ì�´ì¦ˆ ìž…ë ¥ì�´ 있ì�„ 경우
size.X=(short)atoi(argv[1]);
size.Y=(short)atoi(argv[2]);
}
else{//argument로ì�˜ ìž…ë ¥ì�´ ì—†ì�„ 경우
printf("ë§µì�˜ 사ì�´ì¦ˆë¥¼ ìž…ë ¥í•˜ì„¸ìš”(가로 세로): ");
scanf("%d %d",&tempX,&tempY);
size.X=tempX;
size.Y=tempY;
}
map=(CELL**)malloc(sizeof(CELL)*size.Y);//1ì°¨ë�™ì �í• ë‹¹
for(i=0;i<size.Y;i++){
map[i]=(CELL*)malloc(sizeof(CELL)*size.X);//2ì°¨ë�™ì �í• ë‹¹
for(j=0;j<size.X;j++) initialize_cell(&map[i][j]);//초기화 시킴
}
if(argc==4) iNumOfMine=atoi(argv[3]);////argument로ì�˜ 지뢰 개수 ìž…ë ¥ì�´ 있ì�„ 경우
else{
printf("지뢰ì�˜ 개수를 ìž…ë ¥í•˜ì„¸ìš”: ");
scanf("%d",&iNumOfMine);
}
cPosOfMine=make_mine_map(map,size,iNumOfMine);
iNumOfLeftCell=size.X*size.Y;
printf("ìž…ë ¥í•œ ë�°ì�´í„°ì—� 따른 ë§µ ë°� ë�°ì�´í„°ì�˜ 세팅ì�´ 성공ì �으로 완료ë��습니다.\n3ì´ˆ 후 게임ì�´ 시작ë�©ë‹ˆë‹¤.\n");
count_time(3);
//system("pause");
/*게임� 위한 루프 시작*/
time(&tStartTime);//시작시간 ì €ìž¥
do{
print_map(map,size,iNumOfMine,iCurrentFindedMine);
printf("ìˆ˜í–‰í• ìž‘ì—…ì�„ ì„ íƒ�하세요\na: 누르기\ts: 지뢰가 확실히 있ì�Œ\td: 여기는 ë�ê°€ë”ì§€ ëª¨ë¥´ê² ì�Œ\tq: 종료");
cSelect=getch();
fflush(stdin);
cSelect=tolower(cSelect);
switch(cSelect){
case 'a':
iIsAlive=click_cell(map,size,&iNumOfLeftCell);
if(iIsAlive==FALSE){
printf("지뢰가 í�발했습니다\n");
system("pause");//위� 문장� �어야�니까
}
break;
case 's':
one_right_click_cell(map,size,cPosOfMine,iNumOfMine,&iFindedRealMine);
iCurrentFindedMine++;
break;
case 'd':
double_right_click_cell(map,size);
break;
case 'q':
for(i=0;i<size.Y;i++) free(map[i]);//2ì°¨ ë�™ì �í• ë‹¹ í•´ì œ 완료
free(map);
free(cPosOfMine);
printf("게임ì�„ 종료합니다.\nì œìž‘: í�¬ë¦¬ìŠ¤ë§ˆìŠ¤ì—� í• ê²Œ 없었다니까\n");
system("pause");
exit(0);
break;
default:
printf("잘못ë�œ ìž…ë ¥ìž…ë‹ˆë‹¤.");
}
}while(iNumOfLeftCell>iNumOfMine && iIsAlive==TRUE && iFindedRealMine!=iNumOfMine);
time(&tEndTime);//종료시간 ì €ìž¥
free(cPosOfMine);
/*승패 알림 메시지 ì¶œë ¥*/
system("cls");
if(iIsAlive==TRUE) printf("축하합니다! ë‹¹ì‹ ì�´ 승리했습니다.\a\a\a\n");
else if(iIsAlive==FALSE) printf("ë‹¹ì‹ ì�´ 졌습니다.\a\a\n");
else printf("Unproteted error is occured!\a");
/*ëª¨ë“ ì§€ë¢°ì�˜ 위치 ì¶œë ¥*/
for(i=0;i<size.Y;i++){
for(j=0;j<size.X;j++) print_one_cell(map,j,i,TRUE);
free(map[i]);//2ì°¨ ë�™ì �í• ë‹¹ í•´ì œ
Sleep(500);
printf("\n");
}
free(map);//1ì°¨ ë�™ì �í• ë‹¹ í•´ì œ
printf("소요시간: %ldsec.\n",tEndTime-tStartTime);//소요시간 ì¶œë ¥
printf("2010ë…„ í�¬ë¦¬ìŠ¤ë§ˆìŠ¤ì—� í• ê±° 없어서 만듦\n");
system("pause");
return 0;
}
COORD* make_mine_map(CELL **map,COORD size,int iNumOfMine)
{
int i,j;
static COORD *pos_data;
//FILE *txtForDebug=fopen("mine_pos.txt","w");
srand(time(NULL));
pos_data=(COORD*)malloc(sizeof(COORD)*iNumOfMine);//지뢰 개수만í�¼ ë�™ì �í• ë‹¹
/*지뢰좌표 �성*/
for(i=0;i<iNumOfMine;){
pos_data[i].X=rand()%size.X;
pos_data[i].Y=rand()%size.Y;
/*중복 좌표 검사*/
for(j=0;j<i;j++) if(pos_data[i].X==pos_data[j].X && pos_data[i].Y==pos_data[j].Y) continue;//중복 좌표가 �기면 재�성
i++;
}
/*ë§µì—� 지뢰좌표 ìž…ë ¥ ë°� 디버깅용 파ì�¼ ì¶œë ¥*/
for(i=0;i<iNumOfMine;i++){
//printf("%d: %d %d\n",i,pos_data[i].X,pos_data[i].Y);
map[pos_data[i].Y][pos_data[i].X].iIsMine=TRUE;
//fprintf(txtForDebug,"%d: %d %d\n",i,(int)pos_data[i].X,(int)pos_data[i].Y);
}
//system("pause");
return pos_data;
}
void print_map(CELL **map,COORD size,int iNumOfMine,int iCurrentFindedMine)
{
int xIndex,yIndex;
system("cls");
for(yIndex=-1;yIndex<size.Y;yIndex++){
for(xIndex=-1;xIndex<size.X;xIndex++){
if(yIndex==-1){
if(xIndex==-1) printf(" ");
else printf("%d ",xIndex);
}
else if(xIndex==-1) printf("%d",yIndex);
else{
print_one_cell(map,xIndex,yIndex,FALSE);
}
}
printf("\n");
}
printf("남� 지뢰� 개수: %d\n",iNumOfMine-iCurrentFindedMine);
}
int click_cell(CELL** map,COORD size,int *iNumOfLeftCell)
{
COORD input=coord_input(size);
if(map[input.Y][input.X].iIsRevealed==TRUE) return TRUE;//ì�´ë¯¸ ê¹� 것ì�„ ëˆŒë €ì�„ 경우
else if(map[input.Y][input.X].iIsMine==TRUE) return FALSE;//지뢰를 ëˆŒë €ì�„ 경우
else find_mine(map,size,input,&(*iNumOfLeftCell));
return TRUE;
}
void one_right_click_cell(CELL **map,COORD size,COORD *cPosOfMine,int iNumOfMine,int *iFindedRealMine)
{
COORD input=coord_input(size);
if(map[input.Y][input.X].iIsRevealed==TRUE) return;//ì�´ë¯¸ ê¹� 것ì�„ ëˆŒë €ì�„ 경우
else{
if(map[input.Y][input.X].iIsFined==TRUE) map[input.Y][input.X].iIsFined=FALSE;
else map[input.Y][input.X].iIsFined=TRUE;
}
if(search_mine(iNumOfMine,cPosOfMine,input)==TRUE) (*iFindedRealMine)++;
}
void double_right_click_cell(CELL **map,COORD size)
{
COORD input=coord_input(size);
if(map[input.Y][input.X].iIsRevealed==TRUE) return;//ì�´ë¯¸ ê¹� 것ì�„ ëˆŒë €ì�„ 경우
else{
if(map[input.Y][input.X].iIsUnknown==FALSE) map[input.Y][input.X].iIsUnknown=TRUE;
else map[input.Y][input.X].iIsUnknown=FALSE;
}
}
void find_mine(CELL **map,COORD size,COORD pos,int *iNumOfLeftCell)
{
int iNumOfMine=0,coordX,coordY;
COORD temp_pos=pos;
if(map[pos.Y][pos.X].iIsMine==TRUE) return;//만약 지뢰�면 검사 종료
map[pos.Y][pos.X].iIsRevealed=TRUE;//까줌
(*iNumOfLeftCell)--;
for(coordY=-1;coordY<=1;coordY++){
for(coordX=-1;coordX<=1;coordX++){
temp_pos=pos;
if(coordX==0 && coordY==0) continue;//기존 위치� 있는 ��터를 참조했� 때
temp_pos.X=pos.X+coordX; temp_pos.Y=pos.Y+coordY;
if((temp_pos.X>size.X-1 || temp_pos.X<0) || (temp_pos.Y>size.Y-1 || temp_pos.Y<0)) continue;//범위를 초과했� 경우
else if(map[temp_pos.Y][temp_pos.X].iIsRevealed==TRUE) continue;//�미 � 것� 경우
else if(map[temp_pos.Y][temp_pos.X].iIsMine==TRUE) iNumOfMine++;
}
}
map[pos.Y][pos.X].iNumOfMine=iNumOfMine;//주변 지뢰ì�˜ 개수 ì €ìž¥
if(map[pos.Y][pos.X].iNumOfMine!=0) return;//지뢰� 개수가 0개가 아니면 �
else{//주변� ��터 �색시작
for(coordY=-1;coordY<=1;coordY++){
for(coordX=-1;coordX<=1;coordX++){
temp_pos=pos;
temp_pos.X+=coordX; temp_pos.Y+=coordY;
if((temp_pos.X>size.X-1 || temp_pos.X<0) || (temp_pos.Y>size.Y-1 || temp_pos.Y<0)) continue;//범위를 초과했� 경우
if(coordX==0 && coordY==0) continue;//기존 위치를 참조했� 경우. 지우면 stack overflow� 향연
if(map[temp_pos.Y][temp_pos.X].iIsRevealed==TRUE) continue;//ì—´ë ¤ìžˆì�„ 경우는 ê²€ì‚¬í• í•„ìš”ê°€ 없잖아
find_mine(map,size,temp_pos,&(*iNumOfLeftCell));
}
}
}
}
void count_time(int iSecond)
{
for(;iSecond>0;iSecond--){
printf("%d\a ",iSecond);
Sleep(1000);
}
printf("%d\a\n",iSecond);
}
void print_one_cell(CELL **map,int xpos,int ypos,int mine)
{
if(map[ypos][xpos].iIsRevealed==TRUE){
if(mine==TRUE && map[ypos][xpos].iIsMine==TRUE) printf(" *");
else if(map[ypos][xpos].iNumOfMine==0) printf("â–¡");
else printf(" %d",map[ypos][xpos].iNumOfMine);
}
else{
if(map[ypos][xpos].iIsFined==TRUE) printf(" m");
else if(map[ypos][xpos].iIsUnknown==TRUE) printf(" ?");
else if(mine==TRUE && map[ypos][xpos].iIsMine) printf(" *");
else printf("â– ");
}
}
COORD coord_input(COORD size)
{
COORD temp;
int tempX,tempY;
printf("좌표를 ìž…ë ¥í•˜ì„¸ìš”(x y): ");
scanf("%d %d",&tempX,&tempY);
temp.X=(short)tempX;
temp.Y=(short)tempY;
while(temp.X<0 || temp.X>size.X-1 || temp.Y<0 || temp.Y>size.Y-1){
printf("좌표 ìž…ë ¥ì�´ 잘못ë��습니다. 다시 ìž…ë ¥í•˜ì„¸ìš”.\n좌표를 ìž…ë ¥í•˜ì„¸ìš”(x y): ");
scanf("%d %d",&tempX,&tempY);
temp.X=(short)tempX;
temp.Y=(short)tempY;
}
return temp;
}
void initialize_cell(CELL *input)
{
input->iIsFined=FALSE;
input->iIsMine=FALSE;
input->iIsRevealed=FALSE;
input->iIsUnknown=FALSE;
}
int search_mine(int iNumOfMine,COORD *real_mine_cell,COORD target_cell)
{
int i;
for(i=0;i<iNumOfMine;i++) if(real_mine_cell[i].X==target_cell.X && real_mine_cell[i].Y==target_cell.Y) return TRUE;
return FALSE;
}
작년 í�¬ë¦¬ìŠ¤ë§ˆìŠ¤ì—� í• ê²Œ 없어서 모태솔로잉여프로ì �트로 지뢰찾기를 ì œìž‘í•´ë´¤ìŠµë‹ˆë‹¤.
콘솔 프로그램으로 열심히 짜봤구요, �주코딩� 위대함� 깨달았습니다.
콘솔 프로그램으로 열심히 짜봤구요, �주코딩� 위대함� 깨달았습니다.
ê·¼ë�° 버그가 넘ì³�나는거 같아요 ã…










