I have some "void" methods in my project using cocos2d-iphone and would like make them random. Unfortunately, I'v found only little information about genareting random numbers. Any help is appreciated!
If I understand correctly you want to call a random method, right?
Get your method signatures in an array:
NSArray* methods = #[#"myMethod1", #"myMethod2", #"myMethod3"];
Pick a method name:
NSString* method = methods[arc4random()%method.count];
Call it:
[self performSelector:NSSelectorFromString(method)];
It would be also wise to check that self can respond to that selector first.
Try this
.h
-(int) randomGenarete;
.mm
-(int) randomGenarete
{
int random_number = arc4random() % 100; // return random 0 to 99
return random_number;
}
Related
If I have access to an objective-C Protocol and trying to figure out how to look inside it to see what methods it contains, including their signatures, etc.
I've tried NSLog and looking in the object in the debugger, as well as on the internet, and cannot find any way to do this.
I checked out the methods in objc/runtime.h after seeing the answers to this SO post: List selectors for Objective-C object and found a way to NSLog a protocol's method signatures
#import <objc/runtime.h>
Protocol *protocol = #protocol(UITableViewDelegate);
BOOL showRequiredMethods = NO;
BOOL showInstanceMethods = YES;
unsigned int methodCount = 0;
struct objc_method_description *methods = protocol_copyMethodDescriptionList(protocol, showrequiredMethods, showInstanceMethods, &methodCount);
NSLog(#"%d required instance methods found:", methodCount);
for (int i = 0; i < methodCount; i++)
{
struct objc_method_description methodDescription = methods[i];
NSLog(#"Method #%d: %#", i, NSStringFromSelector(methodDescription.name));
}
free(methods)
The only catch is that in protocol_copyMethodDescriptionList you need to specify whether you want required vs. non-required methods and whether you want class vs. instance methods. So to cover all four cases, you would need to call protocol_copyMethodDescriptionList four times and print the results for each list.
I am having trouble getting objects added to my NSMutableArray to log properly (which definitely means they won't process any of the appropriate functions correctly) with Spritebuilder [version 1.4.9, from the Apple App Store]. I am creating several objects using the same class, but each new one is overriding the older objects which exist. I thought an array would help keep things in order (and then on collision, I could call the array to check for which object was collided with), but it simply is not working that way - at all. Here is the relevant code.
Main.h
#property Coven *coven;
#property Nellie *nellie;
#property NSMutableArray *array;
//Physics, other things
Main.m
/Adding other things...
-(void) addCovenMember{
//This function is called on a RANDOM time interval
_array = [[NSMutableArray] alloc]init];
for (i = 0, i < 15, i++){
_coven = (Coven*) [CCBReader load:#"CovenMember"];
[_array addChild:_coven];
}
[_physicNode addChild:_coven];
}
-(BOOL)ccPhysicsCollisionBegin:(CCPhysicsCollisionPair *)pair nellie:(Nellie*)nellie coven:(Coven*)coven{
for (_coven in _array){
NSLog(#"%#",_coven.name)
if (CGRectIntersectsRect(_nellie.boundingBox, _coven.boundingBox){
NSLog(#"We're intersecting!");
}
}
Coven. h
//Nothing Important Here
Coven.m
-(void)didLoadFromCCB{
self.physicsBody.CollisionType = #"coven";
}
Nellie.h
//Nothing Here
Nellie.m
-(void) didLoadFromCCB{
self.physicsBody.CollisionType = #"nellie";
}
The collision is logging with every collision - but only as the name of the LATEST _coven member to be generated, no matter what I am colliding with. This also means that the _coven.boundingBox is solely on the latest _coven member and interaction only occurs when I hit the new member as soon as it generates on to the screen.
Any ideas? Any help?
Note: This is also posted on the Spritebuilder website - I decided to post it here as well because answers can be a little slow on those forums.
The -(void) addCovenMember overwrites (creates a new instance) of _array every time it's called. Thus, when you try to iterate in -ccPhysicsCollisionBegin: you'll only ever see 1 coven.
Add a nil check around your array creation:
if(_array == nil) {
_array = [[NSMutableArray] alloc]init];
}
The for loop in the -addCovenMember method looks broken (at least not a c loop). Reaplace the , with ;:
for (i = 0; i < 15 i++){
Also, using for(_coven in _array) seems wrong, you already have a property self.coven (presumably) with a backing _coven ivar. Try changing it to for(Coven * c in self.array) and use the local c in the loop:
for (Coven * c in _array){
NSLog(#"%#",c.name)
if (CGRectIntersectsRect(_nellie.boundingBox, c.boundingBox){
NSLog(#"We're intersecting!");
}
}
To everyone out in the world struggling with their ccPhysicsCollisions, arrays may not be the answer - this was a simple fix that left me incapacitated for days.
Using the basic ccPhysicsCollisionsBegan that ships with spritebuilder, try this without arrays first:
Scene.m
-(BOOL)ccPhysicsCollisionBegin:(CCPhysicsCollisionPair *)pair nellie:(Nellie*)nellie coven:(Coven*)coven{
[_coven stopAction:coven.path];
}
I initially created the method with:
[_coven stopAction:_coven.path];
Yes, that (underscore) set me back three weeks. Be sure you refer to the object interacting through the physics delegate, and not the object itself, which in my case, was constantly being overwritten by the new ones being generated.
Check your underscores.
Solved! :D
Thanks to #thelaws for your help! I'll get better at Obj C... eventually.
How to compare two strings while some parts of them are same?
Let say I have a string ABCAAAA.
For some reason, only ONE character of the string ABCAAAA can be changed at a time. For example, I can change this string to DBCAAAA.
Now the problem is :
How can I ensure ONLY ONE character is changed each time? Is there a method for NSString to compare how much two strings differ?
Purpose: I put each string into own UITextField to determine whether this one is editable if others had changed. I need to ensure only one is edited at a time. So if one had been edited, I will set UITextField's enable to NO to disable editing.
There is no built-in NSString method available to do what you want. You need to write your own method. Objective-C does let you "extend" classes with new methods to cover cases like this.
This is how I would do it:
#interface NSString(Extend)
-(NSInteger)proximity:(NSString*)otherString;
#end
#implementation NSString(Extend)
-(NSInteger)proximity:(NSString*)otherString
{
NSUInteger length = [otherString length];
if(length != [self length]) return -1;
NSUInteger k;
NSUInteger differences = 0;
for(k=0;k<length;++k)
{
unichar c1 = [self characterAtIndex:k];
unichar c2 = [otherString characterAtIndex:k];
if(c1!=c2)
{
++differences;
}
}
return differences;
}
#end
Then in my code at the place I wanted to check I would say something like
Michael L gave a good answer (+1)
I just wanted to note that if all your text strings are in separate UITextFields, then only one of them can be edited at a time. Therefore I really don't understand what you want to do with enable = NO part.
If text strings must be edited in certain order, just keep count of order by index by yourself.
I have a question regarding integers outside of methods in Objective-C/Xcode. I'm trying to create a simple guessing game, however my randomizer randomize number every time when the method is called, here is the code snipped:
- (IBAction)guessButton:(id)sender {
int tempUserGuess = [self.textField.text integerValue];
int randomNumber = (arc4random() % 11);
if(tempUserGuess == randomNumber){
self.guessAns.text = #"you won!";
}
if (tempUserGuess < randomNumber){
self.guessAns.text = #"no! too low!";
}
if (tempUserGuess > randomNumber){
self.guessAns.text = #"no! too high!";
}
}
The reason why I'm trying to put an int outside of the method is of that once randomized integer should not be randomized every single time (of course). By the way, everything works fine, the app compiles and works but every single time when I hit return, it randomizes the number.
I know how to do this in Java, but Objective-C seems to be more complex.
Your guessButton method is probably a member of some class. You need to add property to that class holding that randomized number.
You only have to create/store a random number once per game play. There is no need to call the randomize method each time the guess button is pressed. The guessButton method is basically like an ActionListener in java. Each time the button is pressed, whatever's inside the curly braces will be executed. If you add a play again button to the game, then you might want to call the randomize method inside of it's action method.
if(tempUserGuess == num){
self.guessAns.text = #"you won!";
}
This will be a good way because it will be using less memory in the sytem when trying to divert the random number. Good work
Okay, I got it.
Here is the answer:
in ViewController.h I had to include:
NSInteger num;
and then in ViewController.m a method that simply returns a number:
-(int)giveRandom {
int randomNumber = (arc4random() % 10);
return randomNumber;
}
And then refer to 'num' in the method with if statements such as:
...
if(tempUserGuess == num){
self.guessAns.text = #"you won!";
}
...
For some reason it returns 0, but I will try to solve it.
Thanks!
I have the following code, intended to select a random string from the array.
NSArray *popupMessages = [NSArray arrayWithObjects:
#"Shoulda' been bobbin' and weaving! Need anything from the shop?",
#"Don't forget you can use old boss's guns! Available in the shop!",
#"Hey Chaz, you Bojo! You need more POWER! Come by the shop for some better weapons!",
#"Aw… lame. Maybe I got something that can help you out here at my shop!",
nil];
int pmCount = popupMessages.count; // Breakpoint Here - pmCount = 971056545
int messageIndex = arc4random() % pmCount; // Breakpoint Here - same as above
I am using ARC with cocos2d. Any ideas as to why the array's count returns such a huge number? Thanks!
Your problem just looks like it's a debugger artifact. It could be optimization-related, for example. Sometimes compilers can generate code that confuses debuggers pretty seriously. Add a log statement to make sure the debugger isn't just telling you lies.
"count" is not a property, AFAIK.
The way I usually get the count for an array is:
[popupMessages count];
Try:
NSInteger pmCount = [popupMessages count];