I put together a Custom Linked List class in hopes of using it for a Talent/Skill Tree for a game. It allows for inserting nodes with NSMutableDictionary
for Skills and Requirements along with a nodeID
and a Boolean to see if said node is activated or not.
I would like some feedback on this and any comments/ideas (all criticism welcome) so I can expand on the idea.
The class is located at Github
//
// JBList.h
//
//
// Created by Julius Btesh on 8/28/13.
//
//
#import <Foundation/Foundation.h>
#import "JBListNode.h"
@interface JBList : NSObject
@property (nonatomic) JBListNode *head; // This always points to the first position of the list
@property (nonatomic) JBListNode *tail; // Always points to the last position
@property (nonatomic) JBListNode *currTop;
@property (nonatomic) JBListNode *currBottom;
@property (nonatomic) int count;
- (void)pushFront:(NSMutableDictionary *)skills;
- (void)pushBack:(NSMutableDictionary *)skills;
- (void)pushFront:(NSMutableDictionary *)skills withRequirements:(NSMutableDictionary *)requirements;
- (void)pushBack:(NSMutableDictionary *)skills withRequirements:(NSMutableDictionary *)requirements;
- (NSMutableDictionary *)popFront;
- (NSMutableDictionary *)popBack;
- (NSMutableDictionary *)popNode:(NSInteger)node;
/* Will not work if you have multiple Skill Dictionaries with the same Keys + Values!!!!!
Will find the FIRST nodeID with said Skill!!!!!
*/
- (NSInteger)findNodeIDForSkills:(NSMutableDictionary *)skills;
/* Used for better search precision incase you have multiple Skill Dictionaries but different Requirement Dictionaries!!!
But same as above, if there are multiple Skill AND Requirement Dictionaries with the same Keys + Values
it will find the FIRST nodeID with said Skill AND Requirement!!!
*/
- (NSInteger)findNodeIDForSkills:(NSMutableDictionary *)skills andRequirements:(NSMutableDictionary *)requirements;
- (void)activateNode:(NSInteger)node;
- (void)deactivateNode:(NSInteger)node;
- (BOOL)isActivated:(NSInteger)node;
- (void)setRequirements:(NSMutableDictionary *)requirements forNode:(NSInteger)node;
- (void)editRequirementsAtNode:(NSInteger)node setValue:(id)value forKey:(NSString *)key;
- (NSMutableDictionary *)findRequirements:(NSMutableDictionary *)requirements forNode:(NSInteger)node;
- (NSMutableDictionary *)findSkillsForNode:(NSInteger)node;
- (void)editSkillsAtNode:(NSInteger)node setValue:(id)value forKey:(NSString *)key;
- (void)allNodes;
@end
//
// JBList.m
//
//
// Created by Julius Btesh on 8/28/13.
//
//
#import "JBList.h"
@implementation JBList {
JBListNode *_head;
JBListNode *_tail;
JBListNode *_currTop;
JBListNode *_currBottom;
int _count;
int nodeID;
}
- (id)init {
if (self = [super init]) {
_head = nil;
_tail = nil;
_count = 0;
}
return self;
}
- (void)dealloc {
int i = 0;
JBListNode *tmp;
while (i < _count){
tmp = _head;
_head = _head.next;
tmp = nil;
}
}
- (void)pushFront:(NSMutableDictionary *)skills {
JBListNode *newElement = [[JBListNode alloc] init];
newElement.skills = skills;
if ( _count == 0 ){
newElement.next = nil; //Set both the head and tail to NULL
newElement.previous = nil;
newElement.nodeID = 1;
_count = 1;
_head = newElement;
_tail = newElement;
_currTop = newElement;
_currBottom = newElement;
return; //Since there is only one element, quit
}
nodeID += 1;
JBListNode *tmp = _head;
newElement.next = tmp; //The new guys next is currently pointing to the bottom most element
newElement.previous = tmp.previous; //Now, whatever the bottom was pointing to (the tail) the new node is pointing to.
newElement.nodeID += 1;
_currBottom = newElement; //The new node is now the bottom most element
tmp.previous = newElement; //Now the former bottom is pointing to the new bottom
_head = newElement; //The head is the bottom most element
_count += 1;
}
- (void)pushBack:(NSMutableDictionary *)skills {
JBListNode *newElement = [[JBListNode alloc] init];
newElement.skills = skills;
if ( _count == 0 ) {
newElement.next = nil;
newElement.previous = nil;
newElement.nodeID = 1;
nodeID = 1;
_count = 1;
_head = newElement;
_tail = newElement;
_currTop = newElement;
_currBottom = newElement;
return; //Since there is only one element, quit
}
nodeID += 1;
JBListNode *tmp = _tail;
newElement.previous = tmp; // The new node is pointing to the last element added
newElement.next = tmp.next; // What ever the current top was pointing to, now the new node is pointing to it
newElement.nodeID = nodeID;
_currTop = newElement; // Top most element
tmp.next = newElement; // Now the former top node is pointing to the new node
_tail = newElement; // The tail is the top element
_count += 1;
}
- (void)pushFront:(NSMutableDictionary *)skills withRequirements:(NSMutableDictionary *)requirements {
JBListNode *newElement = [[JBListNode alloc] init];
newElement.skills = skills;
newElement.requirements = requirements;
if ( _count == 0 ){
newElement.next = nil; //Set both the head and tail to NULL
newElement.previous = nil;
newElement.nodeID = 1;
nodeID = 1;
_count = 1;
_head = newElement;
_tail = newElement;
_currTop = newElement;
_currBottom = newElement;
return; //Since there is only one element, quit
}
nodeID += 1;
JBListNode *tmp = _head;
newElement.next = tmp; //The new guys next is currently pointing to the bottom most element
newElement.previous = tmp.previous; //Now, whatever the bottom was pointing to (the tail) the new node is pointing to.
newElement.nodeID = nodeID;
_currBottom = newElement; //The new node is now the bottom most element
tmp.previous = newElement; //Now the former bottom is pointing to the new bottom
_head = newElement; //The head is the bottom most element
_count += 1;
}
- (void)pushBack:(NSMutableDictionary *)skills withRequirements:(NSMutableDictionary *)requirements {
JBListNode *newElement = [[JBListNode alloc] init];
newElement.skills = skills;
newElement.requirements = requirements;
if ( _count == 0 ) {
newElement.next = nil;
newElement.previous = nil;
newElement.nodeID = 1;
nodeID = 1;
_count = 1;
_head = newElement;
_tail = newElement;
_currTop = newElement;
_currBottom = newElement;
return; //Since there is only one element, quit
}
nodeID += 1;
JBListNode *tmp = _tail;
newElement.previous = tmp; // The new node is pointing to the last element added
newElement.next = tmp.next; // What ever the current top was pointing to, now the new node is pointing to it
newElement.nodeID = nodeID;
_currTop = newElement; // Top most element
tmp.next = newElement; // Now the former top node is pointing to the new node
_tail = newElement; // The tail is the top element
_count += 1;
}
- (NSMutableDictionary *)popFront {
if (_count == 0){//Empty!
NSLog(@"Empty!");
return 0;
}
if (_count - 1 == 0) //If count will equal 0, there is 1 element in the list
{
NSMutableDictionary *value = _currBottom.skills; //hold the data, so i can delete the bottom
_currBottom = nil; //delete the last element
_count = 0;
_head = nil; //head and tail are pointing to NULL
_tail = nil;
return value;
}
NSMutableDictionary *value = _currBottom.skills;
JBListNode *tmp = _head;
JBListNode *tmp2 = tmp.next;
JBListNode *tmp3 = _tail;
tmp2.previous = nil;
tmp3.next = nil;
_head = tmp2;
_currBottom = tmp2;
tmp = nil;
_count -= 1;
return value;
}
- (NSMutableDictionary *)popBack {
if (_count == 0){//Empty!
NSLog(@"Empty!");
return 0;
}
if (_count - 1 == 0) //If count will equal 0, there is 1 element in the list
{
NSMutableDictionary *value = _currTop.skills; //hold the data, so i can delete the tmp
_currTop = nil; //delete the last element
_count = 0;
_head = nil; //head and tail are pointing to NULL
_tail = nil;
return value;
}
NSMutableDictionary *value = _currTop.skills;
JBListNode *tmp = _tail;
JBListNode *tmp2 = tmp.previous;
JBListNode *tmp3 = _head;
tmp2.next = nil;
tmp3.previous = nil;
_tail = tmp2;
_currTop = tmp2;
tmp = nil;
_count -= 1;
return value;
}
- (NSMutableDictionary *)popNode:(NSInteger)node {
JBListNode *tmp = _head;
while (tmp.nodeID != node) {
tmp = tmp.next;
}
if (node == 1) //If count will equal 0, there is 1 element in the list
{
NSMutableDictionary *value = tmp.skills; //hold the data, so i can delete the tmp
_head = tmp.next;
_currBottom = tmp.next;
_count -= 1;
return value;
}
if (node == nodeID) {
NSMutableDictionary *value = tmp.skills;
JBListNode *tmp2 = tmp.previous;
tmp2.next = nil;
_tail = tmp2;
_currTop = tmp2;
tmp = nil;
_count -= 1;
return value;
}
NSMutableDictionary *value = tmp.skills;
JBListNode *tmp2 = tmp.previous;
JBListNode *tmp3 = tmp.next;
tmp2.next = tmp3;
tmp3.previous = tmp2;
tmp = nil;
_count -= 1;
return value;
}
- (NSMutableDictionary *)findSkillsForNode:(NSInteger)node {
JBListNode *tmp = _head;
while (tmp.nodeID != node) {
tmp = tmp.next;
}
return tmp.skills;
}
- (void)editSkillsAtNode:(NSInteger)node setValue:(id)value forKey:(NSString *)key {
JBListNode *tmp = _head;
while (tmp.nodeID != node) {
tmp = tmp.next;
}
[tmp.skills setValue:value forKey:key];
}
- (void)activateNode:(NSInteger)node {
JBListNode *tmp = _head;
while (tmp.nodeID != node) {
tmp = tmp.next;
}
tmp.activated = YES;
}
- (void)deactivateNode:(NSInteger)node {
JBListNode *tmp = _head;
while (tmp.nodeID != node) {
tmp = tmp.next;
}
tmp.activated = YES;
}
- (BOOL)isActivated:(NSInteger)node {
JBListNode *tmp = _head;
while (tmp.nodeID != node) {
tmp = tmp.next;
}
return tmp.activated;
}
- (void)setRequirements:(NSMutableDictionary *)requirements forNode:(NSInteger)node {
JBListNode *tmp = _head;
while (tmp.nodeID != node) {
tmp = tmp.next;
}
tmp.requirements = requirements;
}
- (void)editRequirementsAtNode:(NSInteger)node setValue:(id)value forKey:(NSString *)key {
JBListNode *tmp = _head;
while (tmp.nodeID != node) {
tmp = tmp.next;
}
[tmp.requirements setValue:value forKey:key];
}
- (NSMutableDictionary *)findRequirements:(NSMutableDictionary *)requirements forNode:(NSInteger)node {
JBListNode *tmp = _head;
while (tmp.nodeID != node) {
tmp = tmp.next;
}
return tmp.requirements;
}
- (NSInteger)findNodeIDForSkills:(NSMutableDictionary *)skills {
JBListNode *tmp = _head;
while (tmp.skills != skills) {
tmp = tmp.next;
}
return tmp.nodeID;
}
- (NSInteger)findNodeIDForSkills:(NSMutableDictionary *)skills andRequirements:(NSMutableDictionary *)requirements {
JBListNode *tmp = _head;
while (tmp.skills != skills || tmp.requirements != requirements) {
tmp = tmp.next;
}
return tmp.nodeID;
}
- (void)allNodes {
JBListNode* tmp = _head;
while (tmp != nil){
NSLog(@"NodeID: %d", tmp.nodeID);
NSLog(@"Skill: %@", tmp.skills);
NSLog(@"Requirements: %@", tmp.requirements);
NSLog(@"Activated: %d", tmp.activated);
tmp = tmp.next;
}
}
@end
//
// JBListNode.h
//
//
// Created by Julius Btesh on 8/28/13.
//
//
#import <Foundation/Foundation.h>
@interface JBListNode : NSObject
@property (nonatomic) JBListNode *next;
@property (nonatomic) JBListNode *previous;
@property (nonatomic) NSInteger nodeID;
@property (nonatomic) NSMutableDictionary *skills;
@property (nonatomic) NSMutableDictionary *requirements;
@property (nonatomic) BOOL activated;
@end
//
// JBListNode.m
//
//
// Created by Julius Btesh on 8/28/13.
//
//
#import "JBListNode.h"
@implementation JBListNode {
JBListNode *_next;
JBListNode *_previous;
NSInteger _nodeID;
NSMutableDictionary *_skills;
NSMutableDictionary *_requirements;
BOOL _activated;
}
- (id)init {
if (self = [super init]) {
_next = nil;
_previous = nil;
_activated = NO;
}
return self;
}
@end