Az Objective-C programozási nyelv

Példaprogramok



Letölthető példaprogramok

Kattints a linkre a példaprogramok letöltéséhez!

Hello, World

Egyszerű c hello-world program, ami Objective-C ben is lefordul és működik.

hello.m

#import <stdio.h> /* gcc -o hello hello.m -I /GNUstep/System/Library/Headers \ -L /GNUstep/System/Library/Libraries -lobjc \ -lgnustep-base -fconstant-string-class=NSConstantString */ //szabvanyos c program => szabvanyos objective-c program int main( int argc, const char *argv[] ) { printf( "hello world\n" ); return 0; }
Objektumokat használó hello world program.
A @"Hello, World!" egy Objective-C sztring objektumot hoz létre (automatikusan), ami a program végén szabadul fel.
A <Foundation/Foundation.h> tartalmazza a szükséges osztálydefiniókat, ezért importálni kell.

hellognustep.m

#import <Foundation/Foundation.h> int main (int argc, const char * argv[]) { //utomatikus objektumfelszabaditashoz szukseges NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; //log uzenet kiirasa a standard kimenetre NSLog (@"Hello, World!"); //automatikus objektumfelszabaditas elvegzese [pool drain]; return 0; }

Boolean típus

Érdekesség: true és false helyett YES és NO használható.

boolean.m

#import <stdio.h> #import <Foundation/Foundation.h> int main( int argc, const char *argv[] ) { //logikai változó létrehozása: BOOL típus //Lehetséges értékek: YES / NO BOOL x = YES; if (x) printf("Yes\n"); x = NO; if (x==NO) printf("No\n"); //printf( " \n" ); return 0; }

Osztályok, Kategóriák

Fejléc fájl - az osztály adattagjait és metódusdeklarációit tartalmazza.

Complex.h

#import <Foundation/NSObject.h> //interface: adattagok, majd a megvalositott metodusok @interface Complex: NSObject { //lathatosag - protected az alapertelmezes is @protected double real; double imaginary; } -(void) setReal: (double) a; -(void) setImaginary: (double) b; -(void) setReal: (double) a andImaginary: (double) b; -(double) real; -(double) imaginary; -(void) print; @end

Az osztály metódusainak megvalósítása megvalósítása .m kiterjesztésű fájlokba kerül.

Complex.m

#import "Complex.h" #import "ComplexOperations.h" #import <stdio.h> @implementation Complex // - : objektum metodus //(void) : void visszateresi ertek -(void) print { printf( " %f + i * %f ", real, imaginary ); } //(double) a //double parameter, neve a -(void) setReal: (double) a { real = a; } -(void) setImaginary: (double) b { imaginary = b; } -(double) real { return real; } -(double) imaginary { return imaginary; } //Metodus tobb parameterrel -(void) setReal: (double) a andImaginary: (double) b { //Az objektum onmaganak is kuldhet uzenetet! [self setReal: a]; [self setImaginary: b]; } @end

Az osztályokat kibővíthetjük kategóriákkal, ezek további műveleteket rendelnek az adott osztályhoz.

ComplexOperations.h

#import "Complex.h" //kategoria - kibovito a Complex osztalyt @interface Complex (Operations) -(Complex*) add: (Complex*) c; @end
ComplexOperations.m
#import "ComplexOperations.h" @implementation Complex (Operations) -(Complex*) add: (Complex*) c { //allokalunk az eredmenynek egy Complex objektumot, //es beallitjuk az adattagjait az osszegnek megfeleloen Complex* r = [[Complex alloc] init]; [r setReal: [c real]+[self real] andImaginary: [c imaginary]+[self imaginary]]; return r; } @end
ComplexMain.m
#import <stdio.h> #import <Foundation/Foundation.h> #import <Foundation/NSException.h> #import <Foundation/NSAutoreleasePool.h> #import "Complex.h" //kategoria betoltese: kiegesziti a Complex osztalyt! #import "ComplexOperations.h" /* Forditas: gcc -o complex ComplexOperations.m ComplexMain.m Complex.m -I /GNUstep/System/Library/Headers \ -L /GNUstep/System/Library/Libraries -lobjc -lgnustep-base -fconstant-string-class=NSConstantString */ int main( int argc, const char *argv[] ) { //uj objektum letrehozasa //eloszor memoria allokalas, majd inicializalas Complex *c = [[Complex alloc] init]; //ertekek beallitasa uzenetkuldessel uzenet: parameter formatumban [c setReal: 1.2]; [c setImaginary: 3.4]; printf( "A komplex szam: " ); [c print]; printf( "\n" ); Complex *c2 = [[Complex alloc] init]; //tobb uzenet/parameter kuldese az objektumnak [c2 setReal: 5.6 andImaginary: 7.8]; printf( "Egy masik komplex szam: " ); [c2 print]; printf( "\n" ); //kategoria felhasznalasa: az eredeti osztalyban meg nincs is add //emiatt warning, de lefordul, es mukodik is Complex *c3 = [c add: c2]; printf( "Az osszeguk: \n" ); [c3 print]; printf("\n"); //memoria felszabaditasa [c release]; [c2 release]; [c3 release]; return 0; }

Posing, Protokoll megvalósítás

Posing segítségével lecserléhetjük az osztály belső műveleteit, származtatás nélkül.

posing.m

#import <Foundation/Foundation.h> #import <Foundation/NSObject.h> #import <stdio.h> #import "Complex.h" //leszarmazott osztaly, ami megvaltoztatja a print muveletet //es megvalositja az NSCopying protokollt @interface ComplexB: Complex <NSCopying> -(void) print; @end @implementation ComplexB //print - mas formatumban -(void) print { printf( "(%2.2f; %2.2f)", real, imaginary ); } //NSCopying protokoll megvalostasahoz implementalnunk kell //a copyWithZone muveletet //zone definialja a felhasznalando memoriateruletet, //ezt tovabb kell kuldenunk az allocWithZone uzenettel -(Complex*) copyWithZone: (NSZone*) zone { Complex* r = [[Complex allocWithZone: zone] init]; [r setReal: real]; [r setImaginary: imaginary]; return r; } @end /* Forditas: gcc -o posing posing.m Complex.m -I /GNUstep/System/Library/Headers \ -L /GNUstep/System/Library/Libraries -lobjc -lgnustep-base -fconstant-string-class=NSConstantString */ int main (int argc, const char * argv[]) { //lecseréljük a Complex osztályt, mostantól ComplexB fog létrejönni //poseAsClass -t csak akkor szabad meghívni, amikor még //nem küldtünk semmilyen üzenetet az osztálynak! [ComplexB poseAsClass: [Complex class]]; Complex *c = [[Complex alloc] init]; [c setReal: 1.2 andImaginary: 3.4]; printf( "A komplex szam: " ); [c print]; printf( "\n" ); [c release]; Complex *c2 = [[Complex alloc] init]; [c2 setReal: 1.2 andImaginary: 3.4]; printf( "A komplex szam: " ); [c2 print]; printf( "\n" ); //Protokoll ellenorzes if ( [c2 conformsToProtocol: @protocol( NSCopying )] == YES ) { printf( "Complex conforms to NSCopying\n" ); //NSCopying hasznalat: masolhatoak az objektumok Complex *c3 = c2; printf( "Lemasolva: " ); [c3 print]; printf( "\n" ); } [c2 release]; return 0; }

Őröklődés

Az alábbiakban egy betegeket ellátó intézmény működését szemléltető példaprogramot láthatunk. A betegek különböző betegségekkel jelentkeznek, majd a program betegségek szerint beosztja őket a megfelelő orvosokhoz, ahol azok ellátásban részesülnek.

A projekt neve: MedicalCenter

A projekt struktúrája:

MedicalCenter
|
|__lib
|        |
|        |__entities
|        |   |
|        |   |__Human.h, Human.m
|        |   |__Patient.h, Patient.m
|        |   |__Doctor.h, Doctor.m
|        |   |__Disease.h, Disease.m
|        |   |__Printing.h
|        |
|        |__utils
|            |
|            |__MCManager.h, MCManager.m
|        
|__res
|   |
|   |__doctors.csv
|   |__diseases.csv
|   |__patients.csv
|
|_main.m

Entitások

Human.h:

#ifndef __HUMAN__ #define __HUMAN__ #include #include #include "Printing.h" /** * Emberek osztalya. */ @interface Human : NSObject { NSString* id0; int age; NSString* gender; NSString* name; } /** * Inicializálás */ - (Human*) initWithParams: (NSString*) newName : (NSString*) newId : (int) newAge : (NSString*) newGender; -(NSString*) getName; @end #endif

Human.m:

#include "Human.h" @implementation Human /** * Inicializálás */ - (Human*) initWithParams: (NSString*) newName : (NSString*) newId : (int) newAge : (NSString*) newGender { id0 = newId; age = newAge; gender=newGender; name = newName; } - (NSString*) print { NSString* description = @""; description = [description stringByAppendingString: @"Name: "]; description = [description stringByAppendingString: name]; description = [description stringByAppendingString:@"; id: "]; description = [description stringByAppendingString:id0]; description = [description stringByAppendingString:@"; age: "]; description = [description stringByAppendingString:[NSString stringWithFormat:@"%d", age]]; description = [description stringByAppendingString:@"; gender: "]; description = [description stringByAppendingString:gender]; description = [description stringByAppendingString:@"; "]; return description; } - (NSString*) getName { return name; } @end

Patient.h:

#ifndef __PATIENT__ #define __PATIENT__ #include "Human.h" #include "Disease.h" /** * Betegek osztalya. */ @interface Patient : Human { Disease* disease; } /** * Inicializalas. */ - (Patient*) initPatientWithParams : (NSString*) newName : (NSString*) newId : (int) newAge : (NSString*) newGender : (Disease*) newDisease; - (NSString*) getDescription; - (Disease*) getDisease; @end #endif

Patient.m:

#include "Patient.h" @implementation Patient - (Patient*) initPatientWithParams : (NSString*) newName : (NSString*) newId : (int) newAge : (NSString*) newGender : (Disease*) newDisease { [self initWithParams: newName : newId : newAge : newGender]; disease = newDisease; } - (NSString*) getDescription { NSString* description = [self print]; description = [description stringByAppendingString: @"Disease: "]; description = [description stringByAppendingString: [disease getName]]; description = [description stringByAppendingString: @"; "]; return description; } - (Disease*) getDisease { return disease; } @end

Doctor.h:

#ifndef __DOCTOR__ #define __DOCTOR__ #include #include "Human.h" #include "Disease.h" /* * Orvosok osztalya. */ @interface Doctor : Human { NSArray* diseases; } /** * Inicializalas. */ - (Doctor*) initDoctorWithParams : (NSString*) newName : (NSString*) newId : (int) newAge : (NSString*) newGender : (NSArray*) newDiseases; - (NSString*) getDescription; - (NSArray*) getDiseases; @end #endif

Doctor.m:

#include "Doctor.h" /** * Orvosok osztalya. */ @implementation Doctor /** * Inicializalas. */ -(Doctor*) initDoctorWithParams : (NSString*) newName : (NSString*) newId : (int) newAge : (NSString*) newGender : (NSArray*) newDiseases { [self initWithParams: newName : newId: newAge : newGender]; diseases = newDiseases; } - (NSString*) getDescription { NSString* description = @""; description = [description stringByAppendingString: [self print]]; description = [description stringByAppendingString: @"Diseases: "]; description = [description stringByAppendingString: [diseases description]]; description = [description stringByAppendingString: @"; "]; return description; } - (NSArray*) getDiseases { return diseases; } @end

Disease.h:

#ifndef __DISEASE__ #define __DISEASE__ #include #include #include #include "Printing.h" /** * Betegsegek osztalya. */ @interface Disease : NSObject { NSString* name; NSArray* meds; } /** * Inicializalas. */ - (Disease*) initWithParams: (NSString*) newName: (NSArray*) newMeds; /** * Accessor-ok. */ - (NSString*) getName; - (void) setName: (NSString*) newName; - (NSArray*) getMeds; - (void) setMeds: (NSArray*) newMeds; @end #endif

Disease.m:

#include "Disease.h" @implementation Disease /** * Inicializálás */ - (Disease*) initWithParams: (NSString*) newName : (NSArray*) newMeds { [self setName: newName]; [self setMeds: newMeds]; } /** * Accessor-ok. */ - (NSString*) getName { return name; } - (void) setName: (NSString*) newName { name = newName; } - (NSArray*) getMeds { return meds; } - (void) setMeds: (NSArray*) newMeds { meds = newMeds; } - (NSString*) print { NSString* description = @""; description = [description stringByAppendingString: @"Name: "]; description = [description stringByAppendingString: name]; description = [description stringByAppendingString: @"Meds: "]; description = [description stringByAppendingString: [meds description]]; description = [description stringByAppendingString: @"; "]; return description; } @end

Printing.h:

#ifndef __PRINTING__ #define __PRINTING__ /** * Objektumrol leirast szolgalgato protocol. */ @protocol Printing /** * Visszaadja az objektumrol tarolt informaciokat. */ -(NSString*) print; @end #endif

A manager osztály

MCManager.h

#ifndef __MCMANAGER__ #define __MCMANAGER__ #include #include #include #include /** * Egeszsegkozpont manager osztaly. */ @interface MCManager : NSObject { NSString* doctorResourcePath; NSString* diseaseResourcePath; NSString* patientResourcePath; NSMutableArray* doctors; NSMutableArray* diseases; NSMutableArray* patients; NSMutableDictionary* patientsToDoctorsMap; NSFileManager* fm; } /** * Inicializalas. */ - (MCManager*) initWithParams: (NSString*) newDoctorResourcePath: (NSString*) newDiseaseResourcePath : (NSString*) newPatientResourcePath; /** * Orvosok es kezelt betegsegek betoltese fajlbol. */ - (void) loadDoctors; /** * Betegsegek es gyogyszerek betoltese fajlbol. */ - (void) loadDiseases; /** * Betegek es betegsegek betoltese fajlbol. */ - (void) loadPatients; /** * Betegek beosztasa orvosokhoz. */ - (void) organizePatients; /** * Betegek ellatasa. */ - (void) treatPatients; /** * Orvosok listazasa. */ - (void) listDoctors; /** * Betegek listazasa. */ - (void) listPatients; @end #endif

A főprogram

main.m

#include #include #include #include "lib/entities/Human.h" #include "lib/entities/Patient.h" #include "lib/entities/Doctor.h" #include "lib/entities/Disease.h" #include "lib/utils/MCManager.h" int main(int argc, char* argv[]) { // autorelease pool letrehozasa NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; MCManager* manager = [[MCManager alloc] init]; @try { // manager objektum letrehozasa [manager initWithParams: @"res/doctors.csv" : @"res/diseases.csv" : @"res/patients.csv"]; // adatok betoltese [manager loadDoctors]; [manager loadDiseases]; [manager loadPatients]; // adatok megjelenitese [manager listDoctors]; [manager listPatients]; // betegek beosztasa orvosokhoz [manager organizePatients]; [manager treatPatients]; }@catch(NSException* e) { printf("%s\n", [[e reason] cString]); }@finally { [pool release]; } // memoriaterulet felszabaditasa [pool release]; return 0; }

A program fordítása Linux rendszeren, GCC fordítóval a következőképpen lehetséges:

gcc -o MedicalCenter -I/usr/GNUstep/System/Library/Headers main.m lib/entities/*.m lib/utils/*.m -lobjc /usr/GNUstep/System/Library/Libraries/libgnustep-base.so -fconstant-string-class=NSConstantString -std=gnu99

Kivételkezelés

kivetel.m

#import <stdio.h> #import <Foundation/Foundation.h> #import <Foundation/NSException.h> #import <Foundation/NSAutoreleasePool.h> int main( int argc, const char *argv[] ) { id x; @try { printf ("Nem letezo uzenet elkuldese: "); [x add: x]; } @catch ( NSInvalidArgumentException *e) { printf( "%s: ", [[e name] cString] ); } @finally { } return 0; }

Szálkezelés, lockolás

thread.m

#import <Foundation/Foundation.h> #import <unistd.h> /* gcc -o thread thread.m -I /GNUstep/System/Library/Headers \ -L /GNUstep/System/Library/Libraries -lobjc \ -lgnustep-base -fconstant-string-class=NSConstantString */ @interface NumberPrinter : NSObject +(void) printNumbers: (id) param; @end //zar NSLock *lock; @implementation NumberPrinter +(void) printNumbers: (id) param{ int j; for(j=0;j<40;++j) { //zarolas [lock lock]; printf("j == %i\n",j); usleep(2000); //zar elengedese [lock unlock]; } } @end int main(int argc, char *argv[]) { int i; lock = [[NSLock alloc] init]; //uj szal letrehozasa, ami futtatja a NumberPrinter osztaly printNumbers metodusat [NSThread detachNewThreadSelector:@selector(printNumbers:) toTarget:[NumberPrinter class] withObject:nil]; for(i=0;i<40;++i) { [lock lock]; printf("i == %i\n",i); printf("i ^^\n"); [lock unlock]; usleep(2000); } return 0; }

Szálak - Paraméterátadás, időzítés

timer.m

#import <Foundation/Foundation.h> #import <unistd.h> /* gcc -o thread thread.m -I /GNUstep/System/Library/Headers \ -L /GNUstep/System/Library/Libraries -lobjc \ -lgnustep-base -fconstant-string-class=NSConstantString */ @interface NumberPrinter : NSObject //+ : statikus(osztalyszintu) metodus - nem kell objektumot letrehozni //a hasznalathoz +(void) printNumbers: (id) param; @end //zar NSLock *lock; @implementation NumberPrinter +(void) printNumbers: (id) param{ int j; for(j=0;j<40;++j) { //zarolas (a _lock_ nevu objektumnak kuldott uzenet: "lock") [lock lock]; printf("j == %i\n",j); //zar elengedese (a kuldott uzenet: "unlock") [lock unlock]; usleep(2000); } } @end int main(int argc, char *argv[]) { int i; lock = [[NSLock alloc] init]; //uj szal letrehozasa, ami futtatja a NumberPrinter osztaly printNumbers metodusat [NSThread detachNewThreadSelector:@selector(printNumbers:) toTarget:[NumberPrinter class] withObject:nil]; for(i=0;i<40;++i) { //blokkol, ha mar lock-olva van, megvarja a felszabaditast a //printNumbers metodusban [lock lock]; //a ket print egymas alatt kell, hogy megjelenjen, //nem szakithatja meg oket "j" cimkeju sor a lock miatt printf("i == %i\n",i); printf("i ^^\n"); //felszabaditja a lock-ot, aki varakozik, az folytathatja tovabb a //lockolast es feldolgozast(printNumbers) [lock unlock]; usleep(2000); } return 0; }

Taszkok

tasks.m

