4人で作るじゃんけんアプリ|WinFormsとGitHub Desktopで初めてのチーム開発

広告

グー・チョキ・パーを選んでコンピューターと対戦するアプリを、4人で作ります。目標は、各自のコードをブランチ → Commit → Push → PR → レビュー → マージ → Pullで1つのアプリへつなぐことです。Aはリーダーを兼ね、合計4人で取り組みます。

本編はデザイナー方式です。画面の位置・大きさ・文字の収まりを視覚的に確認し、チームで完成イメージを相談しながら作ります。ルールが身近な題材なので、分担とGit操作に集中できます。

完成するアプリと学習のゴール

  • グー・チョキ・パーのどれかを押すと、相手の手と勝敗を表示する。
  • 1回押すごとに1試合とし、引き分けも1試合に数える。勝ち・負け・引き分け・合計を表示する。
  • 「成績をリセット」で全件を0に戻す。終了時に成績は消える。保存・通信対戦は発展課題にする。
  • 全員が機能PRを1件作り、別の人のPRをレビューし、同じmainで起動する。
じゃんけん!
[グー] [チョキ] [パー]
あなた:グー  相手:チョキ
あなたの勝ち!
勝ち 1 / 負け 0 / 引き分け 0 / 合計 1
[成績をリセット]
完成画面の配置イメージです。実際のスクリーンショットではありません。

Step 0:環境と4人の担当を決める

Windows PC、Visual Studioの「.NET デスクトップ開発」、GitHub Desktop、各自のGitHubアカウントを用意します。講師が授業環境で使えるサポート中の.NET版を指定し、4人のSDKとターゲットフレームワークをそろえてください。.NET Framework版とは混在させません。C#のクラス・メソッド・if・プロパティ・イベントの基本を確認してから進めます。目安は50分×5〜7コマです。

担当役割担当ファイル作業ブランチレビューする人
A(リーダー)画面・イベント接続Form1.csとDesigner.cs・resxの変更分feature/janken-uiB
B相手の手を選ぶComputerPlayer.csfeature/computer-handC
C勝敗を判定するJudge.csfeature/judgeD
D成績を記録するScoreBoard.csfeature/score-boardA

共通ファイルJankenTypes.csの型と、各担当クラスのメソッド名・引数・戻り値は全員の約束です。変更が必要な場合は先に相談します。フォームのデザイナー操作はAだけが行い、自動生成されるDesigner.csを手作業で編集しません。

呼び出し役割
A → B:ChooseHand()相手の手を1つ受け取る
A → C:Decide(player, computer)あなたから見た勝敗を受け取る
A → D:Record(result)勝敗を1試合分記録する
A → D:Reset()と成績プロパティ成績を消去・表示する

Step 1:Aが共通ひな形を作って共有する

1-1:Visual Studioで作り、GitHub Desktopへ追加する

  1. AがC#・.NET版の「Windows Forms アプリ」を作成する。ソリューション名・プロジェクト名は両方TeamJankenAppにする。「場所」は作業する親フォルダーを選ぶ。
  2. チーム共通のフレームワークを選び、F5で空のフォームを起動して終了する。すべて保存する。Visual StudioではGitリポジトリを作らない。
  3. TeamJankenApp.slnまたはTeamJankenApp.slnxが入ったフォルダーを、フォルダーごとGitHub Desktopへドラッグ&ドロップする。
  4. Git未作成の案内でcreate a repository hereを選ぶ。Name:TeamJankenApp、Git ignore:VisualStudio、READMEの作成を選択する。
  5. 作成先がソリューションを含む既存フォルダーそのものであることを確認してCreate repository。内側に同名フォルダーを増やさない。既にGit管理されている場合はAdd repositoryで追加する。

完了条件:Repository → Show in Explorerでソリューションのあるフォルダーが開き、Current Branchがmainになっている。違うブランチ名なら共有前にAが変更します。.vs・bin・objなどの作業用ファイルは.gitignoreで除外します。B・C・Dは新規作成せず、後でCloneします。

1-2:共通の型と仮実装を追加する

ソリューションエクスプローラーでプロジェクトを右クリック → 追加 → クラスから、次の4ファイルを作り、内容全体を置き換えます。JankenTypes.csもこの操作で作り、最初のclass宣言を含めて置き換えて構いません。フォームにはまだ部品を配置しません。

