플레이어의 빙고 테이블 객체 AnimalBingo_player를 만들고
빙고 데이터를 직접 입력하여 삽입하였습니다.
이후 CPU의 빙고 테이블 객체도 만들었죠.
CPU의 빙고 테이블 객체를 생성하는 과정은 플레이어 빙고 테이블 객체를
생성하는 과정과 다르지 않지만, 데이터를 삽입하는 과정은 조금 차이가 있었습니다.
CPU의 빙고 데이터는 이미 존재하는 파일을 읽어 데이터를 삽입하였죠.
이제 CPU와 플레이어가 돌아가면서 빙고 데이터를 하나씩
오픈할 것이고 먼저 3개의 빙고를 완성하는 쪽이 승리하도록 할 겁니다.
두 빙고 테이블을 비교하는 구문은 아래 코드에서

36번째 줄에서 시작됩니다.
VictoryCheck 함수가 가장 먼저 실행되겠네요.
VictoryCheck 함수의 동작을 살펴 봅시다.

해당 함수는 CPU 빙고 테이블 객체를 레퍼런스로 참조합니다.
플레이어가 먼저 3개 이상의 빙고를 완성했다면 enum 클래스인 RESULT의
PLAYER_WIN에 해당하는 값을 반환하고,
CPU가 먼저 3개 이상의 빙고를 완성했다면 enum 클래스인 RESULT의
CPU_WIN에 해당하는 값을 반환하고,
동시에 3개 이상의 빙고를 완성했다면 enum 클래스인 RESULT의
DRAW에 해당하는 값을 반환합니다.

어느 쪽이 먼저 3개 이상의 빙고를 완성했는지 판단하기 전에
서로 빙고 데이터를 선택하여 오픈하는 과정이 필요하겠죠?
그 동작을 하는 함수가 바로 913번째 줄에 있는 BingoPlay 함수입니다.
마찬가지로 CPU 빙고 테이블 객체를 레퍼런스로 받습니다.

891번째 줄의 SelectBingoData 함수로 인해
CPU가 먼저 빙고 데이터를 선택하여 오픈합니다.
SelectBingoData 함수의 동작을 자세히 살펴봅시다.

먼저 인자로 받은 객체가 CPU 빙고 테이블인 경우부터 보시죠.
500번째 줄에서 변수 CurrentCPU_Row에 SelectDataRow_CPU의 값을
대입하고 있네요. SelectDataRow_CPU는 외부 변수로 0으로 초기화되어 있습니다.

기본적으로 CPU는 빙고 데이터를 아래와 그림과 같이 오픈합니다.

이러한 순서대로 데이터를 오픈하기 위해서 505번째 줄에 있는 if 문이
필요한 것이죠. m_BingoSize는 3으로 고정이고 CurrentCPU_Row의 값은
데이터가 하나 오픈될 때마다 1이 올라갑니다. 이 두 값을 뺄셈하였을 때,
SelectDataCol_CPU의 값과 같다면 다음에는 다음 행의 첫 번째 열에 있는
데이터를 오픈할 것입니다. 이 코드로 인해서 0번째 행은 0, 1, 2번째 열까지 오픈하고
1번째 행은 0, 1번째 열까지 오픈하고 2번째 행은 0번째 열까지만 오픈하는 것이죠.
512번째 if 문은 현재 오픈하려는 데이터가 이미 오픈된 상태라면
다음 열의 데이터를 오픈하는 구문입니다. 얼핏 보면 없어도 되는 구문처럼 보입니다.
왜냐하면 어차피 외부 변수 SelectDataCol_CPU과 SelectDataRow_CPU를 통해
다음 오픈할 데이터가 무엇인지 미리 지정해 주고 있기 때문이죠.
하지만 없으면 문제가 발생합니다.
플레이어가 오픈한 데이터가 CPU 빙고 테이블에 존재하여
CPU 빙고 테이블에서도 해당 데이터가 오픈되었다고 가정해 봅시다.

이전에 플레이어가 3을 오픈하면서 CPU 빙고 테이블에서도 3이 오픈되었습니다.
그런데 CPU 입장에서 이제 [0][1]을 오픈할 차례인데, 512번째 줄의 if 문이 존재하지 않는다면
이미 오픈된 3이라는 데이터를 다시 오픈하게 되면서 플레이어 턴으로 넘어가게 되죠.
그래서 이미 오픈 여부를 나타내는 멤버 변수 IsOpened이 true라면
다음 열을 오픈하게 해야 하는 것입니다.

