LoginSignup
24
22

More than 5 years have passed since last update.

リバーシ Swiftバージョン

Last updated at Posted at 2014-12-23

はじめに

演習でお馴染みのリバーシをCからSwiftに書き換えてiPhoneアプリとして動かしてみます。
Xcodeを起動して「Single View Application」としてプロジェクトを作成します。

スライド1.jpg

初期化

ViewController.swiftにコードを足していきます。
ラベルとターン(白黒)と盤面上の石の配置を再代入可能なvarで宣言します。
白い石が1、黒い石が-1、石を配置していないときは0とします。

var label:UILabel?
var turn = 1
var stage:[[Int]] = [
    [0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 1, -1, 0, 0, 0],
    [0, 0, 0, -1, 1, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0]
]

盤面は8×8ですが、上部にラベルを配置するためにスクリーンの高さを9等分します。
ボタンを作成してviewに追加していきます。
ボタンを識別するためにtagを利用します。
tagにはNSIntegerのみ代入可能なためループカウンタのiとjを使ってユニークな数値を作成するようにしています。このユニークな数値を利用して、どのボタンが押下されたか判定しstageの添字としてアクセスします。

ラベルを作成してviewに追加します。このラベルに白黒のどちらのターン、それぞれの点数を表示します。

最後にself.update()を呼び出してボタンのタイトルを書き換えます。

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    let (screenWidth, screenHeight) = (self.view.bounds.width, self.view.bounds.height)
    let (width, height) = (screenWidth/8, screenHeight/9)

    for(var i = 0; i < 8; i++) {
        for(var j = 0; j < 8; j++) {
            let button = UIButton(frame: CGRectMake(width * CGFloat(i), height * CGFloat(j+1), width, height))
            button.setTitle(" ", forState: .Normal)
            button.setTitleColor(UIColor.blackColor(), forState: .Normal)
            button.setTitleColor(UIColor.lightGrayColor(), forState: .Highlighted)
            button.layer.borderColor = UIColor.blackColor().CGColor
            button.layer.borderWidth = 0.5
            button.tag = i * 10 + j
            button.addTarget(self, action: Selector("button:"), forControlEvents: .TouchUpInside)
            self.view.addSubview(button)
        }
    }

    self.label = UILabel(frame: CGRectMake(0, 0, screenWidth, height))
    self.view.addSubview(self.label!)

    self.update()
}

更新

この関数では、ボタンのタイトルの書き換えと点数を計算して表示します。
self.view.subviewsからviewを取り出し、それがUIButtonなのか判定します。
ボタンのtagから配列の添字に変換します。
例えば、tagが4のときは[0][4]、tagが23のときは[2][3]になります。

func update() {
    var (white, black) = (0, 0)
    for view in self.view.subviews {
        if let button = view as? UIButton {
            let (x, y) = (Int(button.tag/10), Int(button.tag%10))
            var title = " "
            switch(self.stage[x][y]) {
            case 1:
                title = "○"
                white++
            case -1:
                title = "●"
                black++
            default:
                break
            }
            button.setTitle(title, forState: .Normal)
        }
    }

    self.label?.text = NSString(format: "%@\t○ %d\t● %d", (self.turn == 1) ? "○" : "●", white, black)
}

ボタンの押下

そのままCからSwiftに書き換えて、ボタンを押下したときの処理を足していきます。
ボタンのtagから配列の添字に変換します。
変数を参照で渡すときは&をつけます。

func button(sender: AnyObject) {
    let button = sender as UIButton
    let (x, y) = (Int(button.tag/10), Int(button.tag%10))

    var count = 0
    if(self.stage[x][y] == 0) {
        self.stage[x][y] = self.turn

        for(var i = -1; i < 2; i++) {
            for(var j = -1; j < 2; j++) {
                self.reverse(x+i, y: y+j, i: i, j: j, count: &count)
            }
        }
        if(count == 0) {
            self.stage[x][y] = 0
        }else {
            self.stage[x][y] = turn
            self.turn *= -1
        }
    }

    self.update()
}

