Shuffle NSString characters and arrange in blocks - iphone

I am trying to develop a puzzle game where we display a shuffled word in blocks and user has to tap in proper order to form the word.I have an array of around 3k words and I have shuffled the array and formed a jumbled array.Now I want to pick a word eventually string,shuffle it and display the shuffled arrangement in boxes,say for instance the word is cricket,it should appear something of the below format on the screen:
Here is how I shuffled the array and formed a jumbled one
srandom(time(NULL));
for (NSInteger x=0;x<[greWordsArray count];x++)
{
NSInteger randomNumber = (random() % ([greWordsArray count] - x)) + x;
[greWordsArray exchangeObjectAtIndex:x withObjectAtIndex:randomNumber];
}
I also forgot to say I have a "new" button where if user clicks it,new word should appear and as usual it should be in shuffled mode,then display in blocks.
Can some one please guide me on how to accomplish this,I wonder what to use for displaying characters in blocks,whether it is buttons,text field or some other object.I also need some assistance regarding changing number of blocks depending on word length.Also how to display the selected character on label.I do acknowledge we can take label and arrange characters on it,but what is the recommended way,should I take a label for each character or a single label,then allow spacing depending on character selection.If so how should I do this.
People would have wondered what I have tried,but please help me as I am new to these kind of puzzle games,at least provide me with some understandable source to get started.

Suppose you have wordsArray which consists of 3k words
int randomWordIndex = arc4random%[wordsArray count];
NSString *jumbledWord = [wordsArray objectAtIndex:randomWordIndex];
NSMutableArray *characterArray = [[NSMutableArray alloc]init];
// character array having all characters of array
for (int i = 0; i< = [jumbledWord length]); i++)
{
int randomCharacterIndex = arc4random%[jumbledWord length];
[characterArray insertObject:
[NSString stringWithFormat: #"%#",
[jumbledWord characterAtIndex:i]]
atIndex:randomCharacterIndex] ;
}
Now you can show it using label or tableview or anything

