kotlinで、一次元配列とシャッフルを使った
簡単な四択クイズアプリを作ってみたいと思います。
動画
コード
▼activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/tvCount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:layout_marginEnd="24dp"
android:layout_marginRight="24dp"
android:text="0問正解"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tvQuestion"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="番号順にタッチせよ"
android:textSize="24sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tvCount" />
<Button
android:id="@+id/btn0"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="90dp"
android:text="Button"
app:layout_constraintTop_toBottomOf="@+id/tvQuestion"
tools:layout_editor_absoluteX="187dp" />
<Button
android:id="@+id/btn1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:text="Button"
app:layout_constraintTop_toBottomOf="@+id/btn0"
tools:layout_editor_absoluteX="129dp" />
<Button
android:id="@+id/btn2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:text="Button"
app:layout_constraintTop_toBottomOf="@+id/btn1"
tools:layout_editor_absoluteX="160dp" />
<Button
android:id="@+id/btn3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:text="Button"
app:layout_constraintTop_toBottomOf="@+id/btn2"
tools:layout_editor_absoluteX="140dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
▼MainActivity.kt
package com.example.simplequiz
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.TextView
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//1)viewを取得(idで) + カウント用のiを用意
val tvCount:TextView =findViewById(R.id.tvCount)
val tvQuestion:TextView =findViewById(R.id.tvQuestion)
val btn0:Button = findViewById(R.id.btn0)
val btn1:Button = findViewById(R.id.btn1)
val btn2:Button = findViewById(R.id.btn2)
val btn3:Button = findViewById(R.id.btn3)
var i =0
//2)配列を用意
val quizData = arrayOf("A0","A1","A2","A3")
//4)0~3までのリスト用意⇒シャッフル
val list = listOf(0,1,2,3)
val num =list.shuffled()
//3)ボタンにquizDataの0~3を表示させてみる
//5)シャッフルされたnumの数字を入れる
btn0.text =quizData[num[0]]
btn1.text =quizData[num[1]]
btn2.text =quizData[num[2]]
btn3.text =quizData[num[3]]
//6)btn0を押した時の正誤判定
btn0.setOnClickListener {
if(btn0.text==quizData[i]){
//正解
//tvQuestion.text="正解!!"
//7)カウントを1増やして無効化
i++
btn0.isEnabled =false
tvCount.text =i.toString() + "問正解"
//9)i==4でGameClear
if(i==4){
tvQuestion.text="全問正解!!Game Clear!!"
}
}else{
//不正解+ボタンの無効化
tvQuestion.text="不正解!!Game Over"
btn0.isEnabled = false
btn1.isEnabled = false
btn2.isEnabled = false
btn3.isEnabled = false
}
}
//8)btn1~3も同じようにする
btn1.setOnClickListener {
if(btn1.text==quizData[i]){
//正解
//tvQuestion.text="正解!!"
//7)カウントを1増やして無効化
i++
btn1.isEnabled =false
tvCount.text =i.toString() + "問正解"
if(i==4){
tvQuestion.text="全問正解!!Game Clear!!"
}
}else{
//不正解+ボタンの無効化
tvQuestion.text="不正解!!Game Over"
btn0.isEnabled = false
btn1.isEnabled = false
btn2.isEnabled = false
btn3.isEnabled = false
}
}
btn2.setOnClickListener {
if(btn2.text==quizData[i]){
//正解
//tvQuestion.text="正解!!"
//7)カウントを1増やして無効化
i++
btn2.isEnabled =false
tvCount.text =i.toString() + "問正解"
if(i==4){
tvQuestion.text="全問正解!!Game Clear!!"
}
}else{
//不正解+ボタンの無効化
tvQuestion.text="不正解!!Game Over"
btn0.isEnabled = false
btn1.isEnabled = false
btn2.isEnabled = false
btn3.isEnabled = false
}
}
btn3.setOnClickListener {
if(btn3.text==quizData[i]){
//正解
//tvQuestion.text="正解!!"
//7)カウントを1増やして無効化
i++
btn3.isEnabled =false
tvCount.text =i.toString() + "問正解"
if(i==4){
tvQuestion.text="全問正解!!Game Clear!!"
}
}else{
//不正解+ボタンの無効化
tvQuestion.text="不正解!!Game Over"
btn0.isEnabled = false
btn1.isEnabled = false
btn2.isEnabled = false
btn3.isEnabled = false
}
}
}
}
テキスト
今回の主な学習のテーマは配列と、シャッフルです。
配列でいくつかの要素を用意して
それをシャッフルして、不規則に表示させる、というのをやっていきましょう。
ちなみに配列以外も色々やっていますが、それらは過去の動画の復習も兼ねています。
例えば、
正解・不正解を条件分岐するのはifですし、
正解表示はアラートダイアログです。
カウントが1ずつ増えるのは、インクリメント。
といった感じになります。
アラートダイアログだけ、次の動画の後編というか、完結編の方で解説しますが
ここでは、配列を表示して、シャッフルして並び替えて、正解・不正解の判定までやっていきます。
で、配列について、少しだけ解説しておきます。
配列について
で、配列について少しだけ解説しておきます。
配列は、このようにアレイオブとかいて、()の中に要素を格納します。
※順番は、左から、0番目、1番目、2番目、3番目、という風に0から数えるので注意が必要です。
取り出し方法ですが、
変数名に四角いカッコで繋ぎます。
これで、この名前の配列、という意味になります。
このかっこに、取り出したい数字を入力します。
例えば、
name[1]と入力したら、
この変数の、左から0番目(いぬ)⇒1番目(さる)で、「さる」、を差します。
数字の方も同じで、例えば
num[3]
と入れると、0⇒1⇒2⇒3番目の 40のことになります。
こんな感じでふんわり、配列が理解できたところで、早速はじめていきましょう
(XMLは割愛)
1.Viewの取得
それではプログラムをやっていきましょう。
ktを開いてください。
まずは、レイアウトの要素をidで取得していきます。
6つですね。
//1)viewを取得(idで) + カウント用のiを用意
val tvCount:TextView=findViewById(R.id.tvCount)
val tvQuestion :TextView = findViewById(R.id.tvQuestion)
val btn0:Button=findViewById(R.id.btn0)
val btn1:Button=findViewById(R.id.btn1)
val btn2:Button=findViewById(R.id.btn2)
val btn3:Button=findViewById(R.id.btn3)
var i = 0
それと、正解数をカウントしていくので、変数iも作っておきましょう。
ひとまず0を代入しておきますが
カウントは後で加算して変更されるのでvalではなくてvarです。
ひとまずこれで完成です。
それでは次に、今回の本題
配列を準備しましょう
2.配列の準備
それでは次に、今回の主役、配列を用意してあげましょう。
ひとまず、「1」の下に続けて表記しておきます。
//2)配列を用意
val quizData = arrayOf("A0","A1","A2","A3")
それでは、これで配列が用意できたので、いったん、この配列をボタンに表示させてみましょう。
3.ボタンに配列を表示させてみる
それではViewが取得できて
配列も用意できたので
ひとまず、これらのボタンに配列を表示させてみましょう。
とりあえず1個、練習がてら
btn0.text = quizData[0]
これで一旦エミュレータを起動して、確認してみましょう。
ボタンの0だけ、配列の0番目が表示されているはずです。てことで、これと同じようにして
全ての配列を表示させてみましょう。
//3)ボタンにquizDataの0~3を表示させてみる
btn0.text = quizData[0]
btn1.text = quizData[1]
btn2.text = quizData[2]
btn3.text = quizData[3]
これで、今はButtonってなっているテキストに
arrayOf(“A0″,”A1″,”A2″,”A3”)
が表示されるようになっているはずです。
ただし、このままだと、何回起動しても、この順番ですよね。
なので、次は順番を並び替える「シャッフル」というのをしていきます。
4.シャッフル
それではですね、
このボタンの表示が毎回違う並びになるようにしたいんですが
そもそもこの並びとはなんぞやと、いうところを見ていきたいと思います。
当然、このquizData[]のならびですよねと。
今は0123,になっているので、順番に、配列の0123,と表示されています。
てことは、ここの数字が0123じゃなくて
毎回違う数字で並んでくれればいいわけです。
てことで、とりあえず説明は後にして正解だけ書いていきますね。
//4)0~3までのリスト用意⇒シャッフル
val list = listOf(0,1,2,3)
val num = list.shuffled()
まず、配列と似たようなやつでlistっていうのを用意してあげます。
配列がarrayOfなのに対して
listはlistOfと書いてあげます。
中身が数字の時は、普通にコンマで区切ればOKです。
文字の時には、チョンチョンで区切ってあげるので、使い分けに注意が必要です。
で、ナンバー略してnumを用意してあげて、この中にシャッフルした数字を代入します。
***********************************
で似たようなやつでランダムっていうのもあります。
ランダムとシャッフルの違いは、同じものが重複するかどうか、みたいな感じです。
以前占いアプリを作りましたが、その時はランダムを使いました。
大吉が何度も出ることもあれば、全然でないこともあると。
一方シャッフルの場合は、順番を並べ替えるだけなので
重複はしませんし、ちゃんと1回出てきます。
という違いがあります。
***********************************
5.シャッフルを表示
そしたら今、numの中には「0~3」までの数字が
何かしら並べ替えられています。
ということは、ここが0123ではなくて
numの、中身はわからないけど0番目
numの、中身はわからないけど1番目
numの、中身はわからないけど2番目
numの、中身はわからないけど3番目
という風にしてあげると、
quizDataの中身が並べ替えられていると思います。
//5)シャッフルされたnumの数字を入れる
btn0.text = quizData[num[0]]
btn1.text = quizData[num[1]]
btn2.text = quizData[num[2]]
btn3.text = quizData[num[3]]
エミュレータを起動して確認してみましょう。
こうですね。
このようになっていますし、
もう一度立ち上げてみると、
今度はこのようになっています。
で、先ほどから気になっている
listOfってなんやねんって話ですよね。
厳密にいうと、中身を書き換えできるとか、できないとか、
使い分ける違いはあるんですが
今回はとりあえずlistを使えばshuffled()が用意されるので簡単ですってだけの話です。
もちろんarrayOfでも使えますが、一手間増えてややこしいんで
せっかくなので紹介がてらlistってのを使った、くらいな感じです。
今回に関して言えば、そんな感じであまり深い理由はないです。
配列と同じ仲間でlistってのがあるので
それを使うと簡単にシャッフルできますよっていう紹介です。
それでは次に、ボタンを押した時の正解・不正解を判定してあげましょう。
6.正誤判定
それでは次に、正誤判定をしていきましょう。
ifを使います。
まずは練習で、
btn0を押して、
それがA0だったら正解
それ以外だったら不正解、としてみましょう。
//6)btn0を押した時の正誤判定
btn0.setOnClickListener {
if(btn0.text==quizData[0]){
//正解
}else{
//不正解
}
}
正解の場合は、ここのタイトルテキストに正解!と表示させて
tvQuestion.text=”正解!!”
それ以外の場合は、
tvQuestion.text=”不正解!!Game Over”
と表示させてみましょう。
//6)btn0を押した時の正誤判定
btn0.setOnClickListener {
if(btn0.text==quizData[0]){
//正解
tvQuestion.text="正解!!"
}else{
//不正解
tvQuestion.text="不正解!!Game Over"
}
}
はい、上手くいきました。
で、正解の場合はともかく、不正解の場合はGame Overなので、
ボタンを押せないように無効化してあげます。
//不正解+ボタンの無効化
tvQuestion.text="不正解!!Game Over"
btn0.isEnabled = false
btn1.isEnabled = false
btn2.isEnabled = false
btn3.isEnabled = false
それではエミュレータを起動して確認してみましょう。
はい、不正解の場合は、ゲームオーバーで、全部のボタンが無効化されました。
あとは、同じことをのこりのボタンにもやってあげるだけなので
不正解の場合は基本的にはひとまずこれで終了です。
では、
正解した場合は、カウントを増やしてあげる、という作業をしていきましょう。
7.正解した場合、カウントiを1加算
正解した場合、カウントiを1増やしてあげましょう。
//7)カウントを1増やす
i++
で、tvQuestionに「正解」と表示させるのをやめて
//tvQuestion.text=”正解!!”
tvCountに正解数を表示させます。
//正解
//tvQuestion.text="正解!!"
//7)カウントを1増やす
i++
tvCount.text=i.toString() + "問正解"
そして、押されたボタンを無効化させたいので、
足した後にはEnabledをfalseにしてあげます。
//7)カウントを1増やして無効化
i++
btn0.isEnabled = false
tvCount.text=i.toString() + "問正解"
これで、ボタンの0を押した時、
クイズデータの0と等しい場合
カウントが1増えて、
ボタンが無効化されて
1問正解と表示されるようになっているはずです。
ではエミュレータを起動して確認してみましょう。
はい、このように、
ボタンが無効化されて
カウントが1増えているのがわかります。
てことはですよ。
これと同じことをしてあげればいいので、
setOnClickListenerを完全にコピーして
数字だけ変えていきましょう。
8.btn1~3も、全ボタンが押せるようにする
それでは、今ボタンの0だけ押せるようになったので
同じことを1,2,3でもやってあげましょう。
てことでbtn0.setOnClickListenerをコピーして
3つはりつけて
btn0となっているところそれぞれ3か所を
各番号に変えてあげます。
———————————
btn1.setOnClickListener {
if(btn1.text==quizData[0]){
btn1.isEnabled = false
———————————-
btn2.setOnClickListener {
if(btn2.text==quizData[0]){
btn2.isEnabled = false
———————————-
btn3.setOnClickListener {
if(btn3.text==quizData[0]){
btn3.isEnabled = false
———————————
これで今何が起きたかというと、
btn1を押した時にquizDataの0番目と等しい場合正解、
それ以外は不正解でボタンは無効化。
btn2も3も、とりあえず0番目と等しいかどうかで
正解、不正解ができるようになりました。
ではエミュレータを起動して確認してみましょう。
はい、0の番号が押されたら
カウントが1追加されて、ボタンが無効化されているのがわかります。
逆に、0以外を押した場合は、
不正解になって、全て無効化されているのがわかります。
てことで、不正解はこれで完全に終了です。
**********************************
で、今はquizDataが0の時ってことになってるんですけど
これを4つのボタン全部「i」に変えてみてください。
最初の0をクリックしたら
もちろん正解。
で、このときiが1加算されているので、
次は条件分岐みてください
quizData[i]
クイズデータの1番目と等しいならば、という風に変わってるんです。
てことはですよ。
A1をクリックすると正解
で、iが1加算されたので今、iは2になってます。
てことは
quizData[i]
クイズデータの2番目と等しいならば、という風に変わってるんです。
ではA2をクリックしてみましょう。
はい、こんな感じですね。
順番に押していくと、iが1つずつ加算されるので
全問正解することができました。
基本的にはこれで終了なんですが、
最後にもう1回if文を追加して
iが4になったら「全問正解」というのも頑張って挑戦してみましょう。
9.if文で全問正解の場合
それでは最後に、
カウントのiが4になった全問正解、と表示させる
条件分岐をしてあげましょう。
btn0のsetOnClickListenerの中で、
iが1増えた一連の流れの下に
//9)i==4でGameClear
if(i==4){
tvQuestion.text="全問正解!!Game Clear!!"
}
これを、各ボタンの下に追加してあげます。
それでは最後にエミュレータを起動して確認してみましょう。
————————————
はい、上手くいっているのがわかります。
動作としてのプログラム解説は以上です。
次回は、重複しているコードを関数で一か所にまとめて、シンプルにする、というのをやって完成です。