cs193p Концентрация: задержка переворота карты Emoji для карт, которые уже были показаны, после нажатия новой игры - PullRequest
0 голосов
/ 01 ноября 2018

Я успешно внедрил решение для первого задания осени 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.

Спасибо

...