#import <Foundation/Foundation.h> /* gcc -o tasks tasks.m -I /GNUstep/System/Library/Headers \ -L /GNUstep/System/Library/Libraries -lobjc \ -lgnustep-base -fconstant-string-class=NSConstantString */ int main (int argc, const char * argv[]) { //autoreleasepool szükséges ahhoz, hogy az automatikusan //felszabadulo objektumok ténylegesen fel is szabaduljanak NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; //Létrehoz egy új taszk objektumot NSTask *task = [[NSTask alloc] init]; //Beállítja a futtatandó programot [task setLaunchPath: @"./hello"]; //pipe a kimenet tárolásához NSPipe *pipe = [ [ NSPipe alloc ] init ]; [task setStandardError:pipe]; [task setStandardOutput:pipe]; //pipe-ból egy file handle segítségével kiolvashatóak lesznek az adatok NSFileHandle *file; file = [pipe fileHandleForReading]; //futtatás [task launch]; //megvárja, amíg befejeződik a taszk [task waitUntilExit]; NSLog (@"Task finished!"); //kiolvassa a fájlból az adatokat NSData *data; data = [file readDataToEndOfFile]; //létrehoz egy sztringet a kiolvasott adatokbol NSString *string; string = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding]; //kiirja az eredmenyt NSLog (@"Result:\n%@", string); //felszabaditja az automatikusan létrehozott objektumokat [pool drain]; return 0; }

RunLoop

runloop.m

#import <Foundation/Foundation.h> #import <unistd.h> /* gcc verzio: i686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5664) build command: gcc -o runloop runloop.m -framework CoreFoundation -framework Foundation -l objc */ /* A RunLoop obszerverenek a visszahivo metodusa Ha tortenik valami a RunLoopban, meghivodik a fuggveny, es a parameterbol kideritheto, hogy mi tortent */ void MyRunLoopObserverCallback( CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info ) { NSString* message = nil; switch (activity) { case kCFRunLoopEntry: message = @"RunLoop entry"; break; case kCFRunLoopBeforeTimers: message = @"RunLoop before timers"; break; case kCFRunLoopBeforeSources: message = @"RunLoop before sources"; break; case kCFRunLoopBeforeWaiting: message = @"RunLoop before waiting"; break; case kCFRunLoopAfterWaiting: message = @"RunLoop after waiting"; break; case kCFRunLoopExit: message = @"RunLoop exit"; break; case kCFRunLoopAllActivities: message = @"RunLoop activities"; break; } NSLog(@"RunLoop observer called: %@", message); } /* A szal osztaly, tartalmazza a szal main fuggvenyet, illetve a timer altal hivott fuggvenyt, illetve egy szamlalot, ami a timer alal hivott fuggveny lefutasait szamolja */ @interface MyThread : NSObject { int counter; } -(void) threadMain; -(void) doFireTimer; @end @implementation MyThread /* A thread main fuggvenye, innen indul a masidik szal vezerlese */ - (void) threadMain { /*Szamlalo nullazasa*/ counter = 0; /*Lekerdezzuk a szalhoz tartozo RunLoop-ot*/ NSRunLoop* myRunLoop = [NSRunLoop currentRunLoop]; /* Letrehozunk egy RunLoopObserver objektumot (ez csak CF objektumkent hozhato letre), es beallitjuk neki visszahivo fuggvenynek a MyRunLoopObserverCallback fuggvenyunket */ CFRunLoopObserverContext context = {0, self, NULL, NULL, NULL}; CFRunLoopObserverRef observer = CFRunLoopObserverCreate(kCFAllocatorDefault, kCFRunLoopAllActivities, YES, 0, &MyRunLoopObserverCallback, &context); /* Hozzaadjuk az observert a RunLoophoz */ if (observer) { CFRunLoopRef cfLoop = [myRunLoop getCFRunLoop]; CFRunLoopAddObserver(cfLoop, observer, kCFRunLoopDefaultMode); } /* Keszitunk egy timert, ami a doFireTimer metodusunkat fogja hivogatni */ [NSTimer scheduledTimerWithTimeInterval:4.5 target:self selector:@selector(doFireTimer) userInfo:nil repeats:YES]; /* 10 iteracion keresztul fogjuk futtatni a RunLoop-unkat */ NSInteger loopCount = 10; do { /* A RunLoop 3 masodpercig var esemenyre, ha erkezik, futtatja majd megszakad a kovetkezo iteracioig */ [myRunLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:3]]; loopCount--; } while (loopCount); } - (void) doFireTimer { NSLog(@"Timer fired %d times", ++counter); } @end int main(int argc, char *argv[]) { /* Letrehozzuk a szal objektumot, majd elinditjuk azt A szemetgyujtes miatt nem kell felszabaditanunk az objektumokat */ MyThread* myThread = [[MyThread alloc] init]; [NSThread detachNewThreadSelector:@selector(threadMain) toTarget:myThread withObject:nil]; return 0; }

Minimalista GNUStep/AppKit desktop alkalmazás

Egy desktop alkalmazás elkészítéséhez először szükség van egy NSApplication példányra, mely az egész alkalmazást hivatott reprezentálni. Két lehetőség van az alkalmazások testreszabására :

  1. Az NSApplication specializálása (származtatása).
  2. Delegált osztály hozzárendelése.
A fent említett két lehetőség közüll a gyakrabban használt megoldás a delegált objektum hozzárendelése.

A Delegált lényege hogy az NSApplication bizonyos eseményeinek kezelésére biztosítson szabványos felületet. Bővebb információkért :

  1. Mac OS X Developer Library - NSApplication class reference
  2. Mac OS X Developer Library - NSApplicationDelegate protocol reference
A most bemutatott alkalmazásban az delegált objektumnak 3 feladata lesz :
  1. Az alkalmazás indulása előtt létre fogja hozni az alkalmazásban használatos GUI elemeket
  2. Eljárást biztosít egy egyszerű "alert" panel kijelzésére
  3. Mechanizmust biztosít a használt ablak láthatóvá tételére

//appdelegate.h #import <Foundation/Foundation.h> #import <AppKit/AppKit.h> @interface AppDelegate : NSObject { NSApplication * owner ; // a delegált objektumhoz rendelt alkalmazás NSWindow * main_window ; // a megjeleníteni kívánt ablak BOOL toggle_window ; // az ablak láthatóságát vezérlő érkék } - (void) dealloc ; // 'clean-up' eljárás - (void) init ; // inicializáció - (void) printHello:(id) Sender; // az egyszerű 'alert' ablak megjelenítése - (void) toggleWindow: (id) Sender ; // az ablak láthatóságát váltogató eljárás - (void) setOwner:(NSApplication *)Owner ; // egyszerű beállító művelet - (void) applicationWillFinishLaunching: (NSNotification *)not ; // NSApplicationDelegate protokol egy megvalósított eleme @end

Az applicationWillFinishLaunching: eljárást az alkalmazás még az indulása előtt futtani fogja, ezért kitűnő alkalom a GUI komponensek inicializációjára. Egy másik inicializációs pont lehetne például az AppDelegate objektum saját init eljárása.

//appdelegate.m #import <appdelegate.h> @implementation AppDelegate : NSObject - (void) init ; { // kezdetben az ablak nem látszik toggle_window = NO ; } -(void) dealloc ; { // az ablak elengedése (csak a referenciaszámláló csökken) [ main_window release]; // az alkalmazás elengedése (csak a referenciaszámláló csökken) [ owner release ]; // egyéb szükséges 'clean-up' eljárások futtatása az ősosztályban [ super dealloc ]; } - (void) printHello:(id) Sender; { // 'alert' panel generálása NSRunAlertPanel(@"Alert Panel", @"Hello world!", @"OK", @"Cancel", nil); } - (void) setOwner:(NSApplication *)Owner ; { // Az előző tulajdonos elengedése // (az nem okoz gondot ha {owner==nil} ugyanis küldhetünk üzenetet nil-nek is!) [owner release] ; // A kapott objettumot beállítjuk az új értéknek owner = Owner ; // Fent tartunk egy referenciát az új objektumra [Owner retain] ; // Egyből beállítjuk az újonnan kapott alkalmazás delegáltjának saját magunkat [owner setDelegate: self]; } - (void) toggleWindow: (id) Sender ; { if( toggle_window == YES ) { // Ha az eljárást úgy hívták meg hogy az ablak látszik akkor eltűntetjük // (csak a képernyőről tűnik el, de nem záródik be!) [ main_window orderOut:nil ]; toggle_window = NO ; } else { // Ha az eljárást úgy hívták meg hogy az ablak nem látszik akkor // előre rendeljük [ main_window makeKeyAndOrderFront:nil ]; toggle_window = YES ; } } - (void) applicationWillFinishLaunching: (NSNotification *)not ; { // a menu elkészítése NSMenuItem * quit_item = [NSMenuItem new]; [ quit_item setTitle: @"Quit" ]; [ quit_item setAction: @selector(terminate:) ]; [ quit_item setTarget: owner]; NSMenuItem * hello_item = [NSMenuItem new]; [ hello_item setTitle: @"Hello" ]; [ hello_item setAction: @selector(printHello:) ]; [ hello_item setTarget: self]; NSMenuItem * show_item = [NSMenuItem new]; [ show_item setTitle: @"Show window" ]; [ show_item setAction: @selector( toggleWindow: ) ]; [ show_item setTarget: self ]; NSMenu * menu = [ NSMenu new]; [menu addItem: hello_item]; [menu addItem: show_item]; [menu addItem: quit_item]; // a kész menü meállítása főmenünek [ owner setMainMenu: menu ]; // az ablak elkészítése NSRect rect = NSMakeRect (0, 0, 640, 480); // A styleMask egyes biteinek állításával tujuk // vezérelni az ablak majdani kinézetét és viselkedését. unsigned int styleMask = NSTitledWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask ; // | NSClosableWindowMask main_window = [NSWindow alloc]; main_window = [main_window initWithContentRect: rect styleMask: styleMask backing: NSBackingStoreBuffered defer: NO]; [main_window setTitle: @"This is a test window"]; // egyéb komponensek elkészítése NSSplitView * view ; NSButton * btn1 ; NSButton * btn2 ; NSTextField * label ; btn1 = [NSButton new]; [ btn1 setTitle: @"Print Hello!"]; [ btn1 sizeToFit]; [ btn1 setTarget: self]; [ btn1 setAction: @selector (printHello:)]; btn2 = [NSButton new]; [ btn2 setTitle: @"Print Hello!2"]; [ btn2 sizeToFit]; [ btn2 setTarget: self]; [ btn2 setAction: @selector (printHello:)]; label = [NSTextField new] ; [ label setStringValue: @"textfield : Hello!"]; [ label setEditable: YES ] ; [ label setBordered : NO ] ; view = [ NSSplitView new ] ; [ view addSubview : btn1 ] ; [ view addSubview : btn2 ] ; [ view addSubview : label ] ; // komponensek hozzáadása, és az ablak középre helyezése [ main_window setContentView : view ]; [ main_window center ]; }@end

Néhány megjegyzés a fenti kódhoz :

Végezetül a program, belépési pontja :

// main.m int main(int argc, const char** argv) { // NSApplication létrehozása NSApplication * app = [NSApplication sharedApplication]; // 'app' helyett használható mindenütt az 'NSApp' konstans // Létrehozzuk a delegált osztályt, majd beállítjuk az alkalmazást. AppDelegate * delegate = [AppDelegate new] ; [ delegate setOwner : app ]; return NSApplicationMain(argc , argv) ; }

A kódot GNUMakefile segítségével fordíthatjuk :

include $(GNUSTEP_MAKEFILES)/common.make APP_NAME = Executable Executable_OBJC_FILES = main.m include $(GNUSTEP_MAKEFILES)/application.make

Tologatós jaték

A továbbiakban a klasszikus tologatós játék egy lehetséges implementációja található. A játék lényege, hogy egy kép összekevert képrészleteit megfelelően elmozgatva, megkapjuk az eredeti képet. A felhasználónak a program indításakor lehetősége van képet választani és meghatározni, hogy egy sor és oszlop hány darabra legyen felosztva.
Két osztályt hozunk létre: a Tilitoli és az AppControl nevűt.

//Tilitoli.h #import <Foundation/Foundation.h> #import <AppKit/AppKit.h> @interface Tilitoli : NSView { // tomb a tablamezok ertekenek tarolasara int tabla[24][24]; // tabla merete: tdim x tdim meretu int tdim; // az ures mezo pozicioja int uresX, uresY; // azt tarolja, megvannak-e keverve a mezok BOOL keverve; //egy mezo merete NSSize darabMerete; NSImage *kep; } - initPont:(NSPoint)p andKep:(NSImage *)k andDimenzio:(int)d; - (BOOL)acceptsFirstResponder; - (int)helyenVan; - mozgatX:(int)x Y:(int)y; - kever:(id)sender; - (void)drawRect:(NSRect)r; - (void)mouseDown:(NSEvent *)e; @end

Most pedig az egyes metódusok implementálása:

//Tilitoli.m #import <Foundation/Foundation.h> #import <AppKit/AppKit.h> #import "Tilitoli.h" @implementation Tilitoli // inicializalo metodus - initPont:(NSPoint)p andKep:(NSImage *)k andDimenzio:(int)d { NSRect keret; int x, y; keret.origin = p; keret.size = [k size]; keret.size.width -= ((int)keret.size.width)%d; keret.size.height -= ((int)keret.size.height)%d; [super initWithFrame:keret]; kep = k; darabMerete.width = keret.size.width/d; darabMerete.height = keret.size.height/d; if (darabMerete.width<20 || darabMerete.height<20){ [NSException raise:NSInvalidArgumentException format:@"A valasztott kep tul kicsi egy %dx%d meretu tablahoz.", d, d]; } tdim = d; keverve = NO; for(y=0; y<tdim; y++){ for(x=0; x<tdim; x++){ tabla[y][x] = y*tdim+x; } } tabla[0][tdim-1] = -1; uresX = tdim-1; uresY = 0; return self; } - (BOOL)acceptsFirstResponder { return YES; } // visszaadja, hogy hany elem van a helyen - (int)helyenVan { int x, y, osszesen = 0; for(y=0; y<tdim; y++){ for(x=0; x<tdim; x++){ if(tabla[y][x] == y*tdim+x){ osszesen++; } } } return osszesen; } // megadott koordinataju elemet (es a kozte es az ures hely kozt levo elemeket) // elmozgatja a negy lehetseges irany (fel, le, jobbra, balra) kozul a // megfelelobe - mozgatX:(int)x Y:(int)y { int m; if(x==uresX && y==uresY){ NSBeep(); } else if(x==uresX){ if(y>uresY){ // le for(m=uresY; m<y; m++){ tabla[m][x] = tabla[m+1][x]; } } else{ // fel for(m=uresY; m>y; m--){ tabla[m][x] = tabla[m-1][x]; } } tabla[y][x] = -1; uresY = y; } else if(y==uresY){ if(x>uresX){ // left for(m=uresX; m<x; m++){ tabla[y][m] = tabla[y][m+1]; } } else{ // right for(m=uresX; m>x; m--){ tabla[y][m] = tabla[y][m-1]; } } tabla[y][x] = -1; uresX = x; } else{ NSBeep(); } return self; } // megkeveri a tablat a veletlenszeruen kivalasztott elemek es irany // szerint. a keverest akkor tekintjuk helyesnek, ha a tablan levo elemek // maximum negyede van jo helyen. - kever:(id)sender { int maxJoHelyen = tdim*tdim/4, maxIteracio = tdim*tdim, i; do { for(i=0; i<maxIteracio; i++){ BOOL xTengelyMenten = lrand48()%2; int m = lrand48()%(tdim-1); if(xTengelyMenten==YES){ if(m>=uresX){ m++; } [self mozgatX:m Y:uresY]; } else{ if(m>=uresY){ m++; } [self mozgatX:uresX Y:m]; } } } while([self helyenVan]>maxJoHelyen); keverve = YES; [self setNeedsDisplay:YES]; return self; } // kirajzolja az egesz kivalasztott kepet, vagy a megfelelo darabokat, // attol fuggoen, hogy a tabla kevert allapotban van-e. akkor kerul meghivasra // miutan meghivjak az NSView osztály setNeedsDisplay metódusát YES parameterrel. - (void)drawRect:(NSRect)r { int x, y; [[NSColor blackColor] set]; if(keverve==NO){ [kep compositeToPoint:r.origin fromRect:r operation:NSCompositeCopy]; [NSBezierPath strokeRect:[self bounds]]; return; } for(y=0; y<dim; y++){ for(x=0; x<tdim; x++){ int val = tabla[y][x], px = val%tdim, py=val/tdim; NSRect honnan, hova; if(val==-1){ continue; } honnan.origin.x = px*darabMerete.width; honnan.origin.y = py*darabMerete.height; honnan.size = darabMerete; hova.origin.x = x*darabMerete.width; hova.origin.y = y*darabMerete.height; hova.size = darabMerete; [kep compositeToPoint:hova.origin fromRect:honnan operation:NSCompositeCopy]; [NSBezierPath strokeRect:hova]; } } } // az eger lenyomasakor meghatarozza az eger poziciojanak megfelelo koordinatakat // majd ez alapjan azt a darabot, amelyik felett az eger all, majd elmozgatja // azt, ha lehet. ha az osszes darab a helyen van, akkor uzenetet ir ki // a jatek vegerol. - (void)mouseDown:(NSEvent *)e { NSPoint p; int x, y; p = [e locationInWindow]; p = [self convertPoint:p fromView: nil]; x = p.x/darabMerete.width; y = p.y/darabMerete.height; if(keverve==NO || (x!=uresX && y!=uresY)){ NSBeep(); return; } [self mozgatX:x Y:y]; if([self helyenVan]==tdim*tdim-1){ keverve = NO; [self display]; NSRunAlertPanel(@"Gratulalok! Nyertel!", @"Sikerult kiraknod a kepet.", @"Ok", nil, nil); } else{ [self setNeedsDisplay:YES]; } } @end

Ezután elkészíthető az AppControl nevű osztály, melyben csak egyetlen metódust implementálunk, méghozzá az NSApplicationDelegate protokolból. A neve applicationDidFinishLaunching. Erre akkor lesz szükség, amikor a program belépési pontjában delegáltként beállítjuk az AppControl osztály egy példányát. Ennek köszönhetően a delegált értesül arról, amikor az alkalmazás elindult és még mielőtt az bármilyen eseményt fogadna lefut az applicationDidFinishLaunching metódus.

//AppControl.h #import <Foundation/Foundation.h> #import "Tilitoli.h" #define MINDIM 3 #define MAXDIM 24 @interface AppControl : NSObject - (void)applicationDidFinishLaunching:(NSNotification *)notif; @end