リバース

この関数もCからそのままSwiftに書き換えます。
inoutを引数の前に指定すると参照渡しになります。

func reverse(x:Int, y:Int, i:Int, j:Int, inout count:Int) -> Int {
    if(x < 0 || x >= 8 || y < 0 || y >= 8) {
        return 0
    }else if(self.stage[x][y] == 0) {
        return 0
    }else if(self.stage[x][y] == turn) {
        return turn
    }else if(self.reverse(x + i, y:y + j, i:i, j:j, count: &count) == turn) {
        self.stage[x][y] *= -1
        count++
        return turn
    }else {
        return 0
    }
}

最終的なコード

最終的に以下のコードになります。

ViewController.swift
import UIKit

class ViewController: UIViewController {
    var label:UILabel?
    var turn = 1
    var stage:[[Int]] = [
        [0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 1, -1, 0, 0, 0],
        [0, 0, 0, -1, 1, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0]
    ]

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        let (screenWidth, screenHeight) = (self.view.bounds.width, self.view.bounds.height)
        let (width, height) = (screenWidth/8, screenHeight/9)

        for(var i = 0; i < 8; i++) {
            for(var j = 0; j < 8; j++) {
                let button = UIButton(frame: CGRectMake(width * CGFloat(i), height * CGFloat(j+1), width, height))
                button.setTitle(" ", forState: .Normal)
                button.setTitleColor(UIColor.blackColor(), forState: .Normal)
                button.setTitleColor(UIColor.lightGrayColor(), forState: .Highlighted)
                button.layer.borderColor = UIColor.blackColor().CGColor
                button.layer.borderWidth = 0.5
                button.tag = i * 10 + j
                button.addTarget(self, action: Selector("button:"), forControlEvents: .TouchUpInside)
                self.view.addSubview(button)
            }
        }

        self.label = UILabel(frame: CGRectMake(0, 0, screenWidth, height))
        self.view.addSubview(self.label!)

        self.update()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func update() {
        var (white, black) = (0, 0)
        for view in self.view.subviews {
            if let button = view as? UIButton {
                let (x, y) = (Int(button.tag/10), Int(button.tag%10))
                var title = " "
                switch(self.stage[x][y]) {
                case 1:
                    title = "○"
                    white++
                case -1:
                    title = "●"
                    black++
                default:
                    break
                }
                button.setTitle(title, forState: .Normal)
            }
        }

        self.label?.text = NSString(format: "%@\t○ %d\t● %d", (self.turn == 1) ? "○" : "●", white, black)
    }

    func button(sender: AnyObject) {
        let button = sender as UIButton
        let (x, y) = (Int(button.tag/10), Int(button.tag%10))

        var count = 0
        if(self.stage[x][y] == 0) {
            self.stage[x][y] = self.turn

            for(var i = -1; i < 2; i++) {
                for(var j = -1; j < 2; j++) {
                    self.reverse(x+i, y: y+j, i: i, j: j, count: &count)
                }
            }
            if(count == 0) {
                self.stage[x][y] = 0
            }else {
                self.stage[x][y] = turn
                self.turn *= -1
            }
        }

        self.update()
    }

    func reverse(x:Int, y:Int, i:Int, j:Int, inout count:Int) -> Int {
        if(x < 0 || x >= 8 || y < 0 || y >= 8) {
            return 0
        }else if(self.stage[x][y] == 0) {
            return 0
        }else if(self.stage[x][y] == turn) {
            return turn
        }else if(self.reverse(x + i, y:y + j, i:i, j:j, count: &count) == turn) {
            self.stage[x][y] *= -1
            count++
            return turn
        }else {
            return 0
        }
    }
}

実行

実行します。完成です。

スライド2.jpg

24
22
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
22