Я успешно внедрил решение для первого задания осени 2017 года - Концентрация.
Все работает отлично, за исключением того, что всякий раз, когда вы переворачиваете карту, которая уже отображалась, после прикосновения к новой игре появляется небольшая анимация задержки / затухания. Этого не происходит, когда вы впервые переворачиваете карту в первой игре (см. Видео по ссылке ниже)
Пример проблемного поведения
Я думал, что это ошибка, но я проверил другие решения, и все они имеют одинаковую задержку.
Если кто-нибудь может дать мне подсказку или знает, почему существует такое отставание, действительно сделаю меня счастливым =)
Примеры решений с одинаковой проблемой:
https://github.com/BestKora/Concentration-CS193P-Fall-2017
https://github.com/jamfly/cs193p-2017-fall-demo-and-solution
https://github.com/TiagoMaiaL/cs193p-assignments
Мой код для Концентрации и ViewController:
class ViewController: UIViewController
{
private lazy var game = Concentration(numberOfPairsOfCards: numberOfPairsOfCards)
var numberOfPairsOfCards: Int {
return (cardButtons.count + 1) / 2
}
private let emojiLibrary = ["?☺️??????????",
"?????????⛓??",
"????????????",
"????????????",
"⚽️??⚾️??????⛳️?",
"?????✊?????☝️"]
private lazy var theme = emojiLibrary[emojiLibrary.count.arc4random]
@IBAction func newGame(_ sender: UIButton) {
// Create new game struct, initialize everything Model
game = Concentration(numberOfPairsOfCards: numberOfPairsOfCards)
// Initialize everything view
gameOverLabel.isHidden = true
emoji.removeAll()
theme = emojiLibrary[emojiLibrary.count.arc4random]
updateViewFromModel(touchedCard: 0)
}
@IBOutlet private weak var flipCountLabel: UILabel!
@IBOutlet private var cardButtons: [UIButton]!
@IBOutlet weak var gameOverLabel: UILabel!
@IBOutlet weak var scoreLabel: UILabel!
@IBAction private func touchCard(_ sender: UIButton) {
if let cardNumber = cardButtons.index(of: sender) {
game.chooseCard(at: cardNumber)
updateCardDisplay(index: cardNumber)
updateViewFromModel(touchedCard: cardNumber)
if game.gameOver {
gameOverLabel.isHidden = false
}
} else {
print("chosen card was not in cardButtons!")
}
}
private func updateCardDisplay(index:Int)
{
let card = game.cards[index]
let button = cardButtons[index]
if card.isFaceUp {
button.setTitle(getEmoji(for: card), for: UIControl.State.normal)
button.backgroundColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)
} else {
button.setTitle("", for: UIControl.State.normal)
button.backgroundColor = card.isMatched ? #colorLiteral(red: 1, green: 1, blue: 1, alpha: 0) : #colorLiteral(red: 1, green: 0.5763723254, blue: 0, alpha: 1)
}
}
private func updateViewFromModel(touchedCard:Int) {
for index in cardButtons.indices {
if index != touchedCard {
let button = cardButtons[index]
let card = game.cards[index]
if !card.isFaceUp {
button.setTitle("", for: UIControl.State.normal)
button.backgroundColor = card.isMatched ? #colorLiteral(red: 1, green: 1, blue: 1, alpha: 0) : #colorLiteral(red: 1, green: 0.5763723254, blue: 0, alpha: 1)
}
}
}
scoreLabel.text = String("Score: \(game.score)")
flipCountLabel.text = String("Flips: \(game.flipCount)")
}
private var emoji = [Card:String]()
private func getEmoji(for card: Card) -> String {
if emoji[card] == nil, theme.count > 0 {
let randomStringIndex = theme.index(theme.startIndex, offsetBy: theme.count.arc4random)
emoji[card] = String(theme.remove(at: randomStringIndex))
}
return emoji[card] ?? "?"
}
}
extension Int {
var arc4random: Int {
if self > 0 {
return Int(arc4random_uniform(UInt32(self)))
} else if self < 0 {
return -Int(arc4random_uniform(UInt32(abs(self))))
} else {
return 0
}
}
}
struct Concentration
{
private(set) var cards: [Card]
private(set) var gameOver = false
private(set) var flipCount = 0
private(set) var score = 0
private(set) var seenCards: Set<Card>
private(set) var indexOfOneAndOnlyFaceUpCard: Int? {
get {
return cards.indices.filter({cards[$0].isFaceUp}).oneAndOnly
}
set {
for index in cards.indices {
cards[index].isFaceUp = (index == newValue)
}
}
}
private var numberOfPlayingCards: Int {
get {
return cards.count - cards.indices.filter({cards[$0].isMatched}).count
}
}
mutating func chooseCard(at index: Int) {
assert(cards.indices.contains(index), "Concentration.chooseCard(at: \(index)): chosen index not in the cards")
if indexOfOneAndOnlyFaceUpCard != index && !cards[index].isMatched {
flipCount += 1
}
if !cards[index].isMatched {
if let matchIndex = indexOfOneAndOnlyFaceUpCard, matchIndex != index {
// check if cards match
if cards[matchIndex] == cards[index] {
cards[matchIndex].isMatched = true
cards[index].isMatched = true
score += 2
} else {
// mismatch of cards
if seenCards.contains(cards[index]) {
score -= 1
} else {
seenCards.insert(cards[index])
}
if seenCards.contains(cards[matchIndex]) {
score -= 1
} else {
seenCards.insert(cards[matchIndex])
}
}
if numberOfPlayingCards == 0 {
gameOver = true
cards[matchIndex].isFaceUp = false
} else {
cards[index].isFaceUp = true
}
} else {
indexOfOneAndOnlyFaceUpCard = index
}
}
}
init(numberOfPairsOfCards: Int) {
assert(numberOfPairsOfCards > 0, "Concentration.init(\(numberOfPairsOfCards)): you must have at least one pair of cards")
cards = [Card]()
for _ in 1...numberOfPairsOfCards {
let card = Card()
cards += [card, card]
}
cards.shuffle()
seenCards = Set<Card>()
}
}
extension Collection {
var oneAndOnly: Element? {
return count == 1 ? first : nil
}
}
Весь код был основан на демоверсии, поэтому должен быть знаком тем, кто выполнял курс / задания cs193p.
Спасибо