본문으로 바로가기

Day-17 MFC 이야기와 실습2

category Programming/TIPS 17기 2017. 8. 29. 17:20

 

 

카드 짝 맞추기 게임을 MFC를 이용해 만들어보자.

 

우선 이미지 파일을 C드라이브 및  temp 폴더에 넣어주자.

카드는 총 19장을 사용한다. 0~18번까지 19개의 숫자를 사용하고 0번은 뒷면이고 1~18번은 그림 이미지를 사용할 것이다.

또한 1~18번을 각 두장씩 뿌려서 같은 번호가 두 개씩 나오도록 해야한다. 카드를 섞을 때는 1~17번 까지 두번을 순서대로 뿌린 후 random하게 2개를 뽑아 자리를 바꾸는 행위를 반복해서 카드를 섞는다. 두 개의 같은 번호(같은 이미지)

 

WM_TIMER 메세지

 

우리가 보통 행위를 해야지 메세지를 받을 수 있는데 일정 시간마다 메시지를 받을 수 있도록 하는것이 TIMER이다. 일정 시간마다 WM_TIMER 메세지를 받는다. WM_TIMER가 싫다면 CALLBACK 함수를 사용하면 되지만 WM_TIMER 메세지를 처리하는것보다 훨씬 어렵다.

 

MFC 프로젝트를 만들어보자.

 

 

 

MFC 응용 프로그램을 선택하고 이름은 한글을 되도록 사용하지 말고 영어와 숫자 조합으로 사용하는 것이 좋다.

솔루션용 디렉터리 만들기를 선택하지 않으면 버그가 생길 수 있기 때문에 반드시 선택하자.

 

 

 

Default는 다중 문서가 선택되어 있지만 대화 상자 기반으로 선택하고, SDL 검사를 빼는 것이 좋다.

 

 

 

 

정보 상자를 빼고 다음을 누르자

 

 

 

고급 기능을 모두 빼고 다음을 누르자.

 

 

 

App, Dlg 파일이 있으면 마침을 눌러 최종적으로 프로젝트를 생성하자.

 

 

MFC 응용 프로그램 생성 후 글꼴을 굴림으로 바꾸자.

 

ExamCard1.cpp 소스 파일에 가서 최소한의 코드만 남긴 후 지워주자.

 

 

위와 같은 소스가 최소한의 소스이다.

 

우선 ExamCard1.h 파일로 이동해 사용할 카드 이미지를 저장할 클래스를 선언하자.

 

 

 

카드의 이미지 파일의 이름은 00x.bmp 이다. 카드는 총 19개가 있으니 000.bmp ~ 019.bmp 까지 총 19개의 이미지 파일이 있다.

CString 클래스는 문자열에 관한 기능을 많이 가지고 있어 초보자들이 사용하기 좋지만 무겁고 느린 클래스이다.

 

 

위와 같이 사용할 수 있다.

str 클래스 내부에서 "abc"를 저장할 수 있는 크기를 동적 할당한 후에 "abc"를 복사해서 저장한다.

printf와 똑같은 형식으로 사용할 수 있다. L은 유니코드를 사용하겠다는 것이다. CString 클래스에 내부적으로 5가 저장된다.

 

이번에는 이미지를 저장하는 소스코드를 작성할 것이다. 이미지는 c:\\temp에 저장을 할 것이다. m_card_list 배열에 각각의 이미지를 로드한다.

 

 

 

m_card_list 배열에 19개의 이미지가 저장되어 있다. 19개의 이미지를 화면에 출력해보자.

(10, 10) 부터 시작하여 20씩 이동하면서 카드를 화면에 나타내보자.

 

 

 

위와 같이 this 포인터를 이용해 카드를 그리면 된다. 위와 같이 작성하고 빌드 후 디버깅을 시작하면 아래와 같이 겹쳐서 아래와 같이 나온다.

 

 

 

 

이제 본격적으로 게임을 만들어보자. 카드를 화면에 출력해 보았으니 게임할 틀을 만들자.

게임할 틀은 위에서 말했들이 18X18 형태이다. 따라서 헤더파일에 게임 틀을 만들 배열을 선언하자.

 

 

 

 

짝 맞추기 게임을 하려면 같은 숫자가 두 개씩 있어야 한다. % 연산자를 보다 쉽게 같은 숫자를 두 개씩 사용할 수 있다.

 

 

 

또한 srand 함수를 이용해 난수를 발생해보자. rand 함수도 난수를 발생시키는 함수이다. 하지만 rand 함수는 난수가 고정되어 발생해 반복되어 게임이 무작위로 섞이지 않고 같은 순서로 바뀐다. 난수 발생의 조건을 바꾸기 위해서 srand 함수를 사용한다. seed가 같으면 난수가 동일하게 나와서 seed 값을 바꾸어줘야 하는데 time 함수는 매 초 늘어나고 있기 때문에 난수가 무작위로 발생한다.

 

 

카드의 가로는 36, 세로는 56이다. 한 줄에 6개씩 6줄을 만들어야 한다. 6칸, 6줄을 만들기 위해서 % 연산자와 / 연산자를 사용한다.

0번은 뒷면이기 때문에 m_game_table[i] + 1을 하여 0번이 아닌 1번부터 나오도록 한다.

 

 

