質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.48%

  • Swift

    7460questions

    Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

  • iOS

    4081questions

    iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

オセロ 

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 1,022

tamago0224

score 53

ブログを見ながらswiftでオセロを作ったのですが、うまく動作しませんでした。
詳しい内容としては初期状態から黒の石を打つとうった場所に黒石が表示されなかったり、裏返されるべき石が裏返されなかったりといったことです。
文法的エラーは見当たらないのですが、わかる方はいませんか?
import UIKit




let EMPTY = 0, WHITE_STONE = 2, BLACK_STONE = 1;




let initboard = [//オセロボード上の初期状態

    [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,0,0,0],

    [0,0,0,0,0,0,0,0,0,0],

    [0,0,0,0,2,1,0,0,0,0],

    [0,0,0,0,1,2,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,0,0,0,0,0,0,0],

    [0,0,0,0,0,0,0,0,0,0]

]




class OthelloView: UIView {

    

    let white = UIColor.whiteColor().CGColor

    let black = UIColor.blackColor().CGColor

    let green = UIColor(red: 0.6,green: 1.0,blue: 0.2, alpha: 1.0).CGColor

    var side: CGFloat = 0.0

    var top: CGFloat = 0.0

    var left: CGFloat = 0

    

    override func drawRect(rect: CGRect){//描写時に呼び出されるメソッド

        let context = UIGraphicsGetCurrentContext()

        //各マスの枠線は白で太さ1.5ピクセル

        CGContextSetStrokeColorWithColor(context,white)

        CGContextSetLineWidth(context,1.5)

        

        for y in 1...8 {

            for x in 1...8 {

                //マスの位置からマスのrect領域を計算

                let rx = left + side * CGFloat(x-1)

                let ry = top + side * CGFloat(y-1)

                let rect = CGRectMake(rx, ry, side, side)

                //まずは盤面を書くので塗りつぶし線を緑に決定

                CGContextSetFillColorWithColor(context, green)

                //塗りつぶし線、枠線を描写

                CGContextFillRect(context,rect)

                CGContextStrokeRect(context,rect)

                

                if board[y][x] == BLACK_STONE {

                    //黒石が置いてあれば塗りつぶし色を黒にして円を描く

                    CGContextSetFillColorWithColor(context,black)

                    CGContextFillEllipseInRect(context,rect)

                } else if board[y][x] == WHITE_STONE {

                    //白石が置いてあれば塗りつぶし色にして円を描く

                    CGContextSetFillColorWithColor(context,white)

                    CGContextFillEllipseInRect(context,rect)

                }

            }

        }

    }

    

    override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {

        //まずはプレイヤーが黒石を置けるかどうかを調べる

        if let canBlack = canPlaced(board, stone: BLACK_STONE) {

            //選択したマスの座標を取り出す

            if let (x,y) = getPos(touches) {

                //ひっくりかえせるか調べる

                if let blackPlaces = flip(board,x: x,y: y,stone: BLACK_STONE) {

                    //ひっくり返す

                    putStone(blackPlaces,stone: BLACK_STONE)

                    //CPUのターンを進める

                    if let whitePlaces = cpuFlip(board, stone: WHITE_STONE) {

                        //ひっくり返す

                        putStone(whitePlaces,stone: WHITE_STONE)

                    }

                }

            }

            

        } else {

        //プレイヤーが石を置けないのでスキップしてCPUのターンを進める

            if let whitePlaces = cpuFlip(board,stone: WHITE_STONE) {

                putStone(whitePlaces,stone: WHITE_STONE)

            }

        }

        upDateGames()//ゲームの勝敗を表示

        setNeedsDisplay()

    }

    

    func upDateGames() {

        let (free,black,white) = calcStones(board)

        let canBlack = canPlaced(board,stone: BLACK_STONE)

        let canWhite = canPlaced(board, stone: WHITE_STONE)

        if free == 0 || (canBlack == nil && canWhite == nil) {

            //開きますがない、または黒も白も置けない場合はゲーム終了

            println("Game Over (Black: \(black) White: \(white)")

        }

    }

    