//AppControl.m #import <Foundation/Foundation.h> #import <AppKit/AppKit.h> #import "AppControl.h" @implementation AppControl // segitsegevel a delegalt tovabbi inicializacios muveleteket hajthat vegre. // ebben az esetben itt tortenik a menu es az alkamazas alakanak letrehozasa, // valamint a Tilitoli objektumunk létrehozása és init muveletehez tartozo // parameterek ellenorzese. - (void)applicationDidFinishLaunching:(NSNotification *)notif { NSProcessInfo *procInfo = [NSProcessInfo processInfo]; NSArray *args = [procInfo arguments]; NSString *kepUtvonal; NSImage *kep; int meret; Tilitoli *tt; NSMenu *menu = [NSMenu new]; NSWindow *ttAblak; NSRect ablakRect; srand48(time(NULL)); [menu addItemWithTitle: @"Keveres" action:@selector(kever:) keyEquivalent:@""]; [menu addItemWithTitle: @"Kilepes" action:@selector(terminate:) keyEquivalent:@"q"]; [NSApp setMainMenu:menu]; [menu display]; if([args count]!=3){ [NSException raise:NSInvalidArgumentException format:@"Meg kell adni az argumentumokat: <meret> <kep>"]; } meret = [[args objectAtIndex:1] intValue]; if(meret<MINDIM || meret>MAXDIM){ [NSException raise:NSRangeException format:@"A meret nem csak a (%d - %d) intervallumbol lehet: %d", MINDIM, MAXDIM, meret]; } kepUtvonal = [args objectAtIndex:2]; kep = [[NSImage alloc] initWithContentsOfFile:kepUtvonal]; if(kep==nil){ [NSException raise:NSInvalidArgumentException format:@"Nincs kep ezen az utvonalon: %@", kepUtvonal]; } tt = [[Tilitoli alloc] initPont:NSMakePoint(0, 0) andKep:kep andDimenzio:meret]; ablakRect.origin = NSMakePoint(0, 0); ablakRect.size = [tt bounds].size; ttAblak = [[NSWindow alloc] initWithContentRect:ablakRect styleMask:NSTitledWindowMask backing:NSBackingStoreBuffered defer:NO]; [ttAblak setTitle:@"Tilitoli"]; [ttAblak setContentView:tt]; [ttAblak setInitialFirstResponder:tt]; [ttAblak center]; [ttAblak makeKeyAndOrderFront:nil]; } @end // a program belepesi pontja int main(int argc, char** argv, char **env) { NSAutoreleasePool *pool = [NSAutoreleasePool new]; NSApplication *app; app = [NSApplication sharedApplication]; [app setDelegate:[AppControl new]]; [app run]; [pool release]; exit(0); }

A fordításhoz a következő GNUmakefile használható:

include $(GNUSTEP_MAKEFILES)/common.make APP_NAME = Tilitoli Tilitoli_OBJC_FILES = Tilitoli.m AppControl.m include $(GNUSTEP_MAKEFILES)/application.make

A fordítás után a Tilitoli.app mappába lépve a parancssorból a futtatható az alkalmazás:

./Tilitoli 4 ../virag.jpg

A fenti módon indított alkalmazás 4x4-es táblát eredményez, amin a virag.jpg kép lesz megjelenitve.

Minimalista tanulmányi rendszer

A következőekben egy egyszerű tanulmányi rendszer implementációjáról olvashatsz. Ebben a következő osztályokat implementálom:

A tanulók és tanárok ősosztálya két tulajdonságot, a nevet és az eha kódot tartalmazza.

//EtrHuman.h #import #import //Base class for students and teachers @interface EtrHuman : NSObject { //EHA code NSString *eha_; NSString *name_; } @property (readonly) NSString *name; @property (readonly) NSString *eha; //init function - (id) init:(NSString *)eha_param Name:(NSString *)name_param; @end
//EtrHuman.m #import "EtrHuman.h" @implementation EtrHuman @synthesize eha=eha_; @synthesize name=name_; - (id) init:(NSString *)eha_param Name:(NSString *)name_param { if (self = [super init]) { eha_ = eha_param; name_ = name_param; } return self; } @end

A diák képes kurzusok felvételére, és a felvett kurzusok adatainak kiírására.

//Student.h #import "EtrHuman.h" #import "Course.h" @interface Student : EtrHuman { //A student attends any number of courses NSMutableArray *attend; } //init function - (id) init:(NSString *)eha_param Name:(NSString *)name_param; //add attended course - (void) addCourse: (Course*)c; //print attended course list to screen - (void) printCourseList; @end
//Student.m #import "Student.h" @implementation Student - (id) init:(NSString *)eha_param Name:(NSString *)name_param; { if (self = [super init:eha_param Name:name_param]) { attend = [[NSMutableArray alloc] init]; } return self; } - (void) addCourse: (Course*)c { NSEnumerator *enumerator = [attend objectEnumerator]; Course *course; while (course = [enumerator nextObject]) { if ([course.code isEqualToString:c.code]) { fprintf(stderr, "Already applied.\n"); return; } } [attend addObject:c]; } - (void) printCourseList { NSEnumerator *enumerator = [attend objectEnumerator]; id course; while (course = [enumerator nextObject]) { [course printData]; printf("\n"); } } @end

A tanárok és kurzusok között egy-egy kapcsolat áll fenn.

//Teacher.h #import "EtrHuman.h" @class Course; @interface Teacher : EtrHuman { //One teacher teaches only one course ... Course *teaches_; } @property (assign, readwrite) Course *teaches; @end
//Teacher.m #import "Teacher.h" @implementation Teacher @synthesize teaches=teaches_; @end

A kurzus számontartja az őt felvevő diákokat, és a hozzárendelt tanárt.

//Course.h #import #import "Teacher.h" @class Student; @interface Course : NSObject { Teacher *teacher_; NSMutableArray *students; NSString *code_; NSString *room_; int day_; int start_; int duration_; } @property (assign, readwrite) Teacher *teacher; //eg.: IPM-08sztPNYPG/x3 @property (readonly) NSString *code; //eg.: D 1-819 @property (copy, readwrite) NSString *room; //day of week, in [1, 7] @property (assign, readwrite) int day; //minutes from midnight @property (assign, readwrite) int start; //duration in minutes @property (assign, readwrite) int duration; //init function - (id) initWithCode:(NSString *)_code; //add attending student - (void) addStudent:(Student *)student; - (void) printData; @end
//Course.m #import "Course.h" @implementation Course @synthesize teacher=teacher_, code=code_, room=room_, day=day_, start=start_, duration=duration_; - (id) initWithCode:(NSString *)_code { if (self = [super init]) { code_ = _code; students = [[NSMutableArray alloc] init]; } return self; } - (void) printData { printf("Code: %s\n", [code_ UTF8String]); printf("Room: %s\n", [room_ UTF8String]); printf("Teacher: %s (%s)\n", [teacher_.name UTF8String], [teacher_.eha UTF8String]); printf("On the %i. day of the week\n", day_); printf("Starts at %i:%i\n", start_ / 60, start_ % 60); printf("Is %i minutes long\n", duration_); printf("Total number of students: %i\n", [students count]); } - (void) addStudent:(Student *)student { [students addObject:student]; } @end

Az ETR végzi a diákok, tanárok és kurzusok listába gyűjtését, felületet biztosít a tantárgyak felvételére és a diákok órarendjének kiírására.

//ETR.h #import #import #import "Student.h" #import "Teacher.h" #import "Course.h" //class for managing courses, teachers, students @interface ETR : NSObject { NSMutableArray *courses; NSMutableArray *teachers; NSMutableArray *students; } - (id) init; //Add course, if not exists. - (void) addCourse: (Course*)c Teacher: (Teacher*)t; //Add student, if not exists. - (void) addStudent: (Student*)s; //Apply student to course, if both exist. - (void) applyCourse: (NSString*)student_eha course: (NSString*)course_code; //find course by code. - (Course*) findCourse: (NSString*)course_code; //find a student or teacher. - (EtrHuman*) findPerson: (NSString*)eha inList:(NSMutableArray*)list; //print timetable for all students in the list - (void) printTimeTable; @end
//ETR.m #import "ETR.h" @implementation ETR - (id) init { courses = [[NSMutableArray alloc] init]; teachers = [[NSMutableArray alloc] init]; students = [[NSMutableArray alloc] init]; return self; } - (Course*) findCourse: (NSString*)course_code { NSEnumerator *enumerator = [courses objectEnumerator]; Course *course; while (course = [enumerator nextObject]) { if ([course.code isEqualToString:course_code]) { return course; } } return nil; } - (EtrHuman*) findPerson: (NSString*)eha inList:(NSMutableArray*)list { NSEnumerator *enumerator = [list objectEnumerator]; EtrHuman *person; while (person = [enumerator nextObject]) { if ([person.eha isEqualToString:eha]) { return person; } } return nil; } //Add course and teacher. (There is a one-one relationship between them.) - (void) addCourse: (Course*)c Teacher: (Teacher*)t { Course *course = [self findCourse:c.code]; if (course != nil) { fprintf(stderr, "Course already exists.\n"); return; } Teacher *teacher = (Teacher*)[self findPerson:t.eha inList:teachers]; if (teacher != nil) { fprintf(stderr, "Teacher already exists.\n"); return; } [courses addObject:c]; [teachers addObject:t]; } - (void) addStudent: (Student*)s { Student *student = (Student*)[self findPerson:s.eha inList:students]; if (student != nil) { fprintf(stderr, "Student already exists.\n"); return; } [students addObject:s]; } - (void) applyCourse: (NSString*)student_eha course: (NSString*)course_code { Student *student = (Student*)[self findPerson:student_eha inList:students]; if (student == nil) { fprintf(stderr, "Student not found.\n"); return; } Course *course = [self findCourse:course_code]; if (course == nil) { fprintf(stderr, "Course not found.\n"); return; } [student addCourse:course]; [course addStudent:student]; } - (void) printTimeTable { NSEnumerator *enumerator = [students objectEnumerator]; Student *student; while (student = [enumerator nextObject]) { printf("%s (%s) studies\n" "--------------------\n", [student.name UTF8String], [student.eha UTF8String]); [student printCourseList]; } } @end

Őröklődés, alakzatok, láncolt lista

A következő példaprogramban alakzatok osztályait származtatjuk egymásból. Ezek téglalap, négyzet, kör és Shape az ősosztály. Objektumokat hozunk létre, majd ezeket szimpla láncolt listába füzzük és meghívjuk a print metódust, ami kiirja az alakzat nevét. A programban van példa dinamikuskötésre (id), methódusok (szelektorok) felüldefiniálására, illetve manuális memória kezelésre (retain, release, dealloc). A programban látható, hogy protokol (printable) segítségével hogyan lehet kőtelezővé tenni metódusok (print) implementálását. A program tartalmaz egy láncolt lista egy lehetséges implementációját is.

//shapes.m // // fordítás: // gcc -o shapes shapes.m -I c:/GNUstep/GNUstep/System/Library/Headers -L c:/GNUstep/GNUstep/System/Library/Libraries -std=c99 -lobjc -lgnustep-base -fconstant-string-class=NSConstantString // #import #import ////////////////////// egy protokoll, ami egy print selectort tartalmaz //////////////////////// @protocol printable @required - (void) print; @end ////////////////////// alakzat osztály definiciója/implementációja //////////////////////// @interface Shape: NSObject @end @implementation Shape -(void) print { printf( "Shape\n"); } @end ////////////////////// alakzatok definiciója és implementációja //////////////////////// @interface Teglalap: Shape @end @interface Negyzet: Teglalap @end @interface Kor: Shape @end @implementation Teglalap -(void) print { printf( "Teglalap\n"); } @end @implementation Negyzet -(void) print { printf( "Negyzet\n"); } @end @implementation Kor -(void) print { printf( "Kor\n"); } @end ////////////////////// a node-ok definiciója és implementációja //////////////////////// @interface Node: NSObject { id obj; id next; } - (id) init: (id) object withNext: (id) nextnode; - (id) obj; - (id) next; @end @implementation Node - (id) init: (id) object withNext: (id) nextnode { self=[super init]; //elmentjük az objektumot, majd a nextet a meglévô elemekre állítjuk //majd mi leszünk a fejelem visszatérés után obj=object; next=nextnode; return self; } - (id) obj { return obj; } - (id) next { return next; } - (void) dealloc { //ha van objektum a node-on akkor törüljük azt if (obj!=nil) { [obj release]; } //ha van next elem, akkor elöbb azt is felszabadítjuk if (next!=nil) { [next release]; } [super dealloc]; } @end ////////////////////// a node-ok listájának definiciója és implementációja //////////////////////// @interface List: NSObject { id head; } - (id) init; - (void) add: (id) shape; @end @implementation List - (id) init { self=[super init]; //listánk alapban üres head=nil; return self; } - (void) add: (id) object { //létrehozunk egy új nodeot, ami a lánc elejére fog kerülni // a meglévô elemeke a node nextje fog majd mutatni head=[[Node alloc] init: object withNext: head]; } - (void) print { //végig megyünk a listán, amíg az aktuális node értéke nill nem nem lesz //az utolsó elem mindig nil lesz for (id node=head;node!=nil;) { //meghívjuk az adott node objektumára a kiirást [[node obj] print]; //majd elkérjük a következô elemet a láncban node=[node next]; } } - (void) dealloc { //ha a fejelem nem üres, akkor törüljük if (head!=nil) { [head release]; } //meghíjuk az ôs deallocját, ha már felüldefiniáltuk azt [super dealloc]; } @end ////////////////////// MAIN PROGRAM //////////////////////// int main(void) { //lista létrehozása List *list=[[List alloc] init]; //alakzatok létrehozása Teglalap *teglalap = [[Teglalap alloc] init]; Negyzet *negyzet = [[Negyzet alloc] init]; Kor *kor = [[Kor alloc] init]; Shape *shape=kor; //hozzáadjuk az elemeket a listához [list add:negyzet]; [list add:teglalap]; [list add:kor]; //vagy akár direkt módon is lehet hozzáadni [list add:[[Negyzet alloc] init]]; //dinamikus teszt, itt kort adunk hozzá valójában [shape retain]; //mert ez ugyanaz a kor amit már hozzáadtunk egyszer, hogy lehessen 2x hivni a dealloc-ot [list add: shape]; //kiirjuk a listát [list print]; //majd töröljuk a listát (ami majd törli az objektumokat is amiket tartalmaz) [list release]; return 0; }

A weblapról hiányzik a felhasználói felület, amivel az adatokat lehet rögzíteni, illetve a főprogram mivel ezek sok érdekességet már nem tartalmaznak. A letölthető programok között ezek is megtalálhatóak.

MonkeyRunner - Alap iOS játék cocos 2D keretrendszer segítségével

A játék iOS platformra készült, nyílt forráskódú cocos 2D keretrendszer segítségével, amely a 2D világ szimulálását segíti.

cocos 2d weboldala

A játékban egy katapult segítségével kell eltalálni banánnal egy távolban lévő majmot.

MonkeyWorldLayer.h - a világot, a katapultot, töltényeket, majmot valamint a textúrákat, kameramozgást és egyéb animációkat leíró fájl header fájlja

#import "cocos2d.h" #import "Box2D.h" #import "GLES-Render.h" #import "MyContactListener.h" // HelloWorldLayer @interface MonkeyWorldLayer : CCLayer { b2World* world; GLESDebugDraw *m_debugDraw; b2Fixture *armFixture; b2Body *armBody; b2RevoluteJoint *armJoint; b2MouseJoint *mouseJoint; b2Body *groundBody; // ammo NSMutableArray *bullets; uint currentBullet; b2Body *bulletBody; b2WeldJoint *bulletJoint; BOOL releasingArm; NSMutableSet *trees; NSMutableSet *monkeys; // zoom logic float oldDist, currentScale; CGPoint oldPos; CCLayerColor *zoombase; CCSprite *background; CGPoint ZB_last_posn; // Collision MyContactListener *contactListener; BOOL checkCollision; } // returns a CCScene that contains the HelloWorldLayer as the only child +(CCScene *) scene; @end

MonkeyWorldLayer.mm - implementációs rész

