1. HOME»
  2. プログラミング・Web»
  3. iPhoneアプリ開発»
  4. SwiftUIでじゃんけんゲームを作ろう。かんたんiPhoneアプリ開発入門

SwiftUIでじゃんけんゲームを作ろう。かんたんiPhoneアプリ開発入門

SwiftUIは、2019年にアップルが発表したフレームワークです。

SwiftUIを使って、iPhoneで遊べるじゃんけんゲームを作成してみましょう。
この入門ではXcodeを使いますので、準備をしておいてください。

今回作るのは、このようなじゃんけんゲームです。
SwiftUI

では、早速はじめていきましょう!

目次
  1. 使用する画像について
  2. 新規プロジェクトの作成
  3. 使用する画像を読み込む
  4. プレビューを使う
  5. テキストの変更
  6. フォントの変更
  7. 縦並びのレイアウト(VStack)
  8. ボタンを作る
  9. ボタンを画像にする
  10. ボタンが押されたときのアクションを加える
  11. チョキとパーのボタンを作る
  12. 横並びのレイアウト(HStack)
  13. ボタンを画面いっぱいに横並びにする
  14. ゲーム全体の画面を作る
  15. 相手の手の向きを変更する
  16. ボタンが押されたとき、自分の手の画像を切り替える
  17. ランダムな値を取得して、相手の手の画像を切り替える
  18. じゃんけんの勝敗を判定する
  19. まとめ

使用する画像について

今回はこちらの画像を使います。
解凍してお使いください。

じゃんけん画像

新規プロジェクトの作成

まずは、新規プロジェクトを作成します。

Xcodeを開くと、次ような画面が表示されると思います。
この画面から、「Create a new Xcode project」をクリックします。
SwiftUI

今回はじゃんけんゲームといえども、とてもシンプルなゲームですので、「Single View App」を選択します。
SwiftUI

すると、次のような画面が表示されます。
たくさん入力する場所がありますが、一つずつ見ていきましょう。
SwiftUI

まず、Project Nameには、プロジェクトの名前を入力します。今回は「Janken」と入力しました。

次にTeamなのですが、これを指定しておかないと、実機でのテストなど、できないことが出てきます。ただ、指定するにはAppleIDが必要だったりと、少々大変なので、今回は「None」の状態で進めたいと思います。(後から変更もできますので、実機テストをしたいと思ったときに、設定すればいいと思います)

Organization Nameは、組織名ですが、個人の方はニックネームを入れてあげればいいと思います。

Organization Identifierは、任意のもので構いませんが、アプリを公開するとなると、注意が必要です。
世界に一つだけのものにしなくてはいけないので、ドメインを持っている人は、それをひっくり返したものを入力します。持っていない人は、とりあえず任意のものを入力してください。

Languageは、開発言語ですので、Swiftを選択してください。

User Interfaceは、SwiftUIを選択してください。

全ての選択が終わったら、「Next」をクリックします。

すると、プロジェクトを作成する場所を選択することができます。
SwiftUI

このとき、「Create Git repository on my Mac」の項目があります。
これは、どちらでもいいのですが、今回はGitでのバージョン管理はしないので、私はチェックを外しました。

おめでとうございます。新規プロジェクトが作成され、SwiftUIで開発する準備が整いました。
SwiftUI

使用する画像を読み込む

では、使用する画像をプロジェクトに読み込んでいきます。

まず、ナビゲーターエリアから、「Assets.xcassets」を選びます。
SwiftUI

もしもナビゲーターエリアが表示されていない場合は、右上のボタンで表示させることができます。
SwiftUI

先ほどダウンロードしたファイルを、全てドラッグして、白いところにドロップします。
SwiftUI

これで画像が読み込まれました。
SwiftUI

プレビューを使う

SwiftUIでは、わざわざエミュレータを使わなくても、プレビューを見るだけで実行結果が分かります。

まず、ContentsView.swiftを開きます。
SwiftUI

画像のように「Resume」をクリックします。
SwiftUI

少々時間がかかりますが、待ちます。
SwiftUI

スマホが表示され、その画面に「Hello,World!」と表示されれば成功です。
SwiftUI

