さいころアプリを作成する~Kotlinプログラミングの基礎~

前回まではバースデーカードアプリを作成しましたが、今回からプログラミング言語Kotlinを使ってさいころアプリを作成したいと思います。
(googleの無料講座の順に進んでいます。)

前回の記事とgoogleの講座はこちらです。
次回の記事はこちらです。

Kotlinの基礎

簡単にKotlinの基礎を解説していきます。
Kotlinの動作確認にはこちらのサイトで行います。

環境構築せずにブラウザ上で確認できるのでなかなか便利です。

変数の宣言

変数を宣言するにはvarとvalの2種類があります。
変数の中身を変える必要がある場合はvarを使い、中身を変える必要が無ければvalを使って宣言します。
val num1 = 1 //書き換え不可
var num2 = 2 //書き換え可能

Kotlinは型の推論をしてくれるので、基本的に型の指定は不要です。
もし型を指定して変数を宣言したい場合は次のようにしてください。
val num1: Int = 1 //var 変数名: 型 = の形です。

print文

print文には最後に改行コードが入らないprintと改行コードが入るprintlnの2つがあります。
print("Hello World!") //改行コードなし
println(
"Hello World!")//改行コードあり
print文の中に変数を埋め込む(というよりは文字列の中に変数を埋め込む)場合は
$マークを付けて{}で囲います。
fun main() {
    var test = 3
    print("testの中身は${test}です")
}

関数の宣言

funで関数を宣言することができます。
fun main() {
 }

googleの講座で関数・クラスに引数を持たせる場合は戻り値を持たせる場合を扱うので、詳しくは後ほど紹介します。

クラスの宣言

classでクラスの宣言ができます。
googleの講座によるとKotlinではクラスをキャメルケースで記述するみたいです。
キャメルケースについて知らない人はこちらを参考にしてください。
class Dice { 
 }

ちなみにgoogleの講座ではクラスについての解説があまりなかったです。
クラスについて知らない人はこちらを参照お願いします。

とりあえず上記がわかればgoogleの講座の中身がわかると思います。

Diceクラスを作る

ここからgooleの講座内容です。(一部順番を変えてある箇所があります)
main関数の下にDiceクラスを作成し、main関数の中でDiceクラスのインスタンスを作成します。
コード内にコメントを書いたのでそちらも参考にしてください。
fun main() {
    val myFirstDice
= Dice()//作ったDiceクラスのインスタンスを生成
    println
(myFirstDice.sides)//Diceクラス内の変数sidesを表示
}

class Dice {
   
var sides = 6 //さいころの面の数
}

次にDiceクラス内にさいころを振るroll関数を作成していきます。
さいころを振るにあたり、Rangeとrandomモジュールを使います。

Rangeは
最初の数..最後の数
というように2つの数値をドット2つでつなぎます。
val diceRange = 1..6
今回はさいころなので、1から6までの範囲で宣言します。

そしてこれとrandomモジュールを使って1~6までの間でランダムな数を生成します。
val randomNumber = diceRange.random()
1から6までの間でランダムで表示するサンプルプログラムがこちらです。
fun main() {
    val diceRange
= 1..6
    val randomNumber
= diceRange.random()
    println
("Random number: ${randomNumber}")
}

今回はこれを使ってDiceクラス内にさいころを振る関数を宣言します。
コード内にコメントを追加したのでそちらも参考にして下さい。
fun main() {
    val myFirstDice
= Dice()//作ったDiceクラスのインスタンスを生成
    println(myFirstDice.sides)//Diceクラス内の変数sidesを表示
    myFirstDice.roll()//Diceクラス内のroll関数をコールする
}

class Dice {
   
var sides = 6
//roll関数:1から6までの数字をランダムで生成して表示
    fun roll
() {
        val randomNumber
= (1..6).random()
        println
(randomNumber)
   
}
}

このままでもいいのですが、roll関数は値を表示するだけで使い勝手が悪いです。
roll 関数を戻り値を返すようにして、生成したランダムな値を別の個所でも使えるようにします。

関数に戻り値を追加するためには以下の2つが必要です。
1.戻り値の型宣言
2.return文の追加

戻り値の型は下記のように追加できます。
fun 関数名(): 型{
}
上記を踏まえてソースコードを変えてものがこちらです。
fun main() {
    val myFirstDice
= Dice()//Dice関数のインスタンスを生成
    val diceRoll
= myFirstDice.roll()//roll関数の戻り値を格納する
    println
("Your ${myFirstDice.sides} sided dice rolled ${diceRoll}!")//ダイスの面とroll関数で生成した値を表示
}


class Dice {
   
var sides = 6//ダイスの面

//roll関数:1から6までの数字をランダムで生成して表示
    fun roll
(): Int {
        val randomNumber
= (1..6).random()
       
return randomNumber
   
}
}
これでさいころを振って値を表示する部分ができました。

さいころを追加する

今回は6面のさいころを1つ振るプログラムでしたが、20面のさいころを追加し2つのさいころを振るプログラムに変えていきます。