#import "MonkeyWorldLayer.h" //Pixel to metres ratio. Box2D uses metres as the unit for measurement. //This ratio defines how many pixels correspond to 1 Box2D "metre" //Box2D is optimized for objects of 1x1 metre therefore it makes sense //to define the ratio so that your most common object type is 1x1 metre. #define PTM_RATIO 32 #define FLOOR_HEIGHT 30.0f #define MIN_SCALE 0.5f #define MAX_SCALE 2.0f // enums that will be used as tags enum { kTagTileMap = 1, kTagBatchNode = 1, kTagAnimation1 = 1, }; @interface MonkeyWorldLayer() - (void)resetGame; -(void)createBullets : (int)count; -(BOOL)attachBullet; -(void)createTargets; -(void)createTarget : (NSString*)imageName atPosition : (CGPoint)position rotation : (CGFloat)rotation isCircle : (BOOL)aCircle isStatic : (BOOL)aStatic isMonkey : (BOOL)aMonkey; -(void)zoomLayer : (float)zoomScale; -(void)moveBoard : (CGPoint)translation from : (CGPoint)lastLocation; @end // MonkeyWorldLayer implementation @implementation MonkeyWorldLayer + (CCScene *)scene { // 'scene' is an autorelease object. CCScene *scene = [CCScene node]; // 'layer' is an autorelease object. MonkeyWorldLayer *layer = [MonkeyWorldLayer node]; // add layer as a child to scene [scene addChild : layer]; // return the scene return scene; } // on "init" you need to initialize your instance -(id)init { // always call "super" init // Apple recommends to re-assign "self" with the "super" return value if((self = [super init])) { // enable touches self.isTouchEnabled = YES; // screen size CGSize screenSize = [CCDirector sharedDirector].winSize; CCLOG(@"Screen width %0.2f screen height %0.2f", screenSize.width, screenSize.height); //[[CCTouchDispatcher sharedDispatcher] addStandardDelegate:self priority:0]; UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget : self action : @selector(handlePanFrom :)]; UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc] initWithTarget : self action : @selector(handlePinchFrom :)]; pan.minimumNumberOfTouches = 2; [[[CCDirector sharedDirector] openGLView] addGestureRecognizer : pan]; [[[CCDirector sharedDirector] openGLView] addGestureRecognizer : pinch]; checkCollision = NO; // Define the gravity vector. b2Vec2 gravity; gravity.Set(0.0f, -10.0f); // Do we want to let bodies sleep? // This will speed up the physics simulation bool doSleep = true; // Construct a world object, which will hold and simulate the rigid bodies. world = new b2World(gravity, doSleep); world->SetContinuousPhysics(true); // Debug Draw functions m_debugDraw = new GLESDebugDraw(PTM_RATIO); world->SetDebugDraw(m_debugDraw); uint32 flags = 0; flags += b2DebugDraw::e_shapeBit; // flags += b2DebugDraw::e_jointBit; // flags += b2DebugDraw::e_aabbBit; // flags += b2DebugDraw::e_pairBit; // flags += b2DebugDraw::e_centerOfMassBit; m_debugDraw->SetFlags(flags); // Initialize the zoombase position ZB_last_posn = self.position; CCSprite *sprite = [CCSprite spriteWithFile : @"grassfront.png"]; sprite.anchorPoint = CGPointZero; sprite.position = CGPointMake(0, FLOOR_HEIGHT - 30); [self addChild : sprite z : 1]; sprite = [CCSprite spriteWithFile : @"grassfront.png"]; sprite.anchorPoint = CGPointZero; sprite.position = CGPointMake(960.0f, FLOOR_HEIGHT - 30); [self addChild : sprite z : 1]; sprite = [CCSprite spriteWithFile : @"jungle.png"]; sprite.anchorPoint = CGPointZero; [self addChild : sprite z : -1]; sprite = [CCSprite spriteWithFile : @"jungle.png"]; sprite.anchorPoint = CGPointZero; sprite.position = CGPointMake(960.0f, 0); [self addChild : sprite z : -1]; sprite = [CCSprite spriteWithFile : @"monkey.png"]; sprite.anchorPoint = CGPointZero; sprite.position = CGPointMake(180.0f, FLOOR_HEIGHT); [self addChild : sprite z : 1]; sprite = [CCSprite spriteWithFile : @"catapult_base_2.png"]; sprite.anchorPoint = CGPointZero; sprite.position = CGPointMake(181.0f, FLOOR_HEIGHT); [self addChild : sprite z : 1]; sprite = [CCSprite spriteWithFile : @"catapult_base.png"]; sprite.anchorPoint = CGPointZero; sprite.position = CGPointMake(180.0f, FLOOR_HEIGHT); [self addChild : sprite z : 3]; // Define the ground body. b2BodyDef groundBodyDef; groundBodyDef.position.Set(0, 0); // bottom-left corner // Call the body factory which allocates memory for the ground body // from a pool and creates the ground box shape (also from a pool). // The body is also added to the world. groundBody = world->CreateBody(&groundBodyDef); // Define the ground box shape. b2PolygonShape groundBox; // bottom groundBox.SetAsEdge(b2Vec2(0, FLOOR_HEIGHT / PTM_RATIO), b2Vec2(screenSize.width * 4.0f / PTM_RATIO, FLOOR_HEIGHT / PTM_RATIO)); groundBody->CreateFixture(&groundBox, 0); // top groundBox.SetAsEdge(b2Vec2(0, screenSize.height * 4.0f / PTM_RATIO), b2Vec2(screenSize.width * 4.0f / PTM_RATIO, screenSize.height * 4.0f / PTM_RATIO)); groundBody->CreateFixture(&groundBox, 0); // left groundBox.SetAsEdge(b2Vec2(0, screenSize.height / PTM_RATIO), b2Vec2(0, 0)); groundBody->CreateFixture(&groundBox, 0); // right //groundBox.SetAsEdge(b2Vec2(screenSize.width*4.0f/PTM_RATIO,screenSize.height*2.0f/PTM_RATIO), b2Vec2(screenSize.width*4.0f/PTM_RATIO,0)); //groundBody->CreateFixture(&groundBox, 0); // Create the catapult's arm CCSprite *arm = [CCSprite spriteWithFile : @"catapult_arm.png"]; arm.rotation = CC_DEGREES_TO_RADIANS(-120); [self addChild : arm z : 2]; b2BodyDef armBodyDef; armBodyDef.type = b2_dynamicBody; armBodyDef.linearDamping = 1; armBodyDef.angularDamping = 1; armBodyDef.angle = CC_DEGREES_TO_RADIANS(45); armBodyDef.position.Set(180.0f / PTM_RATIO, (FLOOR_HEIGHT + 70.0f) / PTM_RATIO); armBodyDef.userData = arm; armBody = world->CreateBody(&armBodyDef); b2PolygonShape armBox; b2FixtureDef armBoxDef; armBoxDef.shape = &armBox; armBoxDef.density = 0.3F; armBox.SetAsBox(11.0f / PTM_RATIO, 91.0f / PTM_RATIO); armFixture = armBody->CreateFixture(&armBoxDef); // Create a joint to fix the catapult to the floor. // b2RevoluteJointDef armJointDef; armJointDef.Initialize(groundBody, armBody, b2Vec2(250.0f / PTM_RATIO, FLOOR_HEIGHT / PTM_RATIO)); armJointDef.enableMotor = true; armJointDef.enableLimit = true; armJointDef.motorSpeed = -200; //-1260; armJointDef.lowerAngle = CC_DEGREES_TO_RADIANS(0); armJointDef.upperAngle = CC_DEGREES_TO_RADIANS(40); armJointDef.maxMotorTorque = 700; //4800; armJoint = (b2RevoluteJoint*)world->CreateJoint(&armJointDef); [self schedule : @selector(tick :)]; [self performSelector : @selector(resetGame) withObject : nil afterDelay : 0.5f]; // Collision contactListener = new MyContactListener(); world->SetContactListener(contactListener); } return self; } -(void)createTargets { [trees release]; [monkeys release]; trees = [[NSMutableSet alloc] init]; monkeys = [[NSMutableSet alloc] init]; [self createTarget : @"monkey_.png" atPosition : CGPointMake(1405.0, FLOOR_HEIGHT) rotation : 0.0f isCircle : NO isStatic : NO isMonkey : YES]; } -(void)createTarget : (NSString*)imageName atPosition : (CGPoint)position rotation : (CGFloat)rotation isCircle : (BOOL)aCircle isStatic : (BOOL)aStatic isMonkey : (BOOL)aMonkey { CCSprite *sprite = [CCSprite spriteWithFile : imageName]; [self addChild : sprite z : 1]; b2BodyDef bodyDef; bodyDef.type = aStatic ? b2_staticBody : b2_dynamicBody; bodyDef.position.Set((position.x + sprite.contentSize.width / 2.0f) / PTM_RATIO, (position.y + sprite.contentSize.height / 2.0f) / PTM_RATIO); bodyDef.angle = CC_DEGREES_TO_RADIANS(rotation); bodyDef.userData = sprite; b2Body *body = world->CreateBody(&bodyDef); b2FixtureDef boxDef; if(aMonkey) { boxDef.userData = (void*)1; [monkeys addObject : [NSValue valueWithPointer : body]]; } if(aCircle) { b2CircleShape circle; circle.m_radius = sprite.contentSize.width / 2.0f / PTM_RATIO; boxDef.shape = &circle; } else { b2PolygonShape box; box.SetAsBox(sprite.contentSize.width / 2.0f / PTM_RATIO, sprite.contentSize.height / 2.0f / PTM_RATIO); boxDef.shape = &box; } boxDef.density = 0.5f; body->CreateFixture(&boxDef); [trees addObject : [NSValue valueWithPointer : body]]; } -(void)resetGame { // Previous bullets cleanup if(bullets) { for(NSValue *bulletPointer in bullets) { b2Body *bullet = (b2Body*)[bulletPointer pointerValue]; CCNode *node = (CCNode*)bullet->GetUserData(); [self removeChild : node cleanup : YES]; world->DestroyBody(bullet); } [bullets release]; bullets = nil; } // Previous targets cleanup if(trees) { for(NSValue *bodyValue in trees) { b2Body *body = (b2Body*)[bodyValue pointerValue]; CCNode *node = (CCNode*)body->GetUserData(); [self removeChild : node cleanup : YES]; world->DestroyBody(body); } [trees release]; [monkeys release]; trees = nil; monkeys = nil; } [self createBullets : 5]; [self createTargets]; [self runAction : [CCSequence actions : [CCMoveTo actionWithDuration : 3.0f position : CGPointMake(-1400.0f, 0.0f)], [CCCallFuncN actionWithTarget : self selector : @selector(attachBullet)], [CCDelayTime actionWithDuration : 0.5f], [CCMoveTo actionWithDuration : 1.0f position : CGPointZero], nil]]; } -(void)createBullets : (int)count { currentBullet = 0; CGFloat pos = 62.0f; if(count > 0) { // delta is the spacing between bananas // 62 is the position o the screen where we want the bananas to start appearing // 165 is the position on the screen where we want the bananas to stop appearing // 30 is the size of the banana CGFloat delta = (count > 1) ? ((165.0f - 62.0f - 30.0f) / (count - 1)) : 0.0f; bullets = [[NSMutableArray alloc] initWithCapacity : count]; for(int i = 0; i < count; i++, pos += delta) { // Create the bullet // CCSprite *sprite = [CCSprite spriteWithFile : @"banana.png"]; [self addChild : sprite z : 2]; b2BodyDef bulletBodyDef; bulletBodyDef.type = b2_dynamicBody; bulletBodyDef.bullet = true; bulletBodyDef.position.Set(pos / PTM_RATIO, (FLOOR_HEIGHT + 15.0f) / PTM_RATIO); bulletBodyDef.userData = sprite; b2Body *bullet = world->CreateBody(&bulletBodyDef); bullet->SetActive(false); b2PolygonShape shape; shape.SetAsBox(sprite.contentSize.width / 2.0f / PTM_RATIO, sprite.contentSize.height / 2.0f / PTM_RATIO); /*b2CircleShape shape; shape.m_radius = 15.0/PTM_RATIO; */ b2FixtureDef ballShapeDef; ballShapeDef.shape = &shape; ballShapeDef.density = 0.8f; ballShapeDef.restitution = 0.2f; ballShapeDef.friction = 0.99f; bullet->CreateFixture(&ballShapeDef); [bullets addObject : [NSValue valueWithPointer : bullet]]; } } } -(BOOL)attachBullet { if(currentBullet < [bullets count]) { bulletBody = (b2Body*)[[bullets objectAtIndex : currentBullet++] pointerValue]; bulletBody->SetTransform(b2Vec2(160.0f / PTM_RATIO, (140.0f + FLOOR_HEIGHT) / PTM_RATIO), 0.0f); bulletBody->SetActive(true); b2WeldJointDef weldJointDef; weldJointDef.Initialize(bulletBody, armBody, b2Vec2(160.0f / PTM_RATIO, (140.0f + FLOOR_HEIGHT) / PTM_RATIO)); weldJointDef.collideConnected = false; bulletJoint = (b2WeldJoint*)world->CreateJoint(&weldJointDef); return YES; } return NO; } -(void)resetBullet { if([monkeys count] == 0) { // game over [self performSelector : @selector(resetGame) withObject : nil afterDelay : 2.0f]; } else if([self attachBullet]) { [self runAction : [CCMoveTo actionWithDuration : 2.0f position : CGPointZero]]; } else { // We can reset the whole scene here [self performSelector : @selector(resetGame) withObject : nil afterDelay : 2.0f]; } checkCollision = NO; } -(void)ccTouchesBegan : (NSSet *)touches withEvent : (UIEvent *)event { if(mouseJoint != nil) return; NSSet *set = [event allTouches]; if(set.count == 1) { UITouch *myTouch = [touches anyObject]; CGPoint location = [myTouch locationInView : [myTouch view]]; location = [[CCDirector sharedDirector] convertToGL : location]; b2Vec2 locationWorld = b2Vec2(location.x / PTM_RATIO, location.y / PTM_RATIO); if(locationWorld.x < armBody->GetWorldCenter().x + 50.0 / PTM_RATIO) { b2MouseJointDef md; md.bodyA = groundBody; md.bodyB = armBody; md.target = locationWorld; md.maxForce = 2000; mouseJoint = (b2MouseJoint *)world->CreateJoint(&md); } } } -(void)ccTouchesMoved : (NSSet *)touches withEvent : (UIEvent *)event { if(mouseJoint == nil) return; NSSet *set = [event allTouches]; if(set.count == 1) { UITouch *myTouch = [touches anyObject]; CGPoint location = [myTouch locationInView : [myTouch view]]; location = [[CCDirector sharedDirector] convertToGL : location]; b2Vec2 locationWorld = b2Vec2(location.x / PTM_RATIO, location.y / PTM_RATIO); mouseJoint->SetTarget(locationWorld); } } -(void)handlePinchFrom : (UIPinchGestureRecognizer *)pinch { if(pinch.state == UIGestureRecognizerStateEnded) { currentScale = pinch.scale; ZB_last_posn = self.position; } else if((pinch.state == UIGestureRecognizerStateBegan || (pinch.state == UIGestureRecognizerStateChanged)) && currentScale != 0.0f) { pinch.scale = currentScale; } if(pinch.scale != NAN && pinch.scale != 0.0) { [self zoomLayer : pinch.scale]; //pinch.view.transform = CGAffineTransformMakeScale(pinch.scale, pinch.scale); } } // Zoom board -(void)zoomLayer : (float)zoomScale { if((self.scale * zoomScale) <= MIN_SCALE) { //zoomScale = MIN_SCALE/self.scale; return; } else if((self.scale * zoomScale) >= MAX_SCALE) { //zoomScale = MAX_SCALE/self.scale; return; } self.scale = zoomScale; //Move self so it appears to zoom from the current center of the screen. self.position = ccp(ZB_last_posn.x * zoomScale, ZB_last_posn.y * zoomScale); ZB_last_posn = self.position; } -(void)handlePanFrom : (UIPanGestureRecognizer *)recognizer { if(recognizer.state == UIGestureRecognizerStateBegan) { ZB_last_posn = self.position; } if(recognizer.state == UIGestureRecognizerStateChanged) { CGPoint translation = [recognizer translationInView : recognizer.view]; translation.y = -1 * translation.y; [self moveBoard : translation from : ZB_last_posn]; } } // Pan board -(void)moveBoard : (CGPoint)translation from : (CGPoint)lastLocation { CGPoint target_position = ccpAdd(translation, lastLocation); CGSize size = [[CCDirector sharedDirector] winSize]; // Insert routine here to check that target position is not out of bounds for your background // Remember that ZB_last_posn is a variable that holds the current position of self if(target_position.x <= 0 && target_position.y <= 0) self.position = target_position; else ZB_last_posn = lastLocation; } -(void)ccTouchesEnded : (NSSet *)touches withEvent : (UIEvent *)event { if(mouseJoint != nil) { if(armJoint->GetJointAngle() >= CC_DEGREES_TO_RADIANS(10)) { releasingArm = YES; } world->DestroyJoint(mouseJoint); mouseJoint = nil; } } -(void)draw { // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY // Needed states: GL_VERTEX_ARRAY, // Unneeded states: GL_TEXTURE_2D, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY glDisable(GL_TEXTURE_2D); glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); world->DrawDebugData(); // restore default GL states glEnable(GL_TEXTURE_2D); glEnableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); } -(void)tick : (ccTime)dt { //It is recommended that a fixed time step is used with Box2D for stability //of the simulation, however, we are using a variable time step here. //You need to make an informed choice, the following URL is useful //http://gafferongames.com/game-physics/fix-your-timestep/ int32 velocityIterations = 8; int32 positionIterations = 1; // Instruct the world to perform a single step of simulation. It is // generally best to keep the time step and iterations fixed. world->Step(dt, velocityIterations, positionIterations); //Iterate over the bodies in the physics world for(b2Body* b = world->GetBodyList(); b; b = b->GetNext()) { if(b->GetUserData() != NULL) { //Synchronize the AtlasSprites position and rotation with the corresponding body CCSprite *myActor = (CCSprite*)b->GetUserData(); myActor.position = CGPointMake(b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO); myActor.rotation = -1 * CC_RADIANS_TO_DEGREES(b->GetAngle()); } } // Arm is being released. if(releasingArm && bulletJoint) { // Check if the arm reached the end so we can return the limits if(armJoint->GetJointAngle() <= CC_DEGREES_TO_RADIANS(10)) { releasingArm = NO; // Destroy joint so the bullet will be free world->DestroyJoint(bulletJoint); bulletJoint = nil; [self performSelector : @selector(resetBullet) withObject : nil afterDelay : 5.0f]; } } // Bullet is moving. if(bulletBody && bulletJoint == nil) { b2Vec2 position = bulletBody->GetPosition(); CGPoint myPosition = self.position; CGSize screenSize = [CCDirector sharedDirector].winSize; // Move the camera. if(position.x > screenSize.width / 4.0f / PTM_RATIO || position.y > screenSize.height / PTM_RATIO) { myPosition.x = -MIN(screenSize.width * self.scale * 4.0f - screenSize.width * self.scale, position.x * self.scale * PTM_RATIO - screenSize.width * self.scale / 4.0f); myPosition.y = -MAX(position.y * self.scale * PTM_RATIO - screenSize.width * self.scale / 4.0f, 0); self.position = myPosition; } checkCollision = YES; } if(checkCollision) { // Check for impacts std::set::iterator pos; for(pos = contactListener->contacts.begin(); pos != contactListener->contacts.end(); ++pos) { b2Body *body = *pos; CCNode *contactNode = (CCNode*)body->GetUserData(); CGPoint position = contactNode.position; [self removeChild : contactNode cleanup : YES]; world->DestroyBody(body); [trees removeObject : [NSValue valueWithPointer : body]]; [monkeys removeObject : [NSValue valueWithPointer : body]]; CCParticleSun* explosion = [[CCParticleSun alloc] initWithTotalParticles : 200]; explosion.autoRemoveOnFinish = YES; explosion.startSize = 10.0f; explosion.speed = 70.0f; explosion.anchorPoint = ccp(0.5f, 0.5f); explosion.position = position; explosion.duration = 1.0f; [self addChild : explosion z : 11]; [explosion release]; } } // remove everything from the set contactListener->contacts.clear(); } // on "dealloc" you need to release all your retained objects -(void)dealloc { // in case you have something to dealloc, do it in this method delete world; world = NULL; [bullets release]; [trees release]; [monkeys release]; delete contactListener; contactListener = NULL; delete m_debugDraw; // don't forget to call "super dealloc" [super dealloc]; } @end

MyContactListener.h - collision detection, vagyis az ütközést detektáló osztály header része

#import "Box2D.h" #import #import class MyContactListener : public b2ContactListener { public: std::setcontacts; MyContactListener(); ~MyContactListener(); virtual void BeginContact(b2Contact* contact); virtual void EndContact(b2Contact* contact); virtual void PreSolve(b2Contact* contact, const b2Manifold* oldManifold); virtual void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse); };

MyContactListener.cpp - implementációs rész

#include "MyContactListener.h" MyContactListener::MyContactListener() : contacts() { } MyContactListener::~MyContactListener() { } void MyContactListener::BeginContact(b2Contact* contact) { } void MyContactListener::EndContact(b2Contact* contact) { } void MyContactListener::PreSolve(b2Contact* contact, const b2Manifold* oldManifold) { } void MyContactListener::PostSolve(b2Contact* contact, const b2ContactImpulse* impulse) { bool isAEnemy = contact->GetFixtureA()->GetUserData() != NULL; bool isBEnemy = contact->GetFixtureB()->GetUserData() != NULL; if (isAEnemy || isBEnemy) { // Should the body break? int32 count = contact->GetManifold()->pointCount; float32 maxImpulse = 0.0f; for (int32 i = 0; i < count; ++i) { maxImpulse = b2Max(maxImpulse, impulse->normalImpulses[i]); } if (maxImpulse > 1.0f) { // Flag the enemy(ies) for breaking. if (isAEnemy) contacts.insert(contact->GetFixtureA()->GetBody()); if (isBEnemy) contacts.insert(contact->GetFixtureB()->GetBody()); } } }

