【C言語】勝つまでじゃんけんするプログラムの書き方

この記事では、C言語を使って「勝つまでじゃんけんするプログラム」を作成する方法を学びます。

じゃんけんのルールやプログラムの基本構成から始まり、ユーザーの手を選ぶ方法、コンピュータの手を生成する方法、勝敗を判定するロジックまで、段階を追ってわかりやすく解説します。

プログラムを通じて、C言語の基本的な使い方を身につけることができるので、初心者の方でも安心して取り組めます。

目次から探す

じゃんけんプログラムの概要

じゃんけんは、日本で非常に人気のあるゲームで、手を使って勝敗を決めるシンプルなルールが特徴です。

このプログラムでは、ユーザーがコンピュータとじゃんけんを行い、勝つまで繰り返すという形式で実装します。

以下では、じゃんけんの基本的なルールと、このプログラムの目的について詳しく説明します。

じゃんけんのルール

じゃんけんは、通常「グー」「チョキ」「パー」の3つの手を使って行います。

それぞれの手には以下のような勝敗の関係があります。

  • グーはチョキに勝つ(グー > チョキ)
  • チョキはパーに勝つ(チョキ > パー)
  • パーはグーに勝つ(パー > グー)

また、同じ手を出した場合は引き分けとなります。

このルールを基に、プログラムではユーザーとコンピュータが対戦し、勝敗を判定します。

プログラムの目的

このプログラムの目的は、ユーザーがコンピュータとじゃんけんを行い、勝つまで繰り返すことです。

具体的には、以下の機能を実装します。

  1. ユーザーが手を選択できるようにする。
  2. コンピュータがランダムに手を選ぶ。
  3. 勝敗を判定し、結果を表示する。
  4. ユーザーが勝つまでこのプロセスを繰り返す。

このプログラムを通じて、C言語の基本的な構文や制御構造、関数の使い方を学ぶことができます。

また、プログラムの実行を通じて、ユーザーはじゃんけんのルールを理解し、プログラミングの楽しさを体験できるでしょう。

プログラムの基本構成

C言語でじゃんけんを実装するためには、プログラムの基本構成を理解することが重要です。

ここでは、必要なライブラリのインクルード、メイン関数の定義、そして変数の宣言について詳しく解説します。

必要なライブラリのインクルード

C言語では、標準ライブラリを使用して様々な機能を利用します。

じゃんけんプログラムでは、ユーザーからの入力を受け取ったり、乱数を生成したりするために、以下のライブラリをインクルードします。

#include <stdio.h>  // 入出力関数を使用するため
#include <stdlib.h> // rand()関数を使用するため
#include <time.h>   // 時間を取得するため
  • stdio.h: 標準入出力ライブラリで、printfscanfなどの関数を使用するために必要です。
  • stdlib.h: 標準ライブラリで、乱数生成に必要なrand関数を使用します。
  • time.h: 現在の時間を取得するために使用し、乱数の初期化に役立ちます。

メイン関数の定義

C言語のプログラムは、必ずmain関数から始まります。

この関数がプログラムのエントリーポイントとなります。

以下のように定義します。

int main() {
    // プログラムの処理をここに書く
    return 0; // プログラムの終了を示す
}
  • int main(): main関数の定義です。

戻り値の型はintで、プログラムが正常に終了したことを示すためにreturn 0;を使用します。

変数の宣言

プログラム内で使用する変数を宣言します。

じゃんけんプログラムでは、ユーザーの手、コンピュータの手、勝敗のカウントなどを管理するための変数が必要です。

以下のように宣言します。

int userHand;      // ユーザーの手(0: グー, 1: チョキ, 2: パー)
int computerHand;  // コンピュータの手
int userWins = 0;  // ユーザーの勝利回数
int computerWins = 0; // コンピュータの勝利回数
  • userHand: ユーザーが選択した手を格納するための変数です。

