#13–2 選擇題 App
功能規劃
- 題庫總共有30題,隨機出10題
- 答對一題得10分,在畫面上顯示
- 畫面上會顯示目前的題數
- 玩完一次後可以重新再玩
- 每題四個選項的順序不固定
- 會顯示前一次回答的選項與答案,一共累計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}