4x4の魔方陣を自動生成するアプリを作ってみた。

(XcodeのiOS6 Simulatorで試しています。)

ポイント

・マトリクス4×4はGLKitを利用

・A ~ Eまでの6種類のマトリクスを以下の式で計算

・問題を作る式は:「8 * matrixX + 4 * matrixX + 2 * matrixX + matrixX」

サンプルコード

#import “ViewController.h”

#import <GLKit/GLKit.h>

#import <QuartzCore/QuartzCore.h>

@interface ViewController () {

    GLKMatrix4 mAll;

    GLKMatrix4 matA;

    GLKMatrix4 matB;

    GLKMatrix4 matC;

    GLKMatrix4 matD;

    GLKMatrix4 matE;

    GLKMatrix4 question;

    GLKMatrix4 answer;

    

    UILabel *selectedAnswer;

}

@end

@implementation ViewController

– (void)viewDidLoad

{

    [super viewDidLoad];

}

– (void)viewDidAppear:(BOOL)animated

{

    [self initMatrix];

    

    [self createQuestion];

    

    [self showQuestion];

    

    [self initAnswers];

    

    [self retryBtn];

}

– (void)initMatrix

{

    

    // 4×4 matrixの種となるマトリクスを6個, 用意

    

    mAll = GLKMatrix4Make(1, 1, 1, 1,

                          1, 1, 1, 1,

                          1, 1, 1, 1,

                          1, 1, 1, 1);

    

    matA = GLKMatrix4Make(1, 1, 0, 0,

                          0, 0, 1, 1,

                          1, 1, 0, 0,

                          0, 0, 1, 1);

    

    matB = GLKMatrix4Make(1, 0, 1, 0,

                          0, 1, 0, 1,

                          0, 1, 0, 1,

                          1, 0, 1, 0);

    

    matC = GLKMatrix4Make(1, 1, 0, 0,

                          0, 0, 1, 1,

                          0, 0, 1, 1,

                          1, 1, 0, 0);

    

    matD = GLKMatrix4Make(1, 1, 0, 0,

                          1, 0, 1, 0,

                          0, 1, 0, 1,

                          0, 0, 1, 1);

    

    matE = GLKMatrix4Make(0, 1, 0, 1,

                          1, 1, 0, 0,

                          0, 0, 1, 1,

                          1, 0, 1, 0);

}

– (void)createQuestion

{

    // 1 ~ 16 で構成された魔方陣にする

    GLKMatrix4 result = mAll;

    

    // 次の式で作る(2進数4桁にはめる)

    // 8 * matrixX + 4 * matrixX + 2 * matrixX + matrixX

    GLKMatrix4 matArr[] = {matA, matB, matC, matD, matE};

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

        int random = arc4random() % (sizeof(matArr) / sizeof(GLKMatrix4));

        GLKMatrix4 choice = [self multipltiply:pow(2, i) matrix:matArr[random]];

        result = GLKMatrix4Add(result, choice);

    }

    question = result;

}

– (GLKMatrix4)multipltiply:(int)coefficient matrix:(GLKMatrix4)mat

{

    for (int a=0; a<16; a++) {

        mat.m[a] = coefficient * mat.m[a];

    }

    return mat;

}

#define NumberView 10

– (void)showQuestion

{

    // 前のラベルを消す

    for (int i=0; i<[self.view.subviews count]; i++) {

        UIView *v = [self.view.subviews objectAtIndex:i];

        if (v.tag == NumberView) {

            v.layer.zPosition = 100 – i;

            [UIView animateWithDuration:0.3 delay:i * 0.05 options:UIViewAnimationOptionCurveEaseIn animations:^{

                v.center = CGPointMake(160, 800);

            } completion:^(BOOL finished) {

                [v removeFromSuperview];

            }];

        }

    }

    

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

        float size = 60.0;

        float x = (i % 4) * size + 70;

        float y = (i / 4) * size + 100;

        

        UILabel *number = [[UILabel alloc] init];

        number.font = [UIFont systemFontOfSize:50];

        number.text = [NSString stringWithFormat:@”%d”, (int)question.m[i]];

        number.textAlignment = 1; // center

        number.bounds = CGRectMake(0,0,size,size);

        number.center = CGPointMake(x, y);

        number.layer.borderWidth = 2.0;

        number.layer.borderColor = [UIColor lightGrayColor].CGColor;

        number.tag = NumberView;

        

        int blank = arc4random() % 3;

        if (blank == 0) {

            number.text = @”?”;

            number.textColor = [UIColor darkGrayColor];

            number.backgroundColor = [UIColor yellowColor];

        }

        [self.view addSubview:number];

    }

}

– (void)retryBtn

{

    // リトライ用のボタンを用意

    UIView *retry = [[UIView alloc] initWithFrame:CGRectMake(280, 10, 30, 30)];

    retry.backgroundColor = [UIColor greenColor];

    retry.layer.cornerRadius = 15.0;

    retry.layer.borderColor = [UIColor lightGrayColor].CGColor;

    retry.layer.borderWidth = 3.0;

    [self.view addSubview:retry];

    

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

    [retry addGestureRecognizer:tap];

}

– (void)initAnswers

{

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

        float size = 35;

        float x = size * (i / 2) + 40;

        float y = size * (i % 2) + 350;

        UILabel *ans = [[UILabel alloc] init];

        ans.backgroundColor = [UIColor clearColor];

        ans.text = [NSString stringWithFormat:@”%d”, i+1];

        ans.frame = CGRectMake(0, 0, size, size);

        ans.center = CGPointMake(x,y);

        ans.backgroundColor = [UIColor yellowColor];

        ans.textAlignment = 1; //center

        ans.layer.cornerRadius = 5.0;

        ans.layer.borderWidth = 4.0;

        ans.layer.borderColor = [UIColor darkGrayColor].CGColor;

        

        ans.userInteractionEnabled = YES;

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

        [ans addGestureRecognizer:pan];

        

        [self.view addSubview:ans];

    }

}

– (void)move:(UIPanGestureRecognizer*)gr

{

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

    

    if (gr.state == UIGestureRecognizerStateBegan) {

        UILabel *label = [[UILabel alloc] init];

        label.text = ((UILabel*)gr.view).text;

        label.textAlignment = 1;

        label.font = [UIFont boldSystemFontOfSize:30];

        label.bounds = CGRectMake(0,0,50,50);

        label.layer.cornerRadius = 10.0;

        label.layer.borderColor = [UIColor yellowColor].CGColor;

        label.layer.borderWidth = 4.0;

        label.alpha = 0.9;

        label.tag = NumberView;

        [self.view addSubview:label];

        label.userInteractionEnabled = YES;

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

        [label addGestureRecognizer:tap];

        selectedAnswer = label;

    }

    selectedAnswer.center = p;

}

– (void)removeTappedPanel:(UIGestureRecognizer*)gr

{

    [UIView animateWithDuration:0.3 animations:^{

        gr.view.center = CGPointMake(160, 800);

    }];

}

– (void)retry

{

    [self createQuestion];

    

    [self showQuestion];

}

– (void)didReceiveMemoryWarning

{

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}

@end