グーを0、チョキを1、パーを2として扱います。

  • computerHand: コンピュータが選択した手を格納するための変数です。
  • userWinscomputerWins: それぞれユーザーとコンピュータの勝利回数をカウントするための変数です。

これで、プログラムの基本構成が整いました。

次のステップでは、ユーザーからの入力を取得する方法について解説します。

ユーザー入力の取得

じゃんけんプログラムでは、ユーザーが自分の手を選択する必要があります。

このセクションでは、ユーザーからの入力を取得し、その入力が正しいかどうかを検証する方法について説明します。

ユーザーの手を選択する

まず、ユーザーにじゃんけんの手を選んでもらうためのプロンプトを表示します。

一般的に、じゃんけんでは「グー」「チョキ」「パー」の3つの手が使われます。

これらの手を選択するために、ユーザーに数字を入力してもらう方法が一般的です。

例えば、以下のように入力を促すことができます。

#include <stdio.h>
int main() {
    int userHand;
    // ユーザーに手を選択させる
    printf("じゃんけんをしましょう!\n");
    printf("0: グー, 1: チョキ, 2: パー\n");
    printf("あなたの手を選んでください (0, 1, 2): ");
    scanf("%d", &userHand);
    // ここで入力を検証する
    return 0;
}

このコードでは、ユーザーに 0 1 2 のいずれかを入力するように促しています。

scanf関数を使って、ユーザーの入力をuserHandという変数に格納します。

入力の検証

ユーザーが入力した値が正しいかどうかを確認するために、入力の検証を行います。

ユーザーが 0 1 2 以外の値を入力した場合、エラーメッセージを表示し、再度入力を促すようにします。

以下のように実装できます。

#include <stdio.h>
int main() {
    int userHand;
    while (1) {
        // ユーザーに手を選択させる
        printf("じゃんけんをしましょう!\n");
        printf("0: グー, 1: チョキ, 2: パー\n");
        printf("あなたの手を選んでください (0, 1, 2): ");
        scanf("%d", &userHand);
        // 入力の検証
        if (userHand >= 0 && userHand <= 2) {
            break; // 正しい入力の場合、ループを抜ける
        } else {
            printf("無効な入力です。0, 1, 2のいずれかを入力してください。\n");
        }
    }
    // 正しい手が選ばれた後の処理
    printf("あなたは %d を選びました。\n", userHand);
    return 0;
}

このコードでは、whileループを使用して、ユーザーが正しい入力をするまで繰り返し入力を促します。

if文を使って、入力が 0 1 2 のいずれかであるかを確認し、正しい場合はループを抜けます。

無効な入力があった場合は、エラーメッセージを表示して再度入力を促します。

このようにして、ユーザーからの入力を安全に取得し、正しい手を選択させることができます。

次のセクションでは、コンピュータの手を生成する方法について説明します。

コンピュータの手の生成

じゃんけんプログラムでは、コンピュータがランダムに手を選ぶ必要があります。

このセクションでは、ランダム数生成の方法と、生成したランダム数を使ってコンピュータの手を決定するロジックについて解説します。

ランダム数生成の利用

C言語では、stdlib.hライブラリに含まれるrand()関数を使用してランダムな数を生成します。

しかし、rand()関数は毎回同じシーケンスの数を生成するため、プログラムを実行するたびに異なる結果を得るためには、乱数のシードを設定する必要があります。

これにはtime.hライブラリのtime()関数を利用します。

以下のコードは、乱数のシードを設定し、0から2の範囲でランダムな数を生成する方法を示しています。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
    // 乱数のシードを設定
    srand(time(NULL));
    // 0から2の範囲でランダムな数を生成
    int computerHand = rand() % 3; // 0: グー, 1: チョキ, 2: パー
    printf("コンピュータの手: %d\n", computerHand);
    return 0;
}

このコードでは、srand(time(NULL));によって現在の時刻をシードとして設定し、rand() % 3で0から2の範囲の整数を生成しています。

これにより、コンピュータの手がグー(0)、チョキ(1)、パー(2)のいずれかになります。

