巢狀迴圈練習:九九乘法表 + 畫幾何圖形

因為大學不是念資工的,學程式的經驗也都是自學來的,想說要多練習一下,就拿彼得潘的這篇這篇合在一起做。

先上成果:

九九乘法表

其實就是一般最常見的迴圈練習,只是為了排版好一點點,分成三段用三個TextView呈現,並多加了幾個button,可以reset成等號右邊沒東西的狀態。

以下是其中一段的內容:

for number in 1...3{
for secondnumber in 1...9{
defaulttext.append("\(number) * \(secondnumber) = \n")
}
defaulttext.append("\n")
}

for number in 4...6{
for secondnumber in 1...9{
defaulttexttwo.append("\(number) * \(secondnumber) = \n")
}
defaulttexttwo.append("\n")
}

for number in 7...9{
for secondnumber in 1...9{
defaulttextthree.append("\(number) * \(secondnumber) = \n")
}
defaulttextthree.append("\n")
}

畫圖部分基本UI

我決定用太陽跟月亮的表情符號,做出類似像素圖案的效果,所以太陽跟月亮要先做成一個二維的Array,再呈現在TextView中

基本的,只有月亮的Array,可以這樣產生:

SunMoonArray = Array(repeating: Array(repeating: "🌚", count: 9), count: 9)

然後用一個自己創的loadview()函數,去把這個Array轉成TextView上的字串:

func loadview(){

if SunMoonTextView.text != "" {
SunMoonTextView.text = ""
}

for i in 0...8{
for s in 0...8{
SunMoonTextView.text.append("\(SunMoonArray[i][s])")
}
SunMoonTextView.text.append("\n")
}

}

接下來,畫面中要用segment跟slider去分別決定圖形、行數,其中要考慮到切換的時候如何重置、重載TextView,或是後面畫菱形跟金字塔的時候,只能接受奇數的行數等等,所以程式碼宣告如下:

var shape = 0
var lines = 0
@IBAction func shapesegment(_ sender: UISegmentedControl) {
shape = sender.selectedSegmentIndex

//切換segment的時候先出現全部月亮的底圖
SunMoonArray = Array(repeating: Array(repeating: "🌚", count: 9), count: 9)
loadview()

//切換segment的時候重置,歸零
SliderOutlet.value = 0
LineLabel.text = "0"
}
@IBAction func linesofsun(_ sender: UISlider) {
lines = Int(sender.value)

//菱形跟金字塔只能用奇數
if shape >= 2 && lines % 2 != 0 || shape < 2 || lines == 0{
LineLabel.text = String(lines)
} else {
LineLabel.text = String(lines - 1)
lines = lines - 1
}
changeview()
}
  • 為了在segment切換的時候讓slider歸零,我把slider拉出第二條程式,改成@IBOutlet,才能在segment的@IBAction中讓他歸零
  • Shape就是代表segment到了哪個分頁,lines就是slider滑到第幾行
  • 因為第三、第四個分頁(shape = 2 , 3) 中,lines只能是奇數,所以才需要寫那些if else去調整slider傳送進lines的值

繪圖部分程式碼

func changeview(){
switch shape {

//正方形
case 0:
SunMoonArray = Array(repeating: Array(repeating: "🌚", count: 9), count: 9)
for i in 0...lines{
for s in 0...lines{
if i != 0, s != 0{
SunMoonArray[i-1][s-1] = "🌞"
}
}
}
loadview()

//三角形
case 1:
SunMoonArray = Array(repeating: Array(repeating: "🌚", count: 9), count: 9)
for i in 0...lines{
for s in 0...i{
if i != 0, s != 0{
SunMoonArray[i-1][s-1] = "🌞"
}
}
}
loadview()

//菱形
case 2:
SunMoonArray = Array(repeating: Array(repeating: "🌚", count: 9), count: 9)

var r : Int

for i in 0...lines{
if i <= 1{
r = 0
}else if Float(i) < Float(lines) / 2{
r = i - 1
}else{
r = lines - i
}

for s in (5-r)...(5+r){
if i != 0, s != 0{
SunMoonArray[i-1][s-1] = "🌞"
}
}
}
loadview()
//金字塔
case 3:
SunMoonArray = Array(repeating: Array(repeating: "🌚", count: 9), count: 9)
var r : Intfor i in 0...lines{
if i <= 1{
r = 0
}else if i % 2 != 0{
r = (i - 1) / 2
}else{
r = (i / 2) - 1
}

for s in (5-r)...(5+r){
if i != 0, s != 0{
SunMoonArray[i-1][s-1] = "🌞"
}
}
}
loadview()

default:
loadview()
}
}
  • 正方形跟三角形比較簡單,只要各自的i跟s(暫時拿來代表array的index)本身就可以做出來
  • 菱形跟金字塔就要另外設一個r,來代表每一行之中,從畫面垂直中線(s = 5)往左、往右畫出幾個太陽
  • 菱形裡面r的部分,就是先分成 i(行)是不是大於lines的一半,見下圖:

如果小於一半,r 就等於 i-1(例如7行菱形中的第1~3行,小於7/2=3.5);如果大於一半,r 就等於 lines-i(例如7行菱形中的第5~7行,大於7/2 = 3.5)。

  • 結果一開始要比較 r 跟 (i / 2)的大小的時候,忘記 i 是Int,除以2如果不是整除會無條件捨去,就出了一點錯誤;後來加上Float也一度寫錯,弄了很久:
// 錯誤的寫法
if Float(i) < Float(lines/2)
// 會變成lines如果是7,(line / 2)變成3,再加上float還是等於3.0
// 最後正確的寫法
if Float(i) < Float(lines) / 2
// 先把lines轉成7.0,再除以2,才會是我要的浮點數3.5
  • 金字塔就簡單多了,只要確定 i 是奇數或偶數就好,因為預想的圖案是兩行兩行為一組寬度

畫圖的部分,雖然花了很多時間去想迴圈要怎麼寫,但我不確定這是不是最好的解法,希望大家可以多多指教><

Github

--

--