I am creating a memory game in swift where the user can select the amount of cards that are going to be available at the screen. This selection is made at the menu view controller and the data is passed to the game view controller. I use a for loop to create the buttons that represent the cards of the game and add each button to an array.
But, when initiating the game, different numbers of cards appear incorrectly depending on the amount of cards that the player chose (e.g., if 8 cards are selected, 8 cards appear. But when 10 cards are selected, 9 cards appear).
Button creation function:
func createCardButtons(){
let initialPos = Int(screenWidth/50)
var xPos = Int(screenWidth/20)
var yPos = Int(screenHeight/20)
let size = Int(screenWidth/5)
let cardBack = #imageLiteral(resourceName: "card_back")
for _ in 0...cardsNum! {
if xPos < Int(screenWidth - size) {
let button = UIButton(frame: CGRect(x: xPos, y: yPos, width: size, height: size))
button.addTarget(self, action: #selector(cardPressed), for: .touchUpInside)
button.setImage(cardBack, for: .normal)
view.addSubview(button)
buttonsArr.append(button)
xPos = size initialPos
} else {
xPos = Int(screenWidth/20)
yPos = size initialPos
}
}
print(buttonsArr)
}
Print message for 8 cards :
[<UIButton: 0x157509950; frame = (18 40; 75 75); opaque = NO; layer = <CALayer: 0x6000029dba60>>,
<UIButton: 0x157509c10; frame = (100 40; 75 75); opaque = NO; layer = <CALayer: 0x6000029dae60>>,
<UIButton: 0x157509ed0; frame = (182 40; 75 75); opaque = NO; layer = <CALayer: 0x6000029db960>>,
<UIButton: 0x15750a190; frame = (264 40; 75 75); opaque = NO; layer = <CALayer: 0x6000029dacc0>>,
<UIButton: 0x15750a450; frame = (18 122; 75 75); opaque = NO; layer = <CALayer: 0x6000029dbc20>>,
<UIButton: 0x15750a710; frame = (100 122; 75 75); opaque = NO; layer = <CALayer: 0x6000029daca0>>,
<UIButton: 0x15750a9d0; frame = (182 122; 75 75); opaque = NO; layer = <CALayer: 0x6000029dbb00>>,
<UIButton: 0x15750ac90; frame = (264 122; 75 75); opaque = NO; layer = <CALayer: 0x6000029dbcc0>>]
Print message for 10 cards:
[<UIButton: 0x15851ba30; frame = (18 40; 75 75); opaque = NO; layer = <CALayer: 0x600002057bc0>>,
<UIButton: 0x15851bcf0; frame = (100 40; 75 75); opaque = NO; layer = <CALayer: 0x600002043300>>,
<UIButton: 0x15851bfb0; frame = (182 40; 75 75); opaque = NO; layer = <CALayer: 0x60000204fba0>>,
<UIButton: 0x15851c270; frame = (264 40; 75 75); opaque = NO; layer = <CALayer: 0x60000204a340>>,
<UIButton: 0x15851c530; frame = (18 122; 75 75); opaque = NO; layer = <CALayer: 0x60000204a1a0>>,
<UIButton: 0x15851c7f0; frame = (100 122; 75 75); opaque = NO; layer = <CALayer: 0x60000206be80>>,
<UIButton: 0x15851cab0; frame = (182 122; 75 75); opaque = NO; layer = <CALayer: 0x600002061840>>,
<UIButton: 0x15851cd70; frame = (264 122; 75 75); opaque = NO; layer = <CALayer: 0x600002063a40>>,
<UIButton: 0x15851d030; frame = (18 204; 75 75); opaque = NO; layer = <CALayer: 0x600002063420>>]
If cardsNum = 8 adds 8 items to the array, why cardsNum = 10 adds only 9?
CodePudding user response:
Because the else
branch of your if-else
inside your for loop doesn't create and append a UIButton
to your array, whenever this branch is called no button is created for that run of the for loop.
You can fix this by updating the yPos
at the start of the loop if necessary, then perform the button creation regardless of whether yPos
was modified or not. For example:
for _ in 0...cardsNum! {
if xPos >= Int(screenWidth - size) {
xPos = Int(screenWidth/20)
yPos = size initialPos
}
let button = UIButton(frame: CGRect(x: xPos, y: yPos, width: size, height: size))
button.addTarget(self, action: #selector(cardPressed), for: .touchUpInside)
button.setImage(cardBack, for: .normal)
view.addSubview(button)
buttonsArr.append(button)
xPos = size initialPos
}
Additionally, with the for loop you are using, cardNum = 8
should actually result in 9 UIButtons
in the array (and cardNum = 10
with 11).
for _ in 0...cardsNum!
This means run the loop from 0 to cardsNum
inclusive, so including 0 and cardsNum
. So here your loop will be called cardsNum 1
times.
If you only want it to be run cardsNum
times use the half-open range operator:
for _ in 0..<cardsNum!
This means run the loop from 0 up to but not including cardsNum
(See more about the different range operators in Swift here.)