    func getPos(touches: NSSet!) -> (Int,Int)? {

        let touch = touches.anyObject() as UITouch

        let point = touch.locationInView(self)

        

        for y in 1...8 {

            for x in 1...8 {

                let rx = left + side * CGFloat(x-1)

                let ry = top + side * CGFloat(y-1)

                let rect = CGRectMake(rx,ry,side,side)

                

                if CGRectContainsPoint(rect, point) {

                    return (x,y)

                }

            }

        }

        

        return nil

    }

    

    var board: [[Int]]

    required init(coder aDecoder: NSCoder) {

        let appFrame = UIScreen.mainScreen().applicationFrame

        side = appFrame.size.width / 8

        top = (appFrame.size.height - (side * 8)) / 2

        board = initboard

        super.init(coder: aDecoder)

    }

    

    func flipLine(board: [[Int]], x: Int, y: Int, stone: Int, dx: Int, dy: Int) -> [(Int,Int)] {

        

        var flipLoop: (Int,Int) -> [(Int,Int)]? = {_ in nil}//ダミー関数オブジェクト

        

        flipLoop = { (x: Int, y: Int) -> [(Int,Int)]? in

            if board[y][x] == EMPTY {

                return nil

            } else if board[y][x] == stone {

                return [] //再起の果てに自分の意思を発見

            } else if var result = flipLoop(x+dx, y+dy) { //resultにはひっくり返す石の座標が入っている

                result += [(x,y)]//nilでなければ相手の石を配列にして返す

                return result

            }

            return nil

        }

        

        if let result = flipLoop(x + dx, y + dy) {

            return result

        }

        return []//ひっくり返す必要のない場合ならから配列を返す。flipLineにはnilの戻り値はいらない

    }

    

    func flip(board: [[Int]], x: Int, y: Int, stone: Int) -> [(Int,Int)]? {

        if board[y][x] != EMPTY {return nil}

        

        var result: [(Int,Int)] = []

        

        result += flipLine(board,x: x,y: y,stone: stone,dx: 1,dy: 0)

        result += flipLine(board,x: x,y: y,stone: stone,dx: -1,dy: 0)

        result += flipLine(board,x: x,y: y,stone: stone,dx: 0,dy: 1)

        result += flipLine(board,x: x,y: y,stone: stone,dx: 0,dy: -1)

        result += flipLine(board,x: x,y: y,stone: stone,dx: 1,dy: 1)

        result += flipLine(board,x: x,y: y,stone: stone,dx: -1,dy: -1)

        result += flipLine(board,x: x,y: y,stone: stone,dx: 1,dy: -1)

        result += flipLine(board,x: x,y: y,stone: stone,dx: -1,dy: 1)

        

        if result.count > 0 {

            return result

        } else {

            return nil

        }

    }

    

    func canPlaced(board: [[Int]], stone: Int) -> [(Int,Int)]? {

        var result: [(Int,Int)] = []

        

        for y in 1...8 {

            for x in 1...8 {

                if let temp = flip(board,x: x,y: y,stone: stone) {

                    result += [(x,y)]

                }

            }

        }

        

        if result.isEmpty {

            return nil

        } else {

            return result

        }

        

    }

    

    func cpuFlip(board: [[Int]], stone: Int) -> [(Int,Int)]? {

        if let places = canPlaced(board, stone: stone) {

            let (x,y) = places[ Int(arc4random()) % places.count]

            return flip(board,x: x,y: y,stone: stone)

        }

        return nil

    }

    

    func calcStones(board: [[Int]]) -> (free: Int, black: Int, white: Int) {

        var free = 0,white = 0,black = 0

        for y in 1...8 {

            for x in 1...8 {

                switch board[y][x] {

                case BLACK_STONE: black++

                case WHITE_STONE: white++

                default : free++

                }

            }

        }

        return (free,black,white)

    }

    

