Non-repetitive random numbers in Objective-C - ios

I have searched through the internet but I haven't find any straightforward answer. What I am trying to develop is basically a three same-object matching game. I have 3 UIButtons in one row. (each of these 3 buttons have a black hat icon).There are gonna be 3 unique types of hats. There are 3 rows of three items each. I want to touch the first hat and reveal a number from 0 to 2 (Let's say 1). After choosing the first hat, I want the second hat to generate a number between the 2 remained numbers( the choices are 0 and 2, let's say 2). And finally when I touch the third hat, it will generate the last remainder (number 0 in this example).The main reason for picking the numbers is because I want a certain number to represent a unique "Hat", so when I pick a hat with the number 1, a blue hat will pop out, with the number 0 a red hat etc... I have implemented the whole animation and stuff. I am just struggling in the "Unique random number picking". I am sure arrays will be a part of the "Random logic" but I haven't managed to implement it correctly... Any help would be HIGHLY appreciated :) Thank you all!

You can write a method that does this really simply with arc4random and a mutable array property that stores the numbers that have been shown as NSNumber objects.
-(NSInteger) randomNumberZeroToTwo {
NSInteger randomNumber = (NSInteger) arc4random_uniform(3); // picks between 0 and n-1 where n is 3 in this case, so it will return a result between 0 and 2
if ([self.mutableArrayContainingNumbers containsObject: [NSNumber numberWithInteger:randomNumber]])
[self randomNumberZeroToTwo] // call the method again and get a new object
} else {
// end case, it doesn't contain it so you have a number you can use
[self.mutableArrayContainingNumbers addObject: [NSNumber numberWithInteger:randomNumber]];
return randomNumber;
}
}
arc4random returns an NSUInteger so you have to cast it to avoid warnings with NSNumber.
Also make sure to instantiate your mutable array by adding this code so it does so automatically when self.mutableArrayContainingNumbers is called (i.e. lazy instantiation).
-(NSMutableArray *) mutableArrayContainingNumbers
{
if (!_mutableArrayContainingNumbers)
_mutableArrayContainingNumbers = [[NSMutableArray alloc] init];
return _mutableArrayContainingNumbers;
}

Have an array of pickable numbers.
pickable = #[0,1,2]; //Use NSNumbers but you get the idea.
/*Code to generate random number (rNum) with the range of 0-([pickable count]-1)*/
/*
Assign the number to your hat
and then remove that object from pickable
*/
[pickable removeObjectAtIndex:rNum]
and loop over that until [pickable count] == 0;
I hope that gives you a start good luck.

Related

How to compare values within two List<List<CustomClass>> in Dart?

I have a 2048-type game where the gameboard grid is made up of a list of 4 other lists (each of which contain 4 Tiles).
Each time a move is made, the newGameboardGrid is saved in yet another list (so that removeLast can be called when a player wants to undo a move).
When a player swipes, I need to compare the newGameboardGrid grid with the previous one to see if any actual movement took place or if the tile values are still the same (as would happen if a player swiped in a direction where no movement was possible).
I tried this code:
if (newGameboardGrid == listOfGameboardGrids.last) {
// do something
}
It almost works in that it is comparing the <List<List< Tile>> from the new move with the <List<List< Tile>> of the last move, but the problem is that it never results in the two <List<List< Tile>> as being equal, even when all the tile values are identical. I believe it's because it is comparing hashcodes and/or other things.
The Tile class has lots of stuff in it, but the thing I would like to compare is that int named "value". Is it possible to compare only the "value" variable for these two <List<List< Tile>>?
Thanks in advance for any help! (And apologies if any of my terms are imprecise.)
Dart list implementations do not override the operator== of Object, so they are only ever equal to themselves. The elements are not checked.
IF you want to compare the elements (and here, the elements of the list elements), you can use the Equality classes from package:collection:
const boardEquality = ListEquality(ListEquality(DefaultEquality()));
This creates a ListEquality object which compares two lists of lists of elements by checking that they contain the same number of lists, which again contains the same number of equal elements. (I assume that Tile implements operator==).
You can the use it as: if (boardEquality.equals(newGameboardGrid, listOfGameboardGrids.last)) { ... }.
You could do an extension method on your particular list type and make an isEqual method for that compares each Tile:
extension TileListComp on List<List<Tile>> {
bool isEqual(List<List<Tile>> other) {
if(this.length != other.length || this[0]?.length != other[0]?.length) {
return false;
}
for(int x = 0; x < this.length; x++) {
for(int y = 0; y < this[0].length; y++) {
if(this[x][y] != other[x][y]) {
return false;
}
}
}
return true;
}
}
If you have not implemented any kind of comparison for your Tile class, you will need to do so. I can advise if necessary.

