2

In a simple memory game I have a struct that defines the two cards that are tapped and returns in mutating functions the integers firstFlippedCard and secondFlippedCard.

If these do not match by another property, I want both cards to 'flip back'. I made a transition function for this - however, I can only make the last tapped button to switch back using the following logic:

    @IBAction func cardsPress(_ sender: UIButton) {

        flip(sender: sender)

        if cardBrain.checkFirstCard(card: sender.tag - 1) == true {
            //stay flipped
        } else if cardBrain.checkForMatch(card: sender.tag - 1).match == true {
            //stay flipped
        } else {
            DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1), execute:  {
                self.backFlip(sender: sender)
            })
        }


    }

Note that multiple UIButtons are linked to cardsPress. How can I make them both flip back instead of only the sender?

1 Answers1

2

Add a property to keep track of the previousButton pressed. Then use this property to flip both the current sender and the previousButton. Finally, set previousButton back to nil after flipping it or deciding to keep it flipped.

var previousButton: UIButton?
var waitForFlip = false

@IBAction func cardsPress(_ sender: UIButton) {

    // ignore button input while waiting for cards to unflip
    guard !waitForFlip else { return }

    flip(sender: sender)

    if cardBrain.checkFirstCard(card: sender.tag - 1) {
        //stay flipped
        previousButton = sender
    } else if cardBrain.checkForMatch(card: sender.tag - 1).match  {
        //stay flipped
        previousButton = nil
    } else {
        waitForFlip = true
        DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1), execute:  {
            self.backFlip(sender: sender)
            if let button = previousButton {
                self.backFlip(sender: button)
                self.previousButton = nil
            }
            self.waitForFlip = false
        })
    }

}

Notes:

  • There is a possibility that the player could start flipping another card before the previous ones flip back. I introduced a waitForFlip property to ignore button inputs while we are waiting for the mismatched cards to flip back to avoid an issue where previousButton gets set and then overwritten to nil by the previous unflip.

  • There is no need to check if a Bool value is == true. Simply check if boolValue { instead of if boolValue == true. I removed two instances of that.

  • You might want to disable the buttons of cards that have been flipped (set sender.isEnabled = false) to keep the player from selecting a flipped card. Remember to reenable them again when they are flipped back by setting their isEnabled properties to true.

vacawama
  • 150,663
  • 30
  • 266
  • 294
  • Thanks! This helps a lot. I only changed the if let button block to directly state self.backFlip(sender: self.previousButton!). I didn't really understand why the if let button block was there? (By the way, button = self.previousButton, without self it didn't work). Now I have it all working and a reset button at the end, but how do I make the reset button backFlip all the buttons in the outlet collection? – Appelmoessi Feb 02 '20 at 18:48
  • The `if let` was just to avoid having to do a force unwrap. Defensive coding. If the buttons are in an outlet collection, you can do something like `for button in collection { if !button.isEnabled { self.backFlip(sender: button); button.isEnabled = true } }`. That will only work if you've implemented my suggestion to disable flipped cards. Otherwise, you'll need to determine another way to know if a card is flipped like looking its `tag` up in a list of flipped tags. – vacawama Feb 02 '20 at 19:21
  • If I do that, I get 'Type UIButton? does not conform to protocol Sequence'? I guess I need to order the collection? – Appelmoessi Feb 02 '20 at 19:30
  • Then you don't have an @IBOutlet collection. A collection is an array like this `@IBOutlet var cards: [UIButton]!` and each of the cards is linked to this collection. – vacawama Feb 02 '20 at 19:32
  • I didn't have it in an Array, just fixed it, the app works now! Thanks again :) – Appelmoessi Feb 02 '20 at 19:34