    func putStone(places: [(Int,Int)], stone: Int) {

        for (x,y) in places {

            board[y][x] = stone

        }

    }

    

}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+2

こんにちは。

OthelloViewのイニシャライザに識別子「required」が付与されていないなど、ソースコードに足りないものがありました。
下記にソースコードを記載させていただきます。ついででしたので、ゲームオーバーの際の処理(ゲームオーバーの判定、レーベル「label」の用意)を書き加えました。
あわせて、最下部にシミュレータのスクリーンショットを添付しました。

ご参考いただければ幸いです。

import UIKit

let EMPTY = 0, BLACK_STONE = 1, WHITE_STONE = 2

let initboard = [
    [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,0,0,0],
    [0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,2,1,0,0,0,0],
    [0,0,0,0,1,2,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,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0],
]

class OthelloView: UIView {
    
    var board:[[Int]] = []
    let white = UIColor.whiteColor().CGColor
    let black = UIColor.blackColor().CGColor
    let green = UIColor(red:0.6, green:1.0, blue:0.2, alpha:1.0).CGColor
    var side:CGFloat = 0.0
    var top:CGFloat = 0.0
    let left:CGFloat = 0
    let label:UILabel = UILabel()
    var gameOver = false
    
    
    required init(coder aDecoder: NSCoder) {
        let appFrame = UIScreen.mainScreen().applicationFrame
        side = appFrame.size.width / 8
        top = (appFrame.size.height - (side * 8)) / 2
        board = initboard
        
        super.init(coder:aDecoder)
        
        label.text = ""
        label.frame = CGRectMake(10, top / 2, appFrame.size.width, top / 2)
        addSubview(label)
    }
    
    
    override func drawRect(rect: CGRect) {
        let context = UIGraphicsGetCurrentContext()
        CGContextSetStrokeColorWithColor(context, white)
        CGContextSetLineWidth(context, 1.5)
        
        for y in 1...8 {
            for x in 1...8 {
                let rx = left + side * CGFloat(x-1)
                let ry = top + side * CGFloat(y-1)
                let rect = CGRectMake(rx, ry, side, side)
                CGContextSetFillColorWithColor(context, green)
                CGContextFillRect(context, rect)
                CGContextStrokeRect(context, rect)
                
                if board[y][x] == BLACK_STONE {
                    CGContextSetFillColorWithColor(context, black)
                    CGContextFillEllipseInRect(context, rect)
                } else if board[y][x] == WHITE_STONE {
                    CGContextSetFillColorWithColor(context, white)
                    CGContextFillEllipseInRect(context, rect)
                }
            }
        }
    }
    
    override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
        if gameOver {
            board = initboard
            updateGame()
            setNeedsDisplay()
            return
        }
        if let canBlack = canPlaced(board, BLACK_STONE) {
            if let (x, y) = getPos(touches) {
                if let blackPlaces = flip(board, x, y, BLACK_STONE) {
                    putStones(blackPlaces, stone: BLACK_STONE)
                    if let whitePlaces = cpuFlip(board, WHITE_STONE) {
                        putStones(whitePlaces, stone: WHITE_STONE)
                    }
                }
            }
        } else {
            if let whitePlaces = cpuFlip(board, WHITE_STONE) {
                putStones(whitePlaces, stone: WHITE_STONE)
            }
        }
        updateGame()
        setNeedsDisplay()
    }
    
    func getPos(touches: NSSet!) -> (Int, Int)? {
        let touch = touches.anyObject() as UITouch
        let point = touch.locationInView(self)
        for y in 1...8 {
            for x in 1...8 {
                let rx = left + side * CGFloat(x-1)
                let ry = top + side * CGFloat(y-1)
                let rect = CGRectMake(rx, ry, side, side)
                if CGRectContainsPoint(rect, point) {
                    return (x, y)
                }
            }
        }
        return nil
    }
    
    func putStones(places:[(Int, Int)], stone: Int) {
        for (x, y) in places {
            board[y][x] = stone
        }
    }
    
    func updateGame() {
        let (free, black, white) = calcStones(board)
        let canBlack = canPlaced(board, BLACK_STONE)
        let canWhite = canPlaced(board, WHITE_STONE)
        if free == 0 || (canBlack == nil && canWhite == nil) {
            label.text = "Game Over (Black:\(black) White:\(white))"
            gameOver = true
        } else {
            label.text = ""
            gameOver = false
        }
    }
}

