I am developing an iOS application. I have 35 buttons on the storyboard. Is there anyway I can use a random generator to randomly rearrange or shuffle the buttons and still maintain the button's functionality?
5 Answers
That is possible, it will require some coding:
- Create NSMutableArray with all buttons of the view in it.
- Randomize its order.
- Run over the buttons array and on each iteration keep last button view and switch its rect with current button and vice versa.
For better understanding, here is the code (ready for use, just copy paste):
- (void)viewDidLoad {
[super viewDidLoad];
// Getting buttons into array
NSMutableArray * buttonsArr = [self getButtonsArray];
// Shuffling buttons location
if(buttonsArr && [buttonsArr count]) {
[self randomizeButtonsLocation:buttonsArr];
} else {
NSLog(@"No buttons found");
}
}
- (void)randomizeButtonsLocation:(NSMutableArray *)buttonsArr {
// Randomizing order in button array
buttonsArr = [self randomizeArr:buttonsArr];
UIButton * lastBtn = nil;
for (UIButton * btn in buttonsArr) {
if(!lastBtn) {
lastBtn = btn;
} else {
// Put a side frames of last and current buttons
CGRect lastBtnRect = [lastBtn frame];
CGRect currentBtnRect = [btn frame];
// Switch frames
[btn setFrame:lastBtnRect];
[lastBtn setFrame:currentBtnRect];
// Keeping last btn for next iteration
lastBtn = btn;
}
}
}
- (NSMutableArray *)getButtonsArray {
// Getting all buttons in self.view and inserting them into a mutable array
NSMutableArray * resultArr = [[NSMutableArray alloc] init];
for (UIButton * btn in [self.view subviews]) {
if([btn isKindOfClass:[UIButton class]]) {
[resultArr addObject:btn];
}
}
return resultArr;
}
- (NSMutableArray *)randomizeArr:(NSMutableArray *)arr {
NSUInteger count = [arr count];
for (NSUInteger i = 0; i < count; ++i) {
unsigned long nElements = count - i;
unsigned long n = (arc4random() % nElements) + i;
[arr exchangeObjectAtIndex:i withObjectAtIndex:n];
}
return arr;
}

- 3,319
- 2
- 27
- 43
You can add all the button objects to an NSMutableArray called buttonsArray and then use the following loop to exchange the buttons:
for (int i = 0; i < buttonsArray.count; i++) {
int random1 = arc4random() % [buttonsArray count];
int random2 = arc4random() % [buttonsArray count];
[buttonsArray exchangeObjectAtIndex:random1 withObjectAtIndex:random2];
}

- 156
- 4
If each of the button is belongs to a class like below then its really easy to shuffle them,
MyRandomButton {
NSInteger uniqueId;
NSString *title;
....
....
}
Now, what you can do is, at initial, prepare number of objets of MyRandomButton (equals to count of buttons on your StoryBoard). And add it into a mutable array (NSMutableArray
).
Like this,
for(NSInteger index = 1; index <= 35; index++) {
MyRandomButton *btnInfo = ...;
btnInfo.uniqueId = index;
btnInfo.title = @sometitle;
[myButtonsArray addObject:btnInfo];
}
In next step, if you're done with something (and you want to shuffle all buttons) then get help from this question, What's the Best Way to Shuffle an NSMutableArray? to shuffle your array.
Loop through all buttons on your StoryBoard (in your case: 1 to 35).
for(NSInteger index = 1; index <= 35; index++) {
UIButton *button = (UIButton *)[yourView viewWithTag:index];
MyRandomButton *btnInfo = [myButtonsArray objectAtIndex:(index-1)];
button.tag = btnInfo.uniqueId;
[button setTitle:btnInfo.title forState:UIControlStateNormal];
}
Inside above loop, we've updated buttons title and tag.
Done!
For anyone who needs to do this in SWIFT, here's how:
func randomlyPositionAnswerButtons() {
var posX = CGFloat()
var posY_button1 = CGFloat()
var posY_button2 = CGFloat()
var posY_button3 = CGFloat()
// if self.view.frame.size.height == 667 { /* ======== IPHONE 7, 7S, 8 ======== */
posX = 24 // Set all buttons to start from 37
posY_button1 = 310
posY_button2 = 405
posY_button3 = 500
// }
let tab = [
[1,2], [0,2], [0,1]
]
let indexArray = [
NSValue(cgRect:CGRect(x: posX, y: posY_button1, width: 350, height: 74)),
NSValue(cgRect:CGRect(x: posX, y: posY_button2, width: 350, height: 74)),
NSValue(cgRect:CGRect(x: posX, y: posY_button3, width: 350, height: 74))
] as NSMutableArray
// Shuffle the array
var p = UInt32()
p = arc4random() % 3
indexArray.exchangeObject(at: 0, withObjectAt: Int(p))
indexArray.exchangeObject(at: tab[Int(p)][0], withObjectAt: tab[Int(p)][1])
// Assign the buttons their new position
optionButtonA.frame = (indexArray[0] as AnyObject).cgRectValue
optionButtonB.frame = (indexArray[1] as AnyObject).cgRectValue
optionButtonC.frame = (indexArray[2] as AnyObject).cgRectValue
}
Rearranging the fixed buttons sounds like a headache, if only in terms of autolayout constraints.
Why don't you:
Create and position 35 "generic" buttons on the storyboard, each with their own outlet (properties named
button01
,button02
, etc.), or better: use an outlet collection?Assign a unique tag to each button (0, 1, 2, 3...) on the storyboard.
Assign the same
@IBAction
method to all your buttons on the storyboard.At runtime, determine and assign a specific "role" to each button at random (and set each button's label accordingly). But keep track of which button is which, using -for example- a
dictionary
.The action linked to all buttons will use the tag of the sender and the information contained in the
dictionary
mentioned above to determine which "role" button was tapped, and act accordingly.
Does it make sense?

- 16,006
- 8
- 81
- 189
-
So I currently have 35 buttons already named button 01 - 35 (each doing a different action). So what is the next step? I am slightly lost. – Param Dec 24 '15 at 07:41
-
You have 35 different "meanings" (= roles) that you want to assign to those buttons, right? Each one corresponds to a different button title. At runtime, shuffle those and assign them to the buttons, on to each. – Nicolas Miari Dec 24 '15 at 07:51