画像の場所を指定した中でランダムにしたい。


質問の内容がわかりずらくてゴメンなさい。

縦４ 横４ の計１６個の画像を配置してあります。  
１５こは同じ画像なのですが１つ違う画像にしてあります。  
その違う１つをタッチするたびに違う場所に出現させたいのですがやり方がわかりません。

ランダムに再配置するやり方がわかりません

touchesBeganの所になんと書けばいいのでしょうか？

コードは以下のとうりです  
見よう見まねでやったので雑でゴメンなさい。

[code]

    class ViewController:UIViewController{
    
        private var myImageView: UIImageView!
        private var myImageView2: UIImageView!
        private var myImageView3: UIImageView!
        private var myImageView4: UIImageView!
        private var myImageView5: UIImageView!
        private var myImageView6: UIImageView!
        private var myImageView7: UIImageView!
        private var myImageView8: UIImageView!
        private var myImageView9: UIImageView!
        private var myImageView10: UIImageView!
        private var myImageView11: UIImageView!
        private var myImageView12: UIImageView!
        private var myImageView13: UIImageView!
        private var myImageView14: UIImageView!
        private var myImageView15: UIImageView!
        private var myImageView16: UIImageView!
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            myImageView = UIImageView(frame: CGRectMake(0,0,60,60))
            let myImage = UIImage(named: "images2.png")
            myImageView.image = myImage
            myImageView.layer.position = CGPoint(x: 60, y: 150)
            self.view.addSubview(myImageView)
    
    
            myImageView2 = UIImageView(frame: CGRectMake(0,0,60,60))
            let myImage2 = UIImage(named: "images.png")
            myImageView2.image = myImage2
            myImageView2.layer.position = CGPoint(x: 140, y: 150)
            self.view.addSubview(myImageView2)
    
            myImageView3 = UIImageView(frame: CGRectMake(0,0,60,60))
            let myImage3 = UIImage(named: "images.png")
            myImageView3.image = myImage3
            myImageView3.layer.position = CGPoint(x: 220, y: 150)
            self.view.addSubview(myImageView3)
    
            myImageView4 = UIImageView(frame: CGRectMake(0,0,60,60))
            let myImage4 = UIImage(named: "images.png")
            myImageView4.image = myImage4
            myImageView4.layer.position = CGPoint(x: 300, y: 150)
            self.view.addSubview(myImageView4)
    
            myImageView5 = UIImageView(frame: CGRectMake(0,0,60,60))
            let myImage5 = UIImage(named: "images.png")
            myImageView5.image = myImage5
            myImageView5.layer.position = CGPoint(x: 60, y: 250)
            self.view.addSubview(myImageView5)
    
            myImageView6 = UIImageView(frame: CGRectMake(0,0,60,60))
            let myImage6 = UIImage(named: "images.png")
            myImageView6.image = myImage6
            myImageView6.layer.position = CGPoint(x: 140, y: 250)
            self.view.addSubview(myImageView6)
    
            myImageView7 = UIImageView(frame: CGRectMake(0,0,60,60))
            let myImage7 = UIImage(named: "images.png")
            myImageView7.image = myImage7
            myImageView7.layer.position = CGPoint(x: 220, y: 250)
            self.view.addSubview(myImageView7)
    
            myImageView8 = UIImageView(frame: CGRectMake(0,0,60,60))
            let myImage8 = UIImage(named: "images.png")
            myImageView8.image = myImage8
            myImageView8.layer.position = CGPoint(x: 300, y: 250)
            self.view.addSubview(myImageView8)
    
            myImageView9 = UIImageView(frame: CGRectMake(0,0,60,60))
            let myImage9 = UIImage(named: "images.png")
            myImageView9.image = myImage9
            myImageView9.layer.position = CGPoint(x: 60, y: 350)
            self.view.addSubview(myImageView9)
    
            myImageView10 = UIImageView(frame: CGRectMake(0,0,60,60))
            let myImage10 = UIImage(named: "images.png")
            myImageView10.image = myImage10
            myImageView10.layer.position = CGPoint(x: 140, y: 350)
            self.view.addSubview(myImageView10)
    
            myImageView11 = UIImageView(frame: CGRectMake(0,0,60,60))
            let myImage11 = UIImage(named: "images.png")
            myImageView11.image = myImage11
            myImageView11.layer.position = CGPoint(x: 220, y: 350)
            self.view.addSubview(myImageView11)
    
            myImageView12 = UIImageView(frame: CGRectMake(0,0,60,60))
            let myImage12 = UIImage(named: "images.png")
            myImageView12.image = myImage12
            myImageView12.layer.position = CGPoint(x: 300, y: 350)
            self.view.addSubview(myImageView12)
    
            myImageView13 = UIImageView(frame: CGRectMake(0,0,60,60))
            let myImage13 = UIImage(named: "images.png")
            myImageView13.image = myImage13
            myImageView13.layer.position = CGPoint(x: 60, y: 450)
            self.view.addSubview(myImageView13)
    
            myImageView14 = UIImageView(frame: CGRectMake(0,0,60,60))
            let myImage14 = UIImage(named: "images.png")
            myImageView14.image = myImage14
            myImageView14.layer.position = CGPoint(x: 140, y: 450)
            self.view.addSubview(myImageView14)
    
            myImageView15 = UIImageView(frame: CGRectMake(0,0,60,60))
            let myImage15 = UIImage(named: "images.png")
            myImageView15.image = myImage15
            myImageView15.layer.position = CGPoint(x: 220, y: 450)
            self.view.addSubview(myImageView15)
    
            myImageView16 = UIImageView(frame: CGRectMake(0,0,60,60))
            let myImage16 = UIImage(named: "images.png")
            myImageView16.image = myImage16
            myImageView16.layer.position = CGPoint(x: 300, y: 450)
            self.view.addSubview(myImageView16)
    
            myImageView.userInteractionEnabled = true
            myImageView2.userInteractionEnabled = true
            myImageView3.userInteractionEnabled = true
            myImageView4.userInteractionEnabled = true
            myImageView5.userInteractionEnabled = true
            myImageView6.userInteractionEnabled = true
            myImageView7.userInteractionEnabled = true
            myImageView8.userInteractionEnabled = true
            myImageView9.userInteractionEnabled = true
            myImageView10.userInteractionEnabled = true
            myImageView11.userInteractionEnabled = true
            myImageView12.userInteractionEnabled = true
            myImageView13.userInteractionEnabled = true
            myImageView14.userInteractionEnabled = true
            myImageView15.userInteractionEnabled = true
            myImageView16.userInteractionEnabled = true
        }
    
        override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
            let touch = touches.first as! UITouch
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
            // Dispose of any resources that can be recreated.
        }
    }
    