Egyszerű böngésző a WebKit keretrendszer használatával OSX platformra.

A navbar-ban megadott címet letölti, az eseményeket naplózza és előre-hátra lép a megtekintett oldalak közt.

SBAppDelegate.h

#import 
#import 

@interface SBAppDelegate : NSObject  {
     int resourceCount;
}

@property (assign) IBOutlet NSWindow *window;
@property (assign) IBOutlet NSTextField *navbar;
@property (assign) IBOutlet WebView *webview;
@property (strong) IBOutlet NSButton *backButton;
@property (strong) IBOutlet NSButton *forwardButton;
@property (strong) IBOutlet NSProgressIndicator *progress;
- (IBAction)go:(id)sender;

@end

SBAppDelegate.mm

#import "SBAppDelegate.h"

@implementation SBAppDelegate
@synthesize backButton;
@synthesize forwardButton;
@synthesize progress;

@synthesize window;
@synthesize navbar;
@synthesize webview;



- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    [navbar setStringValue:@"http://nyelvek.inf.elte.hu/leirasok/Objective_C/"];
    [self go: navbar];
}

- (IBAction)go:(id)sender {
    WebFrame *mainFrame = [webview mainFrame];
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:[navbar stringValue]]]; 
    [mainFrame loadRequest: request];
}

/**
 Frame Load Delegate
 **/
 
/*!
 Keretletöltés kezdete.
 Most a navbar-ba beírjuk a frissen töltött címet
 A bitkolbászt elindítjuk
*/
- (void)webView:(WebView *)sender didStartProvisionalLoadForFrame:(WebFrame *)frame {
    NSLog(@"Keret letöltés indul: %@", [frame name]);
    if(![frame parentFrame]) {
        NSString *url = [[[[frame provisionalDataSource] request] URL] absoluteString];
        [navbar setStringValue:url];
        [progress startAnimation:frame];
    }
}

/*!
  Keret címe megérkezett
*/
- (void)webView:(WebView *)sender didReceiveTitle:(NSString *)title forFrame:(WebFrame *)frame
{
    NSLog(@"Keret cím megérkezett: %@ cím: %@", [frame name], title);

    // Report feedback only for the main frame.
    if (frame == [sender mainFrame]){
        [[sender window] setTitle:title];
    }
}

