🎮 じゃんけんゲーム - 解答と解説
課題2-1の要件
- プレイヤーとコンピュータでじゃんけん
- グー、チョキ、パーを数字で入力
- 勝敗判定の実装
- 継続的な対戦が可能
- 戦績の記録と表示
1. プログラムの実装 (rock_paper_scissors.c)
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef enum {
ROCK = 0,
SCISSORS = 1,
PAPER = 2
} Hand;
typedef struct {
int wins;
int losses;
int draws;
} Record;
void displayHands();
const char* getHandName(Hand hand);
int judgeWinner(Hand player, Hand computer);
void displayResult(int result);
void displayRecord(Record record);
int main() {
system("chcp 65001");
srand((unsigned int)time(NULL));
Record record = {0, 0, 0};
char continue_game;
printf("===じゃんけんゲーム===\n");
do {
displayHands();
Hand player_hand;
do {
printf("あなたの手を選んでください (0-2): ");
if (scanf_s("%d", (int*)&player_hand) != 1) {
while (getchar() != '\n');
printf("無効な入力です。\n");
continue;
}
} while (player_hand < ROCK || player_hand > PAPER);
Hand computer_hand = (Hand)(rand() % 3);
printf("\nあなた: %s\n", getHandName(player_hand));
printf("コンピュータ: %s\n", getHandName(computer_hand));
int result = judgeWinner(player_hand, computer_hand);
displayResult(result);
if (result == 1) record.wins++;
else if (result == -1) record.losses++;
else record.draws++;
displayRecord(record);
printf("\nもう一度プレイしますか? (y/n): ");
while (getchar() != '\n');
continue_game = getchar();
} while (continue_game == 'y' || continue_game == 'Y');
printf("\nゲームを終了します。\n");
return 0;
}
void displayHands() {
printf("\n0: グー\n1: チョキ\n2: パー\n\n");
}
const char* getHandName(Hand hand) {
switch (hand) {
case ROCK: return "グー";
case SCISSORS: return "チョキ";
case PAPER: return "パー";
default: return "不明";
}
}
int judgeWinner(Hand player, Hand computer) {
if (player == computer) return 0;
return ((player == ROCK && computer == SCISSORS) ||
(player == SCISSORS && computer == PAPER) ||
(player == PAPER && computer == ROCK)) ? 1 : -1;
}
void displayResult(int result) {
if (result == 1) printf("あなたの勝ち!\n");
else if (result == -1) printf("コンピュータの勝ち!\n");
else printf("引き分け!\n");
}
void displayRecord(Record record) {
printf("\n===戦績===\n");
printf("勝ち: %d\n", record.wins);
printf("負け: %d\n", record.losses);
printf("引き分け: %d\n", record.draws);
int total_games = record.wins + record.losses + record.draws;
if (total_games > 0) {
float win_rate = (float)record.wins / total_games * 100;
printf("勝率: %.1f%%\n", win_rate);
}
}
2. プログラムの解説
2.1 データ構造
- 列挙型
Hand
- じゃんけんの手を表現
- ROCK(0), SCISSORS(1), PAPER(2)の3種類
- 数値と手の対応を明確化
- 構造体
Record
- wins: 勝利数
- losses: 敗北数
- draws: 引き分け数
2.2 主要な関数
displayHands()
: 選択可能な手の表示
getHandName()
: 手の名前を取得
judgeWinner()
: 勝敗判定
- 戻り値: 1(勝ち), -1(負け), 0(引き分け)
displayResult()
: 対戦結果の表示
displayRecord()
: 戦績の表示
3. 改良のポイント
3.2 発展的な機能追加
- 戦績管理の強化
- ファイルへの保存
- プレイヤー名の登録
- 統計情報の表示
- ゲーム性の向上
- AI機能の実装
よくある間違いと注意点
- 入力処理
- 数値以外の入力チェック漏れ
- 範囲外の値のチェック漏れ
- 入力バッファの処理ミス
- 勝敗判定
- 戦績管理