コンピュータの手を決定するロジック

次に、生成したランダムな数を使って、コンピュータの手を決定するロジックを実装します。

具体的には、生成した数に応じて、対応する手を文字列として表示するようにします。

以下のコードは、コンピュータの手を決定し、表示する方法を示しています。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
    // 乱数のシードを設定
    srand(time(NULL));
    // 0から2の範囲でランダムな数を生成
    int computerHand = rand() % 3; // 0: グー, 1: チョキ, 2: パー
    // コンピュータの手を決定
    if (computerHand == 0) {
        printf("コンピュータの手: グー\n");
    } else if (computerHand == 1) {
        printf("コンピュータの手: チョキ\n");
    } else {
        printf("コンピュータの手: パー\n");
    }
    return 0;
}

このコードでは、if文を使って、生成したランダムな数に応じてコンピュータの手を表示しています。

これにより、ユーザーはコンピュータがどの手を出したのかを確認することができます。

このようにして、コンピュータの手をランダムに生成し、表示するロジックを実装することができました。

次のセクションでは、勝敗判定の実装について解説します。

勝敗判定の実装

じゃんけんプログラムの重要な部分は、勝敗を正確に判定することです。

このセクションでは、勝敗のルールを定義し、それに基づいて勝敗を判定する関数を作成します。

勝敗のルールを定義

じゃんけんの勝敗は、以下のルールに基づいて決まります。

  • グー(0)は、チョキ(1)に勝つ。
  • チョキ(1)は、パー(2)に勝つ。
  • パー(2)は、グー(0)に勝つ。
  • 同じ手の場合は引き分け。

これをプログラムで表現するために、勝敗を判定するための条件を考えます。

具体的には、ユーザーの手とコンピュータの手を比較し、勝敗を決定します。

勝敗を判定する関数の作成

次に、勝敗を判定する関数を作成します。

この関数は、ユーザーの手とコンピュータの手を引数として受け取り、勝敗の結果を返します。

以下にそのサンプルコードを示します。

#include <stdio.h>
// 勝敗を判定する関数
// user手: ユーザーの手 (0: グー, 1: チョキ, 2: パー)
// computer手: コンピュータの手 (0: グー, 1: チョキ, 2: パー)
int judge(int user, int computer) {
    if (user == computer) {
        // 引き分け
        return 0;
    } else if ((user == 0 && computer == 1) || 
               (user == 1 && computer == 2) || 
               (user == 2 && computer == 0)) {
        // ユーザーの勝ち
        return 1;
    } else {
        // コンピュータの勝ち
        return -1;
    }
}

この関数では、まずユーザーの手とコンピュータの手が同じ場合は引き分け(0)を返します。

次に、ユーザーが勝つ条件を満たす場合は1を返し、それ以外の場合は-1を返します。

この関数をメインプログラムに組み込むことで、勝敗を判定し、結果を表示することができます。

次のセクションでは、勝つまで繰り返すロジックを実装していきます。

勝つまで繰り返すロジック

じゃんけんプログラムの核心部分は、プレイヤーが勝つまで繰り返しじゃんけんを行うロジックです。

このセクションでは、ループの構造と勝利条件の設定について詳しく解説します。

ループの構造

C言語では、繰り返し処理を行うためにwhile文やfor文を使用します。

ここでは、while文を使って、プレイヤーが勝つまでじゃんけんを続ける構造を作成します。

以下は、ループの基本的な構造です。

while (勝利していない) {
    // ユーザーの手を取得
    // コンピュータの手を生成
    // 勝敗を判定
}

このループは、プレイヤーが勝つまで続きます。

具体的には、勝利条件を満たすまで、ユーザーの手を取得し、コンピュータの手を生成し、勝敗を判定する処理を繰り返します。

勝利条件の設定

勝利条件を設定するためには、プレイヤーが勝ったかどうかを判定する必要があります。

勝利条件は、勝敗判定の結果に基づいて決まります。