JankenTypes.cs:全員共通の型
namespace TeamJankenApp
{
    public enum Hand { Rock, Scissors, Paper }
    public enum RoundResult { Win, Lose, Draw }
}

enum(列挙型)は、選択肢に名前を付けた型です。Rock=グー、Scissors=チョキ、Paper=パー。Win・Lose・Drawは「あなたから見た」勝ち・負け・引き分けです。

ComputerPlayer.cs:B用の仮実装
namespace TeamJankenApp
{
    public class ComputerPlayer
    {
        public Hand ChooseHand() => Hand.Rock;
    }
}
Judge.cs:C用の仮実装
namespace TeamJankenApp
{
    public class Judge
    {
        public RoundResult Decide(Hand player, Hand computer)
        {
            return RoundResult.Draw;
        }
    }
}
ScoreBoard.cs:D用の仮実装
namespace TeamJankenApp
{
    public class ScoreBoard
    {
        public int Wins { get; private set; }
        public int Losses { get; private set; }
        public int Draws { get; private set; }
        public int Total => Wins + Losses + Draws;
        public void Record(RoundResult result) { }
        public void Reset() { }
    }
}

まだゲームとしては完成していません。相手はグー、判定は引き分け、成績は0のままです。ただし型・メソッドが存在するので、Aは呼び出すコードを先に書けます。他の人の実装待ちによる「未定義」を防ぐひな形です。入力途中の赤い波線はあり得ますが、入力を終えたらビルドで確認します。

1-3:起動確認・Commit・共有をする

  1. すべて保存し、ビルド → ソリューションのビルド。F5で空のフォームが起動することを確認する。
  2. GitHub Desktopで差分を確認し、Summaryを「じゃんけんの共通型と仮実装を追加」にしてCommit to main。
  3. Publish repositoryを押し、リポジトリ名TeamJankenAppとKeep this code privateを確認してGitHubへ共有する。
  4. AがB・C・DをCollaboratorsとして招待し、3人は自分のアカウントで承認する。詳しい手順はGitHub Desktop と WinForms で始めるチーム開発の「1-4:チームメンバーの招待」を参照する。

完了条件:GitHubに共通ひな形があり、B・C・D全員がリポジトリを開ける。

Step 2:B・C・DがCloneして起動する

  1. B・C・Dは招待を承認し、Aが共有したGitHubのTeamJankenAppのリポジトリページを開く。所有者がAであることを確認する。
  2. 緑色のCodeボタンを押し、Open with GitHub Desktopを選ぶ。確認が表示されたら、GitHub Desktopを開くことを許可する。
  3. GitHub DesktopでリポジトリとLocal path(自分のPCの保存先)を確認し、Cloneを押す。
  4. Repository → Show in Explorerから.slnまたは.slnxを開き、ビルド・起動する。
  5. 全員がmainで同じひな形のコミットを受け取ったことをHistoryで確認する。

補足:ブラウザーからGitHub Desktopが開かない場合は、DesktopのFile → Clone repositoryでTeamJankenAppを選んでも同じようにクローンできます。一覧に見つからない場合は、URLタブにAが共有したリポジトリのURLを入力します。Download ZIPではGitの履歴を引き継げないため、この課題では使いません。

完了条件:4人とも空のフォームを起動できる。SDK不足は講師と環境をそろえ、各自で.csprojのフレームワークを変えません。

Step 3:全員が短い紹介ファイルで最初のPRを練習する

A → B → C → Dの順に1人ずつ行います。以下はBの例です。ほかの人は担当文字・ブランチ名・ファイル名を自分の担当に置き換えます。レビューはAのPRをB、BをC、CをD、DをAが担当します。

ブランチの考え方を先に確認:Gitにおける「featureブランチ」の役割と作り方では、担当作業を分ける理由と、PR・マージまでの流れを解説しています。mainの役割から確認したい人は、Gitにおける「main」ブランチの意味と大切さも参照してください。参考記事のコマンドを入力する必要はありません。この課題の操作は、以下のGitHub Desktopの手順で進めます。

3-1:ブランチを作って編集する

  1. Changesが空の状態でmainを選び、Fetch origin、必要ならPull origin。
  2. Current Branch → New Branchでpractice/member-bを作る。分岐元はmain。
  3. リポジトリ直下にmembersフォルダーを作り(既にあれば使う)、その中にb.mdを作り、「担当:B」「実装:相手の手」「確認:3種類の手を返す」の3行を書いて保存する。b.md.txtにならないよう拡張子を表示する。