/*!
 Keret letöltés vége 
 History előre-hátra engedélyezése és tiltása
 A bitkolbászt leállítjuk
*/
- (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame
{
    NSLog(@"Keret letöltés kész: %@", [frame name]);

    if (frame == [sender mainFrame]){
        [backButton setEnabled:[sender canGoBack]];
        [forwardButton setEnabled:[sender canGoForward]];
        [progress stopAnimation:frame];
    }
}

/*!
 A szerver átirányított
*/ 
- (void)webView:(WebView *)sender didReceiveServerRedirectForProvisionalLoadForFrame:(WebFrame *)frame
{
    NSLog(@"Szerveroldali átirányítás: %@", [frame name]);
}

/*!
 Az ideiglenes letöltés sikertelem
*/
- (void)webView:(WebView *)sender didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
{
    NSLog(@"Ideiglenes letöltés sikertelen: %@ hiba: %@", [frame name], [error localizedDescription]);
}

/*!
 A véglegesített letöltés sikertelem
 */
- (void)webView:(WebView *)sender didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
{
    NSLog(@"Végleges letöltés sikertelen: %@ hiba: %@", [frame name], [error localizedDescription]);
}

/*!
 Adat érkezett, letöltés véglegesíthető
*/
- (void)webView:(WebView *)sender didCommitLoadForFrame:(WebFrame *)frame
{
    NSLog(@"Keret letöltés véglegesítve: %@", [frame name]); 
}

/*!
 Keret scroll pozíciója megváltozott
*/ 
- (void)webView:(WebView *)sender didChangeLocationWithinPageForFrame:(WebFrame *)frame
{
    NSLog(@"Keret scroll pozíciója megváltozott: %@", [frame name]); 
}


/*!
 A keret záródik
*/
- (void)webView:(WebView *)sender willCloseFrame:(WebFrame *)frame
{
    NSLog(@"A keret záródik: %@", [frame name]); 
}



/**
 Resource Load Delegate
**/

/*!
 Új erőforrás-azonosító. Számozzuk, a következő üzenetekben a sorszámmal hivatkozunk
*/ 
 
- (id)webView:(WebView *)sender identifierForInitialRequest:(NSURLRequest *)request fromDataSource:(WebDataSource *)dataSource {
    id identifier = [NSNumber numberWithInt:resourceCount++];
    NSLog(@"Új erőforrás sorszám: %@, %@", [request URL], identifier);
    return identifier;
}

/*!
 Indul az erőforrás letöltése
*/
- (NSURLRequest *)webView:(WebView *)sender resource:(id)identifier willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse fromDataSource:(WebDataSource *)dataSource
{
    NSLog(@"Erőforrás letöltése indul: %@", identifier);
    return request;
}

/*!
 Indul az erőforrás letöltése
 */
- (void)webView:(WebView *)sender resource:(id)identifier didReceiveResponse:(NSURLResponse *)response fromDataSource:(WebDataSource *)dataSource
{
    NSLog(@"Adat jött erőforráshoz: %@", identifier);
}

/*!
 Megjött az erőforrás hossza
*/ 
- (void)webView:(WebView *)sender resource:(id)identifier didReceiveContentLength:(int)length fromDataSource:(WebDataSource *)dataSource
{
    NSLog(@"Megjött az erőforrás hossza: %@: %d", identifier, length);
}


/*!
 Erőforrás kész
*/ 
- (void)webView:(WebView *)sender resource:(id)identifier didFinishLoadingFromDataSource:(WebDataSource *)dataSource
{
    NSLog(@"Erőforrás kész: %@", identifier);   
}

/*!
 Erőforrás sikertelen
*/
- (void)webView:(WebView *)sender resource:(id)identifier didFailLoadingWithError:(NSError *)error fromDataSource:(WebDataSource *)dataSource
{
    NSLog(@"Erőforrás sikertelen: %@, hiba: %@", identifier, [error localizedDescription]);   
}
@end

Alapok a GNUStep használatával Linuxra

Két komplex szám (a,b) inicializálása, majd (a+b)*b kiszámítása

main.m

#import "MyComplexDemo.h"
#import 
#import 

int main( int argc, const char *argv[] ) 
{
		NSAutoreleasePool *myPool = [[NSAutoreleasePool alloc] init];
		Writer* w = [[Writer alloc] init];
		MyComplexDemo* demo = [[MyComplexDemo alloc] init];
		[[w class] WriteString : @"MyComplexDemo : Initialized : Done \n"];				 		
		[demo WriteWelcome];
		[[w class] WriteString : @"MyComplexDemo : WriteWelcome : Done \n"];				 		
		[demo SetupDummyComplexes];
		[[w class] WriteString : @"MyComplexDemo : A Initialized : Real : \n"];				 		
		[[w class] WriteDouble : [demo GetReal_A]];
		[[w class] WriteString : @"MyComplexDemo : A Initialized : Imaginary : \n"];				 		
		[[w class] WriteDouble : [demo GetImaginary_A]];
		[[w class] WriteString : @"MyComplexDemo : B Initialized : Real \n"];				 		
		[[w class] WriteDouble : [demo GetReal_B]];						 		
		[[w class] WriteString : @"MyComplexDemo : B Initialized : Imaginary \n"];				 		
		[[w class] WriteDouble : [demo GetImaginary_B]];
		[[w class] WriteString : @"MyComplexDemo : A + B : Real & Imaginary \n"];
		[demo DemoOperationAdd];
		[[w class] WriteDouble : [demo GetReal_A]];
		[[w class] WriteDouble : [demo GetImaginary_A]];
		[[w class] WriteString : @"MyComplexDemo : (A + B)*B : Real & Imaginary \n"];0		
		[demo DemoOperationMultiply];
		[[w class] WriteDouble : [demo GetReal_A]];
		[[w class] WriteDouble : [demo GetImaginary_A]];	
		[myPool drain];
    return 0;
}

MyComplexDemo.h

#import 
#import "MyComplex.h"
#import "Writer.h"
#import "Reader.h"

@interface MyComplexDemo : NSObject
{
	MyComplex* dummyA;
	MyComplex* dummyB;
	Writer* demoWriter;
	Reader* demoReader;
}

- (id) init;
- (void) WriteWelcome;
- (void) SetupDummyComplexes;
- (void) SetupDummy_A;
- (void) SetupDummy_B;
- (double) GetReal_A;
- (double) GetReal_B;
- (double) GetImaginary_A;
- (double) GetImaginary_B;
- (void) DemoOperationAdd;
- (void) DemoOperationMultiply;
@end  

MyComplexDemo.m

#import "MyComplexDemo.h"
#import 

@implementation MyComplexDemo

- (id) init
{
	self = [super init];
	if (!self)
	{
		NSLog(@"Super Class Initialization : Failed \n");
		return nil;
	}
	else
	{
		dummyA = [[MyComplex alloc] init];
		dummyB = [[MyComplex alloc] init];
		demoWriter = [[Writer alloc] init];	
		demoReader = [[Reader alloc] init];
		NSLog(@"Super Class Initialization : Done \n");
		return self;
	}
}

- (void) WriteWelcome
{
	[[demoWriter class] WriteString: @"Welcome to MyComplex Demo Application \n"];
	[[demoWriter class] WriteString: @"This little app will demonstrate calculating with complex numbers \n"];
}

- (void) SetupDummyComplexes
{
	[self SetupDummy_A];
	[self SetupDummy_B];
}

- (void) SetupDummy_A
{
	double tReal, tImaginary;
	[[demoWriter class] WriteString: @"Please enter complex A's Real:"];
	tReal = [demoReader ReadDouble];
	[[demoWriter class] WriteString: @"Please enter complex A's Imaginary:"];  	
	tImaginary = [demoReader ReadDouble];
	[dummyA SetReal : tReal];
	[dummyA SetImaginary : tImaginary];
}

- (void) SetupDummy_B
{
	double tReal, tImaginary;
	demoReader = [[Reader alloc] init];
	[[demoWriter class] WriteString: @"Please enter complex B's Real:"];
	tReal = [demoReader ReadDouble];
	[[demoWriter class] WriteString: @"Please enter complex B's Imaginary:"];  	
	tImaginary = [demoReader ReadDouble];
	[dummyB SetReal : tReal];
	[dummyB SetImaginary : tImaginary];
}

- (double) GetReal_A
{
	return [dummyA GetReal];
}

- (double) GetReal_B
{
	return [dummyB GetReal];
}

- (double) GetImaginary_A
{ 
	return [dummyA GetImaginary]; 
}

- (double) GetImaginary_B
{
	return [dummyB GetImaginary];
}

- (void) DemoOperationAdd
{
	[dummyA Add: dummyB];
}

- (void) DemoOperationMultiply
{		
	[dummyA Multiply: dummyB];
}
@end

MyComplex.h

#import 
#import "IComparable.h"

@interface MyComplex : NSObject 
{
	double real;
	double imaginary;
}

-(id)init;
-(void) SetReal: (double)aReal;
-(void) SetImaginary: (double)anImaginary;
-(double) GetReal;
-(double) GetImaginary;
-(MyComplex*) Add: (MyComplex*)otherComplex;
-(MyComplex*) Multiply: (MyComplex*)otherComplex;
@end

MyComplex.m

#import "MyComplex.h"

@implementation MyComplex

-(id) init
{
	self = [super init];
	if (!self) return nil;
	else
	{
		return self;
	}
}

- (void) SetReal : (double)aReal
{
	if (aReal != 0.0)
	{
		real = aReal;
	}
}

- (void) SetImaginary : (double)anImaginary
{
	if (anImaginary != 0.0)
	{
		imaginary = anImaginary;
	}
}

- (double) GetReal
{
	return real;
}

- (double) GetImaginary
{
	return imaginary;
}

- (MyComplex*) Add : (MyComplex*)otherComplex
{
	if (otherComplex != 0)
	{
		double oReal = [otherComplex GetReal];
		double oImaginary = [otherComplex GetImaginary];
		real += oReal;
		imaginary += oImaginary;
	}
	return self;
}

- (MyComplex*) Multiply: (MyComplex*)otherComplex
{
	if (otherComplex != 0)
	{
		double oReal = [otherComplex GetReal];
		double oImaginary = [otherComplex GetImaginary];
		real = (oReal*real) - (oImaginary*imaginary);
		imaginary = (imaginary*oReal)+(real*oImaginary);		
	}
	return self;
}

- (BOOL) Equals: (id) otherObject
{
	if (real == [otherObject GetReal] && imaginary == [otherObject GetReal])
		return true;
	else
		return false;
}

- (BOOL) GreaterThan: (id) otherObject
{
	if (real >= [otherObject GetReal] && imaginary >= [otherObject GetReal])
		return true;
	else
		return false;
}
@end

IComparable.h

@protocol IComparable
-(BOOL)Equals:(id)otherObject;
-(BOOL)GreaterThan:(id)otherObject;
@end

Reader.h

#import 
#import 

@interface Reader : NSObject
{ 	
}

-(id)init;
-(int) ReadInt;
-(double) ReadDouble;
-(float) ReadFloat;
@end

Reader.m

#import "Reader.h"

@implementation Reader

-(id) init
{
	self = [super init];
	if (!self) return nil;
	else
	{
		return self;
	}
}

- (int) ReadInt
{
	int tempInt;
	scanf(" %d ", &tempInt);
	return tempInt;
}

- (double) ReadDouble
{
	double tempDouble;
	scanf(" %lf", &tempDouble);
	return tempDouble;
}

- (float) ReadFloat
{
	float tempFloat;
	scanf(" %f", &tempFloat);
	return tempFloat;
} 
@end

Writer.h

#import 

@interface Writer : NSObject
{
}

-(id)init;
+(void) WriteString : (NSConstantString*)aSource;
+(void) WriteInt : (NSConstantString*)aMessage : (int)aSource;
+(void) WriteDouble: (double)aSource;
+(void) WriteFloat : (NSConstantString*)aMessage : (float)aSource;
@end

Writer.m

#import "Writer.h"

@implementation Writer

-(id) init
{
	self = [super init];
	if (!self) return nil;
	else
	{
		return self;
	}
}

+ (void) WriteString : (NSConstantString*)aSource
{
	NSLog(aSource);
}

+ (void) WriteInt : (NSConstantString*)aMessage : (int)aSource
{
	NSLog(@"%d",aMessage, aSource);
}

+ (void) WriteDouble : (double)aSource
{
	NSLog(@"%f", aSource);
}

+ (void) WriteFloat : (NSConstantString*)aMessage : (float)aSource
{
	NSLog(aMessage, aSource);
} 
@end

Képek letöltése párhuzamosan

A program lehetőséget biztosít képek letöltésére külön szálakban NSInvocationOperation segítségével. Megadható, hogy hány konkurens szál fusson egyszerre.

Szerző: Tóth Ã�dám (2013)

Használt fejlesztőkörnyezet: OS X 10.9, XCode 4.6.2

Példaprogram letöltése

Számológép, GNUstep alkalmazások segítségével

A fentebb bemutatott eszközök mélyebb megismeréséhez most bemutatom, hogyan lehet ezek segítségével könnyen, gyorsan grafikus felülettel rendelkező programot készíteni Objective-C nyelven Windows alatt.
Indítsuk el a ProjectCenter-t és válasszuk a Project->New lehetőséget. A „New Projectâ€� dialógusban válaszuk az Application projekt típusnak, és válaszuk meg a helyét és a nevét, ami jelen esetben Calculator lesz.

GNUstep install
Ezzel létre jött a projektünk. A megjelenő fő ablakban ball felül válaszuk az Interfaces lehetőséget, aminek hatására tőle jobbra a ProjectCenter verziójától függően több lehetőség jelenik meg. Mivel most csak a grafikus felhasználói felülettel fogunk foglalkozni a Calculator.gorm-on kívül a többit akár el is távolítható a Project->Remove Files és a "Project and Disk" opcióval. Ezután válasszuk a Calculator.gorm-ot aminek hatására elindul a Gorm alkalmazásunk.
Itt jegyezném meg, hogy elsőre elég zavaró lehet, hogy a GNUstep-es alkalmazások olyan módon jelennek meg, hogy külön ablakokban van minden része, és a menüje megint csak külön életet él. Ezt a NextStep-től örökölte és kis idő után meg lehet szokni de az első időkben eléggé oda kell figyelni.
Ha valamelyik ablak nem jelenne meg a Tools menüben tudjuk megjeleníteni őket.
GNUstep install
A Palettes ablakban találhatóak a különböző vezérlők amiket drag&drop technikával fel is tudunk használni.
Először válaszuk a Window-t, és húzuk a Gorm Document-be
GNUstep install GNUstep install
Az új elemet kiválasztva az Inspector ablakban megjelennek annak tulajdonságai, például az ablak címe, amit itt be is alíthatunk, majd egy enter lenyomására, érvényre is jutnak. Ha azonban magának az objektumnak a nevét akarjuk bealítani, azon jobb klikkel Edit -> Set Name-el tudjuk megtenni.
Végre neki állhatunk a felhasználói felület kialakításának. A jól bevált drag&drop technikával a Palettes ablakból tegyük fel a MainWindow-onkra a kívánt elemek, majd állítsuk be a tulajdonságaikat, és elrendezésüket nekünk tetszően.
GNUstep install
Láthatjuk, hogy ehhez elég sok segítséget nyújt a program. Vezető vonalakkal az elrendezéshez, azonnali átméretezéssel, és a rengeteg egyéb tulajdonság bealíthatóságával.
Valami hasonló eredmény elérése a cél:
GNUstep install
Ezután készítsük el a vezérlő osztályunkat. A Gorm fő ablakán válasszuk a Classes részt, majd ott az NSObject osztályt és a menüben Classes -> Create Subclass akciót. Ã�gy létrejön egy „NewClassâ€� osztály. Az új osztályt kiválasztva, az inspector ablakban szerkeszthetjük az osztály paramétereit. Először nevezzük át CalculatorManager-nek, majd adjunk hozzá két Outlets-t, amik az osztály változói lesznek, és 17 Actions-t, amik a metódusai lesznek. Valahogy így:
GNUstep install GNUstep install GNUstep install
Most, hogy létrehoztuk az osztályunkat, azt kiválasztva válaszuk a Classes -> Instantiate. Erre azért van szükség, hogy jelezzük a GNUstep-nek hozzon létre egy példányt belőle, amikor elindul az alkalmazás. Továbbá a Gorm főablakában megjelenik a CalculatorManager objektum is.
Ezután össze kell kötni az osztály és a felület tulajdonságait. Először az outlets-eket kötjük a felületen lévő textbox-okkal, hogy futási időben hozzáférhessünk az értékéhez a változón keresztül. Ezt úgy tehetjük meg hogy a Gorm főablakában rákattintunk a CalculatorManager-re majd a jobb oldali Ctrl-t nyomva tartva drag&drop-oljuk a megfelelő textbox-ra. Ekkor kis magenta T jelenik meg a textbox-ban, és zöld S jelenik meg a CalculatorManager-en. Az inspector-ban pedig kiválaszthatjuk a megfelelő Outlets-et, és ezzel létrejön a kapcsolat.
GNUstep install
Az akciók bekötéséhez is egész hasonlóan kell eljárnunk, csak ebben az esetben a kiválasztott gombot fogjuk meg és a jobboldali Ctrl lenyomása mellett drag&drop-oljuk a CalculatorManager-re, ekkor a kis S és T fordítva jelenik meg, és az inspector-ban megadhatjuk, hogy az előbb definiált action-ok közül melyik legyen a gombnoymás target-je, ezáltal létrejön a kapcsolat.
GNUstep install
A Gorm képes automatikusan elkészíteni az így létrehozott osztály vázát, ehhez válaszuk ki a CalculatorManagert-t a class panelen, és válaszuk a Classes -> Create Class’s Fiels. Két sikeres mentési ablak fog megjelenni a .m és a .h fájloknak. Végül az automatikusan létrejött AppController-t törölhetjük, és így végeztünk is a Gorm használatával.
Térjünk vissza a ProjectCenter alkalmazásba, és dupla klikkeljünk a Classes-re a főablak bal felső részén, és a felugró ablakban válaszuk a CalculatorManager.m fájlt, a header fájl automatikusan hozzáadódik a projekthez. Ezután, megjelenik a második oszlopban, és kiválasztva már szerkeszthetjük is a kódot.
GNUstep install
A ProjectCenter elvileg tudja buildelni, és futatni a projektet, bár nekem nem sikerült működére bírni, de ez nem gond mivel kész make filet gyárt a projekt könyvtárába, és azt promt-ból simán tudjuk buildelni „makeâ€� paranccsal, majd indíthatjuk a projekt könyvtárban lévő „Calculator.appâ€� mappában lévő Calculator.exe-vel.

A forráskód:

CalculatorManager.h

#include 

@interface CalculatorManager : NSObject
{
  id history;
  id result;
  
  double lastKnownValue;
    
  NSString *operand;
    
  BOOL isInEqualMod;
}
- (void) add: (id)sender;
- (void) division: (id)sender;
- (void) eight: (id)sender;
- (void) equal: (id)sender;
- (void) erase: (id)sender;
- (void) five: (id)sender;
- (void) four: (id)sender;
- (void) multiply: (id)sender;
- (void) dot: (id)sender;
- (void) nine: (id)sender;
- (void) one: (id)sender;
- (void) seven: (id)sender;
- (void) six: (id)sender;
- (void) subtract: (id)sender;
- (void) three: (id)sender;
- (void) two: (id)sender;
- (void) zero: (id)sender;
@end
	

CalculatorManager.m

#include 
#include "CalculatorManager.h"

@implementation CalculatorManager

- (BOOL)doesStringContainDecimal:(NSString*) string
{
    NSString *searchForDecimal = @".";
    NSRange range = [[result stringValue] rangeOfString:searchForDecimal];
    
    if (range.location != NSNotFound)
        return YES;
    return NO;
}

- (void)calculate
{
    double currentValue = [result doubleValue];
    
    if (lastKnownValue != 0)
    {
        if ([operand isEqualToString:@"+"])
            lastKnownValue += currentValue;
        else if ([operand isEqualToString:@"-"])
            lastKnownValue -= currentValue;
        else if ([operand isEqualToString:@"*"])
            lastKnownValue *= currentValue;
        else if ([operand isEqualToString:@"/"])
        {
            if (currentValue == 0)
                [result setStringValue: @"ERR: Devide by Zero"];
            else
                lastKnownValue /= currentValue;
        }
    }
    else
        lastKnownValue = currentValue;
}

- (void) add: (id)sender
{
    [self calculate];
    operand = @"+";
    [history setStringValue: [[history stringValue] stringByAppendingFormat:[result stringValue]]];
    [history setStringValue: [[history stringValue] stringByAppendingFormat:@" + "]];
    [result setStringValue: @""];
}


- (void) division: (id)sender
{
    [self calculate];
    operand = @"/";
    [history setStringValue: [[history stringValue] stringByAppendingFormat:[result stringValue]]];
    [history setStringValue: [[history stringValue] stringByAppendingFormat:@" / "]];
    [result setStringValue: @""];
}


- (void) eight: (id)sender
{
  [result setStringValue: [[result stringValue] stringByAppendingFormat:@"8"]];
}


- (void) equal: (id)sender
{   
  [self calculate];
  [history setStringValue: [[history stringValue] stringByAppendingFormat:[result stringValue]]];
  [history setStringValue: [[history stringValue] stringByAppendingFormat:@" = "]];
  [result setStringValue: @""];
  [result setStringValue: [NSString stringWithFormat:@"%g",lastKnownValue]];
  operand = @"";
}


- (void) erase: (id)sender
{
  [result setStringValue: @""];
  [history setStringValue: @""];
  operand = @"";
  lastKnownValue = 0;
}


- (void) five: (id)sender
{
  [result setStringValue: [[result stringValue] stringByAppendingFormat:@"5"]];
}


- (void) four: (id)sender
{
  [result setStringValue: [[result stringValue] stringByAppendingFormat:@"4"]];
}


- (void) multiply: (id)sender
{
    [self calculate];
    operand = @"*";
    [history setStringValue: [[history stringValue] stringByAppendingFormat:[result stringValue]]];
    [history setStringValue: [[history stringValue] stringByAppendingFormat:@" * "]];
    [result setStringValue: @""];
}


- (void) dot: (id)sender
{
   if ([self doesStringContainDecimal:[result stringValue]] == NO && [result stringValue] != @"")
      [result setStringValue: [[result stringValue] stringByAppendingFormat:@"."]];
}


- (void) nine: (id)sender
{
  [result setStringValue: [[result stringValue] stringByAppendingFormat:@"9"]];
}


- (void) one: (id)sender
{
  [result setStringValue: [[result stringValue] stringByAppendingFormat:@"1"]];
}


- (void) seven: (id)sender
{
  [result setStringValue: [[result stringValue] stringByAppendingFormat:@"7"]];
}


- (void) six: (id)sender
{
  [result setStringValue: [[result stringValue] stringByAppendingFormat:@"6"]];
}


- (void) subtract: (id)sender
{ 
    [self calculate];
    operand = @"-";
    [history setStringValue: [[history stringValue] stringByAppendingFormat:[result stringValue]]];
    [history setStringValue: [[history stringValue] stringByAppendingFormat:@" - "]];
    [result setStringValue: @""];
}


- (void) three: (id)sender
{
  [result setStringValue: [[result stringValue] stringByAppendingFormat:@"3"]];
}


- (void) two: (id)sender
{
  [result setStringValue: [[result stringValue] stringByAppendingFormat:@"2"]];
}


- (void) zero: (id)sender
{
  [result setStringValue: [[result stringValue] stringByAppendingFormat:@"0"]];
}

@end
	

Szerző: Kur Barnabás (2013)

Használt fejlesztőkörnyezet: Windows 8 Enterprise x64, GNUStep 0.30

Logikai feladvany

A feladat:

Adott 4 ember, aki át szeretne jutni a szakadék túloldalára egy hídon keresztül. Mivel korom sötét van mindenképpen lámpát kell használniuk a hídon történő áthaladáshoz. Lámpa csak egy van, ezért párban haladnak át a hídon és egy mindig visszahozza azt a maradék embernek. A 4 ember különböző sebességgel képes átkelni a hídon az egyik 10, a másik 5, a harmadik 2 és a negyedik 1 perc alatt. A kérdés, mennyi a legrövidebb idő, ami alatt az átkelés megoldható.

A legrovidebb ut meghatarozasaban az a trukk, hogy a ket leglassabb embernek egyszerre kell atkelnie a hidon mivel igy a masodik leglassab ideje nem szamit bele az utba. Ha atertek mar nem is szabad mozogniuk a ket part kozott.

Ehhez sorba kell oket rendezni es a gyorsabb part atkuldeni elsonek, majd kozuluk valamelyik visszajon (az eredmenyt nem befolyasolja a dontes, hogy melyik). Most elore kell kuldeni a leglassabbakat es a tulpartol megint a leggyorsabb visszajon. Ekkor a ket lassu mar odaat van es a ket gyors meg nem, mar csak nekik kell aterniuk.

Valahogy igy: {1,2} + {1} + {5,10} + {2} + {1,2}

Jeloljuk az embereknek haladasi idejuket t1,t2,t3,t4-vel melyek rendre 1,2,5,10 erteket vesznek fel.

Ha az elobb felvazolt legolcsobb utat kepletre rendezzuk akkor ezt az eredmeny kapjuk

t_min = t1 + 3 * t2 + t4 -> 1 + 3*2 + 10 = 17

A feladathoz ket megoldast keszitettem el az egyikben (GameSpace) lepesenkent haladunk a part kozott es mindig az adott allapottol fuggoen dontunk, hogy ki menjen at. Az egyszerubb megoldasban (SimpleSolution) nincsenek ilyen allapotok a kapott emberek alapjan lefuttatjuk a kepletet es kiirjuk a minimalis koltsegu kombinacionak az erteket, majd a ket part kozotti lepeseket is kiirjuk. Forráskód letöltése

A GameSpace is megkapja a negy embert, majd elkezdi a fent leirt logika alapjan mozgatni az embereket, ember parokat a ket part kozott es menetkozben felirja a haladasi idot. Ha mindenki atert a tulpartra akkor vegeztunk.



A forráskód:

GameSpace.h

	#import 
	#import 
	#import 

	@interface GameSpace : NSObject {
	    NSMutableArray * peopleOnTheLeftSide;
	    NSMutableArray * peopleOnTheRightSide;
	    NSMutableArray * slowPair;
	    NSMutableArray * fastPair;
	    NSMutableArray * movingPair;
	    Lamp * theLamp;
	    int elapsedTime;
	}

	- (id) initGameSpace;

	- (void) startWalking;
	- (void) moveToSide:(Side) side;
	- (void) printStatus;
	- (NSMutableArray*) getFastPair;
	- (NSMutableArray*) getSlowPair;
	- (NSArray*) sortRightSide;

	@end

GameSpace.m

	#import "GameSpace.h"

	@implementation GameSpace

	- (id) initGameSpace
	{
	    self = [super init];
	    if(self)
	    {
	        Person * p1 = [[Person alloc] initWithName:@"Anna" AndSpeed:1];
	        Person * p2 = [[Person alloc] initWithName:@"Bela" AndSpeed:5];
	        Person * p3 = [[Person alloc] initWithName:@"Nora" AndSpeed:2];
	        Person * p4 = [[Person alloc] initWithName:@"Dani" AndSpeed:10];

	        peopleOnTheLeftSide =  [[NSMutableArray alloc] initWithCapacity:4];//WithObjects:p1,p2,p3,p4];
	        [peopleOnTheLeftSide addObject: p1];
	        [peopleOnTheLeftSide addObject: p2];
	        [peopleOnTheLeftSide addObject: p3];
	        [peopleOnTheLeftSide addObject: p4];

	        //!!!peopleOnTheLeftSide Sort;

	        peopleOnTheRightSide = [[NSMutableArray alloc] init];

	        slowPair = [ self getSlowPair];
	        fastPair = [ self getFastPair];

	        theLamp = [[Lamp alloc] init];
	        [theLamp setSide: Left];

	        elapsedTime = 0;
	    }

	    return self;
	}

	- (void) startWalking
	{
	    while([peopleOnTheLeftSide count] != 0)
	    {
	        if([theLamp getSide] == Left)
	            [self moveToSide:Right];
	        else
	            [self moveToSide:Left];
	    }
	}

	- (void) moveToSide:(Side) side
	{

	    if([theLamp getSide] == side) return;



	    switch(side)
	    {
	        case Right:
	            [theLamp setSide: Right];

	            // move the fast pair
	            if([peopleOnTheRightSide count] == 0)
	            {
	                [theLamp setWhoHasTheLamp:[[fastPair objectAtIndex:0] getName]];
	                movingPair = fastPair;
	            }
	            // slow pair is not there yet
	            else if([peopleOnTheRightSide count] == 1)
	            {
	                [theLamp setWhoHasTheLamp:[[slowPair objectAtIndex:0] getName]];
	                movingPair = slowPair;
	            }
	            // slow pair is there
	            else if([peopleOnTheRightSide count] == 2)
	            {
	                [theLamp setWhoHasTheLamp:[[peopleOnTheLeftSide objectAtIndex:0] getName]];
	                movingPair = peopleOnTheLeftSide;
	            }

	            // add moving pair
	            for(id p in movingPair)
	            {
	                [peopleOnTheRightSide addObject:p];
	            }

	            //[peopleOnTheRightSide addObject:[movingPair objectAtIndex:0]];
	            //[peopleOnTheRightSide addObject:[movingPair objectAtIndex:1]];

	            elapsedTime += [[movingPair objectAtIndex:1] getSpeed];

	            if([movingPair isEqualToArray:peopleOnTheLeftSide])
	            {
	                [peopleOnTheLeftSide removeAllObjects];
	            }
	            else
	            {
	                //for(id p in movingPair)
	                //{
	                //    [peopleOnTheLeftSide removeObject:p];
	                //}

	                [peopleOnTheLeftSide removeObject:[movingPair objectAtIndex:0]];
	                [peopleOnTheLeftSide removeObject:[movingPair objectAtIndex:1]];
	            }
	        break;
	        case Left:

	            peopleOnTheRightSide = [NSMutableArray arrayWithArray:[self sortRightSide]];

	            [theLamp setWhoHasTheLamp:[[peopleOnTheRightSide objectAtIndex:0] getName]];
	            [theLamp setSide: Left];

	            elapsedTime += [[peopleOnTheRightSide objectAtIndex:0] getSpeed];

	            [peopleOnTheLeftSide  addObject:   [peopleOnTheRightSide objectAtIndex:0]];
	            [peopleOnTheRightSide removeObject:[peopleOnTheRightSide objectAtIndex:0]];
	        break;
	    }

	    [self printStatus];
	}

	- (NSMutableArray*) getFastPair
	{
	    NSSortDescriptor *sortDescriptor;
	    sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"Speed"
	                                                ascending:YES];
	    NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
	    NSArray *sortedArray = [peopleOnTheLeftSide sortedArrayUsingDescriptors:sortDescriptors];

	    Person * fastPerson_1 = [sortedArray objectAtIndex:0];
	    Person * fastPerson_2 = [sortedArray objectAtIndex:1];
	    NSMutableArray * result = [[NSMutableArray alloc] initWithCapacity:2];
	    [result addObject:fastPerson_1];
	    [result addObject:fastPerson_2];

	    return result;
	}

	- (NSMutableArray*) getSlowPair
	{
	    NSSortDescriptor *sortDescriptor;
	    sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"Speed"
	                                                ascending:YES] autorelease];
	    NSMutableArray *sortDescriptors = [NSMutableArray arrayWithObject:sortDescriptor];
	    NSArray *sortedArray = [peopleOnTheLeftSide sortedArrayUsingDescriptors:sortDescriptors];

	    Person * slowPerson_1 = [sortedArray objectAtIndex:2];
	    Person * slowPerson_2 = [sortedArray objectAtIndex:3];

	    NSMutableArray * result = [[NSMutableArray alloc] initWithCapacity:2];
	    [result addObject:slowPerson_1];
	    [result addObject:slowPerson_2];

	    return result;
	}

	- (NSArray*) sortRightSide
	{
	    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"Speed" ascending:YES];
	    NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
	    return [peopleOnTheRightSide sortedArrayUsingDescriptors:sortDescriptors];
	}


	- (void) printStatus
	{
	            for (id people in peopleOnTheLeftSide)
	            {
	                NSLog([people getName]);
	                NSLog(@"%i",[people getSpeed]);
	            }

	            NSLog(@" /|______|\\ ");

	            for (id people in peopleOnTheRightSide) {
	                NSLog([people getName]);
	                NSLog(@"%i",[people getSpeed]);
	            }

	            NSLog(@"\n=================================================\n");
	            NSLog(@"%i", elapsedTime);
	            NSLog(@"\n=================================================\n");
	}
	@end

Lamp.h

	#import 
	#import 

	@interface Lamp : NSObject {
	    Side side;
	    NSString * whoHasTheLamp;
	}



	-(void)setSide:(Side)s;
	-(Side)getSide;

	-(void) setWhoHasTheLamp:(NSString*)Name;
	-(NSString*)getWhoHasTheLamp;

	@end
	

Lamp.m

	#import "Lamp.h"


	@implementation Lamp

	-(void)setSide:(Side)s;
	{
	    side = s;
	}

	-(Side)getSide
	{
	    return side;
	}

	-(void) setWhoHasTheLamp:(NSString*)Name
	{
	    whoHasTheLamp = Name;
	}

	-(NSString*)getWhoHasTheLamp
	{
	    return whoHasTheLamp;
	}

	@end

Person.h

	@interface Person : NSObject
	{
	    NSString *Name;
	    int Speed;
	}
	    - (id) initWithName:(NSString*)name AndSpeed:(int)speed;

	    - (void) setName:(NSString *) name;
	    - (NSString*) getName;
	    - (void) setSpeed: (int)speed;
	    - (int) getSpeed;

	@end

Person.m

	#import "Person.h"

	@implementation Person

	    - (id) initWithName:(NSString*)name AndSpeed:(int)speed
	    {
	        self = [super init];
	        if(self)
	        {
	            [self setName:name];
	            [self setSpeed:speed];
	        }
	        return self;
	    }

	    - (void) setName:(NSString*) name
	    {
	        Name = name;
	    }

	    - (NSString*) getName
	    {
	        return Name;
	    }

	    - (void) setSpeed:(int) speed
	    {
	        Speed = speed;
	    }
	    - (int) getSpeed
	    {
	        return Speed;
	    }

	@end

Side.h

	typedef enum {
	    Right = 0,
	    Left
	} Side;

SimpleSolution.h

	@interface SimpleSolution : NSObject {
	    NSMutableArray * people;
	}

	- (id) initSimpleSolution;
	- (int) getMinimumTime;
	- (NSArray*) sortPeople;
	- (void) PrintSolution;


	@end

