百日学 Swift(Day 21) – 项目 2 :第 2 部分

百日学 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 的区别

打乱的效果是一样的,只是用途不同。

  • shuffled

    是一个普通函数,有返回值,可以赋值给其他数组。

func shuffled() -> [Base.Element]

  • Shuffle

    是一个 mutating 函数,用于改变自身,所以***没有返回值***,改变的是***调用者***自己。

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))	// 边框 

发布了77 篇原创文章 · 获赞 16 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/hh680821/article/details/105229707
今日推荐