完了条件:作業ブランチにいて、Changesに自分の紹介ファイルが表示される。

3-2:Commit・Push・PRを作成する

  1. Changesの差分を読み、「Bの担当紹介を追加」でCommitする。Commitは手元への履歴記録。
  2. 初回はPublish branch、以後はPush originでGitHubへ送る。
  3. Preview Pull Requestからbase:main、compare:practice/member-bを確認し、Create Pull Requestでブラウザーへ進む。タイトル・変更内容を書いてPRを作成する。

完了条件:GitHubに自分のPRがある。Pushだけではmainは変わりません。

3-3:レビュー・マージ・Pullする

  1. CがFiles changedを読み、Review changes → Approveで承認する。本人の承認で代用しない。
  2. Aがレビューを確認し、Merge pull request → Confirm merge。A自身のPRもBのレビューを受ける。
  3. 全員がmainへ戻り、Fetch origin → Pull origin。紹介ファイルが届いたことを確認する。

完了条件:4人分の紹介ファイルが全員のmainにあり、各自のPRとレビューが残っている。作業完了後のブランチはMergedを確認して削除できます。次は最新mainから新しいブランチを作ります。

Step 4:担当Bがコンピューターの手を作る

全員が最新mainからStep 0のfeatureブランチを作ります。BはComputerPlayer.csだけを以下へ置き換えます。

ComputerPlayer.cs:完成コードと解説
using System;

namespace TeamJankenApp
{
    public class ComputerPlayer
    {
        private readonly Random random = new Random();

        public Hand ChooseHand()
        {
            int number = random.Next(3);
            if (number == 0) return Hand.Rock;
            if (number == 1) return Hand.Scissors;
            return Hand.Paper;
        }
    }
}

random.Next(3)は0・1・2のいずれかを返します。Randomはフィールドに1つ保持し、ChooseHandを呼ぶたびに手を選びます。同じ手が連続することも正常です。

今の完了条件:保存・ビルドが成功し、「コンピューターの手を実装」でCommit・Pushした。画面での確認は統合後です。数回で3種類が必ず出るとは限らず、出現回数が等しい必要もありません。

Step 5:担当Cが勝敗を判定する

Cはfeature/judgeでJudge.csを置き換えます。引数は有効なHandの3種類を渡す約束です。

あなた\相手グーチョキパー
グー引き分け勝ち負け
チョキ負け引き分け勝ち
パー勝ち負け引き分け
Judge.cs:完成コードと解説
namespace TeamJankenApp
{
    public class Judge
    {
        public RoundResult Decide(Hand player, Hand computer)
        {
            if (player == computer)
            {
                return RoundResult.Draw;
            }
            if ((player == Hand.Rock && computer == Hand.Scissors) ||
                (player == Hand.Scissors && computer == Hand.Paper) ||
                (player == Hand.Paper && computer == Hand.Rock))
            {
                return RoundResult.Win;
            }
            return RoundResult.Lose;
        }
    }
}

まず同じ手を引き分けにし、次に勝つ3通りを調べます。有効な手同士なら残りは負けです。画面のLabelを操作せず、結果だけを返します。

今の完了条件:保存・ビルドが成功し、「勝敗判定を実装」でCommit・Pushした。ランダム対戦だけで9通りを検証したことにはしません。統合時にStep 9の固定入力による検証を実施します。

Step 6:担当Dが成績を記録する

Dはfeature/score-boardでScoreBoard.csを置き換えます。

ScoreBoard.cs:完成コードと解説
namespace TeamJankenApp
{
    public class ScoreBoard
    {
        public int Wins { get; private set; }
        public int Losses { get; private set; }
        public int Draws { get; private set; }
        public int Total => Wins + Losses + Draws;

        public void Record(RoundResult result)
        {
            switch (result)
            {
                case RoundResult.Win: Wins++; break;
                case RoundResult.Lose: Losses++; break;
                case RoundResult.Draw: Draws++; break;
            }
        }

        public void Reset()
        {
            Wins = 0;
            Losses = 0;
            Draws = 0;
        }
    }
}

