0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

SwiftUI初心者がじゃんけんアプリを作ってみた

Last updated at Posted at 2024-04-25

はじめに

SwiftUIの勉強のためにじゃんけんアプリを作成しました。
SwiftUIについては、1年以上前に少し触った程度で書き方もあまり詳しくないため、勉強がてらじゃんけんアプリを作成してみました。
もし、手探りで制作したため、誤用などがあればご指摘いただけると幸いです。

ゴール

以下のようなじゃんけんアプリの作成をゴールとします。
プレイヤーがグー、チョキ、パーいずれかの手のボタンをタップすると、CPU😎の手もグー、チョキ、パーのいずれかでランダム生成され、プレイヤーとCPUの手の組み合わせに応じて結果が表示されます。

じゃんけんアプリの作成

列挙型Handの定義

まず、じゃんけんで使用するグー、チョキ、パーの手を定義した列挙型Handを定義します。
Handにはextensionを用いてtextプロパティとemojiプロパティも定義します。
例えば、Hand.rock.textグーとして扱われます。

import Foundation

enum Hand {
    case rock
    case scissors
    case paper
}

extension Hand {
    var text: String {
        switch self {
        case .rock:
            return "グー"
        case .scissors:
            return "チョキ"
        case .paper:
            return "パー"
        }
    }
    
    var emoji: String {
        switch self {
        case .rock:
            return "✊"
        case .scissors:
            return "✌️"
        case .paper:
            return "✋"
        }
    }
}

列挙型Resultの定義

次に、引き分け、勝ち、負けの結果を表す列挙型Resultを定義します。
Resultにはextensionを用いてtextプロパティも定義します。
例えば、Result.draw.text引き分けとして扱われます。

import Foundation

enum Result {
    case draw
    case win
    case lose
}

extension Result {
    var text: String {
        switch self {
        case .draw:
            return "引き分け"
        case .win:
            return "勝ち"
        case .lose:
            return "負け"
        }
    }
}

Utilクラスの定義

ロジック(状態管理を行わない部分)を定義したUtilクラスを定義します。
CPUの手をランダムで生成するgenerateCPUHand関数とじゃんけんの勝敗を判定するjudgeResult関数を定義します。

import Foundation

class Util {
    static func generateCPUHand() -> Hand {
        let hands = [Hand.rock, Hand.scissors, Hand.paper]
        let hand = hands.randomElement()
        return hand!
    }

    static func judgeResult(playerHand: Hand, cpuHand: Hand) -> Result {
        let isDraw = playerHand == cpuHand
        let isWin = (playerHand == .rock && playerHand == .scissors) || (playerHand == .scissors && cpuHand == .paper) || (playerHand == .paper && cpuHand == .rock)
        if isDraw {
            return .draw
        } else if isWin {
            return .win
        } else {
            return .lose
        }
    }
}

Stateクラスの定義

続いて、状態管理を行うために、ObservableObjectを用いてStateクラスを定義します。
@Publishedで状態管理をする変数を定義します。
ボタンをタップした際に状態管理を行う関数onTapHandも定義します。


import Foundation

final class State: ObservableObject {
    @Published var message = "じゃんけん…"
    @Published var result = Result.draw
    @Published var cpuHand = Hand.rock
    
    func onTapHand(hand: Hand) -> Void {
        let playerHand = hand
        cpuHand = Util.generateCPUHand()
        result = Util.judgeResult(playerHand: playerHand, cpuHand: cpuHand)
        message = result.text
    }
}

構造体HandButtonの定義

グー、チョキ、パーのボタンのUIコンポーネントを定義したクラスを定義します。
引数として() -> Void型のonTapとHand型のhandを定義します。


import SwiftUI

struct HandButton: View {
    let onTap: () -> Void
    let hand: Hand

    var body: some View {
        Button(action: {
            onTap()
        }, label: {
            VStack {
                Text(hand.emoji).font(.title)
                Text(hand.text).font(.title)
            }
        })
    }
}

struct HandButton_Previews: PreviewProvider {
    static var previews: some View {
        HandButton(onTap: {
            print("Rock button tapped")
        } ,hand: .rock)
    }
}

ContentViewの編集

最後に、ContentViewを編集し、じゃんけんアプリのUIを表示します。
@ObservedObjectで状態を監視し、UIに反映させます。
ここまでできたらじゃんけんアプリの完成です!

import SwiftUI

struct ContentView: View {
    @ObservedObject private var state = State()

    var body: some View {
        VStack {
            Spacer()
            Text(state.message).font(.title)
            Text("😎" + state.cpuHand.emoji)
            Spacer()
            HStack {
                Spacer()
                HandButton(onTap: {
                    state.onTapHand(hand: .rock)
                }, hand: .rock)
                Spacer()
                HandButton(onTap: {
                    state.onTapHand(hand: .scissors)
                }, hand: .scissors)
                Spacer()
                HandButton(onTap: {
                    state.onTapHand(hand: .paper)
                }, hand: .paper)
                Spacer()
            }
            .padding()
        }
    }
}

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

最後に

enumで列挙型を定義し、ObservableObjectで状態管理を行い、SwiftUIでUIを構築することにより、じゃんけんアプリを作ってみました。
じゃんけんアプリの制作により、SwiftUIの書き方が少しだけわかるようになりました。

参考文献

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?