[C++] 섯다 텍스트 게임 구현

2024. 2. 24. 23:25C++/보드게임 구현

c++의 숙달을 위하여 섰다 게임을 제작했다.

지금까지 배운 반복문과 조건문, 배열 등과 같이 기초적인 명령문을 이용하여 제작하였다.

 

소요 시간 : 대략 8시간

 

해당 게임을 제작하기 위해서 넣은 규칙은 대략 아래와 같다.

[규칙]

1. 총 20장의 카드가 존재한다.

2. 카드의 숫자 범위는 1~10까지로 각 2장씩 존재한다.

3. 플레이를 하는 사람의 수는 사용자가 직접 입력하여 결정한다.

4. 사용자는 어떤 플레이어가 승리할지 예측하여 입력한다.

5. 사용자가 예측에 실패하였을 경우 다시 처음부터 루프 한다.

6. 사용자가 예측에 성공하면 승리라는 문구가 나타나고 루프가 종료된다.

 

더보기
#include<iostream>

int main()
{
	srand(time(NULL));	//난수 초기화
    
	int  playerCount;	//게임 플레이어의 수
	int card[10][2];	//카드 구성
	bool isCheckLight[2];	//광패 확인

	for (int i = 0; i < 2; i++)		//카드 숫자 설정
	{
		for (int k = 0; k < 10; k++)
		{
			card[k][i] = k + 1;
		}
	}	

	while (true)
	{
		int inputNum;	//플레이할 사람의 수 입력값
		int cardPower[4] = {};		//카드의 전투력
		bool Game_Win = true;		//게임의 승패 결정, ture면 승리, false면 패배
        							//초기값을 true로 설정

		std::cout << "플레이할 사람의 숫자를 정해주세요(범위 : 2~4) :";

		while (true)	//입력한 숫자가 범위를 벗어나면 다시 입력하도록 설정
		{
			std::cin >> inputNum;
			if (inputNum > 1 && inputNum < 5) break;
			else
			{
				std::cout << "잘못 입력하셨습니다." << std::endl;
				std::cout << "다시 입력하십시요(범위 : 2~4) : ";
			}
		}

		int inputSelectNum;		//예측한 승리할 사람을 입력

		std::cout << "누가 승리할지 예측하십시요(범위 : 1~" << inputNum << ") : ";
        
		while (true)	//입력값이 범위를 벗어나면 다시 입력하도록 설정
		{
			std::cin >> inputSelectNum;
			if (inputSelectNum > inputNum || inputSelectNum < 1)
			{
				std::cout << "잘못입력하였습니다." << std::endl;
				std::cout << "다시 입력하십시요(범위 : 1~" << inputNum << ") : ";
			}
			else break;
		}

#pragma region Shuffle_Card		//코드를 블록화 시킨다.
	//플레이어들의 카드들 섞기
		playerCount = inputNum;		//플레이어의 수 설정 완료

		int randomCardNum[2];		//1~10 사이의 랜덤한 숫자
		int playerCard[2][4];		//플레이어들이 들고 있는 카드
        //데이터형 배열명 [2장의 카드][플레이어들의 수]

		for (int p = 0; p < playerCount; p++)
		{
			for (int i = 0; i < 2; i++)
			{
				randomCardNum[i] = rand() % 9 + 1;
				playerCard[i][p] = card[randomCardNum[i]][i];
			}
		}

		for (int p = 0; p < playerCount; p++)	//중복된 숫자를 가진 카드가 2이상이면 다시 랜덤 설정 
		{
			for (int i = 0; i < p; i++)
			{
				for (int k = 0; k < 2; k++)
				{
					if (playerCard[k][i] == playerCard[k][p])
					{
						playerCard[k][p] = (rand() % 9 + 1);
						p--;
					}
				}
			}
		}
		
#pragma endregion

#pragma region Game_UI_Text		
	//플레이어 구분
		for (int p = 0; p < playerCount; p++)
		{
			std::cout << "==================================" << std::endl;
			std::cout << p + 1 << "번째 플레이어" << std::endl;;
			std::cout << "==================================" << std::endl;
			for (int i = 0; i < 2; i++)		//플레이어들의 카드 출력
			{
				std::cout << playerCard[i][p] << "  ";		
			}	
			std::cout << std::endl;		//줄 바꿈
			std::cout << std::endl;		//1줄 공백
		}
#pragma endregion

#pragma region Check_CardPower
	//플레이어들의 카드가 어느 족보에 속하는지 확인
		for (int p = 0; p < playerCount; p++)
		{
			bool lightCard[2] = { 0,0 };

			for (int i = 0; i < 2; i++)
			{
				isCheckLight[i] = (playerCard[i][p] == 1 || playerCard[i][p] == 3 || playerCard[i][p] == 8);
				//플레이어의 카드들 중 1, 3, 8 이 존재하는지 확인
				if (isCheckLight[i])
				{
					int randLightCard = rand() % 100;	//카드가 광패일 확률

					if (randLightCard >= 50)		//5할의 확률로 카드가 광패이다.
					{
						lightCard[i] = true;		//플레이어의 1, 3, 8 카드 하나가 광패이다.
					}
				}
			}

			int lightCardtemp = 1;	//bool형의 역할 수행
			for (int i = 0; i < 2; i++)
			{
				lightCardtemp *= lightCard[i];
			}	//카드가 광패으로만 이루어졌는지 확인

			int isCheck_38_Card = 1;	//bool형의 역할 수행
			if (lightCardtemp)
			{
				for (int i = 0; i < 2; i++)
				{
					int isCheckCardClass[2];
					isCheckCardClass[i] = (playerCard[i][p] == 3) || (playerCard[i][p] == 8);
                    //플레이어의 카드가 3, 8로 구성되어 있다.
					isCheck_38_Card = isCheck_38_Card & isCheckCardClass[i];
				}	//카드의 구성이 3과 8로만 이루어졌는지 확인
			}

			int Ali = 1;		//이하 동문
			for (int i = 0; i < 2; i++)
			{
				bool isCheckCardClass[2];
				isCheckCardClass[i] = playerCard[i][p] == 1 || playerCard[i][p] == 2;
				Ali *= isCheckCardClass[i];
			}	//카드의 구성이 1과 2로만 이루어졌는지 확인

			int Dogsa = 1;		//이하 동문
			for (int i = 0; i < 2; i++)
			{
				bool isCheckCardClass[2];
				isCheckCardClass[i] = playerCard[i][p] == 1 || playerCard[i][p] == 4;
				Dogsa *= isCheckCardClass[i];
			}	//카드의 구성이 1과 4로만 이루어졌는지 확인

			int Gupping = 1;		//이하 동문
			for (int i = 0; i < 2; i++)
			{
				bool isCheckCardClass[2];
				isCheckCardClass[i] = playerCard[i][p] == 1 || playerCard[i][p] == 9;
				Gupping *= isCheckCardClass[i];
			}	//카드의 구성이 1과 9로만 이루어졌는지 확인

			int Jangpping = 1;		//이하 동문
			for (int i = 0; i < 2; i++)
			{
				bool isCheckCardClass[2];
				isCheckCardClass[i] = playerCard[i][p] == 1 || playerCard[i][p] == 5;
				Jangpping *= isCheckCardClass[i];
			}	//카드의 구성이 1과 5로만 이루어졌는지 확인

			int Jangsa = 1;		//이하 동문
			for (int i = 0; i < 2; i++)
			{
				bool isCheckCardClass[2];
				isCheckCardClass[i] = playerCard[i][p] == 1 || playerCard[i][p] == 5;
				Jangsa *= isCheckCardClass[i];
			}	//카드의 구성이 4과 10로만 이루어졌는지 확인

			int Selyug = 1;		//이하 동문
			for (int i = 0; i < 2; i++)
			{
				bool isCheckCardClass[2];
				isCheckCardClass[i] = playerCard[i][p] == 4 || playerCard[i][p] == 6;
				Selyug *= isCheckCardClass[i];
			}	//카드의 구성이 4과 6로만 이루어졌는지 확인

			int cardNumSum = 0;		//플레이어의 카드 숫자 합
			for (int i = 0; i < 2; i++)
			{
				cardNumSum += playerCard[i][p];	//플레이어가 가지고 있는 카드들을 더한다.
			}
			if (cardNumSum >= 10)
			{
				cardNumSum %= 10;	//끗패는 0~9까지만 존재한다
                //0끗 -> 망통,		9끗 -> 갑오,	나머지 그냥 끗패
			}

#pragma endregion

			std::cout << p + 1 << "번 플레이어 패 : ";
            
#pragma region Devision_CardPower
			//카드 족보 분류
			if (playerCard[0][p] == playerCard[1][p])	//플레이어의 카드 족보가 땡패이다.
			{
				std::cout << playerCard[0][p] << "땡 " << std::endl;
				switch (playerCard[0][p])	//1~10땡만 존재한다.
				{
				case 1:
					cardPower[p] = 40;	//카드의 전투력
					break;
				case 2:
					cardPower[p] = 41;	//이하동문
					break;
				case 3:
					cardPower[p] = 42;	//이하동문
					break;
				case 4:
					cardPower[p] = 43;	//이하동문
					break;
				case 5:
					cardPower[p] = 44;	//이하동문
					break;
				case 6:
					cardPower[p] = 45;	//이하동문
					break;
				case 7:
					cardPower[p] = 46;	//이하동문
					break;
				case 8:
					cardPower[p] = 47;	//이하동문
					break;
				case 9:
					cardPower[p] = 48;	//이하동문
					break;
				case 10:
					cardPower[p] = 49;	//이하동문
					break;
				default:
					break;
				}
			}
			else
			{
				if (lightCardtemp)		// 광땡 카드 족보
				{
					if (isCheck_38_Card)	//38광땡
					{
						std::cout << "3 8 광땡!!!" << std::endl;
						cardPower[p] = 55;
					}
					else
					{
						for (int i = 0; i < 2; i++)
						{
							int divisionLightCard = 1;
							divisionLightCard *= playerCard[i][p] % 3;
							if (divisionLightCard == 0)	//플레이어의 카드들 중 3이 존재한다.
							{
								std::cout << "1 3 광땡 !!" << std::endl;
								cardPower[p] = 50;
							}
							else	//플레이어의 카드들 중 3이 존재하지 않는다.
							{
								std::cout << "1 8 광땡 !!" << std::endl;
								cardPower[p] = 52;
							}
						}
					}
				}
				else
				{
					if (Ali)
					{
						std::cout << "알리! " << std::endl;
						cardPower[p] = 35;
					}
					else if (Dogsa)
					{
						std::cout << "독사! " << std::endl;
						cardPower[p] = 30;
					}
					else if (Gupping)
					{
						std::cout << "구삥!" << std::endl;
						cardPower[p] = 25;
					}
					else if (Jangpping)
					{
						std::cout << "장삥!" << std::endl;
						cardPower[p] = 20;
					}
					else if (Jangsa)
					{
						std::cout << "장사." << std::endl;
						cardPower[p] = 15;
					}
					else if (Selyug)
					{
						std::cout << "세륙." << std::endl;
						cardPower[p] = 10;
					}
					else
					{
						if (cardNumSum == 9)
						{
							std::cout << "갑오.." << std::endl;
							cardPower[p] = 9;
						}
						else if (cardNumSum == 0)
						{
							std::cout << "망통...." << std::endl;
							cardPower[p] = 0;
						}
						else
						{
							std::cout << cardNumSum << "끗..." << std::endl;
							switch (cardNumSum)
							{
							case 1:
								cardPower[p] = 1;
								break;
							case 2:
								cardPower[p] = 2;
								break;
							case 3:
								cardPower[p] = 3;
								break;
							case 4:
								cardPower[p] = 4;
								break;
							case 5:
								cardPower[p] = 5;
								break;
							case 6:
								cardPower[p] = 6;
								break;
							case 7:
								cardPower[p] = 7;
								break;
							case 8:
								cardPower[p] = 8;
								break;
							}
						}
					}
				}
			}
#pragma endregion

		}
		std::cout << std::endl;

		for (int i = 0; i < playerCount; i++)
		{
			if (cardPower[i] > cardPower[inputSelectNum - 1])	
			{   		//사용자가 예측한 플레이어의 점수가 다른 플레이어보다 낮다.
				Game_Win = false;	//게임 패배
				break;
			}
		}

		if (Game_Win == false)
		{
			std::cout << "당신의 패배..." << std::endl;
		}
		else
		{
			bool equalNum = false;
			//사용자가 예측한 플레이어가 다른 플레이어와 같은 점수를 가진다.
			for (int i = 0; i < playerCount; i++)
			{
				bool equalCard;		//카드의 전투력이 같은지 비교
				equalCard = cardPower[inputSelectNum-1] == cardPower[i] && i != (inputSelectNum - 1);
				if (equalCard)		//카드의 전투력이 같으면 실행한다.
				{
					equalNum = true;	//게임의 결과가 무승부라는 것을 확정
					break;
				}
            }

			if (equalNum)	//사용자가 예측한 플레이어가 최고 점수와 같은 점수를 가진다.
				std::cout << "무승부 발생." << std::endl;
			else			//패배가 아닌 상태에서 무승부까지 제외하여 '승리'라는 결과만 남는다.
			{	
				std::cout << "당신의 승리" << std::endl;
				break;
			}
		}
		std::cout << "당신의 점수 : " << playScore[inputSelectNum - 1] << std::endl;
        //예측한 플레이어의 카드 전투력 출력
		std::cout << std::endl;
	}
}

코드 설명은 접힌 글의 주석으로 달아놓았으니 읽어보면 좋겠다.