profile image

L o a d i n g . . .

반응형

 

이전 버전과 규칙은 동일하다. 이전 버전: https://c1oud9.tistory.com/97

 

[C++] C++로 구현하는 빙고 (vs 컴퓨터)

이중 배열의 각 칸에 순차적으로 숫자를 넣는다. (1~25) 셔플 알고리즘을 통해 숫자를 무작위로 섞는다. 사용자에게 숫자를 입력받는다. 사용자에게 입력받은 숫자를 처리한다. 사용자 및 컴퓨터�

c1oud9.tistory.com

 

youtu.be/bjkK66xrGS0

 

개선점

  • 두 숫자가 동시에 처리되지 않고, 플레이어의 입력 후 컴퓨터가 고를 수 있도록 턴제로 진행되게끔 수정했다. 이때, 컴퓨터가 숫자를 지울 때 2초라는 시간을 지연시켰다.
  • 턴이 지날 때마다 화면을 지우며 자연스럽게 갱신하는 기능을 추가했다.
  • 버그를 수정하였다.

 

※ 공부 중에 만들어 본 코드입니다. 코드가 매끄럽지 않으며, 검색하지 않고 최대한 알고 있는 내용으로만 구현했으니 참고용으로만 봐 주세요!

#include <iostream>
#include <time.h>
#include <windows.h>

using namespace std;

void shuffle(int arr[][5])
{
	int destCol, destRow, sourCol, sourRow, temp;
	for (int i = 0; i < 77; i++)
	{
		destCol = rand() % 5;
		destRow = rand() % 5;
		sourCol = rand() % 5;
		sourRow = rand() % 5;

		temp = arr[destRow][destCol];
		arr[destRow][destCol] = arr[sourRow][sourCol];
		arr[sourRow][sourCol] = temp;
	}
}

void enterNum(int arr[][5], const int& num)
{
	for (int i = 0; i < 5; i++)
	{
		for (int j = 0; j < 5; j++)
		{
			if (arr[i][j] == num)
				arr[i][j] = -1;
		}
	}
}

void checkNum(int arr[][5], int *ldig, int *rdig, int* bingo)
{
	for (int i = 0; i < 5; i++)
	{
		int rowBingo = 0;
		int colBingo = 0;

		for (int j = 0; j < 5; j++)
		{
			if (arr[i][j] == -1)
			{
				if (i == 2 && j == 2)
				{
					(*ldig)++;
					(*rdig)++;
				}
				else if (i + j == 4)
					(*rdig)++;
				else if (i == j)
					(*ldig)++;
				rowBingo++;
			}
			if (arr[j][i] == -1)
			{
				colBingo++;
			}

			if (colBingo == 5) (*bingo)++;
			if (rowBingo == 5) (*bingo)++;
		}
	}
	if (*rdig == 5)
		(*bingo)++;
	if (*ldig == 5)
		(*bingo)++;
}

void printBingo(int arr[][5], int arr2[][5])
{
	system("cls");
	cout << "\n\t\t\t\t\t~ 빙고 게임 ~\n" << endl;
	for (int i = 0; i < 5; i++)
	{
		for (int j = 0; j < 5; j++)
		{
			if (arr[i][j] == -1)
				cout << "#";
			else
				cout << arr[i][j];
			cout << "\t";
		}
		cout << "\t\t";
		for (int j = 0; j < 5; j++)
		{
			if (arr2[i][j] == -1)
				cout << "#";
			else
				cout << arr2[i][j];

			cout << "\t";
		}
		cout << endl << endl;
	}
	cout << endl;
}

void printBottom(int inputNum, int inputNumCom, int bingoPlayer, int bingoCom)
{
	cout << endl;
	cout << "\t>> 당신의 숫자: " << inputNum << " << \t\t\t\t >> 컴퓨터의 숫자: " << inputNumCom << " <<" << endl;
	cout << "\t>> 빙고 카운트: " << bingoPlayer << " << \t\t\t\t >> 빙고 카운트: " << bingoCom << " <<" << endl;
	cout << endl;
}

