Dice
Posted 临风而眠
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Dice相关的知识,希望对你有一定的参考价值。
Dice
我们一起来学习用Android studio做一个Dice roller 掷骰子APP,最终类似于一个随机数猜数小游戏,只是猜数字的形式换成了掷骰子
一.随机数
怎么表现掷骰子的随机性呢,我们很自然的会想到随机数,默默的想起了曾经玩飞行棋当过欧皇也经常当非洲人的经历,我们对C语言的随机数已经很熟悉,下面直接看kotlin语言的随机数代码:
fun main(){
val diceRange = 1..6
val randomNumber = diceRange.random()
println("Random number:${randomNumber}")
}
其中m..n
的用法是一个Kotlin整数范围,表示数字m到数字n(包括m,n)
random()函数是生成并返回给定范围内的随机数
注:
可直接对范围调用random()函数,如(1..6).random()
二.Dice类
kotlin作为一种和java比较类似的面向对象的语言,自然要用到类与对象,那么下面就把骰子的属性和方法封装到Dice类中
1.面数属性
先来测试一下:
fun main(){
val firstDice = Dice()//创建Dice类的对象实例
println(firstDice.sides)
}
class Dice{
var sides = 6//骰子有六个面
}
运行结果是6
看上面的代码会发现和C++类与对象的区别就是实例化的时候,如果用C++就是:
Dice firstDice
注:
与变量命名稍有不同,类名称采用驼峰式大小写形式。例如:AirPlane、OnlineBook 、Dice
2.掷骰子方法
掷骰子产生随机数就要用到前面的random()函数了
fun main(){
val firstDice = Dice()//创建Dice类的对象实例
firstDice.roll()
}
class Dice{
var sides = 6//骰子有六个面
fun roll(){
val randomNumber = (1..6).random()
println(randomNumber)
}
}
学过C++的话上面代码非常好理解
注:
函数和方法的命名惯例是以小写字母开头,采用驼峰式大小写形式,尽可能以操作动词开头
函数返回值
指定返回类型的语法如下:在函数名称后面,在括号后添加冒号、空格,然后为函数返回类型添加关键字
fun main() {
val firstDice = Dice()
val diceRoll = firstDice.roll()
println("Your ${firstDice.sides} sided dice rolled ${diceRoll}!")
}
class Dice {
var sides = 6
fun roll(): Int {
val randomNumber = (1..6).random()
return randomNumber
}
}
3.自定义骰子
自定义骰子的面数numSides
fun main() {
val firstDice = Dice(6)
println("Your ${firstDice.numSides} sided dice rolled ${firstDice.roll()}!")
val secondDice = Dice(20)
println("Your ${secondDice.numSides} sided dice rolled ${secondDice.roll()}!")
}
class Dice (val numSides: Int) {
fun roll(): Int {
return (1..numSides).random()
}
}
三.创建交互按钮
下面就可以去android studio中操作了,先用empty activity新建一个project
1.添加button
打开activity_main.xml,选择Button拖动到显示“Hello world!”的那个TextView下面
2.确定button位置
Button要在TextView正下方,拖动使其重重合
添加从 Button 的左侧和右侧到父级 ConstraintLayout的左侧和右侧的水平约束条件。
3.修改button文字
在Button的text属性里面改成你想要的文字,老问题,规范编码@string
我们之后需要在button上面的textview上显示骰子的点数,所以先把Hello world删掉,此处介绍一个调试功能
tools text
这些文字仅在布局预览中显示,在应用运行时不会显示
4.添加button交互
我们需要实现点击button 就显示骰子的点数
先介绍下导包的配置
用过python和Java 都知道import导包
在这里找到Settings for New Projects
继续找到Auto Import
![image-20210610080306967](https://image.cha138.com/20210719/112304a4971e4877994fe6cd766d6e7d.jpg)
设置成如下配置
Add unambiguous imports on the fly能让 Android Studio 智能补全import
Optimize imports on the fly(for current project)设置会指示 Android Studio 移除unused的导包
在Mainactivity.kt中添加代码
首先调用setContentView方法,关于这个方法,可以看这位大佬的简书的详细解释
findViewById
val rollButton: Button = findViewById(R.id.button)
findViewById() 方法在布局中找到 Button。R.id.button是 Button 的资源 ID,该 ID 是 Button 的唯一标识符
代码将 Button 对象的引用保存到名为 rollButton 的变量中**,而不是保存 Button 对象本身**(引用的概念学过C++应该知道)
Android 会自动为应用中的资源分配 ID 号。例如,Roll 按钮具有资源 ID,按钮文字的字符串也具有资源 ID资源 ID 的格式为 R.<type>.<name>
;例如 R.string.roll
。对于 View
ID,<type>
为 id
,例如 R.id.button
鼠标监听事件setOnClickListener()
val rollButton: Button = findViewById(R.id.button)
rollButton.setOnClickListener {
val toast = Toast.makeText(this, "Dice Rolled!", Toast.LENGTH_SHORT)
toast.show()
}
其中Toast是一条向用户显示的简短消息
通过调用 Toast.makeText()创建包含文字 “Dice Rolled!” 的 Toast,再调用show()方法让Toast自行显示
也可以将两行代码合为一行
Toast.makeText(this, "Dice Rolled!", Toast.LENGTH_SHORT).show()
效果如下:
点击Button后,下方显示一条简短消息
点击 Button 时更新 TextView
最终代码:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val rollButton: Button = findViewById(R.id.button)
rollButton.setOnClickListener {
val resultTextView: TextView = findViewById(R.id.textView)
resultTextView.text = "6"
}
}
}
现在就实现了如下效果
5.添加掷骰子逻辑
完整代码如下
package com.example.dice_roller
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.TextView
import android.widget.Toast
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val rollButton: Button = findViewById(R.id.button)
rollButton.setOnClickListener {
rollDice()
}
}
private fun rollDice() {
val dice=Dice(6)
val diceRoll = dice.roll()
val resultTextView: TextView = findViewById(R.id.textView)
resultTextView.text=diceRoll.toString()
}
}
class Dice(private val numSides: Int){
fun roll(): Int{
return(1..numSides).random()
}
}
toString()是把diceRoll的数字转化为TextView的text属性所需使用的文字
感觉学下来和当时用C++做Qt的时候很相像
效果如下,每点击一次就会随机显示1到numSides的数字
6.代码习惯优化
先全选,再使用键盘快捷键 Ctrl+Alt+L
格式化代码
在每个方法与类前面添加注释
package com.example.dice_roller
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.TextView
import android.widget.Toast
/**
* 用户掷骰子,并且能在屏幕上看到结果
*/
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val rollButton: Button = findViewById(R.id.button)
rollButton.setOnClickListener {
rollDice()
}
}
/**
* 点击掷骰子,就更新数字
*/
private fun rollDice() {
//实例化6个面的骰子对象
val dice = Dice(6)
val diceRoll = dice.roll()
//更新数字
val resultTextView: TextView = findViewById(R.id.textView)
resultTextView.text = diceRoll.toString()
}
}
/**
* 骰子类
* 属性:面数
* 方法:返回随机数
*/
class Dice(private val numSides: Int) {
fun roll(): Int {
return (1..numSides).random()
}
}
四.游戏逻辑
在最开头的时候说了,最终类似于一个随机数猜数小游戏,只是猜数字的形式换成了掷骰子
那我们就设置一个幸运数字luckyNumber
1.if else
下面的代码和C语言很像,判断语句也和C语言差不多,较容易看懂,
fun main() {
val myFirstDice = Dice(6)
val rollResult = myFirstDice.roll()
val luckyNumber = 4
if (rollResult == luckyNumber) {
println("You win!")
} else if (rollResult == 1) {
println("So sorry! You rolled a 1. Try again!")
} else if (rollResult == 2) {
println("Sadly, you rolled a 2. Try again!")
} else if (rollResult == 3) {
println("Unfortunately, you rolled a 3. Try again!")
} else if (rollResult == 4) {
println("No luck! You rolled a 4. Try again!")
} else if (rollResult == 5) {
println("Don't cry! You rolled a 5. Try again!")
} else {
println("Apologies! you rolled a 6. Try again!")
}
}
class Dice(val numSides:Int){
fun roll():Int{
return (1..numSides).random()
}
}
这个和刚学C语言的时候学的猜数游戏就是新瓶子里装旧酒啊
2.when (类似于C的switch)
C语言中,如果条件很多,要写好多的if,else于是有时候我们会选择switch
那么在kotlin中,类似的就是when,就是把C语言中的case : 换成了->
直接看代码吧
fun main() {
val myFirstDice = Dice(6)
val rollResult = myFirstDice.roll()
val luckyNumber = 4
when (rollResult) {
luckyNumber -> println("You won!")
1 -> println("So sorry! You rolled a 1. Try again!")
2 -> println("Sadly, you rolled a 2. Try again!")
3 -> println("Unfortunately, you rolled a 3. Try again!")
4 -> println("No luck! You rolled a 4. Try again!")
5 -> println("Don't cry! You rolled a 5. Try again!")
6 -> println("Apologies! you rolled a 6. Try again!")
}
}
class Dice(val numSides:Int){
fun roll():Int{
return (1..numSides).random()
}
}
五.加入Dice
1.更新布局
删除TextView,并将一个ImageView拖动到Button上方
选择 Sample data 中的 avatars作为临时图片
确定 ImageView 和 Button 的位置
- 为 ImageView 添加水平约束条件。将 ImageView 的左侧与父级 ConstraintLayout 的左边缘连接起来
- 将 ImageView 的右侧与父级的右边缘连接起来。这会使 ImageView 在父级内水平居中
- 为 ImageView 添加垂直约束条件,将 ImageView 的顶部与父级的顶部连接起来。ImageView 会向上滑动到 ConstraintLayout的顶部
- 为 Button 添加垂直约束条件,将 Button 的顶部与 ImageView 的底部连接起来。Button 会向上滑动到ImageView的下方
- 再次选择 ImageView,然后添加垂直约束条件,将 ImageView 的底部与父级的底部连接起来。这会使 ImageView 在 ConstraintLayout内垂直居中
此时已经居中
2.导入骰子图片
如果在APP内没有骰子,真的就变成纯猜数游戏了,下面我们就加入骰子的图片
图片下载链接点击👉这里
按我的上一篇博客里所说的导入图片的方法把六张骰子的图片导入
3.替换临时图片
找到ImageView的设置为头像图片的工具 srcCompat 属性
点击那个小头像,进入此界面,先选择dice_1
emm…too big,调整大小
- 找到layout_width 和 layout_height 属性。它们当前设置为 wrap_content,这意味着
ImageView
的高度和宽度将与其中的内容(源图片)保持一致。 - 为
ImageView
设置 160dp 的固定宽度和 200dp 的固定高度。按 Enter 键。
还需要调整Button和ImageView之间的距离,在 Constraint Widget 中将按钮的上边距设置为 16dp
4.修改代码
下面就要修改代码啦,掷出数字几,骰子就显示那一面
注
控件的id可以在Attributes中看到
将rollDice()方法改成如下:
private fun rollDice() {
//实例化6个面的骰子对象
val dice = Dice(6)
val diceRoll = dice.roll()
//更新数字
val diceImage: ImageView = findViewById(R.id.imageView)
when (diceRoll) {
1 -> diceImage.setImageResource(R.drawable.dice_1)
2 -> diceImage.setImageResource(R.drawable.dice_2)
3 -> diceImage.setImageResource(R.drawable.dice_3)
4 -> diceImage.setImageResource(R.drawable.dice_4)
5 -> diceImage.setImageResource(R.drawable.dice_5)
6 -> diceImage.setImageResource(R.drawable.dice_6)
}
}
优化代码
上面的rollDice()方法中,调用了6次diceImage.setImageResource()
改成下面的,就只需要调用一次
val drawableResource = when(diceRoll) {
1 -> R.drawable.dice_1
2 -> R.drawable.dice_2
3 -> R.drawable.dice_3
4 -> R.drawable.dice_4
5 -> R.drawable.dice_5
6 -> R.drawable.dice_6
}
diceImage.setImageResource(drawableResource)
但此时,when下面出现了红色下划线
出现该错误的原因是 when
表达式的值被赋给 drawableResource
,因此 when
必须涵盖所有情况,它必须处理所有可能的情况,这样,即使您更改为 12 面的骰子,也始终会返回值。Android Studio 建议添加一个 else
分支。您可以通过将 6
的情况更改为 else
来解决此问题。从 1
到 5
的情况不变,但包括 6
在内的所有其他情况都通过 else
处理
val drawableResource = when (diceRoll) {
1 -> R.drawable.dice_1
2 -> R.drawable.dice_2
3 -> R.drawable.dice_3
4 -> R.drawable.dice_4
5 -> R.drawable.dice_5
else -> R.drawable.dice_6
}
diceImage.setImageResource(drawableResource)
5.优化界面,添加代码注释
首次打开APP时,也应该显示一个随机的骰子,让用户一目了然这个APP是干什么的,于是在onCreate方法中添加代码
有点像C++里面的构造函数,自动调用
rollDice()
完整代码如下:
package com.example.dice_roller
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
/**
* 用户掷骰子,并且能在屏幕上看到结果
*/
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val rollButton: Button = findViewById(R.id.button)
rollButton.setOnClickListener {
rollDice()
}
//APP初始化的时候就出现骰子
rollDice()
}
/**
* 点击掷骰子,就更新数字
*/
private fun rollDice() {
//实例化6个面的骰子对象
val dice = Dice(6)
val diceRoll = dice.roll()
//更新数字
val diceImage: ImageView = findViewById(R.id.imageView)
val drawableResource = when (diceRoll) {
1 -> R.drawable.dice_1
2 -> R.drawable.dice_2
3 -> R.drawable.dice_3
4 -> R.drawable.dice_4
5 -> R.drawable.dice_5
else -> R.drawable.dice_6
}
//更新显示的图片资源
diceImage.setImageResource(drawableResource)
//屏幕阅读器可以朗读此内容说明 需要添加
diceImage.contentDescription = diceRoll.toString()
}
}
/**
* 骰子类
* 属性:面数
* 方法:返回随机数
*/
class Dice(private val numSides: Int) {
fun roll(): Int {
return (1..numSides).random()
}
}
下面就可以尽情玩耍啦!😃
想把自己做的APP分享给别人一起玩点击菜单栏的Build-Build APKs,然后把.apk文件发给别人就可以啦!😄
以上是关于Dice的主要内容,如果未能解决你的问题,请参考以下文章
CodeForces 534C - Polycarpus' Dice(思路)
SP1026 FAVDICE - Favorite Dice