가위바위보는 전 세계적으로 인기 있는 손 게임입니다. 단순하면서도 심리전 요소가 있어 많은 사람에게 사랑받고 있습니다. 이 게임의 규칙은 다음과 같습니다:
- 가위는 보를 이깁니다.
- 바위는 가위를 이깁니다.
- 보는 바위를 이깁니다.
주어진 입력에 따라 두 플레이어(Player1, Player2)의 가위바위보 게임 결과를 판별하는 프로그램을 작성해야 합니다.
입력 형식
첫 줄에는 총 게임 횟수를 나타내는 정수 N (1 ≤ N ≤ 100)이 주어집니다.
이어지는 N개의 각 줄에는 Player1과 Player2가 낸 선택이 공백으로 구분되어 주어집니다. 선택은 "Rock", "Scissors", "Paper" 중 하나이며, 대소문자를 구분합니다.
N
S1 S2
...
출력 형식
N개의 줄에 걸쳐 각 게임의 승자를 출력합니다. Player1이 이기면 "Player1", Player2가 이기면 "Player2"를 출력합니다. 비기면 "Tie"를 출력합니다.
입력 예시
3
Rock Scissors
Paper Paper
Rock Paper
출력 예시
Player1
Tie
Player2
이 문제는 다양한 방식으로 해결할 수 있으며, 코드를 점진적으로 개선하는 과정을 통해 C++ 프로그래밍 기법을 익힐 수 있습니다.
접근 방식 1: 단순 조건문 활용
가장 직관적인 방법은 모든 가능한 경우의 수를 직접 비교하는 것입니다. 승리 조건, 무승부 조건, 그리고 그 외의 패배 조건을 순서대로 검사할 수 있습니다. 예를 들어, Player1이 이기는 세 가지 경우를 먼저 확인하고, 그 다음 무승부 조건을 확인한 후, 나머지 경우는 Player2의 승리로 처리할 수 있습니다.
#include <iostream>
#include <string> // std::string을 사용하기 위해 포함
int main() {
std::ios_base::sync_with_stdio(false); // 입출력 속도 향상
std::cin.tie(NULL); // std::cin과 std::cout의 동기화 해제
int gameCount;
std::cin >> gameCount;
for (int i = 0; i < gameCount; ++i) {
std::string player1Move, player2Move;
std::cin >> player1Move >> player2Move;
// Player1이 이기는 경우
if ((player1Move == "Rock" && player2Move == "Scissors") ||
(player1Move == "Scissors" && player2Move == "Paper") ||
(player1Move == "Paper" && player2Move == "Rock")) {
std::cout << "Player1\n";
}
// 무승부인 경우
else if (player1Move == player2Move) {
std::cout << "Tie\n";
}
// 그 외 모든 경우 (Player2 승리)
else {
std::cout << "Player2\n";
}
}
return 0;
}
접근 방식 2: 문자열 첫 글자 비교
이전 방식에서 문자열 전체를 비교하는 대신, 각 선택의 첫 글자만 비교하여 효율성을 높일 수 있습니다. "Rock", "Scissors", "Paper"는 모두 다른 첫 글자(R, S, P)를 가지고 있으므로 이 방법이 유효합니다.
#include <iostream>
#include <string>
int main() {
std::ios_base::sync_with_stdio(false);
std::cin.tie(NULL);
int numGames;
std::cin >> numGames;
for (int i = 0; i < numGames; ++i) {
std::string p1Choice, p2Choice;
std::cin >> p1Choice >> p2Choice;
char p1Initial = p1Choice[0];
char p2Initial = p2Choice[0];
// Player1 승리 조건 (첫 글자 비교)
if ((p1Initial == 'R' && p2Initial == 'S') ||
(p1Initial == 'S' && p2Initial == 'P') ||
(p1Initial == 'P' && p2Initial == 'R')) {
std::cout << "Player1\n";
}
// 무승부 조건
else if (p1Initial == p2Initial) {
std::cout << "Tie\n";
}
// Player2 승리 조건
else {
std::cout << "Player2\n";
}
}
return 0;
}
접근 방식 3: 함수를 이용한 모듈화
코드의 가독성을 높이고 재사용성을 위해 게임 결과 판별 로직을 별도의 함수로 분리할 수 있습니다. 메인 함수는 입력과 출력을 담당하고, 승패 판정은 다른 함수에 위임합니다.
#include <iostream>
#include <string>
// 게임 결과를 판별하여 정수형으로 반환하는 함수
// 0: Tie, 1: Player1 승리, 2: Player2 승리
int determineWinner(const std::string& p1Choice, const std::string& p2Choice) {
char p1Initial = p1Choice[0];
char p2Initial = p2Choice[0];
if ((p1Initial == 'R' && p2Initial == 'S') ||
(p1Initial == 'S' && p2Initial == 'P') ||
(p1Initial == 'P' && p2Initial == 'R')) {
return 1; // Player1 승리
} else if (p1Initial == p2Initial) {
return 0; // 무승부
} else {
return 2; // Player2 승리
}
}
int main() {
std::ios_base::sync_with_stdio(false);
std::cin.tie(NULL);
int numGames;
std::cin >> numGames;
for (int i = 0; i < numGames; ++i) {
std::string player1Move, player2Move;
std::cin >> player1Move >> player2Move;
int result = determineWinner(player1Move, player2Move);
if (result == 1) {
std::cout << "Player1\n";
} else if (result == 2) {
std::cout << "Player2\n";
} else {
std::cout << "Tie\n";
}
}
return 0;
}
접근 방식 4: 수치화 및 모듈로 연산 활용
가위바위보 게임은 순환적인 특징을 가집니다. 이를 수치화하여 모듈로(%) 연산을 통해 승패를 판정할 수 있습니다. 예를 들어, 바위=0, 가위=1, 보=2와 같이 값을 할당합니다. Player1의 선택 값에서 Player2의 선택 값을 뺀 후 3으로 나눈 나머지를 통해 결과를 예측할 수 있습니다.
여기서 중요한 규칙은 `(Player1_값 - Player2_값 + 3) % 3` 입니다:
- 결과가 0이면 무승부 (Player1_값 == Player2_값)
- 결과가 1이면 Player2 승리
- 결과가 2이면 Player1 승리
#include <iostream>
#include <string>
// 가위바위보 선택을 정수 값으로 변환하는 함수
// Rock: 0, Scissors: 1, Paper: 2
int getMoveValue(const std::string& choice) {
char initial = choice[0];
if (initial == 'R') return 0; // Rock
if (initial == 'S') return 1; // Scissors
return 2; // Paper
}
int main() {
std::ios_base::sync_with_stdio(false);
std::cin.tie(NULL);
int numRounds;
std::cin >> numRounds;
for (int i = 0; i < numRounds; ++i) {
std::string move1, move2;
std::cin >> move1 >> move2;
int val1 = getMoveValue(move1);
int val2 = getMoveValue(move2);
// Player1과 Player2의 값 차이를 이용한 승패 판정
// (Player1_값 - Player2_값 + 3) % 3
// 결과 0: Tie, 1: Player2 승리, 2: Player1 승리
int outcome = (val1 - val2 + 3) % 3;
if (outcome == 0) { // 무승부
std::cout << "Tie\n";
} else if (outcome == 2) { // Player1 승리
std::cout << "Player1\n";
} else { // outcome == 1, Player2 승리
std::cout << "Player2\n";
}
}
return 0;
}
접근 방식 5: 결과 메시지 배열 활용
이전 방식에서 도출된 모듈로 연산 결과를 인덱스로 사용하여 미리 정의된 결과 메시지 배열에서 직접 출력값을 가져올 수 있습니다. 이렇게 하면 조건문을 줄이고 코드를 더욱 간결하게 만들 수 있습니다.
#include <iostream>
#include <string>
#include <vector> // std::vector를 사용하기 위해 포함
// 가위바위보 선택을 정수 값으로 변환하는 함수
// Rock: 0, Scissors: 1, Paper: 2
int getMoveNumericalValue(const std::string& choice) {
char initial = choice[0];
if (initial == 'R') return 0; // Rock
if (initial == 'S') return 1; // Scissors
return 2; // Paper
}
int main() {
std::ios_base::sync_with_stdio(false);
std::cin.tie(NULL);
int totalGames;
std::cin >> totalGames;
// (val1 - val2 + 3) % 3 결과에 따른 메시지 배열
// 인덱스 0: Tie
// 인덱스 1: Player2 승리
// 인덱스 2: Player1 승리
std::vector<std::string> gameResults = {"Tie\n", "Player2\n", "Player1\n"};
for (int i = 0; i < totalGames; ++i) {
std::string firstPlayerMove, secondPlayerMove;
std::cin >> firstPlayerMove >> secondPlayerMove;
int firstVal = getMoveNumericalValue(firstPlayerMove);
int secondVal = getMoveNumericalValue(secondPlayerMove);
int resultIndex = (firstVal - secondVal + 3) % 3;
std::cout << gameResults[resultIndex];
}
return 0;
}
접근 방식 6: STL `std::map` 활용
문자열로 된 선택을 정수 값으로 변환하는 작업을 `std::map`을 사용하여 더욱 유연하게 처리할 수 있습니다. 이는 특히 매핑할 문자열이 많거나 복잡할 때 유용합니다. `std::map`은 키-값 쌍을 저장하며, 키(여기서는 가위바위보 선택 문자열)를 통해 값(해당하는 정수)을 빠르게 찾을 수 있습니다.
#include <iostream>
#include <string>
#include <map> // std::map을 사용하기 위해 포함
#include <vector> // std::vector를 사용하기 위해 포함
int main() {
std::ios_base::sync_with_stdio(false);
std::cin.tie(NULL);
int roundCount;
std::cin >> roundCount;
// 가위바위보 선택 문자열을 정수 값으로 매핑
std::map<std::string, int> moveMap;
moveMap["Rock"] = 0;
moveMap["Scissors"] = 1;
moveMap["Paper"] = 2;
// 결과 메시지 배열 (인덱스: 0=Tie, 1=Player2, 2=Player1)
std::vector<std::string> finalOutcomes = {"Tie\n", "Player2\n", "Player1\n"};
for (int i = 0; i < roundCount; ++i) {
std::string p1Hand, p2Hand;
std::cin >> p1Hand >> p2Hand;
int p1Val = moveMap[p1Hand];
int p2Val = moveMap[p2Hand];
// (Player1_값 - Player2_값 + 3) % 3 결과에 따른 인덱스 계산
int outcomeIdx = (p1Val - p2Val + 3) % 3;
std::cout << finalOutcomes[outcomeIdx];
}
return 0;
}