このプレビューですが、もし止まってしまった場合はもう一度「Resume」をクリックしてあげてください。

テキストの変更

続いて、今表示されている「Hello,World!」の文字列を変更してみましょう。
プレビュー画面上の「Hello,World!」をクリックしてください。
SwiftUI

すると、ユーティリティエリアに表示されていたものが、ポンっと変わります。
SwiftUI

もしもユーティリティエリアが表示されていない場合は、右上のボタンで表示させることができます。
SwiftUI

では、テキストを変更してみましょう。
ユーティリティエリアに「Text」という項目があります。
じゃんけんゲームを作るのですから、ここはもちろん「じゃんけん」に変更します。
SwiftUI

すると、ソースとプレビューにも反映されます。
SwiftUI

もちろんソースを直接変更しても構いません。
もしもソースから変更したい場合は、「ContentView.swift」の5行目を「Text(“じゃんけん”)」に変更します。

ContentView.swift

import SwiftUI

struct ContentView: View {
    var body: some View {
        Text("じゃんけん")
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

フォントの変更

続いて、フォントを変更してみましょう。

ユーティリティエリアを見ると、「Font」という項目があります。ここで、フォントを変更することができます。
SwiftUI

とりあえず今回は「Title」に変更してみました。
SwiftUI

プレビューのフォントが若干大きくなりました。
さらに、ソースには.font(.title)という命令が加わっています。
SwiftUI

数値を指定してフォントのサイズを変更する方法もありますが、ここでは割愛します。

縦並びのレイアウト(VStack)

VStackを使うと、縦並びのレイアウトにすることができます。
といっても、ここではまだTextしかないので、表示は変わりません。このあと、ボタンを作った時に反映されます。

ただ、そのままボタンを作ってしまうと、エラーになってしまうので、まずはレイアウトの指定だけしておきます。

では、ソースの「Text(“じゃんけん”)」の、Textの部分をcommandを押しながらクリックします。
そして「Embed in VStack」をクリックします。
SwiftUI

すると、VStack {}が作られ、その中にTextが入ったと思います。

ソースは現在、こうなっております。

ContentView.swift

import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            Text("じゃんけん")
                .font(.title)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

ボタンを作る

つづいて、ボタンを作っていきます。

まず、.font(.title)の後ろにカーソルを移動させ、Enter(return)で改行します。

右上にある「+」をクリックします。
SwiftUI

Buttonを選びます。
SwiftUI

これで、ボタンが作られました。
また、VStackのおかげで「じゃんけん」の文字と「Button」というボタンが縦に並んで配置されました。
SwiftUI

では、このボタンの文字を変更してみます。
先ほどと同じようにユーティリティエリアから変更することも可能ですが、今度はちょっと違う方法を試してみましょう。

プレビューのボタンを、commandを押しながらクリックします。
さらに表示されたメニューから、「Show SwiftUI Inspector…」をクリックします。
SwiftUI

Textを「グー」に変更します。
SwiftUI

これで、プレビューの文字と、ソースが書き換わりました。
SwiftUI

ボタンを画像にする

続いて、ボタンを画像にしてみましょう。
せっかく作ったボタンですが、ちょっと改変していきます。

ソースのText("グー")を削除します。
SwiftUI

するとエラーが発生してしまいますが、ここでは気にしません。
カーソルが、Button(action {}) {}の、後ろの{}の中にあるのを確認します。
SwiftUI

右上にある「+」をクリックします。
SwiftUI

表示されたウィンドウから、「Image」を探して、選択します。
SwiftUI

これで、Image(Image Name)という命令が追加され、エラーも消えました。
SwiftUI

Image Nameのところには、最初に読み込んだ画像ファイル名を入れます。
拡張子は入力しません。
SwiftUI

しかし、このようにボタンが青くなってしまっていると思います。
SwiftUI

そんなときは、レンダリングモードを指定します。
Image("b_gu")の後ろで改行し、以下の命令を入力します。

.renderingMode(.original)

これで、ボタンを画像にすることができました。
SwiftUI

ボタンが押されたときのアクションを加える

つづいて、ボタンが押されたときのアクションを作っていきます。

さきほど作ったボタン、Button(action: {}) {/*省略/}の、最初の{}の中に作っていきます。
しかし、まだ{}が青くなった状態になっているので、ダブルクリックして、入力できるようにします。
SwiftUI

さらにカーソルの位置を{}の中に移動し、enter(return)を押して改行します。
そこに、以下の命令を入力してください。

print("グー")

これでボタンを押すとデバッグエリアに「グー」と表示されるようになるのですが、プレビューのボタンを押しても、ボタンが選択されるだけになってしまいます。

そこでプレビューの右下にある、「▷」を右クリックし、「Debug Preview」をクリックしてください。
SwiftUI

「Preview」の左の、くるくる回っているマークが消えるのを待ちます。
SwiftUI

するとデバッグエリアが表示されます。
SwiftUI

また、デバッグエリアの表示非表示は、右上のボタンから切り替えられます。
SwiftUI

では、実際にプレビューの中の、作成したボタンをクリックしてみてください。
すると、デバッグエリアに「グー」と表示されたと思います。
SwiftUI

これで、ボタンをつくることができました。

全体のソースはこのようになっています。

ContentView.swift

import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            Text("じゃんけん")
                .font(.title)
            Button(action: {
                print("グー")
            }) {
                Image("b_gu")
                    .renderingMode(.original)
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

チョキとパーのボタンを作る

さて、ここまでで、テキストとボタンを作成することができたのですが、ボタンはまだグーしかありません。

では、チョキとパーのボタンも作っていきましょう。
まず、グーボタンのソースを選択して、右クリックからコピーします。
SwiftUI

ボタンのソースの下に、貼り付けます。
SwiftUI

さらにその下に、もう一度貼り付けます。
SwiftUI

これでボタンが3つになりました。
SwiftUI

では、ソースを変更して、グーボタンを、チョキとパーのボタンに、変更していきます。
変更する箇所は画像の通りです。
SwiftUI

今現在のソースは、このようになります。

ContentView.swift

import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            Text("じゃんけん")
                .font(.title)
            Button(action: {
                print("グー")
            }) {
                Image("b_gu")
                    .renderingMode(.original)
            }
            Button(action: {
                print("チョキ")
            }) {
                Image("b_choki")
                    .renderingMode(.original)
            }
            Button(action: {
                print("パー")
            }) {
                Image("b_pa")
                    .renderingMode(.original)
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

これで、それぞれのボタンを押したとき、そのボタンにあった文字が、デバッグエリアに表示されます。
SwiftUI

横並びのレイアウト(HStack)

続いて、ボタンを横並びにしてみたいと思います。

さきほど、VStackという縦並びのレイアウトを使いました。こんどはHStackを使って、横並びのレイアウトを作ってみます。

VStackHStackを組み合わせて、さまざまなレイアウトを作ることが可能です。

では、先ほど作った3つのボタンを、HStack {}の{}に入れるように書いていきます。

ContentView.swift

/** 省略 */
HStack {
    Button(action: {
        print("グー")
    }) {
        Image("b_gu")
            .renderingMode(.original)
    }
    Button(action: {
        print("チョキ")
    }) {
        Image("b_choki")
            .renderingMode(.original)
    }
    Button(action: {
        print("パー")
    }) {
        Image("b_pa")
            .renderingMode(.original)
    }
}
/** 省略 */

これで、ボタンを横並びにすることができます。
SwiftUI

ボタンを画面いっぱいに横並びにする

3つのボタンが横並びになったわけですが、このままではスマホの画面からはみ出てしまっています。
さらに、端末によっては、画面のわりに小さなボタンになってしまったりします。

そんなときに使うのが.resizable()です。
これを使うことで、画像サイズを変更することが可能になります。

3箇所のそれぞれの画像の、.renderingMode(.original)の下に入力します。

/** 省略 */
Button(action: {
    print("グー")
}) {
    Image("b_gu")
        .renderingMode(.original)
        .resizable()    //追加
}
Button(action: {
    print("チョキ")
}) {
    Image("b_choki")
        .renderingMode(.original)
        .resizable()    //追加
}
Button(action: {
    print("パー")
}) {
    Image("b_pa")
        .renderingMode(.original)
        .resizable()    //追加
}
/** 省略 */

すると、このようになります。
画像は画面いっぱいになったものの、比が崩れ、よくない見た目になってしまいました。
SwiftUI

そんなときは、.scaledToFit()を使いましょう。
これを使うことで、アスペクト比を維持しながらリサイズすることができます。

先ほど追加した、.resizable()の下に追加しましょう。

Button(action: {
    print("グー")
}) {
    Image("b_gu")
        .renderingMode(.original)
        .resizable()
        .scaledToFit()    //追加
}
Button(action: {
    print("チョキ")
}) {
    Image("b_choki")
        .renderingMode(.original)
        .resizable()
        .scaledToFit()    //追加
}
Button(action: {
    print("パー")
}) {
    Image("b_pa")
        .renderingMode(.original)
        .resizable()
        .scaledToFit()    //追加
}

これで、画面の横いっぱいにボタンを並べることができました。
SwiftUI

今現在のソースは、このようになっています。

ContentView.swift

import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            Text("じゃんけん")
                .font(.title)
            HStack {
                Button(action: {
                    print("グー")
                }) {
                    Image("b_gu")
                        .renderingMode(.original)
                        .resizable()
                        .scaledToFit()
                }
                Button(action: {
                    print("チョキ")
                }) {
                    Image("b_choki")
                        .renderingMode(.original)
                        .resizable()
                        .scaledToFit()
                }
                Button(action: {
                    print("パー")
                }) {
                    Image("b_pa")
                        .renderingMode(.original)
                        .resizable()
                        .scaledToFit()
                }
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

ゲーム全体の画面を作る

さて、以上のことが分かれば、ゲーム全体の画面をだいたい作ることができます。

では、相手の顔の画像を表示させます。
相手の顔は、画面の一番上に表示させたいので、VStack{}の一番上に作っていきます。
SwiftUI

右上の「+」をクリックします。
SwiftUI

「Image」を選択します。
SwiftUI

Image(Image Name)の()の中を、「”face”」に変更します。
SwiftUI

さらに、画面に合わせて大きさを変更したいので、先ほどのように、.resizable().scaledToFit()を指定します。
入力する場所は、Image("face")の下です。
SwiftUI

さて、今度は手を表示させていきます。
今作成した、顔の画像を表示するソースをコピーします。
SwiftUI

Text("じゃんけん").font(.title)の上と下に貼り付けます。
SwiftUI

今作成したところの、2箇所のfaceは、とりあえず「gu」に変更しておきます。
SwiftUI

これで、じゃんけんゲームの大まかな形ができました。

今現在のソースは、このようになっております。

ContentView.swift

import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            Image("face")
                .resizable()
                .scaledToFit()
            Image("gu")
                .resizable()
                .scaledToFit()
            Text("じゃんけん")
                .font(.title)
            Image("gu")
                .resizable()
                .scaledToFit()
            HStack {
                Button(action: {
                    print("グー")
                }) {
                    Image("b_gu")
                        .renderingMode(.original)
                        .resizable()
                        .scaledToFit()
                }
                Button(action: {
                    print("チョキ")
                }) {
                    Image("b_choki")
                        .renderingMode(.original)
                        .resizable()
                        .scaledToFit()
                }
                Button(action: {
                    print("パー")
                }) {
                    Image("b_pa")
                        .renderingMode(.original)
                        .resizable()
                        .scaledToFit()
                }
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

相手の手の向きを変更する

このままでは、自分の手と相手の手が同じ向きなので、パッと見たとき、どっちがどっちの手か分かりにくいです。

そこで、相手の手の向きを回転させてみましょう。

画像の回転には、.rotationEffect(Angle(degrees: 角度))を使い、「角度」には数値を入れます。

実際には、このように入力します。

/** 省略 */
Image("face")
    .resizable()
    .scaledToFit()
Image("gu")
    .resizable()
    .scaledToFit()
    .rotationEffect(Angle(degrees: 180))    //追加
Text("じゃんけん")
    .font(.title)
/** 省略 */

これで、手の画像を180度回転させることができます。
SwiftUI

コードの全体は、このようになります。

ContentView.swift

import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            Image("face")
                .resizable()
                .scaledToFit()
            Image("gu")
                .resizable()
                .scaledToFit()
                .rotationEffect(Angle(degrees: 180))
            Text("じゃんけん")
                .font(.title)
            Image("gu")
                .resizable()
                .scaledToFit()
            HStack {
                Button(action: {
                    print("グー")
                }) {
                    Image("b_gu")
                        .renderingMode(.original)
                        .resizable()
                        .scaledToFit()
                }
                Button(action: {
                    print("チョキ")
                }) {
                    Image("b_choki")
                        .renderingMode(.original)
                        .resizable()
                        .scaledToFit()
                }
                Button(action: {
                    print("パー")
                }) {
                    Image("b_pa")
                        .renderingMode(.original)
                        .resizable()
                        .scaledToFit()
                }
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

ボタンが押されたとき、自分の手の画像を切り替える

続いて、ボタンが押されたときに、自分の手の画像が切り替わるようにしてみます。

そんなときに使えるのが、変数と条件分岐です。
では、struct ContentView: View {}の一番上に、次の命令を入力します。

@State private var playerHand = 0

@Stateをつけることによって、値を変更することが可能になります。

今回は、勝敗のプログラムが作りやすいように、数値で、なにを出したか、を管理するようにします。

0はグー、1はチョキ、2はパーです。

そして、自分の手の画像を表示している部分は、次のようにして、画像が切り替わるようにします。

/** 省略 */

/** 自分の手 */
if(playerHand == 0) {
    Image("gu")
        .resizable()
        .scaledToFit()
} else if(playerHand == 1) {
    Image("choki")
        .resizable()
        .scaledToFit()
} else if(playerHand == 2) {
    Image("pa")
        .resizable()
        .scaledToFit()
}

/** 省略 */

さらに、ボタンを押したとき、変数の数値が変わるようにします。

/** 省略 */

/** ボタン */
HStack {
    Button(action: {
        print("グー")
        self.playerHand = 0;        //追加
    }) {
        Image("b_gu")
            .renderingMode(.original)
            .resizable()
            .scaledToFit()
    }
    Button(action: {
        print("チョキ")
        self.playerHand = 1;        //追加
    }) {
        Image("b_choki")
            .renderingMode(.original)
            .resizable()
            .scaledToFit()
    }
    Button(action: {
        print("パー")
        self.playerHand = 2;        //追加
    }) {
        Image("b_pa")
            .renderingMode(.original)
            .resizable()
            .scaledToFit()
    }
}

/** 省略 */

すると、ボタンを押すたびに、手の画像が切り替わるようになりました。
SwiftUI

全体のソースは、このようになります。
分かりやすいように、コメントも入れました。

ContentView.swift

import SwiftUI

struct ContentView: View {
    @State private var playerHand = 0
    var body: some View {
        VStack {
            
            /** 顔 */
            Image("face")
                .resizable()
                .scaledToFit()
            
            /** 相手の手 */
            Image("gu")
                .resizable()
                .scaledToFit()
                .rotationEffect(Angle(degrees: 180))
            
            /** 文字 */
            Text("じゃんけん")
                .font(.title)
            
            /** 自分の手 */
            if(playerHand == 0) {
                Image("gu")
                    .resizable()
                    .scaledToFit()
            } else if(playerHand == 1) {
                Image("choki")
                    .resizable()
                    .scaledToFit()
            } else if(playerHand == 2) {
                Image("pa")
                   .resizable()
                   .scaledToFit()
            }
            
            /** ボタン */
            HStack {
                Button(action: {
                    print("グー")
                    self.playerHand = 0;
                }) {
                    Image("b_gu")
                        .renderingMode(.original)
                        .resizable()
                        .scaledToFit()
                }
                Button(action: {
                    print("チョキ")
                    self.playerHand = 1;
                }) {
                    Image("b_choki")
                        .renderingMode(.original)
                        .resizable()
                        .scaledToFit()
                }
                Button(action: {
                    print("パー")
                    self.playerHand = 2;
                }) {
                    Image("b_pa")
                        .renderingMode(.original)
                        .resizable()
                        .scaledToFit()
                }
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

ランダムな値を取得して、相手の手の画像を切り替える

ここまでくると、早く相手の手も切り替わるようにしたいですね。
しかし、相手の手はランダムに切り替わるようにしたいです。

それならば、ランダムな値を取得し、その数値によって、それぞれの画像に切り替わるようにしてみましょう。

ランダムな数値を作るのは、以下のようなプログラムです。
この命令は、0~2までの整数の数値を、randamという変数に代入するものです。

let random = Int.random(in: 0..<3)

では、この命令を使って、コンピュータが出す手を選ぶための関数を作ってみましょう。

関数は以下のように作ります。
これで、コンピュータがなにを出すか、0〜2までの数値がランダムに選ばれます。

func chooseComputerHand() -> Int {
    let random = Int.random(in: 0..<3)
    let computerHand = random
    return computerHand
}

この関数を、ボタンが押されたときの部分から呼び出します。

ContentView.swift

/** 省略 */

/** ボタン */
HStack {
    Button(action: {
        print("グー")
        self.playerHand = 0;
        self.computerHand = chooseComputerHand();        //追加
        
    }) {
        Image("b_gu")
            .renderingMode(.original)
            .resizable()
            .scaledToFit()
    }
    Button(action: {
        print("チョキ")
        self.playerHand = 1;
        self.computerHand = chooseComputerHand();        //追加
    }) {
        Image("b_choki")
            .renderingMode(.original)
            .resizable()
            .scaledToFit()
    }
    Button(action: {
        print("パー")
        self.playerHand = 2;
        self.computerHand = chooseComputerHand();        //追加
    }) {
        Image("b_pa")
            .renderingMode(.original)
            .resizable()
            .scaledToFit()
    }
}

/** 省略 */

さらに、computerHandに入っている数値によって、相手の手の画像も切り替わるようにします。

ContentView.swift

/** 省略 */

/** 相手の手 */
if(computerHand == 0) {
    Image("gu")
        .resizable()
        .scaledToFit()
        .rotationEffect(Angle(degrees: 180))
}
if(computerHand == 1) {
    Image("choki")
        .resizable()
        .scaledToFit()
        .rotationEffect(Angle(degrees: 180))
}
if(computerHand == 2) {
    Image("pa")
        .resizable()
        .scaledToFit()
        .rotationEffect(Angle(degrees: 180))
}

/** 省略 */

まだ、変数computerHandの宣言をしていないので、@State private var computerHand = 0を、playerHandの宣言の下に入力しておきます。

そして、現在のソースはこのようになります。

ContentView.swift

import SwiftUI

struct ContentView: View {
    @State private var playerHand = 0
    @State private var computerHand = 0
    var body: some View {
        VStack {
            
            /** 顔 */
            Image("face")
                .resizable()
                .scaledToFit()
            
            /** 相手の手 */
            if(computerHand == 0) {
                Image("gu")
                    .resizable()
                    .scaledToFit()
                    .rotationEffect(Angle(degrees: 180))
            }
            if(computerHand == 1) {
                Image("choki")
                    .resizable()
                    .scaledToFit()
                    .rotationEffect(Angle(degrees: 180))
            }
            if(computerHand == 2) {
                Image("pa")
                    .resizable()
                    .scaledToFit()
                    .rotationEffect(Angle(degrees: 180))
            }
            
            /** 文字 */
            Text("じゃんけん")
                .font(.title)
            
            /** 自分の手 */
            if(playerHand == 0) {
                Image("gu")
                    .resizable()
                    .scaledToFit()
            } else if(playerHand == 1) {
                Image("choki")
                    .resizable()
                    .scaledToFit()
            } else if(playerHand == 2) {
                Image("pa")
                   .resizable()
                   .scaledToFit()
            }
            
            /** ボタン */
            HStack {
                Button(action: {
                    print("グー")
                    self.playerHand = 0;
                    self.computerHand = chooseComputerHand();
                    
                }) {
                    Image("b_gu")
                        .renderingMode(.original)
                        .resizable()
                        .scaledToFit()
                }
                Button(action: {
                    print("チョキ")
                    self.playerHand = 1;
                    self.computerHand = chooseComputerHand();
                }) {
                    Image("b_choki")
                        .renderingMode(.original)
                        .resizable()
                        .scaledToFit()
                }
                Button(action: {
                    print("パー")
                    self.playerHand = 2;
                    self.computerHand = chooseComputerHand();
                }) {
                    Image("b_pa")
                        .renderingMode(.original)
                        .resizable()
                        .scaledToFit()
                }
            }
        }
    }
}

func chooseComputerHand() -> Int {
    let random = Int.random(in: 0..<3)
    let computerHand = random
    return computerHand
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

これで、相手もランダムに手を変えてくるようになりました。
SwiftUI

じゃんけんの勝敗を判定する

いよいよ、じゃんけんの勝敗を判定するプログラムを作っていきます。

じゃんけんを判定する関数を作ります。
このようにすると、じゃんけんの勝敗を判定することができます。

func determineVictoryOrDefeat(playerHand:Int, computerHand:Int) -> String {
    var result = ""
    var playerHandTemp = playerHand
    playerHandTemp+=1

    if (playerHand == computerHand) {
        result = "ぽん……あいこです";
    }
    else if ((playerHand == 2 && computerHand == 0)||(playerHandTemp == computerHand)) {
        result = "ぽん……あなたの勝ちです";
    }
    else {
        result = "ぽん……あなたの負けです";
    }
    return result
}

では、今作った関数を、ボタンを押したときの部分から呼び出します。

ContentView.swift

/** 省略 */

/** ボタン */
HStack {
    Button(action: {
        print("グー")
        self.playerHand = 0;
        self.computerHand = chooseComputerHand();
        self.text = determineVictoryOrDefeat(playerHand:self.playerHand, computerHand:self.computerHand)        //追加
        
    }) {
        Image("b_gu")
            .renderingMode(.original)
            .resizable()
            .scaledToFit()
    }
    Button(action: {
        print("チョキ")
        self.playerHand = 1;
        self.computerHand = chooseComputerHand();
        self.text = determineVictoryOrDefeat(playerHand:self.playerHand, computerHand:self.computerHand)        //追加
    }) {
        Image("b_choki")
            .renderingMode(.original)
            .resizable()
            .scaledToFit()
    }
    Button(action: {
        print("パー")
        self.playerHand = 2;
        self.computerHand = chooseComputerHand();
        self.text = determineVictoryOrDefeat(playerHand:self.playerHand, computerHand:self.computerHand)        //追加
    }) {
        Image("b_pa")
            .renderingMode(.original)
            .resizable()
            .scaledToFit()
    }
}

/** 省略 */

さらに、「じゃんけん」の文字を変えたいので、text変数に「じゃんけん」という文字列を代入し、それを表示するようにします。
computerHandの宣言の下に、@State private var text = "じゃんけん"を入力して、textの宣言と代入をします。

そして、Text("じゃんけん")の部分は、Text(text)に書き換えます。

/** 文字 */
Text(text)
    .font(.title)

すると、さきほどのプログラムで、determineVictoryOrDefeat()関数が呼ばれた結果がtext変数に代入されるようになっているので、「じゃんけん」の文字が、結果の文字に切り替わるようになります。
SwiftUI

さて、これでじゃんけんゲームの完成です。
さいごに、完成したソース全体になります。

ContentView.swift

import SwiftUI

struct ContentView: View {
    @State private var playerHand = 0
    @State private var computerHand = 0
    @State private var text = "じゃんけん"
    var body: some View {
        VStack {
            
            /** 顔 */
            Image("face")
                .resizable()
                .scaledToFit()
            
            /** 相手の手 */
            if(computerHand == 0) {
                Image("gu")
                    .resizable()
                    .scaledToFit()
                    .rotationEffect(Angle(degrees: 180))
            }
            if(computerHand == 1) {
                Image("choki")
                    .resizable()
                    .scaledToFit()
                    .rotationEffect(Angle(degrees: 180))
            }
            if(computerHand == 2) {
                Image("pa")
                    .resizable()
                    .scaledToFit()
                    .rotationEffect(Angle(degrees: 180))
            }
            
            /** 文字 */
            Text(text)
                .font(.title)
            
            /** 自分の手 */
            if(playerHand == 0) {
                Image("gu")
                    .resizable()
                    .scaledToFit()
            } else if(playerHand == 1) {
                Image("choki")
                    .resizable()
                    .scaledToFit()
            } else if(playerHand == 2) {
                Image("pa")
                   .resizable()
                   .scaledToFit()
            }
            
            /** ボタン */
            HStack {
                Button(action: {
                    print("グー")
                    self.playerHand = 0;
                    self.computerHand = chooseComputerHand();
                    self.text = determineVictoryOrDefeat(playerHand:self.playerHand, computerHand:self.computerHand)
                    
                }) {
                    Image("b_gu")
                        .renderingMode(.original)
                        .resizable()
                        .scaledToFit()
                }
                Button(action: {
                    print("チョキ")
                    self.playerHand = 1;
                    self.computerHand = chooseComputerHand();
                    self.text = determineVictoryOrDefeat(playerHand:self.playerHand, computerHand:self.computerHand)
                }) {
                    Image("b_choki")
                        .renderingMode(.original)
                        .resizable()
                        .scaledToFit()
                }
                Button(action: {
                    print("パー")
                    self.playerHand = 2;
                    self.computerHand = chooseComputerHand();
                    self.text = determineVictoryOrDefeat(playerHand:self.playerHand, computerHand:self.computerHand)
                }) {
                    Image("b_pa")
                        .renderingMode(.original)
                        .resizable()
                        .scaledToFit()
                }
            }
        }
    }
}

func chooseComputerHand() -> Int {
    let random = Int.random(in: 0..<3)
    let computerHand = random return computerHand
}

func determineVictoryOrDefeat(playerHand:Int, computerHand:Int) -> String {
    var result = ""
    var playerHandTemp = playerHand
    playerHandTemp+=1

    if (playerHand == computerHand) {
        result = "ぽん……あいこです";
    }
    else if ((playerHand == 2 && computerHand == 0)||(playerHandTemp == computerHand)) {
        result = "ぽん……あなたの勝ちです";
    }
    else {
        result = "ぽん……あなたの負けです";
    }
    return result
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

まとめ

今回はSwiftUIを使って、じゃんけんゲームを作成しました。

SwiftUIを使うと、少ないコードで書けるようになるので、開発の時間がかなり短縮できそうです。
日本では、iPhoneを使っている人がとても多いので、iPhoneアプリ開発はぜひ覚えておきたいですね。

3件のコメント 「SwiftUIでじゃんけんゲームを作ろう。かんたんiPhoneアプリ開発入門」

  1. if条件でテキストの“あなたの勝ち”の代わりに紙吹雪の動画mp4を表示したいのですが。どのようにすれば良いでしょうか?テキストのところに動画のコードをそのまま全部入れたり、または別viewの名前を入れたりしています。こちらの= 条件には文字列しか入れられないでしょうか?または、別の構造式を使わなければ動画を出すことは出来ないのでしょうか?宜しくご教授お願いいたします。

    1. >いたさん
      こんにちは。コメントありがとうございます。

      動画を表示する方法ですが、「あなたの勝ち」と書かれたところのテキストのところではなく、「じゃんけん」と表示しているところのテキスト(全体のコードの35〜37行目のところ)に、動画のコードを貼り付けても、表示されませんか?
      「if (self.text == “あなたの勝ち”)」のときに動画を表示する、というふうなコードにしてみてください。

      また、「こちらの=条件には文字列しか入れられないでしょうか?」というご質問ですが、関数の戻り値の型がStringになっているので、文字列しか入れられないです。
      これをIntなどに変えれば、数値も入れられるようになりますが、これをすると、それに合わせていろいろと変更が必要になります。

      お役に立てたか分かりませんが、またよろしくお願いします。

  2. ジャンケンアプリコード、大変勉強になります。ひとつ質問があります。教えていただけますでしょうか?

It is R へ返信する コメントをキャンセル

メールアドレスが公開されることはありません。 が付いている欄は必須項目です




オリジナルゲーム.com