From 189bfc0bb8d24b134f77ee91967e280336f4e157 Mon Sep 17 00:00:00 2001 From: Ching Date: Sun, 12 Feb 2023 20:50:41 +0800 Subject: [PATCH] =?UTF-8?q?feat(view,=20viewmodel):=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=20veiwmodel=20=E5=8F=91=E9=80=81=E7=94=A8=E6=88=B7=E7=82=B9?= =?UTF-8?q?=E5=87=BB=E4=BA=8B=E4=BB=B6=EF=BC=8C=E4=BF=AE=E6=94=B9=20card?= =?UTF-8?q?=20=E7=8A=B6=E6=80=81=EF=BC=8C=E5=AE=8C=E6=88=90=20card=20match?= =?UTF-8?q?=20=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 点击 card 修改 card.isFaceUp 属性,当两个 card.content 相同时,将 card 隐藏 Signed-off-by: Ching --- Memorize/ContentView.swift | 51 ++++++++++++++-------------------- Memorize/EmojiMemoryGame.swift | 10 +++++-- Memorize/MemorizeApp.swift | 3 +- Memorize/MemoryGame.swift | 39 ++++++++++++++++++++++---- 4 files changed, 65 insertions(+), 38 deletions(-) diff --git a/Memorize/ContentView.swift b/Memorize/ContentView.swift index 1203249..1937e60 100644 --- a/Memorize/ContentView.swift +++ b/Memorize/ContentView.swift @@ -8,56 +8,47 @@ import SwiftUI struct ContentView: View { - var emojis = ["🚌", "🚙", "🚗", "🚕", "🏎", "🚎", "🚓"] - @State var emojiCount = 2 + @ObservedObject var viewModel: EmojiMemoryGame var body: some View { - VStack { - ScrollView { - LazyVGrid(columns: [GridItem(.adaptive(minimum: 65))]) { - ForEach(emojis[0 ..< emojiCount], id: \.self) { - emoji in CardView(content: emoji).aspectRatio(2 / 3, contentMode: .fit) - } + ScrollView { + LazyVGrid(columns: [GridItem(.adaptive(minimum: 65))]) { + ForEach(viewModel.cards) { + card in CardView(card: card).aspectRatio(2 / 3, contentMode: .fit) + .onTapGesture { + viewModel.choose(card) + } } } - .foregroundColor(/*@START_MENU_TOKEN@*/ .red/*@END_MENU_TOKEN@*/) - .padding(.horizontal) - .font(.largeTitle) } + .foregroundColor(/*@START_MENU_TOKEN@*/ .red/*@END_MENU_TOKEN@*/) .padding(.horizontal) } } struct CardView: View { - @State var isFaceUp: Bool = true - var content: String + let card: MemoryGame.Card var body: some View { ZStack { let shape = RoundedRectangle(cornerRadius: 20.0) - if isFaceUp { - shape - .fill() - .foregroundColor(.white) - shape - .strokeBorder(lineWidth: 3) - Text(content) - .font(.largeTitle) + if card.isFaceUp { + shape.fill().foregroundColor(.white) + shape.strokeBorder(lineWidth: 3) + Text(card.content).font(.largeTitle) + } else if card.isMatched { + shape.opacity(0) + } else { + shape.fill() } - else { - shape - .fill() - } - } - .onTapGesture { - isFaceUp = !isFaceUp } } } struct ContentView_Previews: PreviewProvider { static var previews: some View { - ContentView() + let game = EmojiMemoryGame() + ContentView(viewModel: game) .preferredColorScheme(.dark) - ContentView() + ContentView(viewModel: game) .preferredColorScheme(.light) } } diff --git a/Memorize/EmojiMemoryGame.swift b/Memorize/EmojiMemoryGame.swift index 3132c2a..f7283ea 100644 --- a/Memorize/EmojiMemoryGame.swift +++ b/Memorize/EmojiMemoryGame.swift @@ -8,16 +8,22 @@ import SwiftUI // viewmodel -class EmojiMemoryGame { +class EmojiMemoryGame: ObservableObject{ static let emojis = ["🚌", "🚙", "🚗", "🚕", "🏎", "🚎", "🚓"] static func createMemoryGame() -> MemoryGame { MemoryGame(numberOfPairsOfCards: 5) { pairIndex in EmojiMemoryGame.emojis[pairIndex] } } - private var model: MemoryGame = createMemoryGame() + @Published private var model: MemoryGame = createMemoryGame() var cards: [MemoryGame.Card] { return model.cards } + + // MARK: - Intent(s) + + func choose(_ card: MemoryGame.Card) { + model.choose(card) + } } diff --git a/Memorize/MemorizeApp.swift b/Memorize/MemorizeApp.swift index b685264..809b856 100644 --- a/Memorize/MemorizeApp.swift +++ b/Memorize/MemorizeApp.swift @@ -9,9 +9,10 @@ import SwiftUI @main struct MemorizeApp: App { + let game = EmojiMemoryGame() var body: some Scene { WindowGroup { - ContentView() + ContentView(viewModel: game) } } } diff --git a/Memorize/MemoryGame.swift b/Memorize/MemoryGame.swift index ec65cdf..aa2aa68 100644 --- a/Memorize/MemoryGame.swift +++ b/Memorize/MemoryGame.swift @@ -8,24 +8,53 @@ import Foundation // model -struct MemoryGame { +struct MemoryGame where CardContent: Equatable { private(set) var cards: [Card] + private var indexOfTheOneAndOnlyFaceUpCard: Int? - func choose(_ card: Card) {} + mutating func choose(_ card: Card) { + if let chosenIndex = cards.firstIndex(where: { $0.id == card.id }), !cards[chosenIndex].isFaceUp, !cards[chosenIndex].isMatched { + if let potentialMatchIndex = indexOfTheOneAndOnlyFaceUpCard { + if cards[chosenIndex].content == cards[potentialMatchIndex].content { + cards[chosenIndex].isMatched = true + cards[potentialMatchIndex].isMatched = true + } + indexOfTheOneAndOnlyFaceUpCard = nil + } else { + for index in cards.indices { + if cards[index].isFaceUp { + cards[index].isFaceUp.toggle() + } + } + indexOfTheOneAndOnlyFaceUpCard = chosenIndex + } + cards[chosenIndex].isFaceUp.toggle() + } + } + + func index(of card: Card) -> Int? { + for index in 0 ..< cards.count { + if cards[index].id == card.id { + return index + } + } + return nil + } init(numberOfPairsOfCards: Int, createCardContent: (Int) -> CardContent) { cards = [Card]() // for pairIndex in 0 ..< numberOfPairsOfCards { let content: CardContent = createCardContent(pairIndex) - cards.append(Card(content: content)) - cards.append(Card(content: content)) + cards.append(Card(content: content, id: pairIndex * 2)) + cards.append(Card(content: content, id: pairIndex * 2 + 1)) } } - struct Card { + struct Card: Identifiable { var isFaceUp: Bool = false var isMatched: Bool = false var content: CardContent + var id: Int } }