Corresponding a button with an array slot - objective-c
I want to put a bunch of buttons on the screen that correspond with an array slot.
For example, buttonA corresponds to myArray[3][28].
Would I have to have a ton of else-if statements like this:
else if (x == 3 && y == 28)
//"it's buttonQ" code
else if (x == 3 && y == 29)
//"it's buttonR" code
or is there a better way?
Note: x is the "horizontal" index of the 2D array myArray, while y is its "vertical" index
I think it is feasible to devise a scheme where you can use the position as part of your data scheme. It seems to me that this is what you are doing anyway because you are relating the horizontal coordinates to letters in the alphabet.
So you could do for example something like this:
NSString *letters = #"ABCDEFGHIJKLMNOPQRSTUVXYZ";
...
else if (x == 3) {
NSString *letter = [NSString stringWithFormat:#"%c"
[letters characterAtIndex:y-11]];
// use letter in your code
}
...
Similarly, you could device code that takes into account the row as well in a more complex matrix of buttons.
Related
Pick a next item from NSArray and then start over
I need to toggle three different font sizes in the view controller for terms and conditions screen in an endless loop (13 , 15, 17..13, 15, 17..etc..). The screen is pretty simple, just text on full screen and a button in the navigation bar that when pressed, triggers and event handled in action. The three fonts are represented by three NSString constants. -(IBAction)toggleFontSize:(id)sender { if (self.currentFontIdentifier == regularFontIdentifier) { self.currentFontIdentifier = largeFontIdentifier; } else if (self.currentFontIdentifier == largeFontIdentifier) { self.currentFontIdentifier = smallFontIdentifier; } else { self.currentFontIdentifier = regularFontIdentifier; } self.termsAndConditionsTextView.font = [[BrandingManager sharedManager] fontWithIdentifier:self.currentFontIdentifier]; } This code works (for now :)), but it's a nice Mediterranean IF yacht.I am wondering if there is some more mature approach. I already see the stakeholders changing their mind and adding a 4th font size. I want it to be manageable better, so basically once they add a new size I would only add it into some Array and that would be it. Any ideas for a more mature algorithm?
Declare an instance variable for the current selected index and an array for the three fonts (small, regular and large) and try this: -(IBAction)toggleFontSize:(id)sender { _currentSelectedIndex = (_currentSelectedIndex + 1) % 3; self.currentFontIdentifier = _fontIdentifiers[_currentSelectedIndex]; self.termsAndConditionsTextView.font = [[BrandingManager sharedManager] fontWithIdentifier:self.currentFontIdentifier]; } You may not need currentFontIdentifier property since it can be obtained with _fontIdentifiers[_currentSelectedIndex]
You could use the methods 'indexOfObject and 'lastObject' of the NSArray class, something like: Using an array of sizes: NSArray *fontList = #[#"12","14","18"]; Then you could iterate through it using the indexOfObject NSUInteger ix = [fontList indexOfObject:self.currentFontIdentifier] + 1; if ([[fontList lastObject] isEqual:self.currentFontIdentifier]) ix=0; self.currentFontIdentifier = [fontList objectAtIndex:ix]; or NSUInteger ix = [fontList indexOfObject:self.currentFontIdentifier] + 1; if (ix >= [fontList count]) ix=0; self.currentFontIdentifier = [fontList objectAtIndex:ix];
Changing content of a matrix in c
How do you change just part of a matrix in c (I'm actually in Objective-C, but using matrices in c). For example: NSInteger tempMapMatrix[100][100] = {{0,0,1,1,2,2,1,1,0,2,4,4,4,0,0,1,2,2,1,0,0,0,0,0,0}, {0,1,1,2,3,2,1,1,4,4,3,4,4,0,0,1,2,2,1,0,0,0,0,0,0}, {1,1,2,3,3,2,1,4,1,3,3,4,4,0,0,1,2,2,1,0,0,0,0,0,0}, {1,1,3,3,3,2,4,1,1,1,4,4,4,0,0,1,2,2,1,0,0,0,0,0,0}, {0,1,1,2,2,2,4,4,4,4,4,4,4,0,0,1,1,1,1,0,0,0,4,4,0}, {0,0,1,1,2,2,1,0,0,2,3,4,4,0,0,0,0,0,0,0,0,0,4,4,0}, {4,4,1,1,2,2,1,1,0,1,1,0,4,0,0,0,0,0,0,0,0,0,4,4,4}, {0,4,1,2,2,2,1,1,0,4,4,4,4,4,4,4,0,0,0,0,1,0,0,0,0}, {0,1,2,2,2,2,1,1,0,1,2,4,4,0,0,4,0,3,3,3,3,3,3,3,0}, {0,1,2,2,2,2,1,1,0,1,2,4,4,0,0,4,4,3,2,2,2,2,2,3,0}, {0,1,2,2,2,2,1,1,0,1,2,4,4,0,0,4,4,3,2,3,3,3,2,3,0}, {0,1,2,2,2,2,1,1,0,1,2,4,4,0,0,4,4,3,2,3,2,2,2,3,0}, {0,1,2,2,2,2,1,1,0,1,2,4,4,0,0,4,3,3,2,3,2,3,3,3,0}, {0,1,2,2,2,2,1,1,0,1,2,4,4,0,4,4,1,2,2,3,2,0,0,0,0}, {0,1,2,2,2,2,1,1,0,1,2,4,4,0,4,3,3,3,3,3,0,0,0,0,0}, {0,1,2,2,2,2,1,1,0,1,2,4,4,4,4,0,0,0,0,0,0,0,0,0,0}, {0,1,2,2,2,2,1,1,0,1,2,4,4,0,0,0,1,0,0,0,0,0,0,0,0}, {0,1,2,2,2,2,1,1,0,1,2,4,4,0,0,0,1,0,0,0,1,1,1,0,0}, {0,1,2,2,2,2,1,1,0,1,2,4,4,0,0,1,0,0,0,0,0,1,1,0,0}, {0,0,1,2,2,2,1,0,0,0,4,4,4,0,0,1,1,0,0,0,0,0,1,0,0}}; then I want to change the first couple (x and y) of integers: tempMapMatrix[100][100] = {{5,5,5,5,5,1,2,3}, {5,5,5,5,5,1,2,3}, {5,5,1,1,1,1,2,3}, {5,5,1,5,5,1,2,3}, {5,5,1,1,1,1,2,3}, {5,5,5,5,5,5,5,5}, {5,5,5,5,5,1,2,3}, {5,2,2,2,5,1,2,3}, {5,2,5,2,5,1,2,3}, {5,2,2,2,5,1,2,3}}; but I'm getting an error (Expected Expression). I've tried tempMapArray = stuff; tempMapArray[][] = stuff; but none work. Any way to change the first couple of ints in the matrix?
You need to iterate over them, this is C, you don't have syntactic sugar to assingn pieces of arrays like you want. If you want to change, for example, every first element of each row you could do something like: for (int = 0; i < 100; ++i) { tempMatrix[i][0] = 5; } so for the first couple of every row you should do for (int = 0; i < 100; ++i) { tempMatrix[i][0] = 5; tempMatrix[i][1] = 5; } and so on.
You have to access and change each element in the matrix individually. I.e.: tempMapMatrix[0][0] = 5; tempMapMatrix[0][1] = //... There is no way to "batch change" the contents of an array (one-dimensional or n-dimensional) in C. The easiest way to achieve this effect is to write a for-loop and iterate over the contents of the two dimensional array and insert the required values in the required places.
Check how close UILabels are to each other
I am trying to make a game which has a jumbled up algebra equation. I have assigned an outlet to each component of the equation. For example, if the equation was: x2 + y = 2(a+b) Then x2 (which is x squared), +, y, = and 2(a+b) would all be its own outlet. But the equation is going to be jumbled up and I want the user to move the label outlets to the correct order. I have enabled touchesMoved, but my problem lies in checking if the equation is in the correct order. I would wrap the code into an IBAction button action, but how do I analyze the text? Would I check for the offset between each label? Is there an easy way/API to do this? Thanks!
Assuming your labels are called xLabel,plusLabel, yLabel, equalsLabel, and abLabel, you could do something like this: NSUInteger xLeftBorder = CGRectGetMinX(xLabel.frame); NSUInteger plusLeftBorder = CGRectGetMinX(plusLabel.frame); NSUInteger yLeftBorder = CGRectGetMinX(yLabel.frame); NSUInteger equalsLeftBorder = CGRectGetMinX(equalsLabel.frame); NSUInteger abLeftBorder = CGRectGetMinX(abLabel.frame); if(xLeftBorder < plusLeftBorder && plusLeftBorder < yLeftBorder && yLeftBorder < equalsLeftBorder && equalsLeftBorder < abLeftBorder){ //Correct! } else{ //Incorrect } This is kind of clumsy, but it works. An even better way to do it would be to put this in a function with each parameter being a label to check. For example: bool isCorrect = [self checkIf:xLabel isLessThan: plusLabel isLessThan: yLabel isLessThan:equalsLabel isLessThan:abLabel]; This is assuming the function you write returns a bool. Hope this helped!
Is value "in" some other values, in objective-c
Coming from an extremely spoiled family upbringing (turbo pascal, python, ruby) I'm a bit puzzled when it comes to doing all the household chores myself. Yesterday was one of these days where I just did not find myself a solution. I had to check whether a value matches one of some other values. x = some_function_return_value(); if x in (1,4,17,29,35): That's how I used to write it. Now with Objective-C I obviously can't do that. And I searched the old google, but found no answer, and the old manual, and nothing there, so how do you do this in Objective-C, without doing something cranky like the following? if (x == 1 || x == 4 || x == 17 || x == ...) { Edited: in this case it is an (int), I know for NSArray and NSString there are methods for this
If it's about integer values, you can use switch: switch (x) { case 1: case 4: case 17: case 29: case 35: do_something(); break; } Do not forget that in C/C++/Objective-C, the cases fall through to the next by default. You need to add break; statements to prevent that. For non-integer values, you have to do long if statements with a lot of repetition as C doesn't provide syntactic sugar or features that many scripting languages have to abbreviate this. Another way would be for example to prepare an array and then do: if ([myArray containsObject:[NSNumber numberWithInteger:x]]) or even better, use an NSSet for that. This will work for most objects, for example it will also work with strings.
There is a fast enumeration syntax in objective C that uses "in" to loop over collections, however given it requires converting your int values to NSNumbers, it's probably easier to use C here BOOL success = NO; int size = 5 NSInteger numbers[size] = {1,4,17,29,35}; for (int i = 0; i < size; i++) { if (yourValue == numbers[i]) { success = YES; break; } } if (success) { /* do your stuff */ } admittedly not as nice as python...
Here's my silly program of the day: bool int_exists_in_array(const int n, const int a[], const size_t elementCount) { return (0 != elementCount) && (n == a[0] || int_exists_in_array(n, a + 1, elementCount - 1U)); } so this: if x in (1,4,17,29,35): becomes: const int a[] = { 1, 4, 17, 29, 35 }; if (int_exists_in_array(x, a, sizeof(a)/sizeof(a[0]))) { ... }
You can use NSSet in addition with NSValue.
Given 4 objects, how to figure out whether exactly 2 have a certain property
I have another question on how to make most elegant solution to this problem, since I cannot afford to go to computer school right so my actual "pure programming" CS knowledge is not perfect or great. This is basically an algorhythm problem (someone please correct me if I am using that wrong, since I don't want to keep saying them and embarass myself) I have 4 objects. Each of them has an species property that can either be a dog, cat, pig or monkey. So a sample situation could be: object1.species=pig object2.species=cat object3.species=pig object4.species=dog Now, if I want to figure out if all 4 are the same species, I know I could just say: if ( (object1.species==object2.species) && (object2.species==object3.species) && (object3.species==object4.species) ) { // They are all the same animal (don't care WHICH animal they are) } But that isn't so elegant right? And if I suddenly want to know if EXACTLY 3 or 2 of them are the same species (don't care WHICH species it is though), suddenly I'm in spaghetti code. I am using Objective C although I don't know if that matters really, since the most elegant solution to this is I assume the same in all languages conceptually? Anyone got good idea? Thanks!!
You can use a hash table (or dictionary in objective-C) with the key on the species, incrementing the count every time. For clarity (pseudo-code): // N is 4 for your particular case for ( int i = 0; i < N; i++ ) hashtable[ object[i].species ]++; hashtable[ Species.PIG ]; // number of pigs (constant) or if you want to unroll it manually: hashtable[ object1.species ]++; hashtable[ object2.species ]++; hashtable[ object3.species ]++; hashtable[ object4.species ]++; now you can check through the species to see the count: for each key in hashtable if ( hashtable[ key ] == 3 ) // species "key" has 3 items /* Code */ of course, "hashtable" can be just a simple array if species is just a simple enum/integer. The above should be the same theory in either case.
This is precisely what sets and counted sets are for. BOOL allSameSpecies(NSArray *animals) { NSSet *speciesSet = [NSSet setWithArray:[animals valueForKey:#"species"]]; return [[speciesSet] count] == 1; } BOOL sameSpeciesNumber(NSArray *animals, NSUInteger targetCount) { NSCountedSet *speciesCounts = [NSCountedSet setWithArray:[animals valueForKey:#"species"]]; for (id species in speciesCounts) { if ([speciesCounts countForObject:species] == targetCount) return YES; } return NO. }
You can count how many comparisons match of all possible comparisons. If exactly 1 comparison is true, then exactly 2 items are the same, if 3 comparisons match, exactly 3 items are the same. This example is in C, you'll have to convert it to objective-C on your own. int count = 0; count += object1.species == object2.species; count += object1.species == object3.species; count += object1.species == object4.species; count += object2.species == object2.species; count += object2.species == object3.species; count += object3.species == object4.species; // count 0 - all different // count 1 - exactly 2 are the same // count 2 - two pairs of 2 // count 3 - exactly 3 are the same // count 6 - all are the same The counting can also be implemented as a loop: for (int i = 0; i < 4; i++) for (int j = i + 1; j < 4; j++) count += objects[i].species == objects[j].species; This approach only works if the amount of objects is 5 or less. Because of this and the fact that the amount of comparisons scales quadratically, it's better to use a hashtable if the amount of objects is larger.