반응형
▶ 이전강의
- 바로가기
[C++] 11. 함수와 변수
▶ 이전강의- 바로가기 [C++] 10. 이중포인터▶ 이전강의- 바로가기 [C++] 9. Char, 구조체, void 포인터▶ 이전강의- 바로가기 [C++] 8. 배열과 포인트 연산▶ 이전강의- 바로가기 [C++] 7. 포인터▶ 이전
lhy-info.tistory.com
1. 선언과 정의
#include <iostream>
using namespace std;
// 함수는 선언과 정의 부분으로 나눌 수 있음
void SetNumber(int* parray);
int main()
{
return 0;
}
// 함수의 정의 부분
void SetNumber(int *parray)
{
// 배열의 주소를 받아서 값을 변경
for (int i = 0; i < 5; ++i)
{
parray[i] = i + 1;
}
}
- 위쪽 SetNumber은 선언, 아래 SetNumber은 정의
- 원래 함수는 다 위쪽에다 선언해야지만 이런식으로 위아래 나눠서 가능함
2. 숫자 셋팅
함수화 전ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
//1~25까지의 숫자를 넣는다.
for (int i = 0; i < 25; ++i)
{
iArray[i] = i + 1;
iAIArray[i] = i + 1;
}
함수화 후ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
void SetNumber(int* parray)
{
// 배열의 주소를 받아서 값을 변경
for (int i = 0; i < 25; ++i)
{
parray[i] = i + 1;
}
}
3. 섞기
함수화 전ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
//섞기
int iTemp, idx1, idx2;
for (int i = 0; i < 100; ++i)
{
idx1 = rand() % 25;
idx2 = rand() % 25;
iTemp = iArray[idx1];
iArray[idx1] = iArray[idx2];
iArray[idx2] = iTemp;
//AI 숫자도 섞어준다.
idx1 = rand() % 25;
idx2 = rand() % 25;
iTemp = iAIArray[idx1];
iAIArray[idx1] = iAIArray[idx2];
iAIArray[idx2] = iTemp;
}
함수화 후ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
void Shuffle(int* iArray)
{
//섞기
int iTemp = 0, idx1 = 0, idx2 = 0;
for (int i = 0; i < 100; ++i)
{
idx1 = rand() % 25;
idx2 = rand() % 25;
iTemp = iArray[idx1];
iArray[idx1] = iArray[idx2];
iArray[idx2] = iTemp;
}
}
4. 모드 선택
함수화 전ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
int iBingo = 0, iAIBingo = 0;
int iAIMode = 0;
while (true)
{
cout << "1. Easy" << endl;
cout << "2. Hard" << endl;
cout << "AI 난이도를 선택하세요 : ";
cin >> iAIMode;
if (iAIMode >= AM_EASY && iAIMode <= AM_HARD)
{
break;
}
}
함수화 후ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
AI_MODE SelectAIMode()
{
int iAIMode = 0;
while (true)
{
cout << "1. Easy" << endl;
cout << "2. Hard" << endl;
cout << "AI 난이도를 선택하세요 : ";
cin >> iAIMode;
if (iAIMode >= AM_EASY && iAIMode <= AM_HARD)
{
break;
}
}
return (AI_MODE)iAIMode;
}
5. 별 처리
함수화 전ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 5; j++)
{
if (iArray[i * 5 + j] == INT_MAX)
{
cout << "*\t";
}
else
{
cout << iArray[i * 5 + j] << "\t";
}
}
cout << endl;
}
함수화 후ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
void OutputNumber(int* parray, int ibingo)
{
for (int i = 0; i < 5; ++i)
{
for (int j = 0; j < 5; ++j)
{
if (parray[i * 5 + j] == INT_MAX)
{
cout << "*\t";
}
else
{
cout << parray[i * 5 + j] << "\t";
}
}
cout << endl;
}
cout << "Bingo Line : " << ibingo << endl << endl;
}
6. 중복 체크
함수화 전ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
//모든 숫자를 차례대로 검사해 입력한 숫자와 같은 숫자가 있는지 찾아낸다
for (int i = 0; i < 25; i++)
{
//같은 숫자가 있을 경우
if (iInput == iArray[i])
{
//숫자를 찾았을 경우 중복된 숫자가 아니므로
//bAcc를 false로 만든다
bAcc = false;
//숫자를 *로 만들기 위해 특수한 값인 INT_MAX로 변경
iArray[i] = INT_MAX;
//더이상 다른 숫자를 찾아볼 필요가 없으므로 for문을 빠져나간다.
break;
}
}
함수화 후ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
bool ChangeNumber(int* parray, int iInput)
{
//모든 숫자를 차례대로 검사해 입력한 숫자와 같은 숫자가 있는지 찾아낸다
for (int i = 0; i < 25; ++i)
{
//같은 숫자가 있을 경우
if (iInput == parray[i])
{
//숫자를 *로 만들기 위해 특수한 값인 INT_MAX로 변경
parray[i] = INT_MAX;
//더이상 다른 숫자를 찾아볼 필요가 없으므로 for문을 빠져나간다.
return false;
}
}
//중복된 숫자를 입력했기 때문에 true로 return
return true;
}
7. AI 선택처리
함수화 전ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
//AI가 선택할 수 있는 목록에서 숫자를 선택한다.
switch (iAIMode)
{
/*
AI Easy 모드
- 랜덤으로 숫자를 뽑아서 *로 만든다.
*/
case AM_EASY:
//선택 안된 숫자 개수는 목록을 만들때 카운트한다.
iNoneSelCnt = 0;
//선택 안된 숫자 목록 만들어준다
for (int i = 0; i < 25; ++i)
{
//현재 숫자가 *이 아닐 경우
if (iAIArray[i] != INT_MAX)
{
//*이 아닌 숫자일 경우 iNoneSelect를 인덱스로 활용
//선택 안된 목록에 추가
iNoneSelect[iNoneSelCnt] = iAIArray[i];
++iNoneSelCnt;
}
}
//for문을 빠져 나오게 되면 선택안된 목록이 만들어지고
//선택안된 목록의 개수가 만들어진다.
//그러므로 0~iNoneSelCnt-1까지의 숫자를 랜덤으로 뽑아서
//그 숫자를 *로 만들어주면 된다.
iInput = iNoneSelect[rand() % iNoneSelCnt];
break;
case AM_HARD:
// 하드모드는 현재 숫자중 빙고줄 완성 가능성이 가장 높은 줄을 찾아, 그 줄에 있는 숫자중 하나를 *로 만든다.
int iLine = 0;
int iStarCount = 0;
int iSaveCount = 0;
//가로 라인 중에 가장 *이 많은 라인을 찾아낸다.
for (int i = 0; i < 5; ++i)
{
for (int j = 0; j < 5; ++j)
{
//가로줄 체크
if (iAIArray[i * 5 + j] == INT_MAX)
{
++iStarCount;
}
}
//별이 5개보다 미만이여야 빙고가 아님 && 새로운 라인을 찾았을 때
//그 라인의 별 갯수를 저장하고 그 라인을 선택한다.
//이렇게 하면 별이 가장 많은 라인을 찾을 수 있다.
if (iStarCount < 5 && iSaveCount < iStarCount)
{
//가로 라인중 가장 별이 많은 라인을 체크
//가로 라인은 0~4로 의미를 부여
iLine = i;
iSaveCount = iStarCount;
}
}
//가로 라인 중 가장 별이 많은 라인을 찾았다.
//이 값을 가지고 세로 라인들과 비교하여 별이 가장 많은 라인을 찾아낸다.
for (int i = 0; i < 5; ++i)
{
iStarCount = 0;
for (int j = 0; j < 5; ++j)
{
if (iAIArray[j * 5 + i] == INT_MAX)
{
++iStarCount;
}
}
if (iStarCount < 5 && iSaveCount < iStarCount)
{
//세로 라인중 가장 별이 많은 라인을 체크
//세로 라인은 5~9로 의미를 부여
iLine = i + 5;
iSaveCount = iStarCount;
}
}
//왼쪽 -> 오른쪽 대각선 체크
iStarCount = 0;
for (int i = 0; i < 25; i += 6)
{
if (iAIArray[i] == INT_MAX)
{
++iStarCount;
}
}
if (iStarCount < 5 && iSaveCount < iStarCount)
{
//왼쪽 -> 오른쪽 대각선 체크
//대각선은 10번으로 의미를 부여
iLine = LN_LT;
iSaveCount = iStarCount;
}
//오른쪽 -> 왼쪽 대각선 체크
iStarCount = 0;
for (int i = 4; i <= 20; i += 4)
{
if (iAIArray[i] == INT_MAX)
{
++iStarCount;
}
}
if (iStarCount < 5 && iSaveCount < iStarCount)
{
//오른쪽 -> 왼쪽 대각선 체크
//대각선은 11번으로 의미를 부여
iLine = LN_RT;
iSaveCount = iStarCount;
}
//모든 라인을 조사했으면 iLine에는 가장 별이 많은 라인이 저장되어 있다.
//그 라인에 있는 *이 아닌 숫자중 하나를 선택한다.
//가로줄일 경우
if (iLine <= LN_H5)
{
for (int i = 0; i < 5; ++i)
{
if (iAIArray[iLine * 5 + i] != INT_MAX)
{
iInput = iAIArray[iLine * 5 + i];
break;
}
}
}
//세로줄일 경우
else if (iLine <= LN_V5)
{
for (int i = 0; i < 5; ++i)
{
if (iAIArray[i * 5 + (iLine - 5)] != INT_MAX)
{
iInput = iAIArray[i * 5 + (iLine - 5)];
break;
}
}
}
//왼쪽 -> 오른쪽 대각선
else if (iLine == LN_LT)
{
for (int i = 0; i < 25; i += 6)
{
if (iAIArray[i] != INT_MAX)
{
iInput = iAIArray[i];
break;
}
}
}
//오른쪽 -> 왼쪽 대각선
else if (iLine == LN_RT)
{
for (int i = 4; i <= 20; i += 4)
{
if (iAIArray[i] != INT_MAX)
{
iInput = iAIArray[i];
break;
}
}
}
break;
}
함수화 후ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
int SeletAINumber(int* pArray, AI_MODE iAIMode)
{
//선택안된 목록 배열을 만들어준다
int iNoneSelect[25] = {};
int iNoneSelCnt = 0;
//AI가 선택할 수 있는 목록에서 숫자를 선택한다.
switch (iAIMode)
{
/*
AI Easy 모드
- 랜덤으로 숫자를 뽑아서 *로 만든다.
*/
case AM_EASY:
//선택 안된 숫자 개수는 목록을 만들때 카운트한다.
iNoneSelCnt = 0;
//선택 안된 숫자 목록 만들어준다
for (int i = 0; i < 25; ++i)
{
//현재 숫자가 *이 아닐 경우
if (pArray[i] != INT_MAX)
{
//*이 아닌 숫자일 경우 iNoneSelect를 인덱스로 활용
//선택 안된 목록에 추가
iNoneSelect[iNoneSelCnt] = pArray[i];
++iNoneSelCnt;
}
}
//for문을 빠져 나오게 되면 선택안된 목록이 만들어지고
//선택안된 목록의 개수가 만들어진다.
//그러므로 0~iNoneSelCnt-1까지의 숫자를 랜덤으로 뽑아서
//그 숫자를 *로 만들어주면 된다.
return iNoneSelect[rand() % iNoneSelCnt];
case AM_HARD:
// 하드모드는 현재 숫자중 빙고줄 완성 가능성이 가장 높은 줄을 찾아, 그 줄에 있는 숫자중 하나를 *로 만든다.
int iLine = 0;
int iStarCount = 0;
int iSaveCount = 0;
//가로 라인 중에 가장 *이 많은 라인을 찾아낸다.
for (int i = 0; i < 5; ++i)
{
for (int j = 0; j < 5; ++j)
{
//가로줄 체크
if (pArray[i * 5 + j] == INT_MAX)
{
++iStarCount;
}
}
//별이 5개보다 미만이여야 빙고가 아님 && 새로운 라인을 찾았을 때
//그 라인의 별 갯수를 저장하고 그 라인을 선택한다.
//이렇게 하면 별이 가장 많은 라인을 찾을 수 있다.
if (iStarCount < 5 && iSaveCount < iStarCount)
{
//가로 라인중 가장 별이 많은 라인을 체크
//가로 라인은 0~4로 의미를 부여
iLine = i;
iSaveCount = iStarCount;
}
}
//가로 라인 중 가장 별이 많은 라인을 찾았다.
//이 값을 가지고 세로 라인들과 비교하여 별이 가장 많은 라인을 찾아낸다.
for (int i = 0; i < 5; ++i)
{
iStarCount = 0;
for (int j = 0; j < 5; ++j)
{
if (pArray[j * 5 + i] == INT_MAX)
{
++iStarCount;
}
}
if (iStarCount < 5 && iSaveCount < iStarCount)
{
//세로 라인중 가장 별이 많은 라인을 체크
//세로 라인은 5~9로 의미를 부여
iLine = i + 5;
iSaveCount = iStarCount;
}
}
//왼쪽 -> 오른쪽 대각선 체크
iStarCount = 0;
for (int i = 0; i < 25; i += 6)
{
if (pArray[i] == INT_MAX)
{
++iStarCount;
}
}
if (iStarCount < 5 && iSaveCount < iStarCount)
{
//왼쪽 -> 오른쪽 대각선 체크
//대각선은 10번으로 의미를 부여
iLine = LN_LT;
iSaveCount = iStarCount;
}
//오른쪽 -> 왼쪽 대각선 체크
iStarCount = 0;
for (int i = 4; i <= 20; i += 4)
{
if (pArray[i] == INT_MAX)
{
++iStarCount;
}
}
if (iStarCount < 5 && iSaveCount < iStarCount)
{
//오른쪽 -> 왼쪽 대각선 체크
//대각선은 11번으로 의미를 부여
iLine = LN_RT;
iSaveCount = iStarCount;
}
//모든 라인을 조사했으면 iLine에는 가장 별이 많은 라인이 저장되어 있다.
//그 라인에 있는 *이 아닌 숫자중 하나를 선택한다.
//가로줄일 경우
if (iLine <= LN_H5)
{
for (int i = 0; i < 5; ++i)
{
if (pArray[iLine * 5 + i] != INT_MAX)
{
return pArray[iLine * 5 + i];
}
}
}
//세로줄일 경우
else if (iLine <= LN_V5)
{
for (int i = 0; i < 5; ++i)
{
if (pArray[i * 5 + (iLine - 5)] != INT_MAX)
{
return pArray[i * 5 + (iLine - 5)];
}
}
}
//왼쪽 -> 오른쪽 대각선
else if (iLine == LN_LT)
{
for (int i = 0; i < 25; i += 6)
{
if (pArray[i] != INT_MAX)
{
return pArray[i];
}
}
}
//오른쪽 -> 왼쪽 대각선
else if (iLine == LN_RT)
{
for (int i = 4; i <= 20; i += 4)
{
if (pArray[i] != INT_MAX)
{
return pArray[i];
}
}
}
break;
}
return -1;
}
8. 빙고 줄 수 체크
함수화 전ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
//AI가 선택한 숫자를 AI배열과 플레이어에서 *로 만들어준다.
for (int i = 0; i < 25; i++)
{
if (iInput == iArray[i])
{
iArray[i] = INT_MAX;
break;
}
}
for (int i = 0; i < 25; i++)
{
if (iInput == iAIArray[i])
{
iAIArray[i] = INT_MAX;
break;
}
}
//빙고 수 를 체크하는 것은 매번 숫자를 입력할때마다 처음부터 새로 카운트를 할 것이다
//그러므로 iBingo를 0으로 초기화 한다.
iBingo = 0;
iAIBingo = 0;
//가로, 세로 줄 수를 구해준다
int iStar1 = 0, iStar2 = 0;
int iAIStar1 = 0, iAIStar2 = 0;
for (int i = 0; i < 5; i++)
{
//한줄 체크하기 전 먼저 0으로 초기화
iStar1 = iStar2 = 0;
iAIStar1 = 0, iAIStar2 = 0;
for (int j = 0; j < 5; j++)
{
//가로 별 갯수 구해준다
if (iArray[i * 5 + j] == INT_MAX)
{
++iStar1;
}
//세로 별 개수 구해준다
if (iArray[j * 5 + i] == INT_MAX)
{
++iStar2;
}
//가로 별 갯수 구해준다
if (iAIArray[i * 5 + j] == INT_MAX)
{
++iAIStar1;
}
//세로 별 개수 구해준다
if (iAIArray[j * 5 + i] == INT_MAX)
{
++iAIStar2;
}
}
//j for문이 끝났을 때 iStar1이 5라면 가로 한줄이 모두 *이라는 의미
if (iStar1 == 5)
{
++iBingo;
}
if (iStar2 == 5)
{
++iBingo;
}
//j for문이 끝났을 때 iStar1이 5라면 가로 한줄이 모두 *이라는 의미
if (iAIStar1 == 5)
{
++iAIBingo;
}
if (iAIStar2 == 5)
{
++iAIBingo;
}
}
//왼쪽 상단 -> 오른쪽 하단 대각선 체크
//대각선으로 6씩 증가
iStar1 = 0;
iAIStar1 = 0;
for (int i = 0; i < 25; i += 6)
{
if (iArray[i] == INT_MAX)
{
++iStar1;
}
if (iAIArray[i] == INT_MAX)
{
++iAIStar1;
}
}
if (iStar1 == 5)
{
++iBingo;
}
if (iAIStar1 == 5)
{
++iAIBingo;
}
//오른쪽 상단 -> 왼쪽 하단 대각선 체크
//대각선으로 4씩 증가
iStar1 = 0;
iAIStar1 = 0;
for (int i = 4; i <= 20; i += 4)
{
if (iArray[i] == INT_MAX)
{
++iStar1;
}
if (iAIArray[i] == INT_MAX)
{
++iAIStar1;
}
}
if (iStar1 == 5)
{
++iBingo;
}
if (iAIStar1 == 5)
{
++iAIBingo;
}
}
함수화 후ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
int BingoCounting(int* parray)
{
int iBingo = 0;
//가로줄 체크
iBingo += BingoCountingH(parray);
//세로줄 체크
iBingo += BingoCountingV(parray);
//왼쪽 -> 오른쪽 대각선 체크
iBingo += BingoCountingLTD(parray);
//오른쪽 -> 왼쪽 대각선 체크
iBingo += BingoCountingRTD(parray);
return iBingo;
}
int BingoCountingH(int* iArray)
{
//줄 수를 구해준다
int iStar1 = 0;
int iBingo = 0;
for (int i = 0; i < 5; i++)
{
//한줄 체크하기 전 먼저 0으로 초기화
iStar1 = 0;
for (int j = 0; j < 5; j++)
{
//별 갯수 구해준다
if (iArray[i * 5 + j] == INT_MAX)
{
++iStar1;
}
}
//j for문이 끝났을 때 iStar1이 5라면 가로 한줄이 모두 *이라는 의미
if (iStar1 == 5)
{
++iBingo;
}
}
return iBingo;
}
int BingoCountingV(int* iArray)
{
//줄 수를 구해준다
int iStar1 = 0;
int iBingo = 0;
for (int i = 0; i < 5; i++)
{
//한줄 체크하기 전 먼저 0으로 초기화
iStar1 = 0;
for (int j = 0; j < 5; j++)
{
//별 갯수 구해준다
if (iArray[j * 5 + i] == INT_MAX)
{
++iStar1;
}
}
//j for문이 끝났을 때 iStar1이 5라면 가로 한줄이 모두 *이라는 의미
if (iStar1 == 5)
{
++iBingo;
}
}
return iBingo;
}
int BingoCountingLTD(int* iArray)
{
//줄 수를 구해준다
int iStar1 = 0;
int iBingo = 0;
//왼쪽 상단 -> 오른쪽 하단 대각선 체크
//대각선으로 6씩 증가
iStar1 = 0;
for (int i = 0; i < 25; i += 6)
{
if (iArray[i] == INT_MAX)
{
++iStar1;
}
}
if (iStar1 == 5)
{
++iBingo;
}
return iBingo;
}
int BingoCountingRTD(int* iArray)
{
int iStar1 = 0;
int iBingo = 0;
//오른쪽 상단 -> 왼쪽 하단 대각선 체크
//대각선으로 4씩 증가
iStar1 = 0;
for (int i = 4; i <= 20; i += 4)
{
if (iArray[i] == INT_MAX)
{
++iStar1;
}
}
if (iStar1 == 5)
{
++iBingo;
}
return iBingo;
}
8. 만들어진 전체 함수 리스트
// 함수는 선언과 정의 부분으로 나눌 수 있음
void SetNumber(int* parray);
void Shuffle(int* parray);
void OutputNumber(int* parray, int ibingo);
AI_MODE SelectAIMode();
bool ChangeNumber(int* parray, int iInput);
int SeletAINumber(int* parray, AI_MODE emode);
int BingoCounting(int* parray);
int BingoCountingH(int* parray);
int BingoCountingV(int* parray);
int BingoCountingLTD(int* parray);
int BingoCountingRTD(int* parray);
9. 함수화 한 전체 코드
#include <iostream>
using namespace std;
enum AI_MODE
{
AM_EASY = 1,
AM_HARD
};
enum LINE_NUMBER
{
LN_H1,
LN_H2,
LN_H3,
LN_H4,
LN_H5,
LN_V1,
LN_V2,
LN_V3,
LN_V4,
LN_V5,
LN_LT,
LN_RT
};
// 함수는 선언과 정의 부분으로 나눌 수 있음
void SetNumber(int* parray);
void Shuffle(int* parray);
void OutputNumber(int* parray, int ibingo);
AI_MODE SelectAIMode();
bool ChangeNumber(int* parray, int iInput);
int SeletAINumber(int* parray, AI_MODE emode);
int BingoCounting(int* parray);
int BingoCountingH(int* parray);
int BingoCountingV(int* parray);
int BingoCountingLTD(int* parray);
int BingoCountingRTD(int* parray);
int main()
{
srand((unsigned int)time(0));
int iArray[25] = {};
int iAIArray[25] = {};
//숫자 셋팅
SetNumber(iArray);
SetNumber(iAIArray);
//섞기
Shuffle(iArray);
Shuffle(iAIArray);
int iBingo = 0, iAIBingo = 0;
//AI 난이도 선택
AI_MODE iAIMode = SelectAIMode();
while (true)
{
system("cls");
//숫자를 5x5로 출력한다.
cout << "================== Player ==================" << endl;
OutputNumber(iArray, iBingo);
cout << "================== AI ==================" << endl;
cout << "AI 난이도 : ";
switch (iAIMode)
{
case AM_EASY:
cout << "Easy" << endl;
break;
case AM_HARD:
cout << "Hard" << endl;
break;
}
OutputNumber(iAIArray, iAIBingo);
//줄수가 2이상일 경우 빙고라인을 체크한다.
if (iBingo >= 2)
{
cout << "Player 승리" << endl;
break;
}
else if (iAIBingo >= 2)
{
cout << "AI 승리" << endl;
break;
}
cout << "숫자를 입력하세요(0 : 종료) : ";
int iInput;
cin >> iInput;
//종료
if (iInput == 0)
{
break;
}
//1~25 사이의 숫자가 아닌 경우
else if (iInput < 1 || iInput > 25)
{
cout << "잘못된 숫자입니다." << endl;
continue;
}
//중복 입력 체크하기 위한 변수
bool bAcc = ChangeNumber(iArray, iInput);
//bAcc가 true일 경우 중복된 숫자를 입력해서 숫자*로 만들지 못했으므로
//다시 입력받기 위해 continue를 한다.
if (bAcc)
{
continue;
}
//중복이 아니라면 AI도 숫자를 하나 선택해서 *로 만든다.
bAcc = ChangeNumber(iAIArray, iInput);
//AI가 숫자를 선택한다. AI모드에 맞춰서 선택한다.
iInput = SeletAINumber(iAIArray, iAIMode);
//AI가 선택한 숫자를 AI배열과 플레이어에서 *로 만들어준다.
ChangeNumber(iArray, iInput);
ChangeNumber(iAIArray, iInput);
//빙고 수 를 체크하는 것은 매번 숫자를 입력할때마다 처음부터 새로 카운트를 할 것이다
//그러므로 iBingo를 0으로 초기화 한다.
iBingo = BingoCounting(iArray);
iAIBingo = BingoCounting(iAIArray);
}
return 0;
}
// 함수의 정의 부분
void SetNumber(int* parray)
{
// 배열의 주소를 받아서 값을 변경
for (int i = 0; i < 25; ++i)
{
parray[i] = i + 1;
}
}
void Shuffle(int* iArray)
{
//섞기
int iTemp = 0, idx1 = 0, idx2 = 0;
for (int i = 0; i < 100; ++i)
{
idx1 = rand() % 25;
idx2 = rand() % 25;
iTemp = iArray[idx1];
iArray[idx1] = iArray[idx2];
iArray[idx2] = iTemp;
}
}
AI_MODE SelectAIMode()
{
int iAIMode = 0;
while (true)
{
cout << "1. Easy" << endl;
cout << "2. Hard" << endl;
cout << "AI 난이도를 선택하세요 : ";
cin >> iAIMode;
if (iAIMode >= AM_EASY && iAIMode <= AM_HARD)
{
break;
}
}
return (AI_MODE)iAIMode;
}
void OutputNumber(int* parray, int ibingo)
{
for (int i = 0; i < 5; ++i)
{
for (int j = 0; j < 5; ++j)
{
if (parray[i * 5 + j] == INT_MAX)
{
cout << "*\t";
}
else
{
cout << parray[i * 5 + j] << "\t";
}
}
cout << endl;
}
cout << "Bingo Line : " << ibingo << endl << endl;
}
bool ChangeNumber(int* parray, int iInput)
{
//모든 숫자를 차례대로 검사해 입력한 숫자와 같은 숫자가 있는지 찾아낸다
for (int i = 0; i < 25; ++i)
{
//같은 숫자가 있을 경우
if (iInput == parray[i])
{
//숫자를 *로 만들기 위해 특수한 값인 INT_MAX로 변경
parray[i] = INT_MAX;
//더이상 다른 숫자를 찾아볼 필요가 없으므로 for문을 빠져나간다.
return false;
}
}
//중복된 숫자를 입력했기 때문에 true로 return
return true;
}
int SeletAINumber(int* pArray, AI_MODE iAIMode)
{
//선택안된 목록 배열을 만들어준다
int iNoneSelect[25] = {};
int iNoneSelCnt = 0;
//AI가 선택할 수 있는 목록에서 숫자를 선택한다.
switch (iAIMode)
{
/*
AI Easy 모드
- 랜덤으로 숫자를 뽑아서 *로 만든다.
*/
case AM_EASY:
//선택 안된 숫자 개수는 목록을 만들때 카운트한다.
iNoneSelCnt = 0;
//선택 안된 숫자 목록 만들어준다
for (int i = 0; i < 25; ++i)
{
//현재 숫자가 *이 아닐 경우
if (pArray[i] != INT_MAX)
{
//*이 아닌 숫자일 경우 iNoneSelect를 인덱스로 활용
//선택 안된 목록에 추가
iNoneSelect[iNoneSelCnt] = pArray[i];
++iNoneSelCnt;
}
}
//for문을 빠져 나오게 되면 선택안된 목록이 만들어지고
//선택안된 목록의 개수가 만들어진다.
//그러므로 0~iNoneSelCnt-1까지의 숫자를 랜덤으로 뽑아서
//그 숫자를 *로 만들어주면 된다.
return iNoneSelect[rand() % iNoneSelCnt];
case AM_HARD:
// 하드모드는 현재 숫자중 빙고줄 완성 가능성이 가장 높은 줄을 찾아, 그 줄에 있는 숫자중 하나를 *로 만든다.
int iLine = 0;
int iStarCount = 0;
int iSaveCount = 0;
//가로 라인 중에 가장 *이 많은 라인을 찾아낸다.
for (int i = 0; i < 5; ++i)
{
for (int j = 0; j < 5; ++j)
{
//가로줄 체크
if (pArray[i * 5 + j] == INT_MAX)
{
++iStarCount;
}
}
//별이 5개보다 미만이여야 빙고가 아님 && 새로운 라인을 찾았을 때
//그 라인의 별 갯수를 저장하고 그 라인을 선택한다.
//이렇게 하면 별이 가장 많은 라인을 찾을 수 있다.
if (iStarCount < 5 && iSaveCount < iStarCount)
{
//가로 라인중 가장 별이 많은 라인을 체크
//가로 라인은 0~4로 의미를 부여
iLine = i;
iSaveCount = iStarCount;
}
}
//가로 라인 중 가장 별이 많은 라인을 찾았다.
//이 값을 가지고 세로 라인들과 비교하여 별이 가장 많은 라인을 찾아낸다.
for (int i = 0; i < 5; ++i)
{
iStarCount = 0;
for (int j = 0; j < 5; ++j)
{
if (pArray[j * 5 + i] == INT_MAX)
{
++iStarCount;
}
}
if (iStarCount < 5 && iSaveCount < iStarCount)
{
//세로 라인중 가장 별이 많은 라인을 체크
//세로 라인은 5~9로 의미를 부여
iLine = i + 5;
iSaveCount = iStarCount;
}
}
//왼쪽 -> 오른쪽 대각선 체크
iStarCount = 0;
for (int i = 0; i < 25; i += 6)
{
if (pArray[i] == INT_MAX)
{
++iStarCount;
}
}
if (iStarCount < 5 && iSaveCount < iStarCount)
{
//왼쪽 -> 오른쪽 대각선 체크
//대각선은 10번으로 의미를 부여
iLine = LN_LT;
iSaveCount = iStarCount;
}
//오른쪽 -> 왼쪽 대각선 체크
iStarCount = 0;
for (int i = 4; i <= 20; i += 4)
{
if (pArray[i] == INT_MAX)
{
++iStarCount;
}
}
if (iStarCount < 5 && iSaveCount < iStarCount)
{
//오른쪽 -> 왼쪽 대각선 체크
//대각선은 11번으로 의미를 부여
iLine = LN_RT;
iSaveCount = iStarCount;
}
//모든 라인을 조사했으면 iLine에는 가장 별이 많은 라인이 저장되어 있다.
//그 라인에 있는 *이 아닌 숫자중 하나를 선택한다.
//가로줄일 경우
if (iLine <= LN_H5)
{
for (int i = 0; i < 5; ++i)
{
if (pArray[iLine * 5 + i] != INT_MAX)
{
return pArray[iLine * 5 + i];
}
}
}
//세로줄일 경우
else if (iLine <= LN_V5)
{
for (int i = 0; i < 5; ++i)
{
if (pArray[i * 5 + (iLine - 5)] != INT_MAX)
{
return pArray[i * 5 + (iLine - 5)];
}
}
}
//왼쪽 -> 오른쪽 대각선
else if (iLine == LN_LT)
{
for (int i = 0; i < 25; i += 6)
{
if (pArray[i] != INT_MAX)
{
return pArray[i];
}
}
}
//오른쪽 -> 왼쪽 대각선
else if (iLine == LN_RT)
{
for (int i = 4; i <= 20; i += 4)
{
if (pArray[i] != INT_MAX)
{
return pArray[i];
}
}
}
break;
}
return -1;
}
int BingoCounting(int* parray)
{
int iBingo = 0;
//가로줄 체크
iBingo += BingoCountingH(parray);
//세로줄 체크
iBingo += BingoCountingV(parray);
//왼쪽 -> 오른쪽 대각선 체크
iBingo += BingoCountingLTD(parray);
//오른쪽 -> 왼쪽 대각선 체크
iBingo += BingoCountingRTD(parray);
return iBingo;
}
int BingoCountingH(int* iArray)
{
//줄 수를 구해준다
int iStar1 = 0;
int iBingo = 0;
for (int i = 0; i < 5; i++)
{
//한줄 체크하기 전 먼저 0으로 초기화
iStar1 = 0;
for (int j = 0; j < 5; j++)
{
//별 갯수 구해준다
if (iArray[i * 5 + j] == INT_MAX)
{
++iStar1;
}
}
//j for문이 끝났을 때 iStar1이 5라면 가로 한줄이 모두 *이라는 의미
if (iStar1 == 5)
{
++iBingo;
}
}
return iBingo;
}
int BingoCountingV(int* iArray)
{
//줄 수를 구해준다
int iStar1 = 0;
int iBingo = 0;
for (int i = 0; i < 5; i++)
{
//한줄 체크하기 전 먼저 0으로 초기화
iStar1 = 0;
for (int j = 0; j < 5; j++)
{
//별 갯수 구해준다
if (iArray[j * 5 + i] == INT_MAX)
{
++iStar1;
}
}
//j for문이 끝났을 때 iStar1이 5라면 가로 한줄이 모두 *이라는 의미
if (iStar1 == 5)
{
++iBingo;
}
}
return iBingo;
}
int BingoCountingLTD(int* iArray)
{
//줄 수를 구해준다
int iStar1 = 0;
int iBingo = 0;
//왼쪽 상단 -> 오른쪽 하단 대각선 체크
//대각선으로 6씩 증가
iStar1 = 0;
for (int i = 0; i < 25; i += 6)
{
if (iArray[i] == INT_MAX)
{
++iStar1;
}
}
if (iStar1 == 5)
{
++iBingo;
}
return iBingo;
}
int BingoCountingRTD(int* iArray)
{
int iStar1 = 0;
int iBingo = 0;
//오른쪽 상단 -> 왼쪽 하단 대각선 체크
//대각선으로 4씩 증가
iStar1 = 0;
for (int i = 4; i <= 20; i += 4)
{
if (iArray[i] == INT_MAX)
{
++iStar1;
}
}
if (iStar1 == 5)
{
++iBingo;
}
return iBingo;
}
- 중복이 많이 줄어들고 깔끔해보임
반응형
'C++ > C++입문' 카테고리의 다른 글
[C++] 14. TextRPG 함수화_전투 (1) | 2025.04.15 |
---|---|
[C++] 13. TextRPG 함수화_1 (0) | 2025.04.14 |
[C++] 11. 함수와 변수 (0) | 2025.04.10 |
[C++] 10. 이중포인터 (0) | 2025.04.09 |
[C++] 9. Char, 구조체, void 포인터 (0) | 2025.04.09 |