private setにより外側は成績を読めますが、直接書き換えられません。Recordを1回呼ぶと1試合分だけ増えます。Totalは3種類の合計から求め、別の変数として増やしません。

今の完了条件:保存・ビルドが成功し、「成績の記録とリセットを実装」でCommit・Pushした。入力する画面はまだ不要です。Step 9で成績を固定した結果から確認し、Step 10で実際の画面も確認します。

Step 7:担当Aがデザイナーで画面を作る

Aはfeature/janken-uiで作業します。B・C・Dの実装と並行して進められます。

7-1:部品を配置し、名前とプロパティを設定する

Form1.csを右クリック → デザイナーの表示。ツールボックスから部品を配置し、F4でプロパティを開きます。(Name)はコードから参照する名前、Textは画面に見せる文字です。

部品(Name)Text
ButtonrockButtonグー
ButtonscissorsButtonチョキ
ButtonpaperButtonパー
ButtonresetButton成績をリセット
LabelplayerHandLabelあなた:未選択
LabelcomputerHandLabel相手:未選択
LabelresultLabel手を選んでください
LabelscoreLabel勝ち 0 / 負け 0 / 引き分け 0 / 合計 0

フォームのTextは「4人チームのじゃんけん」、ClientSizeは640, 360を目安にします。各LabelはAutoSize:Trueを基本とし、成績が増えても文字が収まる余白を取ります。3つの手のボタンは同じ大きさで横並びにし、結果と成績はその下に配置します。成績リセットは手のボタンから離すと押し間違いを減らせます。

完了条件:8個の部品があり、(Name)が表と一致し、チームで文字や配置を確認した。

7-2:Form1.csに処理を書く

デザイナーの変更をすべて保存し、コード表示でForm1.cs全体だけを次へ置き換えます。Designer.cs・resx・Program.csは置き換えません。InitializeComponentがデザイナーの部品を作成します。

Form1.cs:デザイナー方式の全処理
using System;
using System.Windows.Forms;

namespace TeamJankenApp
{
    public partial class Form1 : Form
    {
        private readonly ComputerPlayer computer = new ComputerPlayer();
        private readonly Judge judge = new Judge();
        private readonly ScoreBoard score = new ScoreBoard();

        public Form1()
        {
            InitializeComponent();
            ResetDisplay();
        }

        private void RockButton_Click(object? sender, EventArgs e)
        {
            Play(Hand.Rock);
        }

        private void ScissorsButton_Click(object? sender, EventArgs e)
        {
            Play(Hand.Scissors);
        }

        private void PaperButton_Click(object? sender, EventArgs e)
        {
            Play(Hand.Paper);
        }

        private void ResetButton_Click(object? sender, EventArgs e)
        {
            score.Reset();
            ResetDisplay();
        }

        private void Play(Hand playerHand)
        {
            Hand computerHand = computer.ChooseHand();
            RoundResult result = judge.Decide(playerHand, computerHand);
            score.Record(result);
            playerHandLabel.Text = "あなた:" + HandText(playerHand);
            computerHandLabel.Text = "相手:" + HandText(computerHand);
            if (result == RoundResult.Win) resultLabel.Text = "あなたの勝ち!";
            else if (result == RoundResult.Lose) resultLabel.Text = "あなたの負け";
            else resultLabel.Text = "引き分け";
            UpdateScore();
        }

        private string HandText(Hand hand)
        {
            switch (hand)
            {
                case Hand.Rock: return "グー";
                case Hand.Scissors: return "チョキ";
                case Hand.Paper: return "パー";
                default: return "不明";
            }
        }

        private void UpdateScore()
        {
            scoreLabel.Text = $"勝ち {score.Wins} / 負け {score.Losses} / 引き分け {score.Draws} / 合計 {score.Total}";
        }

        private void ResetDisplay()
        {
            playerHandLabel.Text = "あなた:未選択";
            computerHandLabel.Text = "相手:未選択";
            resultLabel.Text = "手を選んでください";
            UpdateScore();
        }
    }
}

Playは相手の手を1回取得し、判定・記録・表示の順に処理します。表示する手と判定に使う手が一致するよう、ChooseHandを何度も呼びません。

完了条件:保存してビルドが成功する。部品が未定義なら(Name)と配置を確認します。まだイベントを接続していないので、ボタンの確認は次で行います。

7-3:イベントを接続して起動する