func flip(board:[[Int]], x:Int, y:Int, stone:Int) -> [(Int, Int)]? {
    if board[y][x] != EMPTY { return nil }
    var result:[(Int, Int)] = []
    result += flipLine(board, x, y, stone, 1, 0)
    result += flipLine(board, x, y, stone,-1, 0)
    result += flipLine(board, x, y, stone, 0, 1)
    result += flipLine(board, x, y, stone, 0,-1)
    result += flipLine(board, x, y, stone, 1, 1)
    result += flipLine(board, x, y, stone,-1,-1)
    result += flipLine(board, x, y, stone, 1,-1)
    result += flipLine(board, x, y, stone,-1, 1)
    if result.count > 0 {
        result += [(x, y)]
        return result
    } else {
        return nil
    }
}

func flipLine(board:[[Int]], x:Int, y:Int, stone:Int, dx:Int, dy:Int) -> [(Int, Int)] {
    var flipLoop: (Int, Int) -> [(Int, Int)]? = { _ in nil }
    flipLoop = { (x: Int, y: Int) -> [(Int, Int)]? in
        if board[y][x] == EMPTY {
            return nil
        } else if board[y][x] == stone {
            return []
        } else if var result = flipLoop(x+dx, y+dy) {
            result += [(x, y)]
            return result
        }
        return nil
    }
    if let result = flipLoop(x+dx, y+dy) {
        return result
    }
    return []
}

func canPlaced(board:[[Int]], stone: Int) -> [(Int, Int)]? {
    var result:[(Int, Int)] = []
    for y in 1...8 {
        for x in 1...8 {
            if let res = flip(board, x, y, stone) {
                result += [(x, y)]
            }
        }
    }
    if result.isEmpty {
        return nil
    } else {
        return result
    }
}

func cpuFlip(board:[[Int]], stone: Int) -> [(Int, Int)]? {
    if let places = canPlaced(board, stone) {
        let (x, y) = places[ Int(arc4random()) % places.count ]
        return flip(board, x, y, stone)
    }
    return nil
}

func calcStones(board:[[Int]]) -> (free:Int, black:Int, white:Int) {
    var free = 0, white = 0, black = 0
    for y in 1...8 {
        for x in 1...8 {
            switch board[y][x] {
            case BLACK_STONE: black++
            case WHITE_STONE: white++
            default: free++
            }
        }
    }
    return (free, black, white)
}

イメージ説明

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

ちゃんと見たわけではありませんがinitboardで準備している配列が10x10のところがfor文で回しているところのindexが8になっているので8のところを10で置き換えればもしかしたらうまくいくんではないかと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/04/07 11:17

    こんにちは。
    画面幅の8分の1をマス目の一辺にしている(side = appFrame.size.width / 8)ことから、マス目は8X8で設計していることがわかります。
    オセロ盤の初期状態を10X10で定義しているのは、おそらく、後半のアルゴリズムで配列の範囲をチェックすることを省略しようとしているのではないかと思われます。
    (横から失礼しました)

    キャンセル

  • 2015/04/07 13:22

    ご指摘ありがとうございます!そもそもオセロは8x8でやるものでそこ変えちゃいけませんでした(^^;;;

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.48%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Swift

    7460questions

    Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

  • iOS

    4081questions

    iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。