위와 같이 수정을 한 뒤 빌드 후 디버깅을 하자.

 

 

 

위와 같이 나오면 된다. 이번에는 카드를 테이블 형태로 화면에 출력을 했으니 카드를 섞는 작업을 해보자. 카드를 섞는 방법에는 여러가지 방법이 있지만 우리는 카드를 순서대로 배열하고 무작위로 두개의 카드를 뽑아서 위치를 바꾸는 작업을 반복해서 카드를 섞을 것이다. 카드 두개를 섞을 때 확률적으로 같은 이미지가 나올 수 있지만 확률적으로 매우 낮고 if문을 사용할 경우 효율성이 떨어지기 때문에 반복 과정을 늘려서 사용하는 것이 좋다.

 

 

 

 

위와 같이 작성하면 무작위로 섞을 수 있다. 빌드 후 디버깅을 하면 아래와 같이 잘 섞이는 것을 알 수 있다.

 

 

 

 

이제 게임을 시작하기 위해 처음 3초만 카드를 보여주고 뒷면으로 바꾸는 작업을 해야한다. SetTimer() 함수를 사용해서 처리해보자.

 

 

 

SetTimer() 함수를 호출하고 난 후 클래스 마법사를 이용해서

 

 

 

 

이후에 타이머 메세지가 왔을 때 처리하는 코드를 작성해주자.

 

 

 

 

카드의 앞면인지 뒷면인지 구분할 필요가 잇다.따라서 구분해줄 수 있는 변수를 선언하자.

 

 

 

flag가 0이면 뒷면을 그려주고 0이 아니면 이미지를 그려주는 소스이다.

 

 

WM_TIMER 메세지가 들어오면 flag=0을 대입해 모두 뒷면으로 만들어주는 소스이다.

 

 

위와 같이 소스를 입력하고 빌드후 디버깅 해보면 아래와 같이 앞면이 보이고 3초뒤 뒷면으로 바뀐다.

 

 

이제 게임의 준비가 끝났다. 하지만 카드를 클릭해도 아무런 변화가 나타나지 않는다. 카드가 클릭될 때 카드가 뒤집히고 같은 카드를 선택했을 때 사라지도록 소스코드를 수정해보자. 클래스 마법사를 이용해 클래스를 추가하자.

 

 

 

 

마우스가 클릭되는 위치를 계산해보자. 이미지 카드의 가로와 세로를 이용해서 소스코드를 작성하자.

 

 

 

위와 같이 소스코드를 작성하면 클릭한 카드가 뒷면에서 앞면으로 바뀌면서 이미지가 그려진다. 빌드 후 디버깅해보자.

 

 

하지만 같은 카드를 선택해도 사라지지 않고 2개 이상 여러개의 카드를 선택할 수 있다. 2개의 카드만 선택할 수 있도록 소스코드를 수정하자.

카드가 처음 선택되었는지 아닌지 확인하기 위해 새로운 변수를 선언해준다.

 

 

변수를 선언하고 카드가 2개를 선택하고 2개의 카드가 같으면 사라지게 소스코드를 작성하자.

 

 

 

같은 위치를 두번 두르는것도 사라지는 경우가 발생한다. 왜냐하면 같은 카드를 누르는 것도 같은 숫자를 고르는것이기 때문이다.

아래와 같이 같은 카드를 두번 누르는 곳을 방지하자.

 

 

 

 

위의 소스 코드는 동시에 여러개를 누르는 것이 가능하다.  두 개의 이미지가 눌리지 않도록 소스코드를 수정하자.

 

 

여기까지 소스코드를 작성하면 기본적인 카드 맞추기 게임이 만들어진다. 빌드 후 디버깅하면 아래와 같이 실행된다.

 

 

 

위와 같이 실행이 잘 될 것이다. 이 상태로 끝내도 재미있지만 힌트 기능이 있었으면 좋겠다는 생각이 든다. 따라서 버튼을 누르면 모든 이미지가 뒷면에서 앞면으로 바뀌는 버튼을 추가해보자.

 

 

button을 드래그해서 윈도우 창에 올리자. button1을 클릭한 후 속성을 클릭해 caption을 3으로 바꾸어주자.

 

 

이제 3 버튼을 더블 클릭하면 ExamCard1Dlg.cpp 파일의 제일 밑에 오버라이딩 된다. 여기서 3을 누르면 2초동안 이미지를 보여주고 3을 2로 바꾸는 과정을 하는 소스를 작성해보자.

 

 

위와 같이 소스를 작성하고 3을 누르면 2로 바뀌고 2를 누르면 1로 바뀌는 것을 알 수 있다.

 

 

 

전체 소스 코드를 적으면 아래와 같다.

 

ExamCard1Dlg.h

 

 

 

ExamCard1Dlg.cpp

 

 

 

ExamCard1.cpp

 

 

 

'Programming > TIPS 17기' 카테고리의 다른 글

Day-16 MFC이야기와 실습1  (0) 2017.08.20
Day-15 Win32 API 이야기와 실습2  (0) 2017.08.17
Day-14 Win32 API 이야가와 실습1  (0) 2017.08.15
Day-13 C++ 이야기3  (0) 2017.08.14
Day-12 C++ 이야기2  (0) 2017.08.11