デザイナーに戻り、部品を選択してプロパティの雷マーク(イベント)を開きます。Click欄のドロップダウンで、既に書いたメソッドを選択します。

部品イベントメソッド
rockButtonClickRockButton_Click
scissorsButtonClickScissorsButton_Click
paperButtonClickPaperButton_Click
resetButtonClickResetButton_Click

イベント登録はこの操作に統一し、Form1.csにClick +=を重ねて書きません。保存・ビルドしてF5で起動し、表示を確認します。仮実装だけなら相手がグー、結果が引き分け、成績が0のままでもこの段階では想定どおりです。

完了条件:4つのイベントが設定され、画面が起動する。Form1.csと変更されたForm1.Designer.cs・Form1.resxを「じゃんけん画面とイベントを実装」でCommit・Pushします。

Step 8:PRをレビューし、順番に統合する

8-1:担当のPRを作ってレビューする

  1. 各自が保存・ビルド・Changesの差分確認を行う。自分のfeatureからmainへのPRを作る。すでに作成済みなら同じPRを使う。
  2. PRに「変更内容」「変更ファイル」「確認済みのこと」「統合後に確認すること」を書く。ビルドだけなら、その旨を明記する。
  3. AのPRをB、BをC、CをD、DをAがレビューする。修正は同じブランチでCommit・Pushし、同じPRで再確認する。

完了条件:各担当のPRがあり、担当範囲と型・メソッドの約束が確認されている。AのPRにはデザイナーによる変更も含めます。

8-2:最新mainを取り込み、B → C → D → Aの順でマージする

Aが指定レビュー担当の確認後に1件ずつマージします。先に別のPRが入った場合、後続の担当者は以下で最新mainを自分のfeatureへ取り込みます。

  1. デバッグを停止し、変更を保存・Commit・PushしてChangesを空にする。
  2. mainへ切り替え、Fetch origin → Pull origin。
  3. 自分のfeatureへ戻り、Current BranchのChoose a branch to merge into…からmainを選ぶ。取り込む方向はmain → 自分のfeature
  4. 再読み込みが必要ならVisual Studioで読み込み直し、ビルド・必要な確認を行ってPushする。更新された差分をレビュー担当に確認してもらう。

featureでPullするだけではmainの更新は入りません。mainからの取り込みは別操作です。今回はRebaseやForce pushを使いません。次の表でStep 9・10を案内したところで先に検証へ進み、成功したらここへ戻って該当PRをマージします。

順番成功条件
B:相手の手ビルド成功。画面はまだ空でよい
C:判定最新mainを取り込み、ビルド成功
D:成績最新mainを取り込み、Step 9の固定入力検証を実施
A:画面最新mainを取り込み、Step 10の画面確認後にマージ

完了条件:確認後の4つのPRがmainに入っている。AのPRもBがレビューします。初期ひな形以降は、mainへ直接編集せずPRで共有します。

Step 9:固定入力で勝敗9通りと成績を確認する

DのPRをマージする前に、C・Dが一緒に確認します。Dは最新main(BとCの完成コード)を取り込んだfeature/score-boardを使います。ランダム対戦を繰り返す代わりに、すべての組み合わせを指定して検証します。

  1. チームのリポジトリとは別の保存場所に、C#のコンソールアプリJankenLogicCheckを作る。
  2. Dの作業ブランチにあるJankenTypes.cs・Judge.cs・ScoreBoard.csをコピーし、検証プロジェクトの「追加 → 既存の項目」で追加する。名前空間TeamJankenAppは変更しない。Form1やProgram.csはコピーしない。
  3. 検証プロジェクトのProgram.csだけを下のコードへ置き換え、実行する。
  4. 「判定9通り・成績記録・リセット:すべて成功」と表示されることを確認する。失敗したら本体の担当クラスを修正し、検証側にも更新したファイルをコピーして再実行する。
検証用Program.cs(コンソールアプリ専用)
using System;
using TeamJankenApp;