[/code]




アプリのグラフィックな部分の開発の、ひとつのテクニック、というかひとつの心得として、できるだけ構成を単純化するということが挙げられると思います。  
今回の件では、同じ画像15個＋異なる画像1個という16個で構成をするから、処理が複雑化しているといえます。これを、

> ・同じ画像（UIImage）のUIImageViewインスタンス16個、A01〜A16  
>  ・異なる画像のUIImageViewインスタンス1個、B

このように17個で構成すれば、とたんに単純化されます。A01〜A16は、格子状に配置して、終始固定したままにできます。A01〜A16の任意のインスタンスの上に、Bを重ねて配置すれば、当初想定した外見になります。あとは、ランダムにBの位置を移動するだけです。

もうひとつの心得を挙げさせてもらうならば、それはアプリのふるまいを、漠然とひとつのふるまいとイメージするのではなく、ひとつひとつの小さなパーツの組み合わせとしてイメージすることです。これも今回の件に即してみていけば、

> ・UIImageViewインスタンスBのタッチをトリガー（引き金）にしてイベントを起こす。  
>  ・UIImageViewインスタンスBの位置を、プログラムで移動する（変更する）。  
>  ・UIImageViewインスタンスBのとることができる位置（A01〜A16の位置）を、配列として保持する。  
>  ・ランダムに0〜15（まあ、1〜16でもかまいませんが）を返す関数を用意する。

このくらいのパーツに分けてみるといいんじゃないでしょうか？  
そして、個々のパーツについて、じぶんの知っている範囲、経験のある範囲でプログラムにできるかを検証して、無理なら、そのパーツについて、絞った質問をするよう、心がけるといいでしょう。

* * *

以上の方針に沿ったサンプルコードを掲載しておきます。（Xcode 7.0 Beta 5、Swift 2.0）（Xcode 6.4、Swift
1.2でも動作するはず）

**base16.png**

