Tips

【Swift3.0対応】色彩チェックアプリを作成してみよう!⑤

【Swift3.0対応】色彩チェックアプリを作成してみよう!⑤

【Swift3.0対応】色彩チェックアプリを作成してみよう!⑤

前回の続きです。前回はランダムに色が表示され、かつ1つのボタンだけ異なる色に
することができました。今回はスコアが進むにつれてボタンの数が増えていく機能や、
色の違いが分かりづらくなっていって難易度が上がるという部分を実装したいと思います。

【STEP9】スコアの表示と残り時間を表示するラベルを配置する

すっかり忘れていたのですが、現状では画面上部にスコア表示と残り時間を表示する
ラベルがありませんね。それを実装していきたいと思います。

ストーリーボードに以下のように4つのラベルを配置します。サイズなどは適宜調整して
ください。

まずはスコアの数値は0、残り時間は60と決め打ちしておきます。

SCORE:とTIME:のラベルは文言が変化しないためストーリーボードに配置するだけで
問題ありませんが、その右の数値はゲームの進行によって値が変化します。
そのためOutlet接続してコードと結びつけてあげましょう。

下図ではそれぞれ、「scoreLabel」と「timeLabel」という名称でOutlet接続しています。
さらにそれらの2つの値を保持する変数も用意しておきましょう。

それぞれ「scoreNum」と「timeNum」とでもしておきます。

スコアは正解ボタンがタップされた際に1ずつ加算されていくので、onClickBtnメソッドの中で
scoreNumの値を1増加させ、それをラベルに表示させるコードを追加します。

追加する場所はonClickBtnメソッドの一番上でいいでしょう。

    //ボタンがタップされた時のメソッドを定義
    func onClickBtn() {
        //スコアを1加算してテキストに埋め込む
        scoreNum = scoreNum + 1    //この部分を追加
        scoreLabel.text = "\(scoreNum)"    //この部分を追加
        
        //正解ボタンをタップすると、まず、一度画面からボタンを取り除き、配列も空にする。
        for i in 0...(countNum*countNum-1) {
            myButtonAry[i].removeFromSuperview()
        }
        myButtonAry.removeAll()
        
        //再度ボタンを生成。これで新しいランダムな色のボタン&正解ボタンもランダムに決められたボタンが画面に表示される。
        makeBtn(num: countNum)
        showBtn(num: countNum)
    }

4、5行目を追加しています。
これで正解ボタンをタップしたらスコアが1増加させることができます。

次に残り時間を60秒からカウントダウンさせる機能も実装させてしまいましょう。
これはTimerクラスを利用します。

Timerクラスのインスタンスをグローバルに生成しておき、viewDidLoadメソッド内で
そのタイマーを発火させスタートさせます。
タイマーは1秒ごとに繰り返し実行されるようにします。

    var myButtonAry: [UIButton] = []
    var countNum: Int = 2
    var scoreNum = 0
    var timeNum = 60
    var timer: Timer = Timer()    //この部分を追加
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        makeBtn(num: countNum)
        showBtn(num: countNum)
        timer = Timer.scheduledTimer(timeInterval: 1.0,
                                     target: self,
                                     selector: #selector(countDown),
                                     userInfo: nil,
                                     repeats: true)    //この部分を追加
    }

5行目の部分でTimerクラスのインスタンスをtimerという変数に代入しています。
12行目から16行目でタイマーを開始させています。改行していますが、5つの引数を取るメソッドの
戻り値を変数timerに代入しています。

timeInterval引数で繰り返し実行する間隔を指定しています。
selector引数でその間隔ごとに繰り返す動作のメソッド名を指定しています。
repeats引数で、繰り返し実行するかどうかを決定しています。falseにすると1秒後に
1回実行されて終了してしまうので、trueにします。

さて、現状では赤色のエラーが表示されているかと思います。このメソッドもボタンをタップした際の
動作を定義したaddTargetメソッドと同じイメージで、1秒ごとにセレクタで指定したcountDownメソッドを
実行する、という動きになります。
そのため、countDownメソッドを定義してあげなければなりません。

countDownメソッドを一番下、onClickBtnメソッドの下あたりにでも定義してあげましょう。

    //残り時間を減らしていくメソッド
    func countDown() {
        //1秒ごとに表示する残り時間を1ずつ減らし、その数値をラベルに表示する
        timeNum = timeNum - 1
        timeLabel.text = "\(timeNum)"
        //0秒でタイマーを止める。
        if timeNum  <= 0 {
            timer.invalidate()
        }
    }

タイマーは0秒になった瞬間に止めてあげなくてはなりません。そうしないとマイナスになっても
ずっと数値が減り続けてしまいます。
7〜9行目のようにif文を使って、残り時間が0秒になったと同時に、
8行目のメソッドを実行することでタイマーをストップさせることができます。

現状では残り時間が0になったらタイマーが止まるだけです。実際は0秒になると
結果表示画面に遷移するのですが、その機能は次回実装します。

【STEP10】スコアが進むにつれてボタンの数が増える&難易度が上がる機能を実装する

次はゲームの進行によってボタンの数と難易度をあげていく機能を実装していきます。

【Swift3.0対応】色彩チェックアプリを作成してみよう!④
で正解ボタン1つだけ回りのボタンの色よりRGBの色を0.1だけ加算して、少しだけ明度を
上げて色の違いを生み出していました。
0.1という値を決め打ちしていましたが、この値を小さくすることで難易度を難しくして
いくことにしたいと思います。

そのため、まずその値を格納する変数を定義しましょう。
一番上で色々な変数を定義していますので、その中にcolorLebelという名前で
変数を追加します。

import UIKit

class GameViewController: UIViewController {