以下のように、勝利条件を設定することができます。

int playerWins = 0; // プレイヤーの勝利回数
int computerWins = 0; // コンピュータの勝利回数
while (playerWins < 1) { // プレイヤーが1回でも勝つまでループ
    // ユーザーの手を取得
    // コンピュータの手を生成
    // 勝敗を判定
    if (勝った場合) {
        playerWins++; // プレイヤーの勝利回数を増やす
        printf("あなたの勝ちです!\n");
    } else if (負けた場合) {
        computerWins++; // コンピュータの勝利回数を増やす
        printf("コンピュータの勝ちです。\n");
    } else {
        printf("引き分けです。\n");
    }
}

このコードでは、playerWinsが1以上になるまでループが続きます。

勝敗判定の結果に応じて、プレイヤーまたはコンピュータの勝利回数を増やし、勝利した場合にはメッセージを表示します。

このようにして、勝つまでじゃんけんを繰り返すロジックを実装することができます。

次のセクションでは、結果の表示について解説します。

結果の表示

じゃんけんプログラムの最後の部分では、勝敗の結果を表示し、プレイヤーにメッセージを送ることが重要です。

このセクションでは、勝敗結果の出力方法と、プレイヤーへのメッセージの表示方法について詳しく解説します。

勝敗結果の出力

勝敗結果を出力するためには、まず勝敗を判定した結果をもとに、どちらが勝ったのかを表示する必要があります。

以下のように、勝敗の結果に応じて異なるメッセージを表示することができます。

// 勝敗結果を表示する関数
void displayResult(int playerChoice, int computerChoice, int result) {
    // 手の選択を表示
    printf("あなたの手: %s\n", choiceToString(playerChoice));
    printf("コンピュータの手: %s\n", choiceToString(computerChoice));
    // 勝敗結果を表示
    if (result == 1) {
        printf("あなたの勝ちです!\n");
    } else if (result == -1) {
        printf("コンピュータの勝ちです。\n");
    } else {
        printf("引き分けです。\n");
    }
}
// 手の選択を文字列に変換する関数
const char* choiceToString(int choice) {
    switch (choice) {
        case 0: return "グー";
        case 1: return "チョキ";
        case 2: return "パー";
        default: return "不明";
    }
}

このコードでは、displayResult関数が勝敗結果を表示します。

choiceToString関数を使って、数値で表された手を日本語の文字列に変換しています。

これにより、プレイヤーにとってわかりやすい出力が実現できます。

プレイヤーへのメッセージ

勝敗結果を表示した後、プレイヤーに対して励ましのメッセージや次回への期待を込めたメッセージを表示することも良いアイデアです。

これにより、プレイヤーはゲームを楽しむことができ、次回も挑戦したくなるでしょう。

// プレイヤーへのメッセージを表示する関数
void displayMessage(int result) {
    if (result == 1) {
        printf("素晴らしい!次も頑張ってください!\n");
    } else if (result == -1) {
        printf("残念でした。次は勝てるように頑張りましょう!\n");
    } else {
        printf("引き分けですね。次は決着をつけましょう!\n");
    }
}

このdisplayMessage関数では、勝敗に応じたメッセージを表示します。

勝った場合は称賛し、負けた場合は励ましの言葉をかけることで、プレイヤーのモチベーションを高めることができます。

以上のように、勝敗結果の出力とプレイヤーへのメッセージを工夫することで、じゃんけんプログラムをより魅力的にすることができます。

これにより、プレイヤーはゲームを楽しみながら、次回の挑戦に意欲を持つことができるでしょう。

完成したコード

ここまでのコードを組み合わせて完成させたものがこちらです。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

// 勝敗を判定する関数
// user手: ユーザーの手 (0: グー, 1: チョキ, 2: パー)
// computer手: コンピュータの手 (0: グー, 1: チョキ, 2: パー)
int judge(int user, int computer) {
    if (user == computer) {
        // 引き分け
        return 0;
    } else if ((user == 0 && computer == 1) || 
               (user == 1 && computer == 2) || 
               (user == 2 && computer == 0)) {
        // ユーザーの勝ち
        return 1;
    } else {
        // コンピュータの勝ち
        return -1;
    }
}

