iT邦幫忙

2023 iThome 鐵人賽

DAY 28
0

目錄

  1. 修改程式
  2. 連結 View
  3. 進度展示

正文

修改程式

第一步是把昨天醜到爆炸的程式改好看一點!

  1. 經過一番查詢,我找到了 keys 這個函式,功能是將 Map 所有的 key 匯聚成 Set 型態並回傳

    // Returns a read-only Set of all keys in this map.
    abstract val keys: Set<K>
    
  2. 接下來我在 Set 形態中又找到了 elementAt 這個函式,由於 Set 沒有順序關係,所以功能是依照 存取的先後順序來讀取第 n 個值

    // Returns an element at the given index or throws an IndexOutOfBoundsException if the index is out of bounds of this array.
    fun <T> Iterable<T>.elementAt(index: Int): T
    
  3. 因為昨天甚麼 index、Number 之類的太容易搞混了,所以我有先修改一些變數名稱:

    private val _questionBankHiragana: Map<String, String> = mapOf("a" to "あ","i" to "い","u" to "う","e" to "え","o" to "お",
                                                                   "ka" to "か","ki" to "き","ku" to "く","ke" to "け","ko" to "こ",
                                                                   "sa" to "さ","shi" to "し","su" to "す","se" to "せ","so" to "そ",
                                                                   "ta" to "た","chi" to "ち","tsu" to "つ","te" to "て","to" to "と")
    private var _question: String = ""
    private val _choices: Array<String?> = arrayOfNulls<String>(5)
    private var _ansNumber: Int = 0
    
  4. 再把 setPaper 那邊的程式碼整理一下,改名成 updateQuestion,變成下面這個樣子:

    public fun updateQuestion(){
          val mode = (1..2).random()
          val correctAnsNumber = (0..getQuestionLastNumber()).random()
          val keys:Set<String> = _questionBankHiragana.keys
          _ansNumber = (1 .. 4).random()
    
          if(mode == 1){ // 題目是 key,選項是 value
              _question = keys.elementAt(correctAnsNumber)
              _choices[_ansNumber] = _questionBankHiragana[_question]
          }
          else if(mode == 2){ // 題目是 value,選項是 key
              _choices[_ansNumber] = keys.elementAt(correctAnsNumber)
              _question = _questionBankHiragana[_choices[_ansNumber]].toString()
          }
          val otherChoice:Array<String?> = getOtherChoice(mode,correctAnsNumber,keys)
          var count = 0
          for (i in 0..3){
              if(i == _ansNumber)
                  continue
              _choices[i] = otherChoice[count]
              count++
          }
      }
    
  5. 還要記得修一下 getOtherChoice 的程式碼,變成下面這個樣子:

    public fun getOtherChoice(mode: Int, correctAnsNumber: Int, keys: Set<String>): Array<String?>{
        val otherChoice: Array<String?> = arrayOfNulls<String>(3)
        var count = 0
        while(count <= 2){
            var worngAnsNumber = (0..getQuestionLastNumber()).random()
            if(worngAnsNumber==correctAnsNumber)
                continue
            if(mode==1){ // 題目是 key,選項是 value
                otherChoice[count] = _questionBankHiragana[keys.elementAt(worngAnsNumber)]
            }
            else if(mode==2){ // 題目是 value,選項是 key
                otherChoice[count] = keys.elementAt(worngAnsNumber)
            }
            count++
        }
        return otherChoice
    }
    

連結 View

  1. 記得先在主程式中宣告 Test

  2. 我們需要學一個酷東西叫做延遲,我希望當點擊選項後大概三秒鐘,才會跳轉到下一題,也方便之後顯示回答是否正確,延遲語法如下

    Handler().postDelayed(Runnable {
        // 延遲後要做的事寫在這裡
    },3000); // 這裡寫想要延遲的秒數,單位是 ms
    
  3. 最後把 onCreateView 的程式改成這樣:

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        binding = FragmentHomeBinding.inflate(inflater,container,false)
        val view = viewBinding.root
        setPaper(viewBinding)
        viewBinding.firstButton.setOnClickListener{
            viewBinding.firstButton.setOnClickListener{
            Handler().postDelayed(Runnable {
                setPaper(viewBinding)
            },3000);
        }
        }
        viewBinding.secondButton.setOnClickListener{
            Handler().postDelayed(Runnable {
                setPaper(viewBinding)
            },3000);
        }
        viewBinding.thirdButton.setOnClickListener{
            Handler().postDelayed(Runnable {
                setPaper(viewBinding)
            },3000);
        }
        viewBinding.fouthButton.setOnClickListener{
            Handler().postDelayed(Runnable {
                setPaper(viewBinding)
            },3000);
        }
        return view
    }
    
  4. 我又多寫了一個 setpaper,用來呼叫 test 得到題目資料

    public fun setPaper(viewBinding: FragmentHomeBinding){
        test.updateQuestion()
        viewBinding.textView2.text = test.getQusetion()
        viewBinding.firstButton.text = test.getChoice(0)
        viewBinding.secondButton.text = test.getChoice(1)
        viewBinding.thirdButton.text = test.getChoice(2)
        viewBinding.fouthButton.text = test.getChoice(3)
    }
    

進度展示

影片連結

總結

昨天的 bug 其實蠻多的,但在重新架構的時候大部分問題就被處理掉了;這邊跟大家講一個小知識,如果按下 RUN app 結果程式一直跳掉代表程式有問題,項是我剛剛在分配題目給 otherChoice的時候,好像有 overflow 的問題,然後改完就正常了,真開心!

下一篇我們來處理排版和偵測答案是否正確 ~

參考資料

Kotlin 學習筆記(8)-集合函數
https://andyludeveloper.medium.com/kotlin-學習筆記-8-集合函數-2922bbf44b77

<>實現delay的效果-以及timer
https://lynn5133.pixnet.net/blog/post/459338761-<>實現delay的效果-以及timer

Android-用 Handler 製造出延遲( delay ) 發生的效果
https://brianchen85.blogspot.com/2014/12/android-handler-delay.html


上一篇
Day.27 夢想專案(日文學習 APP) - 7 程式架構 Map 和 Array
下一篇
Day.29 夢想專案(日文學習 APP) - 9 調整按鈕背景色
系列文
剛學Kotlin的我想要玩安卓開發,自學 Android Studio 30 天31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言