SimpleSolution.m

	#import "SimpleSolution.h"
	#import "Person.h"

	@implementation SimpleSolution

	 - (id) initSimpleSolution
	 {
	    self = [super init];
	    if(self)
	    {
	        Person * p4 = [[Person alloc] initWithName:@"Dani" AndSpeed:10];
	        Person * p1 = [[Person alloc] initWithName:@"Anna" AndSpeed:1];
	        Person * p3 = [[Person alloc] initWithName:@"Nora" AndSpeed:2];
	        Person * p2 = [[Person alloc] initWithName:@"Bela" AndSpeed:5];

	        people =  [[NSMutableArray alloc] initWithCapacity:4];
	        [people addObject: p1];
	        [people addObject: p2];
	        [people addObject: p3];
	        [people addObject: p4];

	    }

	    return self;
	 }

	- (int) getMinimumTime
	{

	    NSArray * sortedArray = [self sortPeople];

	    return [[sortedArray objectAtIndex:0] getSpeed]
	         + [[sortedArray objectAtIndex:1] getSpeed] * 3
	         + [[sortedArray objectAtIndex:3] getSpeed];

	}

	- (NSArray*) sortPeople
	{
	    // comment hogy hogyan lehet rendezni, beepitett lehetosegekkel.
	    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"Speed" ascending:YES];
	    NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
	    return [people sortedArrayUsingDescriptors:sortDescriptors];
	}

	// PRINT SCENARIO
	- (void) PrintSolution
	{
	    // beszedes kimenet.
	    NSLog(@"%i",[self getMinimumTime]);
	}

	@end

main.m

	#import 
	#import 

	int main(int argc, char *argv[])
	{

	   NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

	   GameSpace * theGame = [[GameSpace alloc] initGameSpace];
	   [theGame startWalking];

	   SimpleSolution * sol = [[SimpleSolution alloc] initSimpleSolution];
	   [sol PrintSolution];

	   [pool release];
	   return 0;
	}

Szerző: Gal Otto (2013)

Használt fejlesztőkörnyezet: Xcode 4.6.2

Egyszerű számológép storyboard segítségével

>>> SimpleCalculator progam innent letölthető <<<

Hozzunk létre egy új projektet és ügyeljünk arra, hogy a storyboard is be legyen pipálva.
A fejlesztői környezetből nyissuk meg a Main.storyboard fájlt. A storyboard-ba huzzuk bele a gombokat a jobb alsó sarokból a drag-n-drop módszert alkalmazva. Formázzuk is meg, nevezzük át, stb. Amikor ezzel elkészültnk, osszuk meg a képernyőt, amit úgy tudunk megtenni, hogy a jobb felső sarok középső ikonját választjuk ki (a csokornyakkendőset), majd jelöljük ki egy objektumot. Ekkor a ctrl+bal egér gombot tartsuk lenyomva és húzzuk bele a ViewController.h fájlba, majd eresszük el és rendeljünk hozzá eseményeket, hasonlóan mint a lenti képen (ügyeljünk arra, hogy ha gombokhoz akciót szeretnénk rendelni, akkor az Connection Outlet helyett az IBAction-t válasszuk, a label-ekhez outlet-et használunk). Ha ezzel megvagyunk, hasonlóan kell kinéznie a fáljnak, mint a ViewController.h. A többi részt fejtsük ki a ViewController.m fájlban hasonlóan, mint ami lejjebb megtalálható.
A továbbfejlestzéshez csak a fantáziánk szabhat határt.

storyboard

ViewController.h

#import 

@interface ViewController : UIViewController

@property (weak, nonatomic) IBOutlet UILabel *consoleLabel;
@property (weak, nonatomic) IBOutlet UILabel *operatorLabel;

- (IBAction)one:(id)sender;
- (IBAction)two:(id)sender;
- (IBAction)three:(id)sender;
- (IBAction)four:(id)sender;
- (IBAction)five:(id)sender;
- (IBAction)six:(id)sender;
- (IBAction)seven:(id)sender;
- (IBAction)eight:(id)sender;
- (IBAction)nine:(id)sender;
- (IBAction)zero:(id)sender;

- (IBAction)dot:(id)sender;

- (IBAction)clear:(id)sender;

- (IBAction)divide:(id)sender;
- (IBAction)multiple:(id)sender;
- (IBAction)minus:(id)sender;
- (IBAction)plus:(id)sender;

- (IBAction)sqrt:(id)sender;
- (IBAction)suqare:(id)sender;

- (IBAction)total:(id)sender;

@end

ViewController.m

#import "ViewController.h"

// műveletek deklarálása

typedef enum {
    Plus,
    Minus,
    Multiply,
    Divide,
    Sqrt,
    Square,
    Equal
} Operation;

// változók deklarálása

@interface ViewController ()
{
    double result;
    NSString *store, *log;
    int operator;
    BOOL isCalculated;
}

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
	// Do any additional setup after loading the view, typically from a nib.
    
    [self initialize];
}

// inicializáló függvény

- (void)initialize {
    result = 0;
    store = @"";
    log = @"";
    isCalculated = NO;
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

// az 1-es gomb lenyomása hatására történő esemény

- (IBAction)one:(id)sender {
    [self addNumberToTheConsole:1];
}

// a 2-es gomb lenyomása hatására történő esemény

- (IBAction)two:(id)sender {
    [self addNumberToTheConsole:2];
}

// a 3-as gomb lenyomása hatására történő esemény

- (IBAction)three:(id)sender {
    [self addNumberToTheConsole:3];
}

// a 4-es gomb lenyomása hatására történő esemény

- (IBAction)four:(id)sender {
    [self addNumberToTheConsole:4];
}

// a 5-ös gomb lenyomása hatására történő esemény

- (IBAction)five:(id)sender {
    [self addNumberToTheConsole:5];
}

// a 6-os gomb lenyomása hatására történő esemény

- (IBAction)six:(id)sender {
    [self addNumberToTheConsole:6];
}

// a 7-es gomb lenyomása hatására történő esemény

- (IBAction)seven:(id)sender {
    [self addNumberToTheConsole:7];
}

// a 8-as gomb lenyomása hatására történő esemény

- (IBAction)eight:(id)sender {
    [self addNumberToTheConsole:8];
}

// a 9-es gomb lenyomása hatására történő esemény

- (IBAction)nine:(id)sender {
    [self addNumberToTheConsole:9];
}

// a 0 gomb lenyomása hatására történő esemény

- (IBAction)zero:(id)sender {
    [self addNumberToTheConsole:0];
}

// a , gomb lenyomása hatására történő esemény

- (IBAction)dot:(id)sender {
    store = [store stringByAppendingString:@"."];
    log = [log stringByAppendingString:@"."];
    [self.consoleLabel setText:store];
    [self.operatorLabel setText:log];
}

// a c gomb lenyomása hatására történő esemény

- (IBAction)clear:(id)sender {
    store = @"";
    log = @"";
    result = 0.0;
    isCalculated = YES;
    [self.consoleLabel setText:@"0"];
    [self.operatorLabel setText:log];
}

// a minusz művelet lenyomása hatására történő esemény

- (IBAction)minus:(id)sender {
    [self logic:Minus];
}

// a plusz művelet lenyomása hatására történő esemény

- (IBAction)plus:(id)sender {
    [self logic:Plus];
}

// a szorzás művelet lenyomása hatására történő esemény

- (IBAction)multiple:(id)sender {
    [self logic:Multiply];
}

// az osztás művelet lenyomása hatására történő esemény

- (IBAction)divide:(id)sender {
    [self logic:Divide];
}

// a gyökvonás művelet lenyomása hatására történő esemény

- (IBAction)sqrt:(id)sender {
    [self logic:Sqrt];
}

// a négyzetreemelés művelet lenyomása hatására történő esemény

- (IBAction)suqare:(id)sender {
    [self logic:Square];
}

// az egyenlőség művelet lenyomása hatására történő esemény

- (IBAction)total:(id)sender {
    [self logic:Equal];
}

// a logikákat leíró függvény

- (void)logic:(int)type {
    double tmpNum = [store doubleValue];
    double res = 0.0;
    
    // plusz gomb hatására vonatkozó esemény
    
    if (type == Plus) {
        operator = Plus;
        result = [store doubleValue];
        store = @"";
        [self.consoleLabel setText:store];
        log = [log stringByAppendingString:@" + "];
        [self.operatorLabel setText:log];
    }
    
    // minusz gomb hatására vonatkozó esemény
    
    if (type == Minus) {
        operator = Minus;
        result = [store doubleValue];
        store = @"";
        [self.consoleLabel setText:store];
        log = [log stringByAppendingString:@" - "];
        [self.operatorLabel setText:log];
    }
    
    // szorzás gomb hatására vonatkozó esemény
    
    if (type == Multiply) {
        operator = Multiply;
        result = [store doubleValue];
        store = @"";
        [self.consoleLabel setText:store];
        log = [log stringByAppendingString:@" * "];
        [self.operatorLabel setText:log];
    }
    
    // osztás gomb hatására vonatkozó esemény
    
    if (type == Divide) {
        operator = Divide;
        result = [store doubleValue];
        store = @"";
        [self.consoleLabel setText:store];
        log = [log stringByAppendingString:@" / "];
        [self.operatorLabel setText:log];
    }
    
    // gyökvonás gomb hatására vonatkozó esemény
    
    if (type == Sqrt) {
        operator = Sqrt;
        log = [NSString stringWithFormat:@"sqrt(%f)", tmpNum];
        res = sqrt(tmpNum);
        store = [NSString stringWithFormat:@"%f", res];
        [self.consoleLabel setText:store];
        [self.operatorLabel setText:log];
        store = @"";
        isCalculated = YES;
    }
    
    // négyzetre emelés gomb hatására vonatkozó esemény
    
    if (type == Square) {
        operator = Square;
        log = [NSString stringWithFormat:@"pow(%f, 2)", tmpNum];
        res = pow(tmpNum, 2);
        store = [NSString stringWithFormat:@"%f", res];
        [self.consoleLabel setText:store];
        [self.operatorLabel setText:log];
        store = @"";
        isCalculated = YES;
    }
    
    // egyenlőség gomb hatására vonatkozó esemény
    
    if (type == Equal) {
        log = @"";
        [self.operatorLabel setText:log];
        switch (operator) {
            case Plus:
                res = result + tmpNum;
                break;
            case Minus:
                res = result - tmpNum;
                break;
            case Multiply:
                res = result * tmpNum;
                break;
            case Divide:
                res = result / tmpNum;
                break;
            default:
                break;
        }
        [self.consoleLabel setText:[NSString stringWithFormat:@"%f", res]];
        isCalculated = YES;
    }
}

// a console-ra való kiíratás

-(void)addNumberToTheConsole:(int)number{
    
    if (isCalculated) {
        log = @"";
        store = @"";
        isCalculated = !isCalculated;
        result = 0;
    }
    
    store = [store stringByAppendingString:[NSString stringWithFormat:@"%d", number]];
    log = [log stringByAppendingString:[NSString stringWithFormat:@"%d", number]];
    [self.consoleLabel setText:store];
    [self.operatorLabel setText:log];
}

@end

Szerző: Zsivics Sanel (2014)

Használt fejlesztőkörnyezet: Xcode 5.1

XML Parser használata + lokális értesítések létrehozása iOS rendszeren

>>> A program innen letölthető <<<

XMLParser

// Kezdo tagek beolvasasa. Ha   akkor inicializalom a books tombot, egyebkent ha  akkor letrehozok egy uj Book objektumot
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
  namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName
	attributes:(NSDictionary *)attributeDict {
	
	if([elementName isEqualToString:@"Books"]) {
		// tomb inicializalasa
		appDelegate.books = [[NSMutableArray alloc] init];
	}
	else if([elementName isEqualToString:@"book"]) {
		
		//Book objektum inicializalasa
		aBook = [[Book alloc] init];
		
		//Book ID beallitasa az attributumbol
		aBook.bookID = [[attributeDict objectForKey:@"id"] integerValue];
		
		NSLog(@"id beolvasasa :%i", aBook.bookID);
	}
	
	NSLog(@"Elem feldolgozasa: %@", elementName);
}

// egy XML elem ertekenk olvasasa karakterenkent
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
	// ha ures az aktualis elem, akkor letrehozom
	if(!currentElementValue)
		currentElementValue = [[NSMutableString alloc] initWithString:string];
	else // egyebkent hozzaadom a karaktert
		[currentElementValue appendString:string];
	
	NSLog(@"Ertek feldolgozasa: %@", currentElementValue);
	
}

// zaro tag feldolgozasa, itt kapja meg a vegleges erteket a Book objektum megfelelo tagja
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
  namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
	//  nem kell csinalni semmit
	if([elementName isEqualToString:@"Books"])
		return;
	
	//  elemnel hozzaadom a Book elemet a books tombhoz es felszabaditom
	if([elementName isEqualToString:@"book"]) {
		[appDelegate.books addObject:aBook];
		
		[aBook release];
		aBook = nil;
	}
	else
		[aBook setValue:currentElementValue forKey:elementName];
	
	[currentElementValue release];
	currentElementValue = nil;
}

Értesítések létrehozása kölcsönzési idő lejárat előtti figyelmeztetéshez:

