본문 바로가기
2D 프로그래밍 수업(일부비공개)

수업 28일차 - 다수 가위 바위 보

by MY블로그 2022. 11. 18.

메인 CPP에 와일문사용하면 else continue로 다시선택하기 가능.

클래스 만들어서 클래스 안에 메인을 넣은상태 > 멤버함수

(블랙잭 섯다는 스코프없이 선언되있는 전역함수/어디서든 접근이 가능)

 

플레이어수는 벡터로입력받아야함

 

erase 의 반환값은 iterator 의 지워진 주소값이다. 

녹음해둔 사용법 꼭 외워두자!

 

과제 > 학생기록부 만들기


RPlyaer.h
#pragma once
enum Value // 가위 바위 보
{
	ROCK, 
	SCISSORS,
	PAPER
};

enum Result // 결과 : 승 패 무승부
{
	WIN,
	DRAW,
	LOSE
};

class RPlayer // 플레이어의 구성
{
public: // 변수 구성
	string name; // 이름
	int value; // 값
	int result; // 결과값

public: // 함수 구성
	void Print();
};
RPlyaer.cpp
#include "stdafx.h"

void RPlayer::Print()
{
	cout << name << "\t"; // 제일앞에 이름이 출력되고 (탭간격 띄워주고)

	switch (value) // 그뒤에 값(가위 바위 보)가 출력이되며 (탭간격 띄워주고)
	{
	case ROCK:
		cout << "바위" << "\t";
		break;
	case SCISSORS:
		cout << "가위" << "\t";
		break;
	case PAPER:
		cout << "보" << "\t";
		break;
	}

	switch (result) // 마지막으로 승패의 결과가 출력이 된다. 
	{				// 한줄출력이끝나는부분이라 마지막출력후 줄바꿈
	case WIN:
		cout << "이김" << endl;
		break;
	case DRAW:
		cout << "비김" << endl;
		break;
	case LOSE:
		cout << "짐" << endl;
		break;
	}
}

RSP.h
#pragma once

class RSP
{
public: //퍼블릭 없어도되지만 변수와 함수를 나누기위해서 (가독성)
	int size; // 인원수 입력받을 변수 선언
	int input; // 입력받을 변수 선언
	int Rcount; // 바위 카운트 변수 선언
	int Scount; // 가위 카운트 변수 선언
	int Pcount; // 보 카운트 변수 선언

	vector<RPlayer> players;  // 벡터 배열 만들기
	// 동적할당으로 인원수 확정하고
	// 패배플레이어는 빠져야하기때문에 벡터를 사용한다.

public: //함수나눠놓은 퍼블릭. 큰의미는 x (가독성)
	void PlayRSP();
};
RSP.cpp
#include "stdafx.h"

