feat(view, viewmodel): 修改 veiwmodel 发送用户点击事件,修改 card 状态,完成 card match 逻辑

点击 card 修改 card.isFaceUp 属性,当两个 card.content 相同时,将 card 隐藏

Signed-off-by: Ching <loooching@gmail.com>
This commit is contained in:
Ching 2023-02-12 20:50:41 +08:00
parent 87b6465e68
commit 189bfc0bb8
4 changed files with 65 additions and 38 deletions

View File

@ -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<String>.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)
}
}

View File

@ -8,16 +8,22 @@
import SwiftUI
// viewmodel
class EmojiMemoryGame {
class EmojiMemoryGame: ObservableObject{
static let emojis = ["🚌", "🚙", "🚗", "🚕", "🏎", "🚎", "🚓"]
static func createMemoryGame() -> MemoryGame<String> {
MemoryGame<String>(numberOfPairsOfCards: 5) { pairIndex in EmojiMemoryGame.emojis[pairIndex] }
}
private var model: MemoryGame<String> = createMemoryGame()
@Published private var model: MemoryGame<String> = createMemoryGame()
var cards: [MemoryGame<String>.Card] {
return model.cards
}
// MARK: - Intent(s)
func choose(_ card: MemoryGame<String>.Card) {
model.choose(card)
}
}

View File

@ -9,9 +9,10 @@ import SwiftUI
@main
struct MemorizeApp: App {
let game = EmojiMemoryGame()
var body: some Scene {
WindowGroup {
ContentView()
ContentView(viewModel: game)
}
}
}

View File

@ -8,24 +8,53 @@
import Foundation
// model
struct MemoryGame<CardContent> {
struct MemoryGame<CardContent> 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
}
}