int input_hand() {
    int userHand;
    while (1) {
        // ユーザーに手を選択させる
        printf("じゃんけんをしましょう!\n");
        printf("0: グー, 1: チョキ, 2: パー\n");
        printf("あなたの手を選んでください (0, 1, 2): ");
        scanf("%d", &userHand);
        // 入力の検証
        if (userHand >= 0 && userHand <= 2) {
            break; // 正しい入力の場合、ループを抜ける
        } else {
            printf("無効な入力です。0, 1, 2のいずれかを入力してください。\n");
        }
    }
    return userHand;
}

// 0: グー, 1: チョキ, 2: パー
int get_randomhand() {
    return rand() % 3;
}

// 手の選択を文字列に変換する関数
const char* choiceToString(int choice) {
    switch (choice) {
        case 0: return "グー";
        case 1: return "チョキ";
        case 2: return "パー";
        default: return "不明";
    }
}

// 勝敗結果を表示する関数
void displayResult(int playerChoice, int computerChoice, int result) {
    // 手の選択を表示
    printf("あなたの手: %s\n", choiceToString(playerChoice));
    printf("コンピュータの手: %s\n", choiceToString(computerChoice));
    // 勝敗結果を表示
    if (result == 1) {
        printf("あなたの勝ちです!\n");
    } else if (result == -1) {
        printf("コンピュータの勝ちです。\n");
    } else {
        printf("引き分けです。\n");
    }
}

// プレイヤーへのメッセージを表示する関数
// 今回は未使用
void displayMessage(int result) {
    if (result == 1) {
        printf("素晴らしい!次も頑張ってください!\n");
    } else if (result == -1) {
        printf("残念でした。次は勝てるように頑張りましょう!\n");
    } else {
        printf("引き分けですね。次は決着をつけましょう!\n");
    }
}

int main() {
    // 乱数のシードを設定
    srand(time(NULL));

    int playerWins = 0; // プレイヤーの勝利回数
    int computerWins = 0; // コンピュータの勝利回数

    while (playerWins < 1) { // プレイヤーが1回でも勝つまでループ
        // ユーザーの手を取得
        int playerChoice = input_hand();
        // コンピュータの手を生成
        int computerChoice = get_randomhand();

        int result = judge(playerChoice, computerChoice);

        // 勝敗を判定
        displayResult(playerChoice, computerChoice, result);

        if(result == 1) {
            playerWins++;
        } else if(result == -1) {
            computerWins++;
        }
    }

    // プレイヤーへのメッセージを表示
    printf("あなたが1回勝利するまでにCPUが勝利した回数: %d\n", computerWins);

    return 0;
}

実行するとじゃんけんが始まり、プレイヤーが一回勝利できるまでループします。

