リバーシ Swiftバージョン

# はじめに

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

![スライド1.jpg](https://qiita-image-store.s3.amazonaws.com/0/3862/2f097c2f-540b-a885-3900-e00581c23aac.jpeg)

# 初期化

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
		}
	}

# 最終的なコード

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

```swift: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](https://qiita-image-store.s3.amazonaws.com/0/3862/23ba9711-c7b0-11b9-246d-410f7cd56659.jpeg)