はじめに
演習でお馴染みのリバーシをCからSwiftに書き換えてiPhoneアプリとして動かしてみます。
Xcodeを起動して「Single View Application」としてプロジェクトを作成します。
初期化
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
}
}
最終的なコード
最終的に以下のコードになります。
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
}
}
}
実行
実行します。完成です。