오픈된 데이터가 아니라면 516번째 줄에 있는 else 문 안의 코드가
실행되면서 데이터를 오픈해 줘야겠죠?
519번째 줄에서 오픈할 데이터 앞에
Print_selectCharacter 함수를 통해 손가락 기호를 출력합니다.
그리고 Sleep 함수를 통해 1초 지연을 준 뒤, 선택했음을 표현하기 위해
오픈되기 전 '?' 문자를 파란색 배경으로 표현합니다.
529번째 줄에 있는 Print_checkCharacter 함수를 통해

데이터 앞에 체크 기호가 세 번 깜빡이게 한 후 체크 기호를 지웁니다.
그리고 그곳에 있는 데이터를 반환 변수에 저장하고 데이터가 있는 곳으로
커서를 옮긴 뒤, 오픈되었음을 의미하기 위해 파란색을 배경으로 데이터를 재출력합니다.
해당 빙고 칸이 오픈되었음을 의미하기 위해 멤버 IsOpened를 true로 합니다.
다시 CPU 차례가 되었을 때 다음 열의 데이터를 오픈하게 하기 위해
SelectDataRow_CPU의 값을 하나 올립니다.
다시 BingoPlay 함수로 돌아와서,

891번째 줄의 SelectBingoData 함수로 인해 CPU 빙고 테이블에 있는
데이터가 하나 오픈되었습니다. 그러면 이제 해당 데이터가
플레이어 빙고 테이블에도 존재하는지 체크를 해 줘야겠죠.
이 동작을 하는 함수가 Check_DataExist 함수입니다.

SelectBingoData 함수가 반환한 오픈된 빙고 칸의 데이터를
레퍼런스로 참조합니다. 그리고 모든 빙고 칸을 하나씩 돌면서
레퍼런스로 참조한 데이터와 같은 데이터가 있다면
해당 빙고 칸의 IsOpened를 true로 하고
해당 빙고 칸의 데이터를 파란색 배경으로 하여 재출력합니다.
BingoPlay 함수에서 892번째 줄을 보시면
BingoCheck 함수가 있습니다.
BingoCheck 함수는 인자로 받은 빙고 테이블 객체의

빙고를 체크하는 함수이죠. 또한 for 문을 통해 하나씩 증가시킨 i값을
인자로 받아 0 ~ 2번 패턴을 체크합니다. 데이터를 오픈되면 상대방의 빙고 테이블에도
해당 데이터가 있는지 체크한 후에는 BingoCheck 함수를 통해 빙고인지 아닌지를
체크하는 것입니다. 먼저 가로 빙고부터 체크하게 됩니다.
BingoCheck_Horizontal 함수를 통해 0번 패턴([0][0] ~ [0][2]), 1번 패턴( [1][0] ~ [1][2]),
2번 패턴( [2][0] ~ [2][2])으로 체크합니다.
BingoCheck_Horizontal 함수를 살펴보죠.

현재 가로 빙고를 체크하려는 빙고 테이블이
플레이어 것이라면 HorizontalPatern_PLAYER의 멤버를,
CPU의 것이라면 HorizontalPatern_CPU의 멤버를 확인합니다.
HorizontalPatern이라는 객체는 tBingoCheckPatern형이며,
플레이어와 CPU 따로 갖고 있습니다.

자료형 tBingoCheckPatern는 구조체이며

세 개의 멤버로 구성되어 있는데
각 멤버는 0 ~ 2번 패턴을 나타내며 멤버의 값이
true라면 해당 패턴은 빙고가 완성된 패턴임을,
false라면 해당 패턴은 아직 빙고가 완성되지 않았음을 의미합니다.
다시 BingoCheck_Horizontal 함수로 돌아와서

만약 인자로 받은 _paternNum의 값이 0이면
가로 빙고 0번 패턴을 체크하게 됩니다. 이때 빙고 체크를 하려는
테이블이 플레이어 것이라면 HorizontalPatern_PLAYER의 멤버 중
0번 패턴을 의미하는 멤버 Bingoed_0가 true인지 살펴봐야겠죠.
만약 0번 패턴을 체크하려는데 Bingoed_0가 이미 true라면
굳이 검사할 필요없이 BingoCheck_Horizontal 함수를 종료하면 됩니다.
플레이어 빙고 테이블의 가로 빙고 0번 패턴을 체크하려는데