// letrehozza az ertesiteseket a kolcsonzesi ido lejaratarol, es ertesit rogton a lejart kolcsonzesi hataridokrol.
- (void) setExpires {
	[[UIApplication sharedApplication] cancelAllLocalNotifications];
	// vegig megy a beolvasott konyveken
	for (Book* book in books) {		
		UILocalNotification* localNotification = [[UILocalNotification alloc] init]; 
		NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
		// date formatter letrehozasa a string -> date konverziohoz, ha a DateFormatter string nem egyezik az XML-ben 
		// levo date string formatumaval akkor nil objektumot kapunk!
		[dateFormatter setDateFormat:@"yyyy.MM.dd"];
		//[dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:@"Europe/Budapest"]];
		NSDate *dateFromString = [[NSDate alloc] init];
		// \n\r karakterek torlese a datum stringbol
		book.expiration = [book.expiration stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
		// datumma konvertalas
		dateFromString = [dateFormatter dateFromString:book.expiration];
		// konverzios hiba volt?
		if (dateFromString == nil)
		{
			[self showMsg:[NSString stringWithFormat:@"Hiba tortent a %@ datum konvertalasakor.", book.expiration]];
			continue;
		}
		localNotification.timeZone = [NSTimeZone timeZoneWithName:@"Europe/Budapest"];
		// lejart a kolcsonzesi ido?
		if ([self isExpired:dateFromString])
		{
			// ertesitem a felhasznalot
			[self showMsg:[NSString stringWithFormat:@"A %@ könyv %@-n már lejárt!", book.title, book.expiration]];
		}
		else { // kesobb fog lejarni, letrehozom a lejarati ido - 1 nap-ra az ertesitest
			
			dateFromString = [dateFromString dateByAddingTimeInterval:-1*24*60*60];
			localNotification.fireDate = dateFromString;
			localNotification.alertBody = [NSString stringWithFormat:@"A %s könyv holnap lejár!", book.title];
			[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
			[localNotification release];
		}
		[dateFormatter release];
	}
	// letrehozott ertesitesek kiloggolasa
	[self logNotifications];
}

Szerző: Fahmi Arman (2014)

Használt fejlesztői környezet: Xcode 4.2

Bináris keresőfa

>>> A program innen letölthető <<<

A példaprogram egy bináris keresőfa, amely tetszőleges, összehasonlítható értékű elemek tárolására alkalmas. Rendelkezik beszúrás és törlés műveletekkel, valamint egy inorder bejárás művelettel is. Az inorder bejárás egyben ki is írja az egyes csúcsok értékeit, így rendezett sorozatot kapunk. A program két fő fájlból áll: Node.m és Node.h. Ezen kívül létrehoztam egy main.m fájlt, ami a bináris keresőfa használatát mutatja be.

Node.h

// A C-s include helyett importot használunk
#import 

//Node osztály specifikációja 
@interface Node : NSObject // minden osztály alapértelmezett ősosztálya az NSObject
{
    //adattagok, alapértelmezetten protected elérésűek
    Node *left; // bal gyerek
    Node *right; // jobb gyerek
    NSObject *data; // a csúcsban tárolt adat
}

// metódusok deklarációja, amelyeket az implementációban (.m fájl) valósítunk meg
// a metódusok neve magába foglalja a paraméterek nevét is
// - jel jelöli a példánymetódusokat, + az osztálymetódusokat
// a függvénynek két paramétere van: egy Node* és egy NSObject*, visszatérési értéke Node*
-(Node*) insertNode:(Node*) root Object:(NSObject*)data; 
// a függvénynek két paramétere van: egy Node* és egy NSObject*, visszatérési értéke Node*
-(Node*) deleteNode:(Node*) root Value:(NSObject*) value; 
//a függvénynek egy paramétere van: Node* és void visszatérési értékű
-(void) inorderTraversal:(Node*) root; 
 
// a property kulcsszóval ellátott adattagokhoz automatikusan
// getter és setter művelet generálódik, ha az implementációban
// synthesize kulcsszóval látjuk el 
@property (nonatomic, assign) Node *left; // assign jelentése, hogy cím szerinti értékadást szeretnénk biztosítani az adattagnak
@property (nonatomic, assign) Node *right;
@property (nonatomic, assign) NSObject *data;
@end  // end kulcsszó jelöli a specifikáció végét

Node.m

  // A C-s include helyett importot használunk
#import "Node.h"
 
@implementation Node  // osztály megvalósítását az implementation kulcsszó vezeti be
@synthesize left; // a synthesize kulcsszóval ellátott adattagokhoz automatikus getter és setter művelet generálódik
@synthesize right;
@synthesize data;
 
// beszúrás művelet, amely a közismert bináris keresőfa beszúrás algoritmusnak megfelelően működik
-(Node*) insertNode:(Node*) root Object:(NSObject*)data
{    
    Node *current = root;
    Node *previous = nil;
     
    Node *temp = [[Node alloc] init]; // temp objektum inicializálása az init művelettel, memóriafoglalás pedig az alloc művelettel
    temp.data = data;
    temp.left = temp.right = nil; //lehetőség van többszörös értékadásra
    
    
    if(root == nil) //ha a fa üres, akkor beszúrjuk az első elemet
    {
        root = temp;
    }
    else // ha a fa nem üres
    {
        // végigjárjuk a csúcsokat, megkeressük az új érték helyét
        while (current != nil) 
        {
            previous = current;
            NSString *strValue2 = (NSString*) current.data;
            // ha a beszúrandó érték kisebb, mint az aktuálisan vizsgált elem, akkor balra, egyébként jobbra lépünk a fában
            current = ([data compare:current.data options:(NSCaseInsensitiveSearch | NSAnchoredSearch)] == NSOrderedAscending) ? current.left :current.right;
        }

        if ([data compare:previous.data options:(NSCaseInsensitiveSearch | NSAnchoredSearch)] == NSOrderedAscending)
        {
            previous.left = temp;
        }
        else
        {
            previous.right = temp;
        }
    }
    return root;
}
 
// érték törlése a fából, amely a közismert bináris keresőfa törlés algoritmusnak megfelelően működik
-(Node*) deleteNode:(Node*) root Value:(NSObject*) value
{   
    if (root == nil) // ha a fa üres
    {
        return root;
    }
     
    Node *current = root;
    Node *parent; //a törléshez meghatározzuk és számontartjuk az keresendő érték szülő csúcsát
    while (current != nil &&  [value compare:current.data options:(NSCaseInsensitiveSearch | NSAnchoredSearch)] != NSOrderedSame ) 
    {
        parent = current;
        // ha a törlendő érték kisebb, mint az aktuálisan vizsgált elem, akkor balra, egyébként jobbra lépünk a fában
        current = [value compare:current.data options:(NSCaseInsensitiveSearch | NSAnchoredSearch)] == NSOrderedAscending ? current.left : current.right;
    }
     
    if (current == nil) // ha nem találtuk meg az értéket a fában
    {
        return root;
    }
     
    Node *helper;
    Node *suc;
    if (current.left == nil) //ha a törlendő csúcs bal részfája üres
    {
        helper = current.right;
    }
    else if (current.right == nil) //ha a törlendő csúcs jobb részfája üres
    {
        helper = current.left;
    }
    else //ha a törlendő csúcs egyik részfája sem üres
    {
        suc = current.right;
        while (suc.left != nil) 
        {
            suc = suc.left;
        }
        suc.left = current.left;
        helper = current.right;
    }
     
    if (parent == nil) 
    {
        return helper;
    }
    if (current == parent.left) 
    {
        parent.left = helper;
    }
    else
    {
        parent.right = helper;
    }
    current = nil;
    return root;
}
 
// fa bejárása rekurzívan, inorder módon, így rendezett sorozatot kapunk 
-(void) inorderTraversal:(Node*)root
{
    if(root != nil)
    {
        // self objektum az aktuális osztálypéldányt tartlmazza, arra hívjuk meg rekurzívan az inorderTraversal műveletet 
        [self inorderTraversal:root.left];
        // NSLog függvény a konzolra írja a megadott adatot, hasonló a használata, mint a printf függvénynak C- ben
        NSLog(@"%@ ", root.data);
        [self inorderTraversal:root.right];
    }
}

@end // az osztály megvalósítását az end kulcsszóval zárjuk

main.m

// A C-s include helyett importot használunk
#import "Node.m"

//main függvény
int main(void)
{
    Node *binarySearchTreeString = [[Node alloc] init]; // memóriafoglalás a Node osztály számára, majd példányosítása
    
    Node *rootString = nil; // a C-ből ismert NULL helyett itt nil-t használunk
    // tömb inicializálása karakterekkel, memóriafoglalás az alloc művelettel
    NSArray *arrayString = [[NSArray alloc] initWithObjects:@"b",@"d",@"c",@"f",@"h",@"x",@"y", nil]; // értékek megadásakor az utolsó elem kötelezően a nil
    for (NSObject *val in arrayString) //a C#- ból ismert foreach ciklus megfelelője
    {
        // a Smalltalk üzenetküldésének mintájára történő metódushívás root és val paraméterekkel
        // egyenként hozzáadjuk az array elemeit a fához
        rootString=[binarySearchTreeString insertNode:rootString Object:val];
    }
    
    // törlés függvény hívása root és "x" paraméterekkel
    // a @ jel jelöli az Objective-C objektumokat
    [binarySearchTreeString deleteNode:rootString Value:@"x"];
    [binarySearchTreeString deleteNode:rootString Value:@"d"];
    // fa inorder bejárása, amely a rendezett sorozat képernyőre írását eredményezi
    [binarySearchTreeString inorderTraversal:rootString];
    
    
    Node *binarySearchTreeInt = [[Node alloc] init]; // memóriafoglalás a Node osztály számára, majd példányosítása    
    Node *rootInt = nil; // a C-ből ismert NULL helyett itt nil-t használunk
    // tömb inicializálása egész értékekkel, memóriafoglalás az alloc művelettel
    NSArray *arrayInt = [[NSArray alloc] initWithObjects:@"13",@"49",@"51",@"19",@"87",@"33",@"75", nil]; // értékek megadásakor az utolsó elem kötelezően a nil
    for (NSObject *val in arrayInt) //a C#- ból ismert foreach ciklus megfelelője
    {
        // a Smalltalk üzenetküldésének mintájára történő metódushívás root és val paraméterekkel
        // egyenként hozzáadjuk az array elemeit a fához
        rootInt=[binarySearchTreeInt insertNode:rootInt Object:val];
    }
    
    // törlés függvény hívása root és "75" paraméterekkel
    // a @ jel jelöli az Objective-C objektumokat
    [binarySearchTreeInt deleteNode:rootInt Value:@"75"];
    [binarySearchTreeInt deleteNode:rootInt Value:@"19"];
    // fa inorder bejárása, amely a rendezett sorozat képernyőre írását eredményezi
    [binarySearchTreeInt inorderTraversal:rootInt];
    
    return 0;
}

Szerző: Bereczki Gréta Tamara (2014)

Használt fordító: GNUStep Windows Developer 1.4.0

Reflekciós műveletek

>>> A program innen letölthető <<<

A példaprogram futási időben létrehoz egy (ős)osztályt, amelynek van egy darab művelete. Majd létrehozunk egy (gyermek)osztályt (szintén futási időben), amely megöröki ezt a műveletet, majd ebben felüldefiniáljuk az ősosztály műveletét. A példa bemutatja ezen reflekciós eszközök használatát, valamint azt, hogy például el tudjuk érni, hogy a gyermek osztályból a szülő osztály eredeti műveletét hívjuk meg. Lekérdezzük a metódusokat, kiváltsunk metódust, típusellenőrzést végezzünk.

main.m

#import "objc/runtime.h"
#import 

static id instanceOfRuntimeSuperClass;
static id instanceOfRuntimeSubClass;

static Class runtimeSuperClass;
static Class runtimeSubClass;

//skeleton of the dummy main method
static NSString *MainMethod(id self, SEL _cmd)
{
    NSString* className = NSStringFromClass([self class]);
    return [NSString stringWithFormat: @"This is a MAIN METHOD, from 'MainMethod' method from: %@", className];
}

//skeleton of the the dummy sub method
static NSString *SubMethod(id self, SEL _cmd)
{
    NSString* className = NSStringFromClass([self class]);
    return [NSString stringWithFormat: @"This is a SUB METHOD, from 'SubMethod' method from: %@", className];
}

//add the given method to the SuperClass by "easy" encoding, (without handwritten signature string)
void addMethodToSuperClassByEasyEncoding()
{
    //add the type by getting the info from another class
    Method description = class_getInstanceMethod([NSObject class], @selector(description));
    const char *types = method_getTypeEncoding(description);
    
    //now add the method (with signature and implementation)
    class_addMethod(runtimeSuperClass, @selector(description), (IMP)MainMethod, types);
}

//create a superclass and its instance
void createARuntimeSuperClass()
{
    //Create a superclass
    runtimeSuperClass = objc_allocateClassPair([NSObject class], "RuntimeSuperClass", 0);
    
    //Get classname of runtime class
    NSString* className = NSStringFromClass([runtimeSuperClass class]);
    
    addMethodToSuperClassByEasyEncoding();
    
    //register the class
    objc_registerClassPair(runtimeSuperClass);
    
    //create an instance of the RuntimeClass
    instanceOfRuntimeSuperClass = [[runtimeSuperClass alloc] init];
    
    NSLog(@"Instance of the SuperClass has been created...");
}

void overrideMethodInSubClassByHardEncoding(void)
{
    //add the type by getting the info from another class
    Method description = class_getInstanceMethod([NSObject class], @selector(description));
	
	//create the signature string for the method
    NSString *typesNS = [NSString stringWithFormat: @"%s%s%s%s",
                         @encode(NSUInteger),
                         @encode(id), @encode(SEL),
                         @encode(id)];
    const char *types = [typesNS UTF8String];
    
    //'override' the 'description' method with the other implementation
    class_addMethod(runtimeSubClass, @selector(description), (IMP)SubMethod, types);
}

void createARuntimeSubClass()
{
    //create subclass
    runtimeSubClass = objc_allocateClassPair([runtimeSuperClass class], "RuntimeSubClass", 0);
    
    //register the subclass
    objc_registerClassPair(runtimeSubClass);
    
    //create an instance of the subclass
    instanceOfRuntimeSubClass = [[runtimeSubClass alloc] init];
    
    //the subclass inherited the method from the superclass
    NSLog(@"1. call SubClass's method, it will be not yet overridden.");
    NSLog([instanceOfRuntimeSubClass description]);
    
    overrideMethodInSubClassByHardEncoding();
    
    NSLog(@"Instance of the SubClass has been created...");
}

void invokeSuperClassMethodFromSubClass()
{
    //create a superclass object from the subclass
    struct objc_super superClass = {
        .receiver = instanceOfRuntimeSubClass,
        .super_class = class_getSuperclass([instanceOfRuntimeSubClass class])
    };
    
    //call the superclass's method from subclass
    NSLog(@"2. call SuperClass's method, from SubClass.");
    NSLog(objc_msgSendSuper(&superClass, @selector(description)));
    
    //call the subclass's changed method
    NSLog(@"3. call SubClass's overridden method.");
    NSLog([instanceOfRuntimeSubClass description]);
}

void checkKindOfSuperClass()
{
    NSLog(@"\n");
    //check the kind of superclass's instance
    if ([instanceOfRuntimeSuperClass isKindOfClass:runtimeSuperClass])
        NSLog(@"The type of instanceOfRuntimeSuperclass is RuntimeSuperClass");
    else
        NSLog(@"The type if instanceOfRuntimeSuperClass is not RuntimeSuperClass");
}

void checkKindOfSubClass()
{
    NSLog(@"\n");
    //check the kind of subclass's instance
    if ([instanceOfRuntimeSubClass isKindOfClass:runtimeSubClass])
        NSLog(@"The type of instanceOfRuntimeSubclass is RuntimeSubClass");
    else
        NSLog(@"The type if instanceOfRuntimeSubClass is not RuntimeSubClass");
}

//check the kind of the given instances
void checkKindsOfInstances()
{
    checkKindOfSuperClass();
    checkKindOfSubClass();
}

void getMethodsOfClassInstances()
{
    NSLog(@"\n");
    unsigned int numberOfMethods;
    
    //get the method list of superclass
    Method* methods = class_copyMethodList([runtimeSuperClass class], &numberOfMethods);
    
    //print the methods from the list
    NSLog(@"The superclass has: %d method(s)", numberOfMethods);
    for (int i = 0; i < numberOfMethods; i++)
        NSLog(@"Method name: %@", NSStringFromSelector(method_getName(methods[i])));
    
    //get the method list from subclass
    methods = class_copyMethodList([runtimeSubClass class], &numberOfMethods);
    
    //print the methods
    NSLog(@"The subclass has: %d method(s)", numberOfMethods);
    for (int i = 0; i < numberOfMethods; i++)
        NSLog(@"Method name: %@", NSStringFromSelector(method_getName(methods[i])));
    
}

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        createARuntimeSuperClass();
        createARuntimeSubClass();
       
        invokeSuperClassMethodFromSubClass();
        
        checkKindsOfInstances();
        getMethodsOfClassInstances();
    }
    return 0;
}

Szerző: Siklósi Benjamin (2014)

Használt fordító: XCode 5.1

>>> A program innen letölthető <<<

A program a moon buggy játék egy egyszerű klónja. Az interaktív konzolos felülethez pdcurses-t használ. Windows-on ezt a GNUStep-rendszer shelljében a mingw-get pdcurses-el lehet installálni, ezek után a pdc34dllw.zip -t kell letölteni és ebből a .h-kat a GNUStep/include-ba, a .dll-t a GNUStep/bin-be és a .lib-et a GNUStep/lib mappába kell másolni. A program ez után a mellékelt makefile-al fordítható lesz.

Egyke.h

#include 

@interface Egyke : NSObject {}
	+(Egyke*)instance;
@end

Egyke.m

#include "Egyke.h"
#include 

@implementation Egyke 
	static Egyke* _instance = nil;
	
	+(Egyke*)instance { 
		@synchronized(self) {
			if (!_instance) 
				[[self alloc] init];
				return _instance; 
			} 
		return nil; 
	} 
	
	+(id)alloc { 
		@synchronized(self) { 
			NSAssert(_instance == nil, @"Megprobaltad a masodik egyket letrehozni!!!"); 
			_instance = [super alloc]; 
			return _instance; 
		} 
		return nil; 
	} 
	
	-(id)init {
		self = [super init];
		if (self != nil) { 
		} 
		return self; 
	} 
@end

Observable.h

#include 

@interface Observable : NSObject {
	NSMutableArray* observers;
}
	-(id) init;
	-(void) dealloc;
	-(void) attach: (id) object withSelector: (SEL) sel;
	-(void) detach: (id) object withSelector: (SEL) sel;
	-(void) notify;
@end

Observable.m

#include "observable.h"

@implementation Observable
	-(id) init{
		observers = [[NSMutableArray alloc] init];
		return self;
	}
	
	-(void) dealloc{
		[observers release];
		[super dealloc];
	}
	
	-(void) attach: (id) object withSelector: (SEL) sel{ //Egy figyelo csatlakoztatása
		NSInvocation* handler = [NSInvocation invocationWithMethodSignature: 
								[[object class] instanceMethodSignatureForSelector: sel]];
		[handler setTarget: object];
		[handler setSelector: sel];
		[observers addObject: handler];
	}
	
	-(void) detach: (id) object withSelector: (SEL) sel{ //Egy figyelő megkeresése és leválasztása
		NSMutableArray* discard = [NSMutableArray array];
		for(NSInvocation* invocation in observers){
			if( [invocation.target isEqual: object] && sel_isEqual(invocation.selector, sel)){
				[discard addObject: invocation];
			}
		}
		[observers removeObjectsInArray: discard];
	}
	
	-(void) notify{
		for(NSInvocation* invocation in observers)
		{
			[invocation invoke];
		}
	}
@end

main.m

#include 
#include 
#include 

#include 
#include 

#include "Egyke.h"
#include "observable.h"

//A boilerplate kod egy kis elrejtese.

@interface CursesScreen: Egyke {
	boolean isRunning; // A belso megjelenitesi ciklus futasat jelzi, amit ennek atkapcsolasaval illetve a stop fv-el lehet leallitani
	Observable* draw;  // backingfield
}
	@property (readonly) Observable* draw;
	//Ezen az "esemenyen" keresztul adja at a vezerlest az esetleg rajzolni akaroknak

	-(id) init;
	-(void) dealloc;
	-(void) start;
	-(void) stop;
@end

@implementation CursesScreen
	@synthesize draw;
	
	-(id) init{
		isRunning = false;
		draw = [Observable new];
		initscr(); // inicializalja a default kepernyot(stdscr)
		
		nl(); // a bevitelnel az enter newline lesz
		noecho(); // ne irja ki a beutott karaktereket
		curs_set(0); // lathatatlanna teszi a kurzort
		timeout(0); // nem blokkolo bemenetre kapcsolja az ablakot
		keypad(stdscr, TRUE); // bekapcsolja a numpadot
		
		return self;
	}
	
	-(void) start{
		isRunning = true;

		while(isRunning){
			clear();
			[draw notify]; // a vezerles atadasa az esetleges rajzoloknak-vezerloknek.
			napms(50);  
		}
		
		erase();
		curs_set(1); //visszaallitjuk a konzolt..
		endwin();
	}
	
	-(void) stop{
		isRunning = false;
	}
	
	-(void) dealloc{
		[draw release];
		[super dealloc];
	}
@end

@interface Game : NSObject {
	CursesScreen* screen; //amire rajzolhatunk (bar itt csak a leallitashoz hasznaljuk)
	
	int carY; // az auto helyzete
	int maxY; // a sorok szama
	int maxX; // az oszlopok szama
	
	char groundText[500]; // a "fold". megjegyzendo, hogy csak 500 oszlop szeles konzolig mukodik, ami a normalis 8-9 szerese
	int groundIndex;
	
	
	bool running;
	bool gameOver;
}
	-(id) init: (CursesScreen*) scr;
	-(void) draw;
	-(void) initGroundText;
	-(void) generateGroundText: (int) i;
@end

@implementation Game
	-(id) init: (CursesScreen*) scr{
		
		groundIndex = 0;
		running = false;
		gameOver = false;
		
		
		screen = scr;
		getmaxyx(stdscr, maxY, maxX); // lekerjuk a konzol mereteit
		
		carY = 0;
		[self initGroundText];
		
		srand(time(NULL));
		return self;
	}
	
	-(void) initGroundText{ //A jatek elkezdesekor a palya generalasa
		groundIndex = 0;
		int i;
		for(i=0;i 0) ||//ezzel biztositjuk, hogy barmely ket lyuk koze befer a kocsi
		   (groundText[(i-1)%maxX] == '_' && prevHole > 4) 	 //ezzel pedig hogy at is tudjon ugorni az ilyen lyukakon
			) 
				groundText[i%maxX] = '#'; 
		else if(rand()% 1000 < i) //< sqrt(i*10)*(3-prevHole)) egy korabbi generalo probalkozas
			groundText[i%maxX] = '_'; //veletlenszeruen eldontjuk, hogy van-e lyuk.
		else groundText[i%maxX] = '#'; // rand() % 4 < 3 ? '#' : 'Z'; // kis valtozatossagot hoz, de osszessegeben zavaro
		
	}
	
	-(void) draw{
		if(carY>0) carY-=4; // gravitacio
		else if(carY<0) carY = 0; // hatha tul melyre esett
		
		if(carY == 0 && (//katyu vizsgalat
			groundText[(groundIndex+11)%maxX] == '_' ||
			groundText[(groundIndex+12)%maxX] == '_' ||
			groundText[(groundIndex+13)%maxX] == '_' ||
			groundText[(groundIndex+14)%maxX] == '_')) {
			
			running = false;
			gameOver = true;
		}
		
		mvaddstr(2,2,"Uj jatek inditasahoz nyomja meg az r-gombot."); // egyszeru kiirasok (y,x,szoveg)
		mvaddstr(3,2,"Kilepeshez nyomja meg a q-gombot.");
		
		
		if(gameOver){
			mvaddstr(maxY/2-1,maxX/2-5,"Game Over!");
			mvprintw(maxY/2,maxX/2-7,"Pontszam: %d ", groundIndex);//kiiras printf szeru formatummal
		}
		
		mvaddstr(maxY-3-(carY/4), 10, " /^\\");	//a holdjaro kirajzolasa
		mvaddstr(maxY-2-(carY/4), 10, "O---O");
		
		int i;
		for(i=0;i

Szerző: Lengyel Mihály (2014)

Használt fordító: GNUStep