まず初めにrandomで生成する乱数の範囲を変えます。
今は乱数の範囲が直値で設定されているため、変数で範囲を変えられるようにします。
 val randomNumber = (1..6).random()

...といっても6となっている箇所を最初に宣言したさいころの面の変数sidesに置き換えるだけです。
val randomNumber = (1..sides).random()
次にクラス内の変数の変え方についてです。
インスタンス名.変数名 = 変更したい値
で変えることが可能です。
今回の場合は下記のようになります。
myFirstDice.sides = 20
上記を踏まえてさいころを追加したプログラムがこちらです。
fun main() {
   
    val myFirstDice
= Dice()
    val diceRoll
= myFirstDice.roll()
    println
("Your ${myFirstDice.sides} sided dice rolled ${diceRoll}!")

    myFirstDice
.sides = 20//ここでDiceクラスの変数の中身を変える
    println
("Your ${myFirstDice.sides} sided dice rolled ${myFirstDice.roll()}!")//変数の中身を変えたうえで再度Diceクラスのroll関数をコールしてさいころを振りなおす
}

class Dice {
   
var sides = 6

    fun roll
(): Int {
        val randomNumber
= (1..sides).random()
       
return randomNumber
   
}
}

Diceクラスに引数を渡せるようにする。

今のやり方はDiceクラスの変数を直接変えることで、さいころの面の数を変えています。
これでは使い勝手がよくないので、さいころの面をDiceクラスに引数で渡せるようにしていきます。

引き数の追加は次のようにできます。
class クラス名 (val 引数の変数名: ) {
}
Diceクラスに引数を追加したものがこちらです。
class Dice (val numSides: Int) {

    fun roll
(): Int {
        val randomNumber
= (1..numSides).random()
       
return randomNumber
   
}
}
これでDiceクラスに引数を渡せるようになりました。
実際にDiceクラスに面の数6を渡してさいころを振るプログラムがこちらです。
(下記コードはDiceクラスが無いので、コンパイルエラーが起きます。)
fun main() {
    val myFirstDice
= Dice(6)
    val diceRoll
= myFirstDice.roll()
    println
("Your ${myFirstDice.numSides} sided dice rolled ${diceRoll}!")
}
これでDiceクラスに引数を渡して2つ目のさいころを作れるようにします。
fun main() {
    val myFirstDice
= Dice(6)//一つ目のさいころのインスタンスを生成し、引数に6を代入
    val diceRoll
= myFirstDice.roll()//一つ目のサイコロを振る
    println
("Your ${myFirstDice.numSides} sided dice rolled ${diceRoll}!")//一つ目のさいころの面の数とさいころを振った結果を表示
   
    val mySecondDice
= Dice(20)//二つ目のサイコロのインスタンスを生成し、引数に20を代入
    println
("Your ${mySecondDice.numSides} sided dice rolled ${mySecondDice.roll()}!")//二つ目のさいころの面の数とさいころを振った結果を表示(二つ目のサイコロはここでさいころを振ってます)
}

class Dice (val numSides: Int) {

    fun roll
(): Int {
        val randomNumber
= (1..numSides).random()
       
return randomNumber
   
}
}

以上でさいころを振るプログラムの作成はおしまいです。

(補足)作成したコードを短くする

今回のままでも十分ですが、より短くしてコードの容量を小さくします。
このようにコードの挙動を変えずにコードを短くしたり、効率よくしたり、読みやすくすることをリファクタリングというそうです。

最初にコードを書いて、リファクタリングをしていくことで洗練されたコードにしていきます。

今回作成したコードの中で無駄な箇所は2つです。
1つはroll関数の中身です。
randomNumber中にさいころを振ったっ結果を入れてからその変数を返り値で返していますが、さいころを振った結果をそのまま返り値で返せばより短くすることできます。

変更前
fun roll(): Int {
        val randomNumber
= (1..numSides).random()
       
return randomNumber
}
変更後
fun roll(): Int {
   
return (1..numSides).random()
}
二つともコードの挙動は変わりませんが、変更後の方が短いソースコードになりました。

2つ目はmain関数内の1つ目のさいころを振る箇所です。
2つ目のさいころと同様にprintlnで表示する際にさいころを振れば、1行短くすることができます。

最終的に短くなったコードがこちらです。
fun main() {
    val myFirstDice
= Dice(6)
    println
("Your ${myFirstDice.numSides} sided dice rolled ${myFirstDice.roll()}!")
   
    val mySecondDice
= Dice(20)
    println
("Your ${mySecondDice.numSides} sided dice rolled ${mySecondDice.roll()}!")
}

class Dice (val numSides: Int) {

    fun roll
(): Int {
       
return (1..numSides).random()
   
}
}
これで最初に作ったコードと同じ挙動で、より短いコードとなりました。

詳しく知りたい人へ

講座に記載された参考URLを記載します(今回は全部英語なので、わかりにくいかもしれませんが)

0 件のコメント :

コメントを投稿