iPhoneアプリ長さ比べ

右と左に長さの違うしかくが出てくるよ。どっちの方が長いかな?長い四角の上にあるマークと、Longと書いてある方のマークを線でつなげてみよう。短い方と、Shortと書いてあるマークをつなげてもいいよ。という感じの、長さの比較アプリをサンプルとして書きました。

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


ポイント
画面上段の丸にLong, Shortとラベルをつけておいて、画面中央の丸はその下に、長さの違う四角を表示しています。長さは、100, 80, 60, 20からランダムで取得しています。正しく、丸を線で繋げられたら次の問題を表示するようにしました。違うところに線を引いた場合は、NSTimerでCAShapeLayerのstrokeEndの値を減らしていくことで、ビヨンと書いた線が戻るようなアニメーションにしています。丸と丸が正解か?という比較は、ゴリゴリ書いてしまいました。もっとさっぱり2行くらいで書きたいと思いつつ。

サンプルコード

#import “ViewController.h”

#import <QuartzCore/QuartzCore.h>

typedef enum {

    None,

    LongMark,

    ShortMark,

    LeftMark,

    RightMark,

} MarkType;;

@interface ViewController () {

    CAShapeLayer *sl;

    int shortObjectTag;

}

@end

@implementation ViewController

– (void)viewDidLoad

{

    [super viewDidLoad];

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

    

    [self createLongAndShortObjects];

    

    [self createMarks];

}

– (void)createLongAndShortObjects

{

    NSMutableArray *lengthArr = [@[@100, @80, @60, @20] mutableCopy];

    NSArray *colors = @[[UIColor orangeColor], [UIColor redColor], [UIColor greenColor]];

    

    UIColor *color = [colors objectAtIndex:arc4random() % 3];

    

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

        float x = i * 160 + 20;

        UIView *v = [[UIView alloc] initWithFrame:CGRectMake(x, 320, 120, 160)];

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

        v.layer.borderWidth = 3;

        [self.view addSubview:v];

        

        int random = arc4random() % [lengthArr count];

        NSNumber *choice = [lengthArr objectAtIndex:random];

        [lengthArr removeObject:choice];

        

        UIView *object = [[UIView alloc] initWithFrame:CGRectMake(40, 160 – [choice intValue], 40, [choice intValue])];

        object.backgroundColor = color;

        [v addSubview:object];

        

        // 10:left, 11:right

        v.tag = 10 + i;

    }

}

– (void)createMarks

{

    UILabel *longLabel = [self myLabel];

    longLabel.text = @”LONG”;

    longLabel.center = CGPointMake(90, 50);

    [self.view addSubview:longLabel];

    

    UILabel *shortLabel = [self myLabel];

    shortLabel.textAlignment = 2;

    shortLabel.text = @”SHORT”;

    shortLabel.center = CGPointMake(230, 50);

    [self.view addSubview:shortLabel];

    

    CGPoint points[] = {CGPointMake(80, 90), CGPointMake(240, 90), CGPointMake(80, 280), CGPointMake(240, 280)};

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

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

        mark.backgroundColor = self.view.backgroundColor;

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

        mark.layer.borderWidth = 3;

        mark.center = points[i];

        mark.layer.cornerRadius = 20;

        [self.view addSubview:mark];

        

        mark.tag = i + 1;

        

        UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(line:)];

        [mark addGestureRecognizer:pan];

    }

}

– (UILabel*)myLabel

{

    UILabel *l = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 30)];

    l.font = [UIFont boldSystemFontOfSize:25];

    l.textColor = [UIColor whiteColor];

    l.backgroundColor = self.view.backgroundColor;

    return l;

}

– (void)line:(UIPanGestureRecognizer*)gr

{

    CGPoint p = [gr locationInView:self.view];

 

    if (gr.state == UIGestureRecognizerStateBegan)

    {

        [sl removeFromSuperlayer];

        sl = [[CAShapeLayer alloc] initWithLayer:self.view.layer];

        sl.fillColor = [UIColor clearColor].CGColor;

        sl.strokeColor = [UIColor whiteColor].CGColor;

        sl.lineWidth = 10;

        [self.view.layer addSublayer:sl];

    } else if (gr.state == UIGestureRecognizerStateEnded) {

        // check

        UIView *v = [self.view hitTest:p withEvent:nil];

        if (v.tag > 0 && v.tag < 5) {

            [self checkA:gr.view B:v];

        } else {

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

        }

    }

    UIBezierPath *path = [UIBezierPath bezierPath];

    [path moveToPoint:gr.view.center];

    [path addLineToPoint:p];

    sl.path = path.CGPath;

}

– (void)checkA:(UIView*)a B:(UIView*)b

{

    // check answer. short and long

    BOOL check1 = (a.tag == LongMark) && (b.tag == LeftMark || b.tag == RightMark) && ![self isShort:b];

    BOOL check2 = (a.tag == ShortMark) && (b.tag == LeftMark || b.tag == RightMark)  && [self isShort:b];

    BOOL check3 = (a.tag == LeftMark) && [self isShort:a] && b.tag == ShortMark;

    BOOL check4 = (a.tag == RightMark) && [self isShort:a] && b.tag == ShortMark;

    BOOL check5 = (a.tag == LeftMark) && ![self isShort:a] && b.tag == LongMark;

    BOOL check6 = (a.tag == RightMark) && ![self isShort:a] && b.tag == LongMark;

    if (check1 || check2 || check3 || check4 || check5 || check6){

        [self next];

        

    } else {

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

    }

}

– (BOOL)isShort:(UIView*)v

{

    // left object

    UIView *left = [[self.view viewWithTag:10].subviews objectAtIndex:0];

    // right object

    UIView *right = [[self.view viewWithTag:11].subviews objectAtIndex:0];

    

    if (v.tag == LeftMark) {

        return left.bounds.size.height < right.bounds.size.height;

    } else {

        return left.bounds.size.height > right.bounds.size.height;

    }

}

– (void)revercePath:(NSTimer*)sender

{

    sl.strokeEnd -= 0.2;

    if (sl.strokeEnd < 0) {

        [sender invalidate];

    }

}

– (void)next

{

    [[self.view viewWithTag:10] removeFromSuperview];

    [[self.view viewWithTag:11] removeFromSuperview];

    [sl removeFromSuperlayer];

    

    [self createLongAndShortObjects];

}

– (void)didReceiveMemoryWarning

{

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}

@end