void RSP::PlayRSP()
{ // cpp파일에는 정의만두고 선언은 헤더파일로!
	cout << "플레이어 수 : "; cin >> size; // size 변수 선언 헤더파일에있음
	players.resize(size); // 선언으로 사이즈 초기화! 리사이즈!

	for (int i = 0; i < players.size(); i++) 
	{ // 플레이어인원수만큼 포문돌려서 이름입력
		cout << i+1 << "번째 이름 : "; 
		cin >> players[i].name;
	}

	while (true) // 반복문시작
	{
		cout << "안내면 진거 가위 바위 보" << endl;
		cin >> input;

		Rcount = 0; // 가위 바위 보 카운트 0으로 시작에 초기화
		Scount = 0;
		Pcount = 0;

		for (int i = 0; i < players.size(); i++)
		{
			players[i].value = rand() % 3; //값은 0 1 2 중 랜덤으로

			switch (players[i].value) // 플레이어의 값에따라 카운트 추가
			{
			case ROCK:
				Rcount++;
				break;
			case SCISSORS:
				Scount++;
				break;
			case PAPER:
				Pcount++;
				break;
			}
		}

		for (int i = 0; i < players.size(); i++) // 경우의 수를 잘 파악해야 한다!!!!!
		{
			//무승부
			if ((Rcount == players.size()) || (Scount == players.size()) || 
				(Pcount == players.size())) // 가위 바위 보 의 갯수가 인원수랑 같다면 
			{								// 한종류의 값만 나왔다는것 = 이는 동점을의미함
				players[i].result = DRAW;
			}
			else if ((Rcount != 0) && (Scount != 0) && (Pcount != 0))
			{ // 가위 바위 보가 전부 하나도 안나오지않았을때!  즉, 모든 경우가 나왔을때 무승부
				players[i].result = DRAW;
			}
			else //승패
			{
				if (Rcount == 0) //가위 보
				{ // 바위의 카운트가 0일경우 > 바위빼고 2개의 경우가있을때
					for (int i = 0; i < players.size(); i++)
					{
						if (players[i].value == SCISSORS)
						{ // 가위를 가진 플레이어가 승리
							players[i].result = WIN;
						}
						else
						{ // 보를 가진 플레이어가 패배
							players[i].result = LOSE;
						}
					}
				}
				else if (Scount == 0) //바위 보
				{ // 가위의 카운트가 0일경우 > 가위빼고 2개의 경우가 있을때
					for (int i = 0; i < players.size(); i++)
					{
						if (players[i].value == PAPER)
						{ // 보를 가진 플레이어가 승리
							players[i].result = WIN;
						}
						else
						{ // 바위를 가진 플레이어가 패배
							players[i].result = LOSE;
						}
					}
				}
				else //바위 가위
				{ //위의 2개경우 외 보의 카운트가 0개이면 바위와 가위만 있는경우
					for (int i = 0; i < players.size(); i++)
					{ 
						if (players[i].value == ROCK)
						{// 바위를 가진 플레이어가 승리
							players[i].result = WIN;
						}
						else
						{// 가위를 가진 플레이어가 패배
							players[i].result = LOSE;
						}
					}
				}
			}
		}

		//출력 - 출력은 플레이어가 가지고있는게좋다 ( 이름도 가지고있고 값도 가지고있기때문)
		for (int i = 0; i < players.size(); i++) // 승패 구성이 완료된후 출력시킨다.
		{
			players[i].Print(); // 플레이어[i],가 가진 이름 값 결과를 접근해서 출력시킨다.
		}

		//진사람 빼기. ------------------------------기존에 우리라면 이런식으로 빼도된다.
		/*for (int i = 0; i < players.size(); i++) --이터레이터를 사용하는 방식으로 쓰도록하자.
		{
			if (players[i].result == LOSE)
			{
				players.erase(players.begin() + i);
				i--;
			}
		}*/


		//이터는 포인터 같은 사용을 한다.(주소를 가르킨다)
		for (vector< RPlayer>::iterator it = players.begin(); it != players.end();)
		{  // 이터레이터를 사용하여 플레이어의 시작부분 부터~ 끝부분이아닌곳까지(끝앞부분)반복
			if ((*it).result == LOSE) // 배열시작~끝부분중 패배가 있다면
			{
				it = players.erase(it); // LOSE플레이어는 erase되고 그자리부터 다시검사
				// 삭제되고 이터가 ++ 되버리면 삭제뒤에당겨진 배열은 검사를 건너뛰게된다!
			}
			else
			{
				it++; // 패배가없다면 배열하나그냥 증가시켜서 검사진행 
			}
		} // 이부분은 정말 중요하다. 이터레이터와 벡터의 erase 기능에 아주중요한 규칙이다.
		  // 지워진부분을 검사시작점으로 정해주지않는다면 뒤에있는 배열이 앞으로 당겨지면서
		  // 만일 바로 뒷부분도 지워야된다면 당겨진부분의배열이 그자리-1 위치이기때문에
		  // 그부분은 검사가진행되지않는다! 때문에 지워져서 배열이 당겨지는 경우는
		  // 지워진 자리가 바로뒷자리에있던 배열이 들어오기때문에 주의하자!

		if (players.size() == 1) // 최후 플레이어가 1명이 나오는경우 승리자 출력
		{
			cout << players[0].name << "승리!" << endl; //지워지면서 배열은 당겨지고
										//최후의 한자리는 맨앞이되기때문에 0배열출력
			break;  // 반복문을 탈출하게되면 RSP 게임밖으로나가진다. 
					// 게임선택 화면으로 갈수있다.
		}
	}
}

 

 

 

 

 

댓글