#13–2 選擇題 App

功能規劃

  1. 題庫總共有30題,隨機出10題
  2. 答對一題得10分,在畫面上顯示
  3. 畫面上會顯示目前的題數
  4. 玩完一次後可以重新再玩
  5. 每題四個選項的順序不固定
  6. 會顯示前一次回答的選項與答案,一共累計10題,在重玩時消除

產生一個新的類別

路徑:File / New / File ,選擇 Swift File ,接著在 Save AS 欄位填入自創的 Class 名稱 Question。

定義需要使用的變數,因為之後才會帶值進去先讓它是空的字串。

class Question{var description = [“”]var answer = “”var worngAnswer = [“”]}

說明

因為選擇題需要對答案,所以將選項分成兩個變數:分別是一個『答案』和三個『錯誤的答案』。

而問題描述部份使用 array 是因為不知道怎麼調整 UILabel 內文字的間距,其實只是為了讓字不要黏在一起並且讓空格和其他字一樣寬。

回到 ViewController 設定 @IBOutlet

//記錄分數的Label
@IBOutlet
weak var scoreLabel: UILabel!
//記錄題數的Label
@IBOutlet
weak var sequenceLabel: UILabel!
//顯示問題的Label(因為是四個字的成語所以分成四個Label)
@IBOutlet
var questionLabel: [UILabel]!
//選項
@IBOutlet
var optionButton: [UIButton]!
//用來顯示結果(對答案用的)
@IBOutlet
weak var resultLabel: UILabel!
//再一次按鈕(因為希望在第10題才顯示,所以需要命名)
@IBOutlet
weak var againButton: UIButton!
//用來儲存所有問題的array
var
questions = [Question]()
//用來存取次數及存取問題array的數值
var
index = 0
//用來計算分數
var
point = 0
//用來記錄答案
var
result = “”

Function1 -設定初始畫面/資料的 ViewDidLoad

override func viewDidLoad() {super.viewDidLoad()/*...這裡有一大段程式是在設定背景和問題後面的線條...
因為和功能沒有直接關係先刪除...*/
//顯示分數:0
scoreLabel.text = “\(point)”
//顯示目前一剛開始的題數:1
sequenceLabel.text = “第 \(index + 1) 題”
//設定第一個問題並加入questions的array裡
let
question1 = Question()
//問題是『』步自封
question1.description = [“”,”步”,”自”,”封”]
//三個錯誤答案的選項
question1.worngAnswer = [“固”,”梏”,”涸”]
//一個正確答案的選項
question1.answer = “故”
questions.append(question1)/*後面重複29次...因為都是一樣的先刪除...*///把問題的次序打亂
questions.shuffle()
//顯示問題,詳細請見下面說明***
for
n in 0…3{
questionLabel[n].text = questions[index].description[n]}//把所有的答案包進選項裡面
var
option = [questions[index].answer , questions[index].worngAnswer[0] , questions[index].worngAnswer[1] , questions[index].worngAnswer[2]]
//把選項的次序打亂
option.shuffle()
//顯示選項,詳細在下面說明***
for
i in 0…3 {
optionButton[i].setTitle(option[i], for: .normal)}//隱藏再一次按鈕
againButton.isHidden = true
}

說明

顯示問題的程式

for n in 0…3{questionLabel[n].text = questions[index].description[n]}

questionLabel 是 array 一共有四個,設定的問題也是有四個 String 的 array ,所以要照順序把問題填進 UILabel 裡。這裡的重點在於讀取 array 的順序,只要順序一樣字就不會亂掉。因此,設定一個變數叫 n ,然後依照順序填進 0 到 3 的數值。

questionLabel[0].text 表示是最左邊的 questionLabel
questions[index].description[0] 表示成語的第一個字
用 questions[index]是因為用來存取題目的變數是 index

顯示選項的程式