じゃんけんをしましょう!
0: グー, 1: チョキ, 2: パー
あなたの手を選んでください (0, 1, 2): 2
あなたの手: パー
コンピュータの手: チョキ
コンピュータの勝ちです。
じゃんけんをしましょう!
0: グー, 1: チョキ, 2: パー
あなたの手を選んでください (0, 1, 2): 1
あなたの手: チョキ
コンピュータの手: チョキ
引き分けです。
じゃんけんをしましょう!
0: グー, 1: チョキ, 2: パー
あなたの手を選んでください (0, 1, 2): 1
あなたの手: チョキ
コンピュータの手: チョキ
引き分けです。
じゃんけんをしましょう!
0: グー, 1: チョキ, 2: パー
あなたの手を選んでください (0, 1, 2): 2
あなたの手: パー
コンピュータの手: チョキ
コンピュータの勝ちです。
じゃんけんをしましょう!
0: グー, 1: チョキ, 2: パー
あなたの手を選んでください (0, 1, 2): 3
無効な入力です。0, 1, 2のいずれかを入力してください。
じゃんけんをしましょう!
0: グー, 1: チョキ, 2: パー
あなたの手を選んでください (0, 1, 2): 2
あなたの手: パー
コンピュータの手: チョキ
コンピュータの勝ちです。
じゃんけんをしましょう!
0: グー, 1: チョキ, 2: パー
あなたの手を選んでください (0, 1, 2): 1
あなたの手: チョキ
コンピュータの手: グー
コンピュータの勝ちです。
じゃんけんをしましょう!
0: グー, 1: チョキ, 2: パー
あなたの手を選んでください (0, 1, 2): 1
あなたの手: チョキ
コンピュータの手: グー
コンピュータの勝ちです。
じゃんけんをしましょう!
0: グー, 1: チョキ, 2: パー
あなたの手を選んでください (0, 1, 2): 1
あなたの手: チョキ
コンピュータの手: パー
あなたの勝ちです!
あなたが1回勝利するまでにCPUが勝利した回数: 5

このようにループし、勝つまでじゃんけんするプログラムが完成しました。

プログラムのテストとデバッグ

プログラムが正しく動作することを確認するためには、テストとデバッグが不可欠です。

このセクションでは、じゃんけんプログラムのテストケースの作成方法と、デバッグのポイントについて解説します。

テストケースの作成

テストケースは、プログラムが期待通りに動作するかを確認するための具体的なシナリオです。

じゃんけんプログラムの場合、以下のようなテストケースを考えることができます。

  1. ユーザーが「グー」を選択した場合
  • コンピュータが「チョキ」を選択 → ユーザーの勝ち
  • コンピュータが「パー」を選択 → コンピュータの勝ち
  • コンピュータが「グー」を選択 → 引き分け
  1. ユーザーが「チョキ」を選択した場合
  • コンピュータが「パー」を選択 → ユーザーの勝ち
  • コンピュータが「グー」を選択 → コンピュータの勝ち
  • コンピュータが「チョキ」を選択 → 引き分け
  1. ユーザーが「パー」を選択した場合
  • コンピュータが「グー」を選択 → ユーザーの勝ち
  • コンピュータが「チョキ」を選択 → コンピュータの勝ち
  • コンピュータが「パー」を選択 → 引き分け

これらのテストケースを実行することで、プログラムが正しく勝敗を判定できるかを確認します。

また、ユーザー入力の検証が正しく行われているかもチェックする必要があります。

例えば、無効な入力(数字や記号など)があった場合に、プログラムが適切にエラーメッセージを表示するかどうかを確認します。

デバッグのポイント

デバッグは、プログラムのバグを見つけて修正するプロセスです。

以下のポイントに注意してデバッグを行うと、効率的に問題を解決できます。

  1. エラーメッセージの確認
  • プログラムがエラーを出力した場合、そのメッセージをよく読み、どの部分に問題があるのかを特定します。
  1. 逐次的なテスト
  • プログラムの各部分を個別にテストし、どの部分が正しく動作していないかを確認します。

例えば、ユーザー入力の取得部分や勝敗判定の部分をそれぞれテストします。

  1. デバッグ用の出力
  • プログラムの中にデバッグ用の出力(printf文など)を追加し、変数の値やプログラムの流れを確認します。

これにより、どの時点で期待通りの動作をしていないかを把握できます。

  1. ロジックの見直し
  • 勝敗判定やループの条件など、プログラムのロジックを見直し、誤りがないかを確認します。

特に、条件分岐やループの条件が正しく設定されているかは重要です。

  1. 他の人にコードを見てもらう
  • 自分では気づかないバグがあるかもしれません。

他の人にコードを見てもらい、意見をもらうことで新たな視点から問題を発見できることがあります。

これらのテストとデバッグの手法を用いることで、じゃんけんプログラムの品質を向上させ、ユーザーにとって使いやすいプログラムを作成することができます。

目次から探す