I found a lot more precise and logical answer to my problem,
As alpha mentioned,we need to shuffle the array and form a sorted one,we need to assign a random word to jumbledWord based on index,say for instance:
int randomWordIndex = (int)arc4random%[greWordsArray count];
self.jumbledWord = [greWordsArray objectAtIndex:randomWordIndex];
Now we are ready with creating buttons based on word length.Here it is:
-(void)buttonsCreation:(int)noOfButtons
{
NSMutableArray *charactersArray = [NSMutableArray array];
self.wordButtons = [[NSMutableArray alloc]initWithCapacity:20];
BOOL record = NO;
int randomNumber;
for (int i=0; [charactersArray count] < jumbledWord.length; i++) //Loop for generate different random values
{
randomNumber = arc4random() % jumbledWord.length;//generating random number
if(i==0)
{
[charactersArray addObject:[NSNumber numberWithInt:randomNumber]];
}
else
{
for (int j=0; j<= [charactersArray count]-1; j++)
{
if (randomNumber ==[[charactersArray objectAtIndex:j] intValue])
record = YES;
}
if (record == YES)
record = NO;
else
[charactersArray addObject:[NSNumber numberWithInt:randomNumber]];
}
}
int arrayValue;
float x = 100.0;
float y = 100.0;
for(int i=0;i<[jumbledWord length];i++)
{
if(i>=0 && i<10)
{
arrayValue = [[charactersArray objectAtIndex:i] intValue];
x = x + 33;
UIButton *characterButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
characterButton.frame = CGRectMake(x,175.0, 35.0, 35.0);
[wordButtons addObject:characterButton];
NSString *characterValue = [NSString stringWithFormat:#"%c",[jumbledWord characterAtIndex:arrayValue]];
[characterButton setTitle:characterValue forState:UIControlStateNormal];
[characterButton addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
[characterButton setTag:arrayValue];
[self.view addSubview:characterButton];
}
else if(i>=10 && i<15)
{
y = y + 33;
UIButton *characterButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
characterButton.frame = CGRectMake(y,200.0, 35.0, 35.0);
[wordButtons addObject:characterButton];
NSString *characterValue = [NSString stringWithFormat:#"%c",[jumbledWord characterAtIndex:i]];
[characterButton setTitle:characterValue forState:UIControlStateNormal];
[characterButton addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
[characterButton setTag:i];
[self.view addSubview:characterButton];
}
}
}
Please note that the x and y values may vary based on one's requirement.I have briefly set co-ordinate locations of x and y based on word length,You may change if you want,thanks :)
Hope it helps some one,happy coding!!

Related

NSMutableArray integer storage

I am trying to store numbers inside the NSMutableArray, and have wrapped them like so:
-(IBAction)opUp:(id)sender{
opBool = YES;
opNum = [sender tag];
[numArray addObject:[NSNumber numberWithLong:number2]];
[opArray addObject:[NSNumber numberWithInt:opNum]];
number1 = 0;
number2 = 0;
opNum = 0;
NSLog(#"Operand %i", opNum);
NSLog(#"%i, %i", numArray.count, opArray.count);
}
But when I call them later using this:
final2 = [numArray objectAtIndex:i];
operthing = [opArray objectAtIndex:i];
I get this error message:
operthing equals 111526320
'operthing' is not supposed to go beyond 20.
Can someone help me with this?
Thanks.
operthing = [[opArray objectAtIndex:i] intValue];

problem with collision of UIImageViews

-(void)moveTheImage{
for (NSUInteger i = 0; i < [views count]; i++) {
image = [views objectAtIndex:i];
X = [[XArray objectAtIndex:i] floatValue];
Y = [[YArray objectAtIndex:i] floatValue];
image.center=CGPointMake(image.center.x + X, image.center.y + Y);
if(!intersectFlag)
{
if(CGRectIntersectsRect(image.frame,centre.frame))
{
intersectFlag = YES;
label.text= [NSString stringWithFormat:#"%d", count];
++count;
}
}
else
{
if(!CGRectIntersectsRect(image.frame,centre.frame))
{
intersectFlag = NO;
}
}
}
I would like that every time "image" intersect with "centre" the count increase of 1 but when there is a collision the count grows very fast until "image" doesn't touch "centre". More precisely "image" moves an then pass through "centre" and the count grows and when "image" is not in contact with "centre" the counter stops.How cn I solve this please? sorry for my english I'm french :/
As I said on the last comment, I think your count problem comes because of the frame rate.
So you can use an NSMutableSet which will contain all the objects being in collision.
In the interface, you declare your new set:
NSMutableSet * collisionObjects;
In the init method:
collisionObjects = [[NSMutableSet alloc] init];
In the dealloc:
[collisionObjects release];
And your method becomes:
-(void)moveTheImage{
for (NSUInteger i = 0; i < [views count]; i++) {
image = [views objectAtIndex:i];
X = [[XArray objectAtIndex:i] floatValue];
Y = [[YArray objectAtIndex:i] floatValue];
image.center=CGPointMake(image.center.x + X, image.center.y + Y);
if (CGRectIntersectsRect(image.frame,centre.frame)) {
// If the object is in collision, we add it to our set
// If it was already in it, it does nothing
[collisionObjects addObject:image];
}
else {
// If the object is not in collision we remove it,
// just in case it was in collision last time.
// If it was not, it does nothing.
[collisionObjects removeObject:image];
}
}
// The intersectFlag is updated : YES if the set is empty, NO otherwise.
intersectFlag = [collisionObjects count] > 0;
// We display the count of objects in collision
label.text= [NSString stringWithFormat:#"%d", [collisionObjects count]];
}
And this way you always have the count of your objects in collision using [collisionObjects count].

Accurately and seamlessly splitting text into two UILabels

I'm trying to create a "wrapping" like effect for text around an image that has set dimensions.
___________
........|
........| image
label.1.|
........|___________
....................
.......label.2......
....................
....................
Here is the method im using right now:
- (NSArray *)splitString:(NSString*)str maxCharacters:(NSInteger)maxLength { //this will split the string to add to two UILabels
NSMutableArray *tempArray = [NSMutableArray arrayWithCapacity:1];
NSArray *wordArray = [str componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
NSInteger numberOfWords = [wordArray count];
NSInteger index = 0;
NSInteger lengthOfNextWord = 0;
while (index < numberOfWords) {
NSMutableString *line = [NSMutableString stringWithCapacity:1];
while ((([line length] + lengthOfNextWord + 1) <= maxLength) && (index < numberOfWords)) {
lengthOfNextWord = [[wordArray objectAtIndex:index] length];
[line appendString:[wordArray objectAtIndex:index]];
index++;
if (index < numberOfWords) {
[line appendString:#" "];
}
}
[tempArray addObject:line];
}
return tempArray;
}
I give it the maxCharacters value of where I want to split the text, which is the max height of the first UILabel. This method is essentially what I want, but sometimes the last line of the first UILabel is "higher" than others leaving a gap between the first UILabel and the second UILabel.
Here is how I use the method:
NSArray *splitStringArray = [self splitString:eventRecord.summary maxCharacters:280];
UILabel *firstSumValue = [[UILabel alloc] init];
NSString *firstSumString = [splitStringArray objectAtIndex:0];
CGSize maxFirstSumSize = CGSizeMake(185.0,150.0);
UIFont *firstSumFont = [UIFont fontWithName:#"HelveticaNeue-Bold" size:12];
CGSize firstSumStringSize = [firstSumString sizeWithFont:firstSumFont
constrainedToSize:maxFirstSumSize
lineBreakMode:firstSumValue.lineBreakMode];
CGRect firstSumFrame = CGRectMake(10.0, presentedValue.frame.origin.y + presentedValue.frame.size.height, 185.0, firstSumStringSize.height);
firstSumValue.frame = firstSumFrame;
firstSumValue.font = [UIFont fontWithName:#"HelveticaNeue" size:12];
firstSumValue.lineBreakMode = UILineBreakModeWordWrap;
firstSumValue.numberOfLines = 0 ;
[self.mainScrollView addSubview:firstSumValue];
firstSumValue.text = [splitStringArray objectAtIndex:0];
UILabel *secondSumValue = [[UILabel alloc] init];
NSInteger isSecond = 0; //no
if([splitStringArray count] > 1){
isSecond = 1; //yes
NSString *secondSumString = [splitStringArray objectAtIndex:1];
CGSize maxSecondSumSize = CGSizeMake(310.0,9999.0);
UIFont *secondSumFont = [UIFont fontWithName:#"HelveticaNeue-Bold" size:12];
CGSize secondSumStringSize = [secondSumString sizeWithFont:secondSumFont
constrainedToSize:maxSecondSumSize
lineBreakMode:secondSumValue.lineBreakMode];
CGRect secondSumFrame = CGRectMake(10.0, firstSumValue.frame.origin.y + firstSumValue.frame.size.height, 310.0, secondSumStringSize.height);
secondSumValue.frame = secondSumFrame;
secondSumValue.font = [UIFont fontWithName:#"HelveticaNeue" size:12];
secondSumValue.lineBreakMode = UILineBreakModeWordWrap;
secondSumValue.numberOfLines = 0 ;
[self.mainScrollView addSubview:secondSumValue];
secondSumValue.text = [splitStringArray objectAtIndex:1];
}
How do I keep everything consistent and aligned properly. Perhaps, there is a better method one could recommend. Not core text because it's out of my scope of knowledge.
Consider using a UIWebView instead, with the layout defined in a local HTML file. It can save you a lot of headache rather than trying to deal with complex layouts by hand.

Assigning a button tag from an array which stores integers

I am trying to assign a tag to button. The normal command is:
button.tag = 1;
The tag must be an integer.
My problem is that I would like to assign an integer which I stored in an array (tabReference) which is yet again part of a class (currentNoteBook). So I need this:
int k = 0;
button.tag = [currentNoteBook.tabReference objectAtIndex:k]; // This is where I get the warning.
This doesn't seem to work, however, as xCode tells me: Passing argument 1 of setTag: makes integer from pointer without a cast.
My array looks like this (I tried to use integers...):
NSMutableArray *trArray = [[NSMutableArray alloc] init];
NSNumber *anumber = [NSNumber numberWithInteger:1];
[trArray addObject: anumber];
[trArray addObject: anumber];
[trArray addObject: anumber];
[trArray addObject: anumber];
currentNoteBook.tabReference = trArray;
An NSMutableArray stores a modifiable array of objects. You can't directly store an integer in an NSMutableArray. That's why you have to do something like this to store a bunch of integers:
NSMutableArray *the_array = [[NSMutableArray alloc] init];
int max = 100;
for (int i = 0; i < max; i++)
{
NSNumber *temp_number = [NSNumber numberWithInt:arc4random() % max];
[the_array addObject:temp_number];
}
Of course, you could do pretty much the same thing and store something else in there:
NSMutableArray *the_array = [[NSMutableArray alloc] init];
int max = 100;
int max_x = 50;
int max_y = 25;
int max_w = 100;
int max_h = 200;
for (int i = 0; i < max; i++)
{
CGFloat temp_x = arc4random() % max_x;
CGFloat temp_y = arc4random() % max_y;
CGFloat temp_w = arc4random() % max_w;
CGFloat temp_h = arc4random() % max_h;
CGRect temp_rect = CGRectMake(temp_x, temp_y, temp_w, temp_h);
[the_array addObject:[NSValue valueWithCGRect:temp_rect]];
}
When you go to retrieve these values you need to specify what it is you want out of the array because the same array can contain very different objects.
For your integers:
for (int i = 0; i < max; i++)
{
NSLog(#"%i: %i", i, [[the_array objectAtIndex:i] intValue]);
}
For the CGRect example:
for (int i = 0; i < max; i++)
{
CGRect temp_rect = [[the_array objectAtIndex:i] CGRectValue];
NSLog(#"%i: x:%f y:%f w:%f h:%f", i, temp_rect.origin.x, temp_rect.origin.y, temp_rect.size.width, temp_rect.size.height);
}
In a nutshell, you are storing objects not integers in your code. You have to pull them out of there as objects and then extract your integer to get your data back.
Just found the answer in another question I posed:
it must be:
btn.tag = [[currentNoteBook.tabReference objectAtIndex:k] intValue];

Why doesn't this for loop execute?

I have a picker view controller to select a chemical source and possibly a concentration. If the source doesn't have concentrations, it just presents a single picker. It gets populated by an NSDictionary with source type names as keys and a custom model object I made called Chemical that has four properties, two NSString, one float and one BOOL.
When I trigger this with dictionary that has 2 components, I want to extract the four values from the Chemical that is represented. Note that I populate the picker with values from the first two properties, but not the float or BOOL. I run through the array for the key that's selected in the first component and check the string from the second component against the chemConcentration property from each of the Chemicals in the key/value array. When the chemConcentration matches, I know I have the right Chemical and I can get its properties to send back.
Whew!
The problem is that even though I know I get to the for loop, it seems to get skipped. The NSLog right before it prints, but the one inside doesn't. sourceConstant and sourceIsLiquid stay 0.0 and NO
- (IBAction)selectedSourceButton {
NSLog(#"selectedSourceButton pressed");
NSInteger sourceRow = [picker selectedRowInComponent:kSourceComponent];
NSString *selectedSource = [self.sources objectAtIndex:sourceRow];
NSArray *selectedChemicalGroup = [dictionaryOfSources objectForKey:selectedSource];
NSInteger concentrationRow = [picker selectedRowInComponent:kConcentrationComponent];
NSString *selectedConcentration = [[NSString alloc] init];
float selectedConstant = 0.0;
BOOL selectedIsLiquid = NO;
if (numberOfComponents == 2) {
NSLog(#"numberOfComponents = 2 if/then chosen"); // <-- This prints.
selectedConcentration = [self.concentrations objectAtIndex:concentrationRow];
NSLog(#"begin selectedConcentration for loop. Number of loops = %d", [selectedChemicalGroup count]); // <-- And so does this.
for (int i; i<[selectedChemicalGroup count]; i++) { // <-- But this doesn't seem to fire!
NSLog(#"selectedConcentration = %#, from selectedChemicalGroup = %#", selectedConcentration, [[selectedChemicalGroup objectAtIndex:i] chemConcentration]); // <-- Because this doesn't print.
if ([selectedConcentration isEqualToString:[[selectedChemicalGroup objectAtIndex:i] chemConcentration]]) {
selectedConstant = [[selectedChemicalGroup objectAtIndex:i] chemConstant];
selectedIsLiquid = [[selectedChemicalGroup objectAtIndex:i] chemIsLiquid];
}
}
}
else {
selectedConcentration = #"";
selectedConstant = [[selectedChemicalGroup objectAtIndex:0] chemConstant];
selectedIsLiquid = [[selectedChemicalGroup objectAtIndex:0] chemIsLiquid];
}
NSLog(#"selectedSourceButton source to return = %#, concentration = %#, sourceConstant = %1.7f, isLiquid = %d", selectedSource, selectedConcentration, selectedConstant, selectedIsLiquid);
if ([self.delegate respondsToSelector:#selector (sourcePickerViewController:didSelectSource:andConcentration:andConstant:andIsLiquid:)]) {
[self.delegate sourcePickerViewController:self didSelectSource:selectedSource andConcentration:selectedConcentration andConstant:selectedConstant andIsLiquid:selectedIsLiquid];
}
}
You need to initialize your variable i: for (int i = 0; ...
But there's a better way to do this, using "fast enumeration":
for (MyChemicalGroupClass *group in selectedChemicalGroup) {
if ([selectedConcentration isEqualToString:[group chemConcentration]]) {
...
}
}
Initialize loop count i
for (int i = 0; i<[selectedChemicalGroup count]; i++)
Do the following and you will understand why:
int i;
NSLog(#"%d", i);