iPhoneバブルソート

今日は、バブルソートをアニメーションさせるようなiPhoneアプリのサンプルコードを描いてみます。

動かすとこんな感じです

サンプルコード

#import “ViewController.h”

@interface MyBubble : NSObject

@property (nonatomic, strong) NSMutableArray *arr;

@property (nonatomic, strong) NSString *changeMessage;

@end

@implementation MyBubble

– (id)init

{

    self = [super init];

    if (self) {

        self.arr = [NSMutableArray array];

        for (int i=0; i<20; i++) {

            [self.arr addObject:@(arc4random() % 10)];

        }

    }

    return self;

}

– (int)intValueAtIndex:(NSUInteger)idx

{

    return [self.arr[idx] intValue];

}

– (void)exchangeObjectAtIndex:(NSUInteger)idx1 withObjectAtIndex:(NSUInteger)idx2

{

    [self.arr exchangeObjectAtIndex:idx1 withObjectAtIndex:idx2];

    self.changeMessage = [NSString stringWithFormat:@”%d,%d”, idx1 + 1, idx2 + 1];

}

@end

@interface ViewController ()

@property (nonatomic, strong) MyBubble *myBubble;

@property (nonatomic, strong) NSMutableArray *animationQueue;

@end

@implementation ViewController

– (void)viewDidLoad

{

    [super viewDidLoad];

    

    [self addObserver:self forKeyPath:@”myBubble.changeMessage” options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:NULL];

    

    self.myBubble = [[MyBubble alloc] init];

    self.view.backgroundColor = [UIColor colorWithRed:0.0 green:0.5 blue:0.1 alpha:1.0];

    

    for (int i=0; i<self.myBubble.arr.count; i++) {

        float x = CGRectGetMaxX(self.view.frame) – (i / 5) * 6060;

        float y = (i % 5) * 40 + 80;

        UILabel *bubble = [[UILabel alloc] initWithFrame:CGRectMake(x, y, 30, 30)];

        bubble.tag = i + 1;

        bubble.layer.cornerRadius = 15;

        bubble.layer.borderWidth = 2;

        bubble.layer.borderColor = [UIColor whiteColor].CGColor;

        bubble.font = [UIFont fontWithName:@”ChalkboardSE-Light” size:20];

        bubble.text = [@([self.myBubble intValueAtIndex:i]) stringValue];

        bubble.textAlignment = NSTextAlignmentCenter;

        bubble.textColor = [UIColor whiteColor];

        [self.view addSubview:bubble];

    }

}

– (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

{

    [self bubbleSort:self.myBubble];

}

– (void)bubbleSort:(MyBubble *)bubble

{

    for (int i=0; i<bubble.arr.count; i++) {

        for (int j=bubble.arr.count1; j>i; j–) {

            if ([bubble intValueAtIndex:j] < [bubble intValueAtIndex:j-1]) {

                [bubble exchangeObjectAtIndex:j withObjectAtIndex:j-1];

            }

        }

    }

    

    [self startBubbleAnimation];

}

– (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context

{

    if ([keyPath isEqualToString:@”myBubble.changeMessage”]) {

        id new = change[@”new”];

        if (new != (id)[NSNull null]) {

            NSArray *idx = [new componentsSeparatedByString:@”,”];

            if (!self.animationQueue) {

                self.animationQueue = [NSMutableArray array];

            }

            [self.animationQueue addObject:idx];

        }

    }

}

– (void)startBubbleAnimation

{

    [self swapPosition];

}

– (void)swapPosition

{

    NSArray *idx = self.animationQueue[0];

    [self.animationQueue removeObjectAtIndex:0];

    

    UIView *v0 = [self.view viewWithTag:[idx[0] intValue]];

    UIView *v1 = [self.view viewWithTag:[idx[1] intValue]];

    v0.tag = v1.tag;

    v1.tag = [idx[0] intValue];

    

    CGPoint newP0 = v1.center;

    [UIView animateWithDuration:0.2 animations:^{

        v1.center = v0.center;

        v0.center = newP0;

    } completion:^(BOOL finished) {

        if (self.animationQueue.count) {

            [self swapPosition];

        }

    }];

}

@end