[![base16.png](https://i.stack.imgur.com/3B1Dc.png)](https://i.stack.imgur.com/3B1Dc.png)

**heart.png**

[![heart.png](https://i.stack.imgur.com/pFdRv.png)](https://i.stack.imgur.com/pFdRv.png)

Single View Applicationのプロジェクトを新規作成します。  
上のふたつの画像を、プロジェクトに追加します。  
`ViewController.swift`を下のように編集します。

**ViewController.swift**

[code]

    import UIKit
    
    class ViewController: UIViewController {
    
        // heartViewのプロパティtagを100とるす定数
        let heartTag = 100
        // 要素数16、CGPointの配列を用意する。
        var points = [CGPoint](count: 16, repeatedValue: CGPointZero)
    
        // ランダムな位置（CGPoint）を返すメソッド
        func randomPoint(under: Int) -> CGPoint {
            let n = Int(arc4random_uniform(UInt32(under)))
            // 「頼みもしない機能」を実装
            let tmp = points[n]
            points[n] = points[15]
            points[15] = tmp
            return tmp
        }
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            // 配列pointsに、位置座標を代入
            points[0] = CGPoint(x: 38.0, y: 38.0 + 36.0)
            points[1] = CGPoint(x: 114.0, y: 38.0 + 36.0)
            points[2] = CGPoint(x: 190.0, y: 38.0 + 36.0)
            points[3] = CGPoint(x: 266.0, y: 38.0 + 36.0)
            points[4] = CGPoint(x: 38.0, y: 114.0 + 36.0)
            points[5] = CGPoint(x: 114.0, y: 114.0 + 36.0)
            points[6] = CGPoint(x: 190.0, y: 114.0 + 36.0)
            points[7] = CGPoint(x: 266.0, y: 114.0 + 36.0)
            points[8] = CGPoint(x: 38.0, y: 190.0 + 36.0)
            points[9] = CGPoint(x: 114.0, y: 190.0 + 36.0)
            points[10] = CGPoint(x: 190.0, y: 190.0 + 36.0)
            points[11] = CGPoint(x: 266.0, y: 190.0 + 36.0)
            points[12] = CGPoint(x: 38.0, y: 266.0 + 36.0)
            points[13] = CGPoint(x: 114.0, y: 266.0 + 36.0)
            points[14] = CGPoint(x: 190.0, y: 266.0 + 36.0)
            points[15] = CGPoint(x: 266.0, y: 266.0 + 36.0)
    
            // base16.pngをviewに貼り付け。
            let baseView = UIImageView(image: UIImage(named: "base16.png"))
            baseView.center = CGPoint(x: 152.0, y: 152.0 + 36.0)
            baseView.userInteractionEnabled = false
            self.view.addSubview(baseView)
    
            // heart.pngをviewに貼り付け
            let heartView = UIImageView(image: UIImage(named: "heart.png"))
            // heartViewをランダムな位置にする。
            heartView.center = randomPoint(16)
            heartView.userInteractionEnabled = true
            // heartViewのプロパティtagをheartTag（100）にする
            heartView.tag = heartTag
            self.view.addSubview(heartView)   
        }
    
        // heartViewをタップすると
        override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
            // タッチイベントを受け取ったviewが、heartViewなら
            if let touch = touches.first,
                let theView = touch.view
                where theView.tag == heartTag {
                    // それっぽく見せるために、フリップ（裏返す）アニメーションを付加
                    UIView.transitionWithView(theView, duration: 0.4, options: UIViewAnimationOptions.TransitionFlipFromRight, animations: {
                            theView.hidden = true
                        }, completion: {
                            (finished) in
                            theView.center = self.randomPoint(15)
                            UIView.transitionWithView(theView, duration: 0.4, options: UIViewAnimationOptions.TransitionFlipFromRight, animations: {
                                    theView.hidden = false
                                }, completion: nil)
                    })
            }
        }
    
    }
    
[/code]

上のコードには、頼まれていない処理が付加されています。  
ランダムに`heartView`の位置を変更すると、16分の1の確率で、移動前と同じ位置に移動する、すなわち見た目移動しない結果になります。それはかっこよくないので、かならず現在位置から移動するようにしたいものです。その処理を付加しています。




アプリのグラフィックな部分の開発の、ひとつのテクニック、というかひとつの心得として、できるだけ構成を単純化するということが挙げられると思います。  
今回の件では、同じ画像15個＋異なる画像1個という16個で構成をするから、処理が複雑化しているといえます。これを、

> ・同じ画像（UIImage）のUIImageViewインスタンス16個、A01〜A16  
>  ・異なる画像のUIImageViewインスタンス1個、B

このように17個で構成すれば、とたんに単純化されます。A01〜A16は、格子状に配置して、終始固定したままにできます。A01〜A16の任意のインスタンスの上に、Bを重ねて配置すれば、当初想定した外見になります。あとは、ランダムにBの位置を移動するだけです。

もうひとつの心得を挙げさせてもらうならば、それはアプリのふるまいを、漠然とひとつのふるまいとイメージするのではなく、ひとつひとつの小さなパーツの組み合わせとしてイメージすることです。これも今回の件に即してみていけば、

> ・UIImageViewインスタンスBのタッチをトリガー（引き金）にしてイベントを起こす。  
>  ・UIImageViewインスタンスBの位置を、プログラムで移動する（変更する）。  
>  ・UIImageViewインスタンスBのとることができる位置（A01〜A16の位置）を、配列として保持する。  
>  ・ランダムに0〜15（まあ、1〜16でもかまいませんが）を返す関数を用意する。

このくらいのパーツに分けてみるといいんじゃないでしょうか？  
そして、個々のパーツについて、じぶんの知っている範囲、経験のある範囲でプログラムにできるかを検証して、無理なら、そのパーツについて、絞った質問をするよう、心がけるといいでしょう。

* * *

以上の方針に沿ったサンプルコードを掲載しておきます。（Xcode 7.0 Beta 5、Swift 2.0）（Xcode 6.4、Swift
1.2でも動作するはず）

**base16.png**

[![base16.png](https://i.stack.imgur.com/3B1Dc.png)](https://i.stack.imgur.com/3B1Dc.png)

**heart.png**

[![heart.png](https://i.stack.imgur.com/pFdRv.png)](https://i.stack.imgur.com/pFdRv.png)

Single View Applicationのプロジェクトを新規作成します。  
上のふたつの画像を、プロジェクトに追加します。  
`ViewController.swift`を下のように編集します。

**ViewController.swift**

[code]

    import UIKit
    
    class ViewController: UIViewController {
    
        // heartViewのプロパティtagを100とるす定数
        let heartTag = 100
        // 要素数16、CGPointの配列を用意する。
        var points = [CGPoint](count: 16, repeatedValue: CGPointZero)
    
        // ランダムな位置（CGPoint）を返すメソッド
        func randomPoint(under: Int) -> CGPoint {
            let n = Int(arc4random_uniform(UInt32(under)))
            // 「頼みもしない機能」を実装
            let tmp = points[n]
            points[n] = points[15]
            points[15] = tmp
            return tmp
        }
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            // 配列pointsに、位置座標を代入
            points[0] = CGPoint(x: 38.0, y: 38.0 + 36.0)
            points[1] = CGPoint(x: 114.0, y: 38.0 + 36.0)
            points[2] = CGPoint(x: 190.0, y: 38.0 + 36.0)
            points[3] = CGPoint(x: 266.0, y: 38.0 + 36.0)
            points[4] = CGPoint(x: 38.0, y: 114.0 + 36.0)
            points[5] = CGPoint(x: 114.0, y: 114.0 + 36.0)
            points[6] = CGPoint(x: 190.0, y: 114.0 + 36.0)
            points[7] = CGPoint(x: 266.0, y: 114.0 + 36.0)
            points[8] = CGPoint(x: 38.0, y: 190.0 + 36.0)
            points[9] = CGPoint(x: 114.0, y: 190.0 + 36.0)
            points[10] = CGPoint(x: 190.0, y: 190.0 + 36.0)
            points[11] = CGPoint(x: 266.0, y: 190.0 + 36.0)
            points[12] = CGPoint(x: 38.0, y: 266.0 + 36.0)
            points[13] = CGPoint(x: 114.0, y: 266.0 + 36.0)
            points[14] = CGPoint(x: 190.0, y: 266.0 + 36.0)
            points[15] = CGPoint(x: 266.0, y: 266.0 + 36.0)
    
            // base16.pngをviewに貼り付け。
            let baseView = UIImageView(image: UIImage(named: "base16.png"))
            baseView.center = CGPoint(x: 152.0, y: 152.0 + 36.0)
            baseView.userInteractionEnabled = false
            self.view.addSubview(baseView)
    
            // heart.pngをviewに貼り付け
            let heartView = UIImageView(image: UIImage(named: "heart.png"))
            // heartViewをランダムな位置にする。
            heartView.center = randomPoint(16)
            heartView.userInteractionEnabled = true
            // heartViewのプロパティtagをheartTag（100）にする
            heartView.tag = heartTag
            self.view.addSubview(heartView)   
        }
    
        // heartViewをタップすると
        override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
            // タッチイベントを受け取ったviewが、heartViewなら
            if let touch = touches.first,
                let theView = touch.view
                where theView.tag == heartTag {
                    // それっぽく見せるために、フリップ（裏返す）アニメーションを付加
                    UIView.transitionWithView(theView, duration: 0.4, options: UIViewAnimationOptions.TransitionFlipFromRight, animations: {
                            theView.hidden = true
                        }, completion: {
                            (finished) in
                            theView.center = self.randomPoint(15)
                            UIView.transitionWithView(theView, duration: 0.4, options: UIViewAnimationOptions.TransitionFlipFromRight, animations: {
                                    theView.hidden = false
                                }, completion: nil)
                    })
            }
        }
    
    }
    
[/code]

上のコードには、頼まれていない処理が付加されています。  
ランダムに`heartView`の位置を変更すると、16分の1の確率で、移動前と同じ位置に移動する、すなわち見た目移動しない結果になります。それはかっこよくないので、かならず現在位置から移動するようにしたいものです。その処理を付加しています。

