1. 开始之前
您已经为掌握 Kotlin 编程基础知识付出了辛勤的努力,现在是时候将所学知识付诸实践了。
这些练习将测试您对所学概念的理解。它们围绕着现实世界的用例展开,其中一些您可能以前遇到过。
按照说明找到每个问题的解决方案。如果您遇到困难,一些练习提供了可以帮助您的提示。解决方案代码可在末尾找到,但强烈建议您在检查答案之前先解决练习。
可以将提供的解决方案视为解决问题的一种方法,请随意以您认为舒适的方式进行实验。有些练习可以通过多种方式解决,您可以使用不同的函数和变量名称。
按照您感到舒适的节奏解决问题。虽然列出了建议时长,但无需严格遵守这些时间,因为它们只是估算。建议您花尽可能多的时间仔细思考并解决每个问题。
建议您使用 Kotlin Playground 来解决这些练习。
前提条件
- 熟悉 Kotlin Playground
- 能够定义和调用函数
- 了解基本的 Kotlin 数据类型
- 了解不可变变量和可变变量
- 了解
println()
函数 - 完成以下 Codelab:您的第一个 Kotlin 程序、在 Kotlin 中创建和使用变量,以及 在 Kotlin 中创建和使用函数
您将需要
- 一台联网的计算机和一个网络浏览器
2. 打印消息
告诉您的朋友您在此学习路线中学到的知识。
- 您能否编写一个
main()
函数,将这些消息分四行打印出来?
Use the val keyword when the value doesn't change. Use the var keyword when the value can change. When you define a function, you define the parameters that can be passed to it. When you call a function, you pass arguments for the parameters.
3. 修复编译错误
此程序打印一条消息,通知用户收到了朋友的聊天消息。
fun main() {
println("New chat message from a friend'}
}
- 您能否找出此程序中编译错误的根本原因并修复它们?
- 代码是否使用了适当的符号来指示字符串和函数参数的开头和结尾?
提示:您可以使用 Kotlin Playground 运行代码并查看编译错误。
修复错误后,程序应该可以无误地编译并打印此输出
New chat message from a friend
4. 字符串模板
此程序通知用户有关特定商品的促销活动。它使用了一个字符串模板,该模板依赖于 discountPercentage
变量表示折扣百分比,并依赖于 item
变量表示促销商品。但是,代码中存在编译错误。
fun main() {
val discountPercentage: Int = 0
val offer: String = ""
val item = "Google Chromecast"
discountPercentage = 20
offer = "Sale - Up to $discountPercentage% discount on $item! Hurry up!"
println(offer)
}
- 您能否找出错误的根本原因并修复它们?
- 在 Kotlin Playground 中运行代码之前,您能否确定此程序的输出?
提示:您能否重新为只读变量赋值?
修复错误后,程序应该可以无误地编译并打印此输出
Sale - Up to 20% discount on Google Chromecast! Hurry up!
5. 字符串拼接
此程序显示聚会的总人数。聚会中有成年人和孩子。numberOfAdults
变量存储聚会中的成年人数,numberOfKids
变量存储孩子的人数。
fun main() {
val numberOfAdults = "20"
val numberOfKids = "30"
val total = numberOfAdults + numberOfKids
println("The total party size is: $total")
}
步骤 1
- 在 Kotlin Playground 中运行代码之前,您能否确定此程序的输出?
确定输出后,在 Kotlin Playground 中运行代码,然后检查您的输出是否与显示的输出匹配。
提示:当您对两个字符串使用 +
运算符时会发生什么?
步骤 2
代码可以工作并打印一些输出,但输出没有显示参加聚会的总人数。
- 您能否找到代码中的问题并修复它,使其打印此输出?
The total party size is: 50
6. 消息格式化
此程序显示员工本月获得的总薪资。总薪资分为两部分:baseSalary
变量,这是员工每月收到的基本工资,以及 bonusAmount
变量,这是授予员工的额外奖金。
fun main() {
val baseSalary = 5000
val bonusAmount = 1000
val totalSalary = "$baseSalary + $bonusAmount"
println("Congratulations for your bonus! You will receive a total of $totalSalary (additional bonus).")
}
- 在 Kotlin Playground 中运行此代码之前,您能否确定其输出?
- 在 Kotlin Playground 中运行代码时,它是否打印了您预期的输出?
7. 实现基本数学运算
在此练习中,您将编写一个执行基本数学运算并打印输出的程序。
步骤 1
此 main()
函数包含一个编译错误
fun main() {
val firstNumber = 10
val secondNumber = 5
println("$firstNumber + $secondNumber = $result")
}
- 您能否修复此错误,使程序打印此输出?
10 + 5 = 15
步骤 2
代码可以工作,但两个数字相加的逻辑位于结果变量内部,使得您的代码重用性较差。您可以将加法运算提取到一个 add()
函数中,以便代码可以重用。为此,请使用下面列出的代码更新您的代码。请注意,代码现在引入了一个新的 val
变量 thirdNumber
,并打印此新变量与 firstNumber
的结果。
fun main() {
val firstNumber = 10
val secondNumber = 5
val thirdNumber = 8
val result = add(firstNumber, secondNumber)
val anotherResult = add(firstNumber, thirdNumber)
println("$firstNumber + $secondNumber = $result")
println("$firstNumber + $thirdNumber = $anotherResult")
}
// Define add() function below this line
- 您能否定义
add()
函数,使程序打印此输出?
10 + 5 = 15 10 + 8 = 18
步骤 3
现在您有了一个可重用的函数来添加两个数字。
- 您能否像实现
add()
函数一样实现subtract()
函数?同时修改main()
函数以使用subtract()
函数,以便您可以验证其是否按预期工作。
提示:思考加法、减法和其他数学运算之间的区别。从那里开始编写解决方案代码。
8. 默认参数
Gmail 有一个功能,当用户在新设备上尝试登录时会发送通知。
在此练习中,您将编写一个程序,使用此消息模板向用户显示消息
There's a new sign-in request on operatingSystem for your Google Account emailId.
您需要实现一个函数,该函数接受 operatingSystem
参数和 emailId
参数,以给定格式构造消息并返回该消息。
例如,如果使用 "Chrome OS
" 作为 operatingSystem
参数值,并使用 "sample@gmail.com
" 作为 emailId
参数值调用该函数,它应该返回此字符串
There's a new sign-in request on Chrome OS for your Google Account sample@gmail.com.
步骤 1
- 您能否在此程序中实现
displayAlertMessage()
函数,使其打印显示的输出?
fun main() {
val operatingSystem = "Chrome OS"
val emailId = "sample@gmail.com"
println(displayAlertMessage(operatingSystem, emailId))
}
// Define your displayAlertMessage() below this line.
- 您的程序是否打印此输出?
There's a new sign-in request on Chrome OS for your Google Account sample@gmail.com.
步骤 2
做得好!您显示了消息。但是,在某些情况下,您发现无法确定用户的操作系统。在这种情况下,您需要将操作系统名称指定为 Unknown OS
。您可以进一步优化代码,以便在每次调用函数时都不需要传递 Unknown OS
参数。
- 您能否根据此信息找到一种优化代码的方法,使其打印此输出?
There's a new sign-in request on Unknown OS for your Google Account user_one@gmail.com. There's a new sign-in request on Windows for your Google Account user_two@gmail.com. There's a new sign-in request on Mac OS for your Google Account user_three@gmail.com.
- 要打印上面的消息,请将
main()
函数的实现替换为以下代码
fun main() {
val firstUserEmailId = "user_one@gmail.com"
// The following line of code assumes that you named your parameter as emailId.
// If you named it differently, feel free to update the name.
println(displayAlertMessage(emailId = firstUserEmailId))
println()
val secondUserOperatingSystem = "Windows"
val secondUserEmailId = "user_two@gmail.com"
println(displayAlertMessage(secondUserOperatingSystem, secondUserEmailId))
println()
val thirdUserOperatingSystem = "Mac OS"
val thirdUserEmailId = "user_three@gmail.com"
println(displayAlertMessage(thirdUserOperatingSystem, thirdUserEmailId))
println()
}
9. 计步器
计步器是一种计算行走步数的电子设备。如今,几乎所有手机、智能手表和健身装备都内置了计步器。健康与健身应用使用内置计步器计算行走步数。此函数根据用户的步数计算用户消耗的卡路里。
- 您能否根据最佳实践重命名此程序中的函数、函数参数和变量?
fun main() {
val Steps = 4000
val caloriesBurned = PEDOMETERstepsTOcalories(Steps);
println("Walking $Steps steps burns $caloriesBurned calories")
}
fun PEDOMETERstepsTOcalories(NumberOFStepS: Int): Double {
val CaloriesBURNEDforEachStep = 0.04
val TotalCALORIESburned = NumberOFStepS * CaloriesBURNEDforEachStep
return TotalCALORIESburned
}
10. 比较两个数字
现代手机内置了屏幕时间跟踪功能,即每天您花在手机上的时间。
在此练习中,您将实现一个函数,该函数比较您今天花在手机上的分钟数与昨天花在手机上的分钟数。该函数接受两个整数参数并返回一个布尔值。
第一个参数存储您今天花在手机上的分钟数,第二个参数存储您昨天花在手机上的分钟数。如果您今天花在手机上的时间比昨天多,则函数返回 true
;否则,返回 false
。
例如,如果您使用以下命名参数调用函数
timeSpentToday = 300
且timeSpentYesterday = 250
,函数返回true
值。timeSpentToday = 300
且timeSpentYesterday = 300
,函数返回false
值。timeSpentToday = 200
且timeSpentYesterday = 220
,函数返回false
值。
提示: >
比较运算符在前一个值大于后一个值时返回 true
值。否则,返回 false
值。
11. 将重复代码移动到函数中
此程序显示不同城市的天气。它包括城市名称、当天的最高和最低温度以及降雨概率。
fun main() {
println("City: Ankara")
println("Low temperature: 27, High temperature: 31")
println("Chance of rain: 82%")
println()
println("City: Tokyo")
println("Low temperature: 32, High temperature: 36")
println("Chance of rain: 10%")
println()
println("City: Cape Town")
println("Low temperature: 59, High temperature: 64")
println("Chance of rain: 2%")
println()
println("City: Guatemala City")
println("Low temperature: 50, High temperature: 55")
println("Chance of rain: 7%")
println()
}
打印每个城市天气的代码有很多相似之处。例如,有些短语重复出现了多次,例如 "City:"
和 "Low temperature:"
。类似重复的代码会增加程序出错的风险。对于某个城市,您可能会出现拼写错误或遗漏某个天气详情。
- 您能否创建一个函数来打印单个城市的天气详情,以减少
main()
函数中的重复,然后对剩余的城市执行相同的操作? - 您能否更新
main()
函数,使其为每个城市调用您创建的函数,并传递适当的天气详情作为参数?
12. 解决方案代码
打印消息
解决方案使用 println()
函数在每行打印消息。
fun main() {
println("Use the val keyword when the value doesn't change.")
println("Use the var keyword when the value can change.")
println("When you define a function, you define the parameters that can be passed to it.")
println("When you call a function, you pass arguments for the parameters.")
}
修复编译错误
代码包含两个编译错误
- 字符串应以双引号而不是单引号结束。
- 函数参数应以括号而不是花括号结束。
fun main() {
println("New chat message from a friend")
}
字符串模板
编译错误是由于将 discountPercentage
和 offer
这两个只读变量赋值为新值所致;这种赋值是不允许的。
fun main() {
val discountPercentage = 20
val item = "Google Chromecast"
val offer = "Sale - Up to $discountPercentage% discount off $item! Hurry Up!"
println(offer)
}
作为替代解决方案,您可以使用 var
关键字声明 discountPercentage
整数和 offer
字符串。然而,在程序的上下文中,它们的值是不可变的,因此您可以继续使用 val
关键字。
字符串拼接
步骤 1
程序打印此输出
The total party size is: 2030
这是一个技巧性问题。当 +
运算符用于 String
值时,它会生成一个拼接后的字符串。整数被双引号包裹,因此它们被视为字符串而不是整数,所以输出是 2030
。
步骤 2
您可以移除 numberOfAdults
和 numberOfKids
变量周围的双引号,将它们转换为 Int
变量。
fun main() {
val numberOfAdults = 20
val numberOfKids = 30
val total = numberOfAdults + numberOfKids
println("The total party size is: $total")
}
如果您还记得,Kotlin 编译器可以根据变量被赋的值来推断其类型。在这种情况下,编译器推断 numberOfAdults
和 numberOfKids
变量是 Int
类型。
消息格式化
程序打印此输出
Congratulations for your bonus! You will receive a total of 5000 + 1000 (additional bonus).
"$baseSalary + $bonusAmount"
使用模板表达式语法。在模板表达式中,代码先被求值,然后结果被拼接到字符串中。
在问题中,$baseSalary
变量被求值为 5000
,$bonusAmount
变量被求值为 1000
。然后,结果被拼接生成 "5000 + 1000"
并赋值给 result
变量。
实现基本数学运算
步骤 1
使用 val
关键字定义一个不可变的 result
变量,然后将加法运算的结果赋值给它
fun main() {
val firstNumber = 10
val secondNumber = 5
val result = firstNumber + secondNumber
println("$firstNumber + $secondNumber = $result")
}
步骤 2
- 创建一个
add()
函数,该函数接受一个firstNumber
参数和一个secondNumber
参数,两者都是Int
类型,并返回一个Int
值。 - 在
add()
函数体内输入加法运算的代码,然后使用return
关键字返回运算结果。
fun add(firstNumber: Int, secondNumber: Int): Int {
return firstNumber + secondNumber
}
步骤 3
- 定义一个
subtract()
函数,该函数接受一个firstNumber
参数和一个secondNumber
参数,两者都是Int
类型,并返回一个Int
值。 - 在
subtract()
函数体内输入减法运算的代码,然后使用return
关键字返回运算结果。
fun subtract(firstNumber: Int, secondNumber: Int): Int {
return firstNumber - secondNumber
}
- 修改
main()
函数以使用新的subtract()
函数。一个示例解决方案可能如下所示
fun main() {
val firstNumber = 10
val secondNumber = 5
val thirdNumber = 8
val result = add(firstNumber, secondNumber)
val anotherResult = subtract(firstNumber, thirdNumber)
println("$firstNumber + $secondNumber = $result")
println("$firstNumber - $thirdNumber = $anotherResult")
}
fun add(firstNumber: Int, secondNumber: Int): Int {
return firstNumber + secondNumber
}
fun subtract(firstNumber: Int, secondNumber: Int): Int {
return firstNumber - secondNumber
}
默认参数
步骤 1
- 创建一个
displayAlertMessage()
函数,该函数接受一个operatingSystem
参数和一个emailId
参数,两者都是String
类型,并返回一个String
值。 - 在函数体内,使用模板表达式更新消息并返回它。
fun displayAlertMessage(operatingSystem: String, emailId: String): String {
return "There is a new sign-in request on $operatingSystem for your Google Account $emailId."
}
步骤 2
- 将
"Unknown OS"
值赋给operatingSystem
参数。
fun displayAlertMessage(
operatingSystem: String = "Unknown OS",
emailId: String
): String {
return "There is a new sign-in request on $operatingSystem for your Google Account $emailId."
}
计步器
函数名和变量名应遵循驼峰命名法规范。
如果名称包含多个单词,则将第一个单词的首字母小写,后续单词的首字母大写,并删除单词之间的空格。
示例函数名包括
calculateTip
displayMessage
takePhoto
示例变量名包括
numberOfEmails
cityName
bookPublicationDate
要了解有关名称的更多信息,请参阅 命名规则。
避免使用 Kotlin 关键字 作为函数名,因为这些词在 Kotlin 语言中已经有了特定的含义。
您的解决方案代码应类似于此代码片段
fun main() {
val steps = 4000
val caloriesBurned = pedometerStepsToCalories(steps)
println("Walking $steps steps burns $caloriesBurned calories")
}
fun pedometerStepsToCalories(numberOfSteps: Int): Double {
val caloriesBurnedForEachStep = 0.04
val totalCaloriesBurned = numberOfSteps * caloriesBurnedForEachStep
return totalCaloriesBurned
}
比较两个数字
- 创建一个
compareTime()
函数,该函数接受一个timeSpentToday
参数和一个timeSpentYesterday
参数,两者都是Int
类型,并返回一个Boolean
值。
解决方案依赖于 >
比较运算符。该运算符求值为一个 Boolean
值,因此 compareTime()
函数只需返回 timeSpentToday > timeSpentYesterday
的结果。
例如,如果您将 300
参数传递给 timeSpentToday
参数,并将 250
参数传递给 timeSpentYesterday
参数,函数体将求值为 300 > 250
,这将返回 true
值,因为 300 大于 250。
fun main() {
println("Have I spent more time using my phone today: ${compareTime(300, 250)}")
println("Have I spent more time using my phone today: ${compareTime(300, 300)}")
println("Have I spent more time using my phone today: ${compareTime(200, 220)}")
}
fun compareTime(timeSpentToday: Int, timeSpentYesterday: Int): Boolean {
return timeSpentToday > timeSpentYesterday
}
Have I spent more time using my phone today: true Have I spent more time using my phone today: false Have I spent more time using my phone today: false
将重复代码移动到函数中
- 在
main()
函数之后创建一个函数,用于打印安卡拉市的天气详情。
函数名可以使用 printWeatherForCity()
或类似的名称。
- 从
main()
函数调用该函数。
程序应该打印安卡拉的天气详情。
fun main() {
printWeatherForCity()
}
fun printWeatherForCity() {
println("City: Ankara")
println("Low temperature: 27, High temperature: 31")
println("Chance of rain: 82%")
println()
}
现在您可以创建另一个更灵活的函数,以便它可以打印其他城市的天气详情。
- 将
println()
语句中特定于安卡拉的部分替换为变量。
请记住对变量名使用驼峰命名法约定,并在变量名前使用 $
符号,以便使用变量的值而不是变量名。这些是您在之前的 Codelab 中了解到的字符串模板。
fun printWeatherForCity() {
println("City: $cityName")
println("Low temperature: $lowTemp, High temperature: $highTemp")
println("Chance of rain: $chanceOfRain%")
println()
}
- 修改函数定义,使这些变量成为调用函数时必须传入的参数,并为每个参数指定数据类型。
cityName
参数是 String
类型,而 lowTemp
、highTemp
和 chanceOfRain
参数是 Int
类型。
函数定义中不需要 return
值,因为消息被打印到输出。
fun printWeatherForCity(cityName: String, lowTemp: Int, highTemp: Int, chanceOfRain: Int) {
println("City: $cityName")
println("Low temperature: $lowTemp, High temperature: $highTemp")
println("Chance of rain: $chanceOfRain%")
println()
}
- 更新
main()
函数,调用printWeatherForCity()
函数并传入安卡拉的天气详情。
城市名称为 "Ankara"
,最低温度为 27
,最高温度为 31
,降雨概率为 82
。
fun main() {
printWeatherForCity("Ankara", 27, 31, 82)
}
fun printWeatherForCity(cityName: String, lowTemp: Int, highTemp: Int, chanceOfRain: Int) {
println("City: $cityName")
println("Low temperature: $lowTemp, High temperature: $highTemp")
println("Chance of rain: $chanceOfRain%")
println()
}
- 运行程序,验证输出是否显示安卡拉的天气详情。
- 使用其他城市的天气详情调用
printWeatherForCity()
函数。
fun main() {
printWeatherForCity("Ankara", 27, 31, 82)
printWeatherForCity("Tokyo", 32, 36, 10)
printWeatherForCity("Cape Town", 59, 64, 2)
printWeatherForCity("Guatemala City", 50, 55, 7)
}
fun printWeatherForCity(cityName: String, lowTemp: Int, highTemp: Int, chanceOfRain: Int) {
println("City: $cityName")
println("Low temperature: $lowTemp, High temperature: $highTemp")
println("Chance of rain: $chanceOfRain%")
println()
}
- 运行程序。
它应该打印与原始程序相同的输出,但现在您的代码更简洁,并且不包含不必要的重复!所有打印城市天气详情的代码都集中在一个地方:printWeatherForCity()
函数。如果您想更改天气详情的显示方式,只需在一处更改即可应用于所有城市。
13. 额外练习
要进一步练习 Kotlin 语言,请查看 JetBrains Academy 提供的 Kotlin Core 学习路径。要跳转到特定主题,请访问知识图谱,查看该学习路径涵盖的主题列表。