iPhone組合せ数3D

組合せのパターン数を3Dでなんとなく体感するiPhoneアプリのサンプルコードを描いてみます。

#import “ViewController.h”

@import SceneKit;

@import SpriteKit;

@interface ViewController () <SCNSceneRendererDelegate>

@property (nonatomic, weak) SCNView *sceneView;

@property (nonatomic) NSTimeInterval start;

@property (nonatomic) int count;

@end

@implementation ViewController

– (void)viewDidLoad {

    [super viewDidLoad];

    [self setupScene];

    [self createBoard];

    [self createConsole];

    [self createCamera];

}

– (void)setupScene {

    SCNView *sv = [[SCNView alloc] initWithFrame:self.view.bounds];

    sv.backgroundColor = [self color:0];

    sv.scene = [SCNScene scene];

    sv.delegate = self;

    [self.view addSubview:sv];

    

    self.sceneView = sv;

}

– (void)createBoard {

    SCNBox *box = [SCNBox boxWithWidth:20 height:1 length:20 chamferRadius:0];

    box.firstMaterial.diffuse.contents = [self color:1];

    SCNNode *boxNode = [SCNNode nodeWithGeometry:box];

    boxNode.physicsBody = [SCNPhysicsBody staticBody];

    [self.sceneView.scene.rootNode addChildNode:boxNode];

    

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

        SCNBox *line = [SCNBox boxWithWidth:20 height:0.1 length:0.1 chamferRadius:0];

        line.firstMaterial.diffuse.contents = [self color:2];

        SCNNode *lineNode = [SCNNode nodeWithGeometry:line];

        float a = (i % 11) * 210;

        if ((i / 11) > 0) {

            lineNode.position = SCNVector3Make(a, 0.6, 0);

            lineNode.rotation = SCNVector4Make(0, 1, 0, M_PI * 0.5);

        } else {

            lineNode.position = SCNVector3Make(0, 0.6, a);

        }

        

        [self.sceneView.scene.rootNode addChildNode:lineNode];

    }

}

– (void)createConsole {

    self.sceneView.overlaySKScene = [SKScene sceneWithSize:self.view.bounds.size];

    

    SKSpriteNode *console = [SKSpriteNode spriteNodeWithColor:[[self color:3] colorWithAlphaComponent:0.3] size:CGSizeMake(100, 100)];

    console.position = CGPointMake(CGRectGetMidX(self.view.bounds), CGRectGetMaxY(self.view.bounds) – 80);

    [self.sceneView.overlaySKScene addChild:console];

    

    NSArray *words = @[@”(“, @”n”, @”m”, @”)”];

    CGPoint pts[] = {CGPointMake(-30, 0), CGPointMake(0, 20), CGPointMake(0, –20), CGPointMake(30, 0)};

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

        SKLabelNode *l = [SKLabelNode labelNodeWithText:words[i]];

        l.position = pts[i];

        [console addChild:l];

    }

}

– (void)createCamera {

    SCNNode *camera = [SCNNode node];

    camera.camera = [SCNCamera camera];

    camera.position = SCNVector3Make(0, 15, 30);

    camera.rotation = SCNVector4Make(1, 0, 0, –0.3);

    [self.sceneView.scene.rootNode addChildNode:camera];

}

– (void)renderer:(id<SCNSceneRenderer>)aRenderer updateAtTime:(NSTimeInterval)time

{

    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{

        self.start = time;

    });

    

    if (time – self.start > 0.4 && self.count < 10) {

        self.start = time;

        [self createBallAt:self.count m:0];

        self.count++;

    }

}

– (void)createBallAt:(int)n m:(int)m{

    int c = 0;

    if (m <= n && m != 0) {

            // combination (n, m)

        c =(^{

            int result = 1;

            for(int i=n; i>n-m; i–) result *= i;

            return result;}())

        /

        (^{

            int result = 1;

            for(int i=m; i>0; i–) result *= i;

            return result;}());

    }

    

    NSLog(@”n:%d m:%d c:%d”, n, m ,c);

    

    float x = n * 29.0;

    float z = m * 29.0;

    

    

    SCNSphere *sphere = [SCNSphere sphereWithRadius:0.2];

    sphere.firstMaterial.diffuse.contents = (c==0) ?  [UIColor blackColor] : [self color:4];

    SCNNode *sphereNode = [SCNNode nodeWithGeometry:sphere];

    sphereNode.position = SCNVector3Make(x, 20, z);

    sphereNode.physicsBody = [SCNPhysicsBody dynamicBody];

    sphereNode.physicsBody.velocityFactor = SCNVector3Make(0, 1, 0);

    sphereNode.physicsBody.angularVelocityFactor = SCNVector3Zero;

    [self.sceneView.scene.rootNode addChildNode:sphereNode];

    

    for (int i=1; i<c; i++) {

        SCNSphere *sphere = [SCNSphere sphereWithRadius:0.2];

        sphere.firstMaterial.diffuse.contents = [self color:4];

        SCNNode *sphereNode = [SCNNode nodeWithGeometry:sphere];

        sphereNode.position = SCNVector3Make(x, 20 + i * 20, z);

        sphereNode.physicsBody = [SCNPhysicsBody dynamicBody];

        sphereNode.physicsBody.velocityFactor = SCNVector3Make(0, 1, 0);

        sphereNode.physicsBody.angularVelocityFactor = SCNVector3Zero;

        [self.sceneView.scene.rootNode addChildNode:sphereNode];

    }

    

    if (m<9) {

        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.05 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

            [self createBallAt:n m:m+1];

        });

    }

    

}

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

{

    [self createBallAt:self.count m:0];

    self.count++;

}

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

– (UIColor *)color:(int)i {

    if (i>4) return nil;

    int colorCodes[] = {0xBFAAAA, 0x9086A6, 0xF2F2E9, 0xF2EFBB, 0x735D36};

    return ColorHex(colorCodes[i]);

}

@end