百日学 Swift(Day 21) – Project 2, part two(项目 2 :第 2 部分)
没有完全按照教程的内容,适当做了一些调整
1. 准备工作
(1)创建国旗的结构体,两个属性:国旗图片名(flagName
)和国家名(name
)。
struct country { // 国家
var flagName: String // 图片名称
var name: String // 国家名称
}
(2)初始化国旗数组
let countryArray: [country] = [ // 初始化,这个内容不能放在 ContentView 中,否则报错
country(flagName: "Estonia", name: "爱沙尼亚"),
country(flagName: "France", name: "法国"),
country(flagName: "Germany", name: "德国"),
country(flagName: "Ireland", name: "爱尔兰"),
country(flagName: "Italy", name: "意大利"),
country(flagName: "Nigeria", name: "尼日利亚"),
country(flagName: "Poland", name: "波兰"),
country(flagName: "Russia", name: "俄罗斯"),
country(flagName: "Spain", name: "西班牙"),
country(flagName: "UK", name: "英国"),
country(flagName: "US", name: "美国")
]
以上两步的代码要放在 ContentView 结构体之外,否则会报错。
(3)准备好题目
@State private var countries = countryArray.shuffled() // 打乱数组元素顺序
@State private var correctAnswer = Int.random(in: 0...2) // 在 0-2 之间随机选一个值
Shuffled 和 shuffle 的区别
打乱的效果是一样的,只是用途不同。
func shuffled() -> [Base.Element]
mutating func shuffle()
*(4)声明记录分数的状态
@State private var score = 0 // 得分,答对数量
@State private var questionNum = 0 // 题目数
2. Stacking up buttons(堆叠按钮)
有了前面的准备,现在开始设计 UI,使用 VStack 作为容器。
(1)先使用一个 VStack 将文字部分包裹好。
VStack(spacing: 20) {
Text("猜国旗")
.font(.largeTitle)
.fontWeight(.black)
Text("请点击下面你认为正确的国旗")
// .font(.subheadline)
.fontWeight(.bold)
Text(countries[correctAnswer].name)
.font(.title)
.fontWeight(.black)
}.foregroundColor(.white)
(2)使用循环创建三个按钮,按钮的图片为国旗,动作为调用 flagTapped()
,传入当前按钮的索引值供检查正确与否。
ForEach(0..<3) { number in
Button(action: {
self.flagTapped(number) // 按钮动作
}) {
Image(self.countries[number].flagName)
.renderingMode(.original)
.clipShape(Capsule())
.overlay(Capsule().stroke(Color.gray, lineWidth: 1))
}
.shadow(color: Color(.white), radius: 5, x: 15, y: 15)
}
(3)将按钮与文字部分共同放入一个 VStack 中。
(4)使用 ZStack 包裹,在最底层增加底色。
ZStack {
// Color.blue.edgesIgnoringSafeArea(.all) 是另一种使用纯色的方法
LinearGradient(
gradient: Gradient(colors: [.blue, .black]),
startPoint: .topLeading,
endPoint: .bottomLeading).edgesIgnoringSafeArea(.all) // 使用渐进做底色
VStack(spacing: 30) {
VStack(spacing: 20) { //文字部分
(5)适当调整界面,如边距、字体、颜色等.
var body: some View {
ZStack {
// Color.blue.edgesIgnoringSafeArea(.all)
LinearGradient(
gradient: Gradient(colors: [.blue, .black]),
startPoint: .topLeading,
endPoint: .bottomLeading).edgesIgnoringSafeArea(.all) // 使用渐进做底色
VStack(spacing: 30) {
VStack(spacing: 20) { //文字部分
Text("猜国旗")
.font(.largeTitle)
.fontWeight(.black)
Text("请点击下面你认为正确的国旗")
// .font(.subheadline)
.fontWeight(.bold)
Text(countries[correctAnswer].chsName) // 国家中文名字
.font(.title)
.fontWeight(.black)
}.foregroundColor(.white)
ForEach(0..<3) { number in // 三个按钮
Button(action: {
self.flagTapped(number) // 按钮动作
}) {
Image(self.countries[number].name) // 图片名称
.renderingMode(.original) // 显示原图
.clipShape(Capsule()) // 剪裁成胶囊形状
.overlay(Capsule().stroke(Color.black, lineWidth: 1)) // 边框
}
.shadow(color: Color(.black), radius: 5, x: 0, y: 5) // 阴影
}
Spacer()
}
.padding(.top, 30) // 边距
}
.alert(isPresented: $showingScore) {
Alert(
title: Text(scoreTitle),
message: Text("你已经猜了 \(questionNum) 次\n你猜对了 \(score) 次"),
dismissButton: .default(Text("继续")){
self.askQuestion()
})
}
}
2. Showing the player’s score with an alert(使用警告消息显示玩家得分)
(1)声明控制警告对话框的状态
@State private var showingScore = false // 控制显示警告,默认不显示
@State private var scoreTitle = "" // 警告信息
(2)响应按钮的点击动作的函数 flagTapped
func flagTapped(_ number: Int) {
questionNum += 1 // 题目数量 +1
if number == correctAnswer {
scoreTitle = "恭喜你,答对了!!"
score += 1 // 答对时,得分 +1
} else {
scoreTitle = "不太对呢,再想想?"
}
showingScore = true
}
(3)给 ZStack 加上 alert 修饰
.alert(isPresented: $showingScore) {
Alert(
title: Text(scoreTitle),
message: Text("你已经猜了 \(questionNum) 次\n你猜对了 \(score) 次"),
dismissButton: .default(Text("继续")){
self.askQuestion() // 点击 继续 按钮的动作
})
}
(4)复位题目 askQuestion
func askQuestion() {
countries.shuffle()
correctAnswer = Int.random(in: 0...2)
}
3. Styling our flags(修改国旗的样式)
Image(self.countries[number].name) // 图片名称
.renderingMode(.original) // 显示原图
.clipShape(Capsule()) // 剪裁成胶囊形状
.overlay(Capsule().stroke(Color.black, lineWidth: 1)) // 边框