var option = [questions[index].answer , questions[index].worngAnswer[0] , questions[index].worngAnswer[1] , questions[index].worngAnswer[2]]option.shuffle()for i in 0…3 {optionButton[i].setTitle(option[i], for: .normal)

最前面有說到,選擇題有四個選項而且必須要對答案,所以變數分成了兩個:『一個正確答案』和『三個錯誤的答案』。但選項是四個 optionButton 集合的 array ,所以要先把答案們變成一個 array 這樣才能分別填進 UIButton 裡。

但是變成 array 的 option 出了一個毛病,就是第一個都是正確答案,這樣就跟遇到不會的題目就選第一個一樣,所以派出 shuffle() 來把選項次序打亂。

最後就跟問題一樣,按照順序把打亂的 option 放進 optionButton 裡。這裡沒有用到 index 是因為在設定 option 參數時已經設定好了,不會有牛頭不對馬嘴的情形 😄。

Function2 -按下選項的按鈕以後…

@IBAction func answer(_ sender: UIButton) {//設定被按下的按鈕就是你的答案
let
yourAnswer = sender.currentTitle!
//設定這個問題的答案是正確答案
let
correctAnswer = questions[index].answer
/* 前面這兩個很重要,如果不設定這兩個常數,app有時候會不認識被按下的按鈕,得不到分數事小,要是被投訴要求賠償很麻煩 *///如果你的答案跟正確答案一樣,會加10分(要記得顯示分數),然後標註起來打個勾
if
yourAnswer == correctAnswer {
point = point + 10scoreLabel.text = “\(point)”result = result + “第 \(index + 1) 題答案 『\(correctAnswer)』,你的選擇『 \(yourAnswer)』✔️”} else {//如果答案不一樣,那麼一樣要標註起來給個叉
result = result + “第 \(index + 1) 題答案 『\(correctAnswer)』,你的選擇『 \(yourAnswer)』❌”
}//如果在第1~9題,每按下一次選項就會到下一題
if
index < 9 {
index = index + 1sequenceLabel.text = “第 \(index + 1) 題”for n in 0…3{questionLabel[n].text = questions[index].description[n]}var option = [questions[index].answer , questions[index].worngAnswer[0] , questions[index].worngAnswer[1] , questions[index].worngAnswer[2]]option.shuffle()for i in 0…3 {optionButton[i].setTitle(option[i], for: .normal)}} else if index == 9 {
//如果在第10題,就不會顯示下一題,但給你一個『再一次』按鈕
againButton.isHidden = false}resultLabel.text = result}

沒關係!是 result 啊~

每次按下選項後只有分數會說明對錯感覺很空虛,就用 result 來幫忙標示正確答案。但是如果只能看前一題的答案有點奇怪,所以就讓每一題的答案都顯示出來(像對答案一樣)。這裡出現了一個我想了一個晚上的問題:UILabel 怎麼換行?結果答案超簡單,把寬度設定好就可以了,這樣超出範圍就會自己換行了 😆

不過因為這個 result 就沒有版面可以放玩家歷史紀錄了,阿哈 😅

Function3 -歸零的再一次按鈕

顧名思義按下再一次按鈕要把一切從頭來過,讓 index 、 point 變回 0、result 清乾淨,記得這裡就要在 UILabel 顯示不然要等到下一題才會消失。問題和選項要在打亂排序後顯示,最後記得把再一次按鈕藏起來,就這樣結束 👏👏👏

@IBAction func tryAgain(_ sender: Any) {index = 0point = 0result = “”scoreLabel.text = “\(point)”sequenceLabel.text = “第 \(index + 1) 題”resultLabel.text = resultquestions.shuffle()for n in 0…3{questionLabel[n].text = questions[index].description[n]}var option = [questions[index].answer , questions[index].worngAnswer[0] , questions[index].worngAnswer[1] , questions[index].worngAnswer[2]]option.shuffle()for i in 0…3 {optionButton[i].setTitle(option[i], for: .normal)}againButton.isHidden = true}

完整程式盡在GitHub

https://github.com/LetaLei/theNewCrosswordApp

--

--