Obj-C - Use one of two image arrays programatically?

I have two sets of arrays in my app that consist of 3 images each. Every time my app is used, I want one of the two arrays to be set as array _finalSelection (e.g. each time one or the other should be set to _finalSelection randomly). How can I achieve this?
ViewController.m
-(void)viewDidLoad {
_pageImages = #[#"britt001.png", #"britt02.png", #"britt030.png"];
_pageImages2 = #[#"britt001.png", #"britt02.png", #"britt030.png"];
_finalSelection = [one of the two above arrays];
}
Use arc4random() division by 2.
_finalSelection = arc4random() % 2 ? _pageImages : _pageImages2;

Average of textfields depending on how many textfield are "used"

Little explication: I have an app with 5 textfields, i already got the code to make the avaerage of them. Using floates and giving a variable to each textfield.so, the adding of the value of all the textfield /5 (divided per 5)
My problem is that when a textfield is leaved emptty, its not goona be /5, if user fill in only 4 cells it will be/4 and so on.
Question: how to divide the adding of cells depending in how many cells have content?
I was tryng with textfield.text.length > 0 in an if. But i dont get it
Thanks, hope i was clear.
You could check each textfield and see if the text is NULL or blank (#"")
Use an int to keep track of the number of textfields that have a value.
For example:
int counter = 0;
float total = 0.0;
if([textfield1.text length] > 0)
{
counter++;
float thisValue = [textfield1.text floatValue];
total = total + thisValue;
}
repeat this for all 5 textfields and then divide your total by the counter variable.
You could include the if statement in a loop if you are going to vary the number of text fields or to reduce the amount of coding you do.
EDIT I have changed my answer based on the good suggestions of other to use text.length
try to count the number of used textfields by increasing a number every time you read out a textfield that has valid text in it and divide the result by that number. (logically the "number" should be initialized as 0)

iOS: Tapku Calendar: Need to select multiple dates

I've been checking the Tapku Calendar code for a bit and searched and read all the relevant questions and responses here however none seem to really offer the correct solution to the problem: How to select multiple dates, either programmatically or by tapping. Just a simple blue tile over two adjacent dates would make me happy :-) The post below seems to have a similar question however the answer does not work. The place in the code is not hit unless the month changes - not exactly what I am looking for. What would be great is a higher-level implementation of selectDate: that would select multiple dates. But just the right place to tweak in the library would be a great place to start is anyone is more familiar with the code. Much appreciated.
iOS: Tapku calendar library - allow selecting multiple dates for current month
So after a bit of stepping through code, I have this rudimentary method using a hammer. I adopted most of the code from TKCalendarMonthView.m->selectDay:day method. The method I created basically creates a new TKCalendarMonthTiles object and fills in the details and then adds subviews onto the main TKCalendarMonthTiles object (self). I tag the subviews so I can first get rid of them if they exist at the beginning of the method as I only want to select one additional day (you could leave the subviews attached if you want them to remain in the UI). I don't track the dates or store them or anything however this meets my needs.
The idea is to simply create a view with the correct tile image you want to use and one that contains the text label of the actual "date" like "14" then add those views as subviews to self. The borrowed code does all the calculations for "where" that date tile resides in the grid, so the view is drawn at the correct location. Code:
- (void)markDay:(int)day {
// First, remove any old subviews
[[self viewWithTag:42] removeFromSuperview];
[[self viewWithTag:43] removeFromSuperview];
int pre = firstOfPrev < 0 ? 0 : lastOfPrev - firstOfPrev + 1;
int tot = day + pre;
int row = tot / 7;
int column = (tot % 7)-1;
TKCalendarMonthTiles *deliveryTile = [[TKCalendarMonthTiles alloc] init];
deliveryTile.selectedImageView.image = [UIImage imageWithContentsOfFile:TKBUNDLE(#"TapkuLibrary.bundle/Images/calendar/MyDateTile.png")];
deliveryTile.currentDay.text = [NSString stringWithFormat:#"%d",day];
if(column < 0){
column = 6;
row--;
}
CGRect r = deliveryTile.selectedImageView.frame;
r.origin.x = (column*46);
r.origin.y = (row*44)-1;
deliveryTile.selectedImageView.frame = r;
deliveryTile.currentDay.frame = r;
[[deliveryTile selectedImageView] setTag:42];
[[deliveryTile currentDay] setTag:43];
[self addSubview:deliveryTile.selectedImageView];
[self addSubview:deliveryTile.currentDay];
} // markDay:
I call this method at the end of TKCalendarMonthView.m->selectDay:day as well as at the end of TKCalendarMonthView.m->-reactToTouch:down. Limited testing so far so good. Off to figure out why the timezone setting keeps thinking its tomorrow (I am in Pacific time zone).
Cheers, Michael

multi image collision detection

heres the problem
i have 5 balls floating around the screen that bounce of the sides, top and bottom. thats working great.
what i want to do now is work out if any of them collide with each other.
i know about
if (CGRectIntersectsRect(image1.frame, image2.frame))
{
}
but that only checks two images, i need to check all and each of them..
ive checked everywhere but cant find the answer, only others searching the same thing, any ideas?
thanks in advance
Spriggsy
edit:
im using this to find the CGRect and store it in an array
ball1 = NSStringFromCGRect(image1.frame);
ball2 = NSStringFromCGRect(image2.frame);
ball3 = NSStringFromCGRect(image3.frame);
ball4 = NSStringFromCGRect(image4.frame);
ball5 = NSStringFromCGRect(image5.frame);
bingoarray = [NSMutableArray arrayWithObjects:ball1,ball2,ball3,ball4,ball5,nil];
this then gets passed to a collision detection method
-(void)collision {
for (int i = 0; i<[bingoarray count]-1 ; i++) {
CGRect ballA = CGRectFromString([bingoarray objectAtIndex:i]);
if (CGRectIntersectsRect(ballA, image1.frame)) {
NSLog(#"test");
}
}
this i guess should check one ball against all the others.
so ball 1 gets checked against the others but doesnt check ball 2 against them. is this nearly there?
}
The ideal solution is to store all the rectangles into a interval tree or a segment tree in order to efficiently compute any overlapping areas. Note that you will have to generalize to 2 dimensions for your use case.
Another efficient approach would be to use a K-d tree to find the nearest other balls and compare against the nearest neighbor until there isn't a collision.
The simple approach is to simply iterate over all the balls and compare them to all other balls with a higher ID (to avoid double checking ball1 -> ball2 and ball2 -> ball1).
Since you only have 5 at once, the iterative approach is likely fast enough to not be dropping frames in the animation, but you should consider a more scalable solution if you plan to support more balls since the simple appreach run in quadratic time.
That is a fun little math problem to avoid being redundant.
You can create an array of the images. And loop through it, checking if each member collides with any successive members.
I can spell it out more with code if need be.
EDIT I couldn't resist
// the images are in imagesArray
//where you want to check for a collision
int ballCount = [imagesArray count];
int v1Index;
int v2Index;
UIImageView * v1;
UIImageView * v2;
for (v1Index = 0; v1Index < ballCount; v1Index++) {
v1 = [imagesArray objectAtIndex:v1Index];
for (v2Index = v1Index+1; v2Index < ballCount; v2Index++) {
v2 = [imagesArray objectAtIndex:v2Index];
if (CGRectIntersectsRect(v1.frame, v2.frame)) {
// objects collided
// react to collision here
}
}
}

Resources