HorizontalPatern_PLAYER의 멤버 Bingoed_0가 false라면 검사를 해 봐야겠죠.
0번 패턴은 [0][0] ~ [0][2]를 검사하는 것이죠? 즉 열의 값을 하나씩 올리면서
검사를 해 보면 되는 겁니다. 검사한 빙고 칸의 멤버 IsOpened의 값이
true라면 openCount의 값을 하나 올립니다. 이 openCount의 값이
빙고 테이블의 한 줄 크기를 나타내는 m_BingoSize와 같다면
한 줄이 모두 오픈된 상태로, 즉 빙고가 완성된 상태라는 의미겠죠.
그러면 549번째 줄에 있는 if 문 안의 코드가 실행될 겁니다.
597번째 줄에 있는 for 문을 통해 빙고가 완성된 칸 가장 처음 칸으로
가서 사운드를 출력하고 빙고가 완성된 칸임을 표현하기 위해
빨간 배경색으로 하여 데이터를 재출력합니다.
그리고 해당 빙고 테이블의 완성된 빙고의 개수를 나타내는
멤버 m_BingoCount의 값을 하나 올립니다.
이러한 빙고 완성 동작이 발생한 후에는
누구의 빙고 테이블인지에 따라,

현재 검사한 빙고 패턴을 나타내는 변수 _paternNum의 값에 따라,
객체를 선택하여 해당 빙고 패턴을 나타내는 멤버의 값을 true로 해 줍니다.
다시 BingoCheck 함수로 돌아와서

가로 빙고를 체크하는 BingoCheck_Horizontal 함수를 수행하고 나면
다음에는 세로 빙고를 체크하는 BingoCheck_Vertical 함수를
실행해야 합니다.
BingoCheck_Vertical 함수도



BingoCheck_Horizontal 함수의 동작과 크게 다르지 않습니다.
다만 세로 빙고 체크 패턴의 빙고 완성 여부를 나타내는 외부 변수는

또 따로 존재한다는 점만 파악하면 되겠습니다.
이제 마지막으로 대각선 빙고도 체크를 해야 합니다.

BingoCheck_Diagonal 함수가 대각선 빙고 체크 역할을 해 주죠.
주의할 점은 대각선 빙고 체크는 좌상단에서 우하단 방향과,
우상단에서 좌하단 방향으로 두 가지 패턴만 존재한다는 점입니다.
그래서 748번째 줄과 767번째 줄의 if 문에서 보이듯이
_paternNum의 값이 1이라면, 즉 1번 패턴을 검사하게 된다면
바로 return하여 함수를 종료하고 있죠.
먼저 좌상단에서 우하단 방향 대각선 빙고 체크 코드입니다.

0번 패턴이죠.
다음은 우상단에서 좌하단 방향 대각선 빙고 체크 코드입니다.

2번 패턴이죠.
다시 BingoPlay 함수로 돌아와서 살펴봅시다.

데이터를 선택하였고 해당 데이터가 상대방의 테이블에도
존재하는지 체크를 하였습니다. 그리고 그 과정에서 빙고가 완성되었는지
체크하였죠. 이 과정은 계속 반복될 겁니다.
바로 어느 한쪽 멤버 함수 GetBingoCount의 반환값이
m_BingoSize의 값과 같거나 클 때까지 말이죠.
(GetBingoCount 함수는 m_BingoCount의 값을 반환하는 함수입니다.)
즉 어느 한쪽이 3개 이상의 빙고를 완성할 때까지
데이터를 선택하고 빙고 체크하는 것을 계속 반복하다가
어느 한쪽이 3개 이상의 빙고를 완성하게 되면 BingoPlay 함수는
종료되는 겁니다.
'C++ > 빙고 게임 제작' 카테고리의 다른 글
| C++ 빙고 게임 제작 : 게임 결과 출력 (0) | 2024.06.14 |
|---|---|
| C++ 빙고 게임 제작 : 빙고 데이터 입력 (0) | 2024.06.12 |
| C++ 빙고 게임 제작 : 메인 메뉴 (0) | 2024.06.08 |