Judge judge = new Judge();
Hand[] hands = { Hand.Rock, Hand.Scissors, Hand.Paper };
RoundResult[,] expected =
{
    { RoundResult.Draw, RoundResult.Win, RoundResult.Lose },
    { RoundResult.Lose, RoundResult.Draw, RoundResult.Win },
    { RoundResult.Win, RoundResult.Lose, RoundResult.Draw }
};
int passed = 0;
for (int row = 0; row < 3; row++)
{
    for (int col = 0; col < 3; col++)
    {
        RoundResult actual = judge.Decide(hands[row], hands[col]);
        if (actual != expected[row, col])
            throw new Exception($"判定エラー:{hands[row]} vs {hands[col]}");
        passed++;
    }
}
ScoreBoard score = new ScoreBoard();
score.Record(RoundResult.Win);
score.Record(RoundResult.Win);
score.Record(RoundResult.Lose);
score.Record(RoundResult.Draw);
if (score.Wins != 2 || score.Losses != 1 || score.Draws != 1 || score.Total != 4)
    throw new Exception("記録エラー");
score.Reset();
if (score.Wins != 0 || score.Losses != 0 || score.Draws != 0 || score.Total != 0)
    throw new Exception("リセットエラー");
Console.WriteLine($"判定{passed}通り・成績記録・リセット:すべて成功");

これはWinForms本体のProgram.csに貼り付けるコードではありません。期待する9通りの結果を表として用意し、実際の結果と比較しています。

完了条件:9通りと成績の記録・リセットがすべて成功し、実施結果をDのPRへ記載する。コピーしたファイルの検証なので、元のクラスを変更したら再検証が必要です。この検証だけでは画面のイベント接続やランダム処理は確認できません。

Step 10:全員の画面で完成確認する

まずAのPRをマージする前に、最新mainを取り込んだAのブランチでA・Bが確認します。マージ後は全員がmainへ切り替え、Fetch → Pullし、同じ最新コミットからビルド・起動して再確認します。

操作期待する結果
起動直後手は未選択、成績はすべて0
各手のボタンを1回ずつ押す選んだ手が「あなた」に表示され、相手の手と勝敗が出る。合計は1回につき1だけ増える
表示された手を9通りの表と照合するあなたから見た勝敗と一致する
複数回対戦する勝ち・負け・引き分けの合計が総試合数と一致する。同じ相手の手が続いても正常
成績をリセットすべて0、手は未選択、案内は「手を選んでください」
リセット後に1回対戦合計が1になる
終了して再起動保存機能はないため成績は0
画面の見た目文字が切れず、成績が増えても部品が重ならない

完了条件:全員が自分のPCで確認し、結果を記録する。ランダムな手が出たことだけで公平性を証明したとは扱いません。

困ったときの確認表

症状確認すること
型・メソッドが未定義共通ひな形をCloneしたか、ファイル追加先・名前空間・綴りが正しいか
ボタン名が未定義Aが先にデザイナーで部品を作り、(Name)を設定したか
押しても何も起きないClick欄に指定したメソッドが設定されているか
1回で成績が2増えるイベントをプロパティとClick +=で二重登録していないか
ずっとグー/引き分け/0のまま仮実装のままか、PRがMergedか、自分のブランチへ必要な変更を取り込んだか
変更が届かないPushだけでなくマージが済み、mainでPullしたか
コンフリクト同じ箇所の変更を担当者と読み合わせる。Designer.csや.csprojを判断できない場合はマージを中止し講師と確認する
bin・objが大量に出る.gitignoreとリポジトリの場所を確認。追跡済みなら.gitignore追加だけでは解除されないので講師に相談する

提出物と振り返り

  • チーム:リポジトリURL、完成コミット、画面画像、固定入力検証と画面確認の結果。非公開リポジトリは講師に閲覧権限を用意する。
  • 個人:練習PR・機能PR・レビューしたPRのURL、担当クラスの役割を3文で説明する。
  • 「CommitとPushの違い」「仮実装があると未定義にならない理由」「画面と勝敗判定を分ける理由」を話し合う。

完成後の発展課題

  • グー・チョキ・パーに画像を付ける。リソースの変更もPRで共有する。
  • 連勝数や勝率を追加する。引き分けを勝率の分母に含めるか先に相談する。
  • 効果音や成績保存を追加する。まず1つの機能に絞ってPRを回す。

参考として、画面はコードだけで作ることもできます。デザイナーも内部では部品を生成するコードを作っています。本編は視覚的に確認できるデザイナーに統一し、別方式は完成後に簡易レジアプリの記事末尾の参考資料で学べます。そのコードをじゃんけんアプリへそのまま追加するものではありません。

参考記事

訪問数 6 回, 今日の訪問数 6回

広告