int main()
{
	int numPlayer[5][5], numCom[5][5];
	int inputNum = 0, bingoPlayer = 0, inputNumCom = 0, bingoCom = 0;
	bool playerWin = false;

	srand(time(NULL));

	// 기본 숫자로 초기화한다. (0 ~ 25)
	for (int i = 0; i < 5; i++)
	{
		for (int j = 0; j < 5; j++)
		{
			numPlayer[i][j] = 5 * i + j + 1;
			numCom[i][j] = 5 * i + j + 1;
		}
	}

	// 숫자를 랜덤하게 섞는다.
	shuffle(numPlayer);
	shuffle(numCom);

	printBingo(numPlayer, numCom);
	printBottom(0, 0, 0, 0);

	while (true)
	{
		int colBingo = 0, leftDigBingo = 0, rightDigBingo = 0;
		int colBingoCom = 0, leftDigBingoCom = 0, rightDigBingoCom = 0;
		int checkBingo = 0, checkBingoCom = 0;


		cout << "숫자 입력: ";
		cin >> inputNum;
		// 잘못된 값이 들어왔을 경우, continue를 통해 맨 처음으로 돌아간다.
		if (inputNum < 1 || inputNum > 25) {
			cout << "잘못된 입력입니다. 다시 입력해 주세요." << endl << endl;
			continue;
		}

		// 사용자로부터 입력받은 숫자를 처리한다.
		enterNum(numPlayer, inputNum);
		enterNum(numCom, inputNum);

		checkNum(numPlayer, &leftDigBingo, &rightDigBingo, &checkBingo);
		checkNum(numCom, &leftDigBingoCom, &rightDigBingoCom, &checkBingoCom);

		bingoPlayer = checkBingo;
		bingoCom = checkBingoCom;

		printBingo(numPlayer, numCom);
		printBottom(inputNum, inputNumCom, bingoPlayer, bingoCom);

		if (bingoPlayer == 5 || bingoCom == 5)
		{
			break;
		}

		leftDigBingo = 0;
		leftDigBingoCom = 0;
		rightDigBingo = 0;
		rightDigBingo = 0;
		checkBingo = 0;
		checkBingoCom = 0;

		Sleep(2000);


		// check: 0 ~ 4는 가로, 5 ~ 9는 세로, 10은 좌측 상단의 대각선(\), 11은 우측 상단의 대각선(/)
		// 각 가로/세로/대각선에 -1이 얼마나 선언되어 있는지를 저장한다.
		// numbers: 빙고가 된 줄을 제외하고, 가장 많이 -1을 가진 줄의 숫자를 저장한다.
		int check[12]{ 0 };
		int numbers[5]{ 0 };

		for (int i = 0; i < 5; i++)
		{
			for (int j = 0; j < 5; j++)
			{
				// 지워진 숫자일 경우
				if (numCom[i][j] == -1)
				{
					// 정중앙의 숫자는 두 대각선 모두에 포함된다.
					if (i == 2 && j == 2)
					{
						check[10]++;
						check[11]++;
					}
					else if (i == j) check[10]++;      // 좌측 대각선
					else if (i + j == 4) check[11]++;   // 우측 대각선
					check[i]++;      // 가로
				}
				if (numCom[j][i] == -1)
				{
					check[5 + i]++;   // 세로
				}
			}
		}

		// 가장 큰 수를 찾는다. 같은 수가 있다면 우선 순위는 가로 > 세로 > 대각선이다.
		// 5는 이미 빙고가 된 줄이기 때문에 제외한다.
		int a = 0, idx = 0;
		for (int i = 0; i < 12; i++)
		{
			if (check[i] != 5 && a < check[i])
			{
				a = check[i];
				idx = i;
			}
		}

		if (idx / 5 == 0) // 0~4
		{
			for (int i = 0; i < 5; i++)
				numbers[i] = numCom[idx][i];
		}
		else if (idx / 5 == 1) // 5~9
		{
			for (int i = 0; i < 5; i++)
				numbers[i] = numCom[i][idx % 5];
		}
		else // 10,11
		{
			if (idx == 10)
			{
				for (int i = 0; i < 5; i++)
					numbers[i] = numCom[i][i];
			}
			else
			{
				for (int i = 0; i < 5; i++)
					numbers[i] = numCom[i][4 - i];
			}
		}

		while (true)
		{
			int t_idx = rand() % 5;
			// 랜덤으로 정한 인덱스 자리에 숫자가 남아 있다면, 컴퓨터의 숫자로 지정한다.
			if (numbers[t_idx] != -1)
			{
				inputNumCom = numbers[t_idx];
				break;
			}
		}

		enterNum(numPlayer, inputNumCom);
		enterNum(numCom, inputNumCom);

		checkNum(numPlayer, &leftDigBingo, &rightDigBingo, &checkBingo);
		checkNum(numCom, &leftDigBingoCom, &rightDigBingoCom, &checkBingoCom);

		bingoPlayer = checkBingo;
		bingoCom = checkBingoCom;

		printBingo(numPlayer, numCom);
		printBottom(inputNum, inputNumCom, bingoPlayer, bingoCom);

		if (bingoPlayer == 5 || bingoCom == 5)
		{
			break;
		}
	}

	printBingo(numPlayer, numCom);
	printBottom(inputNum, inputNumCom, bingoPlayer, bingoCom);

	if (bingoPlayer >= bingoCom)
	{
		cout << "승리하셨습니다!" << endl;
	}
	else
	{
		cout << "컴퓨터의 승리입니다." << endl;
	}

	return 0;
}
반응형
복사했습니다!