iPhone あみだくじ

今日はあみだくじをiPhoneアプリで作ってみます。グリッド状に基準となる点を決めておいて、そこにランダムに線を描いていきます。


動作イメージ
XcodeからiOS6 iPhone Simulatorで動かすとこんな感じになります。

ポイント
データ構造を思いつくまま作ってしまいました。いつにも増してガリガリ描いてしまっています。(※いつか、イケテルあみだデータ構造を知りたい。)縦に6本線を引いた後、ランダムで横線を引いています。横線の中心点を保持しています。タッチすると、タイマーでマーカーが動いていく感じにして、タイマーの左右50pt以内に横棒の中心点があった場合、タイマーを一時停止して横に動かしています。

サンプルコード

#import “ViewController.h”

#import <QuartzCore/QuartzCore.h>

@interface ViewController () {

    UIView *amida;

    CGPoint point[36];

    BOOL bar[20];  // bar[0] : point[6] to point[7] …

    CGPoint barPoint[20];

    int goal;

    UIView *selected;

}

@end

@implementation ViewController

– (void)viewDidLoad

{

    [super viewDidLoad];

    self.view.backgroundColor = [self color:2];

    

    [self createGrid];

    

    [self createGoal];

    

    [self createStartButton];

}

– (void)createGrid

{

    amida = [[UIView alloc] initWithFrame:self.view.bounds];

    [self.view addSubview:amida];

    

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

        float x = 50 * (i % 6) + 35;

        float y = 70 * (i / 6) + 35;

        point[i] = CGPointMake(x, y);

    }

    

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

        if (arc4random()%3) {

            bar[i] = YES;

        } else {

            bar[i] = NO;

            barPoint[i] = CGPointZero;

        }

    }

    

    UIBezierPath *path = [UIBezierPath bezierPath];

    // vertical line

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

        [path moveToPoint:point[i]];

        [path addLineToPoint:point[i + 30]];

    }

    

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

        if (bar[i]) {

            int col = i % 5;

            int row = i / 5 + 1;

            CGPoint s = point[col + row * 6];

            CGPoint e = point[col + row * 6 + 1];

            

            // 線が一直線にならないようにずらす

            if (col % 2) {

                [path moveToPoint:s];

                [path addLineToPoint:e];

                barPoint[i] = CGPointMake((s.x + e.x) / 2.0, s.y);

            } else {

                [path moveToPoint:CGPointMake(s.x, s.y35)];

                [path addLineToPoint:CGPointMake(e.x, e.y35)];

                barPoint[i] = CGPointMake((s.x + e.x) / 2.0, s.y35);

            }

        }

    }

    

    CAShapeLayer *sl = [[CAShapeLayer alloc] init];

    sl.strokeColor = [self color:0].CGColor;

    sl.fillColor = [UIColor clearColor].CGColor;

    sl.lineWidth = 15;

    sl.path = path.CGPath;

    

    sl.shadowOpacity = 0.7;

    sl.shadowRadius = 4.0;

    sl.shadowOffset = CGSizeMake(3, 3);

    

    [amida.layer addSublayer:sl];

}

– (void)createGoal

{

    goal = arc4random() % 6;

    

    UIView *mark = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 40, 40)];

    mark.center = point[goal];

    mark.backgroundColor = [self color:1];

    mark.layer.shadowOpacity = 0.7;

    mark.layer.shadowRadius = 4.0;

    mark.layer.shadowOffset = CGSizeMake(3, 3);

    

    [amida addSubview:mark];

}

– (void)createStartButton

{

    for (int i= 30; i<36; i++) {

        UIView *mark = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 40, 40)];

        mark.center = point[i];

        mark.backgroundColor = [self color:4];

        mark.layer.cornerRadius = 20;

        mark.layer.shadowOpacity = 0.7;

        mark.layer.shadowRadius = 4.0;

        mark.layer.shadowOffset = CGSizeMake(3, 3);

        mark.tag = i;

        [amida addSubview:mark];

        

        UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(start:)];

        [mark addGestureRecognizer:tap];

    }

}

– (void)start:(UITapGestureRecognizer*)gr

{

    selected = gr.view;

    

    [NSTimer scheduledTimerWithTimeInterval:2.0/60.0 target:self selector:@selector(tick:) userInfo:nil repeats:YES];

}

– (void)tick:(NSTimer*)sender

{

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

        

        // check light

        if (CGRectContainsPoint(CGRectMake(selected.center.x, selected.center.y, 50, 1), barPoint[i])) {

            [sender invalidate];

            [UIView animateWithDuration:0.5 animations:^{

                selected.center = CGPointMake(selected.center.x + 50, selected.center.y);

            } completion:^(BOOL finished) {

                

                selected.center = CGPointMake(selected.center.x, selected.center.y2);

                // continue

                [NSTimer scheduledTimerWithTimeInterval:2.0/60.0 target:self selector:@selector(tick:) userInfo:nil repeats:YES];

            }];

            return;

        }

        

        // check left

        if (CGRectContainsPoint(CGRectMake(selected.center.x50, selected.center.y, 50, 1), barPoint[i])) {

            [sender invalidate];

            [UIView animateWithDuration:0.5 animations:^{

                selected.center = CGPointMake(selected.center.x50, selected.center.y);

            } completion:^(BOOL finished) {

                

                selected.center = CGPointMake(selected.center.x, selected.center.y2);

                // continue

                [NSTimer scheduledTimerWithTimeInterval:2.0/60.0 target:self selector:@selector(tick:) userInfo:nil repeats:YES];

            }];

            return;

        }

    }

    

    // up!!

    selected.center = CGPointMake(selected.center.x, selected.center.y1);

    

    if (selected.center.y == 10) {

        [sender invalidate];

        

        // restart

        for (UIView *v in self.view.subviews) {

            [v removeFromSuperview];

            

            [self createGrid];

            [self createGoal];

            [self createStartButton];

        }

    }

}

#define UIColorHex(rgbValue) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 green:((float)((rgbValue & 0xFF00) >> 8))/255.0 blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0]

– (UIColor*)color:(int)i

{

    switch (i) {

        case 0:

            return UIColorHex(0xF88D00);

        case 1:

            return UIColorHex(0xED4500);

        case 2:

            return UIColorHex(0xFCFBE5);

        case 3:

            return UIColorHex(0xD9224C);

        case 4:

            return UIColorHex(0xBBD400);

        default:

            break;

    }

    return nil;

}

– (void)didReceiveMemoryWarning

{

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}

@end