看斯坦福的 SwiftUI 教程, 里面有个卡片连连看的游戏, 比如有 3 对卡, 点击后翻面, 当翻两个卡牌相同时候, 这两个相同的卡牌会消失; 当翻两个时候没有匹配, 点击下一个卡牌时候, 前两个卡牌需要自动翻到背面.
我想到的逻辑代码(伪代码):
var lastRememberedCard = -1
func choose(cardIndex) {
if lastRememberedCard > -1 {
if cards[cardIndex].content == cards[lastRememberedCard].content {
// matched the card, flag it to `isMatched`
cards[cardIndex].isMatched = true
cards[lastRememberedCard].isMatched = true
}
cards[cardIndex].isFaceUp = true
lastRememberedCard = -1 // reset to -1, next turn
} else {
lastRememberedCard = cardIndex
cards.forEach { $0.isFaceUp = $0 == cardIndex }
}
}
但是斯坦福老师写的代码, 一开始逻辑是上面的, 但经过重构后变成下面这样:
struct MemoryGame<CardContent> where CardContent: Equatable {
private var indexOfTheOneAndOnlyFaceUpCard: Int? {
get { cards.indices.filter({ cards[$0].isFaceUp }).oneAndOnly }
set { cards.indices.forEach { cards[$0].isFaceUp = $0 == newValue } }
}
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
}
cards[chosenIndex].isFaceUp = true
} else {
indexOfTheOneAndOnlyFaceUpCard = chosenIndex
}
}
}
init() {...}
struct Card: Identifiable {...}
}
extension Array {
var oneAndOnly: Element? {
self.count == 1 ? self.first : nil
}
}
老师的方法使用了 swift 中 Computed Properties, 比较绕的逻辑:
正常逻辑是, 当偶数次点击时候, 将 flag 置空, 就像我的代码中 lastRememberedCard = -1
.
老师的逻辑是, 当偶数次点击时候不去管, 当下一次点击时候, 使用 get 方法来获取是否只有一个卡牌被翻正, 是的话就返回这卡牌的下标, 否则返回 nil.
通过这个逻辑, 这么一想, 我手动在偶数次将 lastRememberedCard = -1
重置的作用就是为了下一次使用时候它是空的, 我的逻辑比较 explicit.
所以目前疑惑老师这段代码逻辑是为了教学(swift computed property), 还是 Swift 项目中真是普遍使用这种逻辑?
1
Building 2022-09-05 10:01:13 +08:00 via iPhone
换我我也用斯坦福的方法,可以确保状态是同步的,非必要不用额外变量记录状态
|
2
kujio 2022-09-05 10:03:39 +08:00
不应该是咋想的就咋写吗,写完觉得不够优雅再结合进度慢慢优化。
|
3
Building 2022-09-05 10:10:55 +08:00 via iPhone
你的方法在顺序点击翻牌的时候是可以的,但是多线程模拟翻牌的时候可能会出现状态不一致的 bug
|
4
zongwan 2022-09-05 22:31:59 +08:00
老師的模板全面, 畢竟不止教一個學生
你能簡化重構老師的, 教學目的也達到了 另外你的在兩次點擊同一張卡牌時有邏輯錯誤 |
5
zongwan 2022-09-05 22:40:52 +08:00
此外如果擴展游戲功能 - 重開洗牌
你的代碼需要注意重置 lastRememberedCard --- 老師都沒講給你, 説明老師很佛係 你還是自己多實踐來感悟吧 |