    @IBOutlet weak var centerView: UIView!
    @IBOutlet weak var scoreLabel: UILabel!
    @IBOutlet weak var timeLabel: UILabel!
    
    var myButtonAry: [UIButton] = []
    var countNum: Int = 2
    var scoreNum = 0
    var timeNum = 60
    var colorLebel: CGFloat = 0.1    //この部分を追加
    var timer: Timer = Timer()
    
    override func viewDidLoad() {
        super.viewDidLoad()

13行目で変数を定義していますね。この0.1という値は必ずCGFloat型で定義しておきます。

次に難易度を決定するdecideDifficultyメソッドを定義しましょう。
上で定義したcountDownメソッドの下にでも書いていきます。
以下のように記述しましょう。

    //スコアに応じて表示されるボタンの数と難易度を決めるメソッド。
    func decideDifficulty() {
        switch scoreNum {
        case 0:
            countNum = 2
            colorLebel = 0.1
        case 1:
            countNum = 3
            colorLebel = 0.09
        case 2:
            countNum = 4
            colorLebel = 0.08
        case 3,4:
            countNum = 5
            colorLebel = 0.07
        case 5,6:
            countNum = 6
            colorLebel = 0.06
        case 7...9:
            countNum = 7
            colorLebel = 0.05
        case 10...15:
            countNum = 8
            colorLebel = 0.04
        case 16...29:
            countNum = 9
            colorLebel = 0.03
        default:
            countNum = 10
            colorLebel = 0.02
        }
    }

この辺の書き方でいい方法が思い浮かばなかったので、とりあえずswitch-case文で
全部網羅させています。コードが長くなるのでちょっと嫌なんですが。。

switch文でscoreNum(点数)の値を基に条件分岐させています。
点数が0から1に変わると、つまり最初の2×2のボタンで正解するとcountNumの値が
2から3になります。countNumは初回で定義した変数で、ボタンの◯×◯の、
◯の数値を表す変数でした。
つまり、1回正解すると2×2から3×3のボタンに変化します。
あとの流れは同じですね。

同様にcolorLevelの値も変えています。0に近ければ近いほど色の違いが小さい
ことになりますので、見分けがつきにくくなっていきます。

この定義したメソッドをonClickBtnメソッドの中で実行します。
onClickBtnメソッドの中に1行追加します。

    //ボタンがタップされた時のメソッドを定義
    func onClickBtn() {
        //スコアを1加算してテキストに埋め込む
        scoreNum = scoreNum + 1
        scoreLabel.text = "\(scoreNum)"
        
        //正解ボタンをタップすると、まず、一度画面からボタンを取り除き、配列も空にする。
        for i in 0...(countNum*countNum-1) {
            myButtonAry[i].removeFromSuperview()
        }
        myButtonAry.removeAll()
        
        //難易度調整メソッド実行。このメソッドを実行することでボタンの数と色の違いが変わる。
        decideDifficulty()    //この部分を追加
        
        //再度ボタンを生成。これで新しいランダムな色のボタン&正解ボタンもランダムに決められたボタンが画面に表示される。
        makeBtn(num: countNum)
        showBtn(num: countNum)
    }

14行目を追加しています。この後にmakeBtnメソッドが実行されますので、ボタンの数がちゃんと
反映されますね。

次に、makeColorメソッドも書き換えます。
RGBの色を+0.1していた部分を+colorLebelに変更します。

    //ランダムな色を生成するメソッド
    func makeColor() -> (UIColor, UIColor) {
        //RGBのそれぞれの値をランダムに生成する。このように書くことで、0〜1までの小数点以下3桁までの値を取得できる。
        //このように書くことで、色のバリエーションが増える(ような気がする)
        let red: CGFloat = CGFloat(arc4random_uniform(1001)) / 1000
        let green: CGFloat = CGFloat(arc4random_uniform(1001)) / 1000
        let blue: CGFloat = CGFloat(arc4random_uniform(1001)) / 1000
        
        let color = UIColor(red: red, green: green, blue: blue, alpha: 1)
        
        //正解となるボタンの色を生成する。明度を明るくすることで違いを生み出す。
        //RGBの色は0〜1の値を設定することができ、1に近づけば近づくほど白色寄りに、0に近づけば黒色寄りになるため、
        //ちょっと色の値を小さくする。
        let correctRed: CGFloat = red + colorLebel        //この部分を変更
        let correctGreen: CGFloat = green + colorLebel    //この部分を変更
        let correctBlue: CGFloat = blue + colorLebel      //この部分を変更
        
        let correctColor = UIColor(red: correctRed, green: correctGreen, blue: correctBlue, alpha: 1)

        //外れボタンの色と正解ボタンの色を戻り値としてタプルで返す
        return (color, correctColor)
    }

14行目から16行目を変更しています。
ただし、colorLebelが最後の方になると0.2とか0.1になります。
そうなるとほとんど見分けがつかなくなるので、難易度をもう少し優しくしてあげた
方がいいかもしれません。笑

現状でアプリでの動きをシミュレータで確認してみると以下のようになります。


スコア、残り時間もちゃんと表示されています。
またスコアが進むとボタンの数も多くなり、難易度が難しくなっているのもわかりますね!

今回はこれで終わりとします。次回は残り時間が0になった際の画面遷移や
スコアに基づいた結果表示などを行いたいと思います。

TechProjin 開発系基礎講座 連載リンク

基礎からPHPWEBアプリ解発を学ぶなら・・
PHP基礎 連載

AIなどで注目急上昇!これから学ぶならPython!!
独学で学ぶ-pythonプログラミング 連載

汎用性◎ 定番プログラミング言語JAVA
Java基礎講座 連載

Recent News

Recent Tips

Tag Search