右と左に長さの違うしかくが出てくるよ。どっちの方が長いかな?長い四角の上にあるマークと、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