Java Web程序员Kotlin

24. 简单玩玩kotlin for android,随机数字买

2017-11-21  本文已影响202人  厚土火焱

现在 kotlin 用的较多的领域,应该是 android 应用开发了吧。最近开了个小差,有人买彩票不想自己预测了,也不想现场用彩票店的机器出号,太费事儿。就用 kotlin 写个手机 apk 给他。要求也不高,只要随机出数字就行。
需求搞清楚了,可以开工了。
首先要确定,他可能还要给自己的旧手机也装上,为求万千稳妥,API 的最小版本选择了 15。

选择API版本
之后选择空的 Activity 就开场了。
选择空活动
系统默认给出一个界面。
我们不理他,因为,还计划着以后再继续在这个项目中万一增加其他小工具呢。
所以新建一个package,取名就用汉语拼音吧。CaiPiao
新建package
新建好的package
然后在这个 package 下新建一个空活动(Empty Activity)
新建空活动
下面,我们要做的第一件事,就是让第一个活动(MainActivity)被应用启动后,直接跳转到我们这个 CaiPiao 下的空活动来。
主活动和彩票的活动
打开 MainActivity ,添加代码。先写一个函数 OpenCaiPiao ,在函数内实现需要的功能。
    //跳转到彩票界面
    fun OpenCaiPiao(){//我要顺顺的来
        val intent = Intent()
        intent.setClass(this, CaipiaoActivity::class.java)
        startActivity(intent)
    }

把它放在 class MainActivity 内,并在 onCreate 函数内添加调用语句 OpenCaiPiao()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        OpenCaiPiao()

    }

这时候,我们的注意力就可以专注到真正的业务模块中了。
在 res>layout 中打开 activity_caipiao.xml,拖拽三个 button 和 两个 textview。
一个 button 对应“双色球”
一个 button 对应“大乐透”
一个 button 对应“清除”功能
一个 textview 对应给出的彩票号码
一个 textview 对应给出彩票号码的时间
现在流行最新的布局方式,也是默认的ConstraintLayout。我就用这种了。


出号界面布局

这个布局中,为了保持“随机号码”和“出号时间”的左对齐,只设定了上边和左边的距离,它们字号不同,控制了右边距离的话,文字内容发生改变,会有对不齐的情况发生。
双色球和大乐透两个按钮,略有不同,双色球设置了上、左、右到边沿,而大乐透的左边是指在双色球按钮的右侧控键上。这样,两个按钮的位置就相对固定了。不论横屏还是竖屏都不会变。
相似的“清除按钮”的上边constraint也控制到双色球按钮的下侧控键上,这样“清除按钮”和“双色球按钮”的相对位置也就保持不变了。


界面设置完毕
下面就该填写这个Activity中的代码了。
界面中可以直接操作就是这三个按钮了,先在 CaiPiaoActivity.kt 的 OnCreate 中增加这三个按钮的 OnClick 事件的监听。
        //双色球
        btnGetShuangSeQiu.setOnClickListener {
        }
        //大乐透
        btnDaLeTou.setOnClickListener {
        }
        //清除取消
        btnCancel.setOnClickListener {
        }

随机出彩票号码,那么核心功能是随机了。先写一个在指定的范围内出随机数字的函数出来。

/**
 * 取得min到max之间的随机整数(不包含max)
 * @min 最小取值
 * @max 最大取值边界(此值不取)
 * */
fun cofoxRandom(min: Int = 0, max: Int): Int {
    var t_min = min
    var t_max = max
    if (t_min > t_max) {
        var temp: Int
        temp = t_min
        t_min = t_max
        t_max = temp
    }
    var random = (Math.floor(Math.random() * (t_max - t_min))).toInt() + t_min

    return random
}

这里要注意这个注释的写法

/**
 *
 * */

这样标准的写法能够被 IDE 准确的识别,才能有下面的效果。

标准的注释写法很重要,会让你很方便。
我们要写双色球的随机出号了
首先定义一个整数数组,先都赋值为 0 好了。
var ints = intArrayOf(0, 0, 0, 0, 0, 0, 0)

当然你也可以这样写

var ints = Array(7,{0})

第一种写法,是方便直接把所有的数组元素(不同值)都写进去。
第二种写法,更简洁一些,适合初始化时候都赋相同值的情况。
建立了数组,就该把随机数字填写进去了。

    for (i in 1..6) {
        ints[i - 1] = cofoxRandom(1, 34)
    }

双色球是 6 + 1 的出球方式。我们先出 6 个红球,所以是 1..6。
由于 cofoxRandom 函数的max值是不包含在可选范围内的,所以1-33个红球号码,我们需要的参数是(1, 34)
至于 ints[i-1],是因为,数组的下标是从 0 开始的。
这样就可以把 6 个球号得到了。
但是,还有个问题,数字是乱的。我们需要给这 6 个数字排序。这也是一个很常见的需求。

    //排序前六位,第七位当临时存储位
    for (i in ints.indices) {
        for (j in ints.indices - i) {
            if (j < ints.size - 1) {
                if (ints[j] > ints[j + 1]) {
                    ints[ints.size - 1] = ints[j + 1]
                    ints[j + 1] = ints[j]
                    ints[j] = ints[ints.size - 1]
                }
            }
        }
    }

这里,我们为了节省内存,就不再另外加变量了。先利用那个蓝色号码的位置,作为排序时的临时存储位。每次循环,都把较大的一个数字往后移动一位。于是,在第二层循环,每次循环都可以少循环一个已经确定了的较大数字。这就是

    for (i in ints.indices) {
        for (j in ints.indices - i) {

这个的来由。顺便说一下,indices是取得ints下标的意思。这样i和j就能得到当前循环的具体下标了。
循环完,一个由小到大排列好的数组就出来了。
如果想完美,还有一个问题要解决,重复数字。随机给出的数字经常是重复的。只要再加一个逻辑,当新的随机数出来后,判断一下在数组中是否存在这个数字了即可。如果存在,当前循环内再次取得随机数,直到取得了不在数组中的数字为止。
我们可以用 for 循环嵌套 while 循环实现。我们来修改刚才那个 随机数字填写 的 for 循环。

    for (i in 1..6) {
//        ints[i - 1] = cofoxRandom(1, 34)
        var temp = cofoxRandom(1, 34)
        while (temp in ints){
            temp = cofoxRandom(1, 34)
        }
        ints[i - 1] = temp
    }

现在,数组内的号码球数字不会重复了。
双色球还有一个蓝色号码求哦,这个就直接出好了。

ints[ints.size-1] = cofoxRandom(1, 17)//蓝色号码球

数字都出完了。我们还可以来调一调数字格式。因为,有一位数也有两位数嘛,排列总是看起来有点不够整齐。那就一位数的都在左侧补0吧。不仅如此,每个数字之间用逗号(,)分隔开,再把红球和蓝球用短横线(-)分隔开。

    //按格式书写
    var str = "双色球:"
    for (i in ints.indices) {
        if (ints[i].toString().length < 2){
            str += "0"+ints[i].toString()
        }else {
            str += ints[i]
        }

        if (i == ints.size-2){
            str += " - "
        }else if (i == ints.size -1){

        }else{
            str += ", "
        }
    }

好了。重要的代码都写完了。剩下就是把 str 赋值给界面控件了吧?
还可以再多做一点事情。不要把这么多的代码都放进 onCreate ,独立出一个函数来。让代码更整洁。于是,我们可以得到一个“福彩双色球随机猜想出号”函数了。

/**
 * 福彩双色球随机猜想出号
 * */
fun cofoxShuangSeQiu(ttvw:TextView){
//    var ints = intArrayOf(0, 0, 0, 0, 0, 0, 0)
    var ints = Array(7,{0})
    for (i in 1..6) {
//        ints[i - 1] = cofoxRandom(1, 34)
        var temp = cofoxRandom(1, 34)
        while (temp in ints){
            temp = cofoxRandom(1, 34)
        }
        ints[i - 1] = temp
    }
    //排序前六位,第七位当临时存储位
    for (i in ints.indices) {
        for (j in ints.indices - i) {
            if (j < ints.size - 1) {
                if (ints[j] > ints[j + 1]) {
                    ints[ints.size - 1] = ints[j + 1]
                    ints[j + 1] = ints[j]
                    ints[j] = ints[ints.size - 1]
                }
            }
        }
    }

    ints[ints.size-1] = cofoxRandom(1, 17)//蓝色号码球

    //按格式书写
    var str = "双色球:"
    for (i in ints.indices) {
        if (ints[i].toString().length < 2){
            str += "0"+ints[i].toString()
        }else {
            str += ints[i]
        }

        if (i == ints.size-2){
            str += " - "
        }else if (i == ints.size -1){

        }else{
            str += ", "
        }
    }
    ttvw.text = str
}

而 onCreate 中对这个函数进行调用。

cofoxShuangSeQiu(ttvwRandomNumber)

ttvwRandomNumber 就是 textview 的 id
在界面上为了更友好一些,我们增加了出号时间。现在就是添加这个功能代码的时候了。

/**
 * 显示当前出号时间
 * */
fun cofoxGetNumberTime(ttvw: TextView){
    //出号时间
    var ver = android.os.Build.VERSION.SDK_INT
    if (ver >= 24){
        ttvw.text = SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Date())
    }else{
        val calendar = GregorianCalendar()
        ttvw.text = GregorianCalendar().get(Calendar.YEAR).toString() +"-"+ (GregorianCalendar().get(Calendar.MONTH)+1).toString() +"-"+ GregorianCalendar().get(Calendar.DAY_OF_MONTH).toString() +" "+ GregorianCalendar().get(Calendar.HOUR).toString() +":"+ GregorianCalendar().get(Calendar.MINUTE).toString() +":"+ GregorianCalendar().get(Calendar.SECOND).toString()
    }
}

好吧,这也是写成了一个函数。并且其中用了两种取得当前时间的方法。因为,我们开始的时候,希望这个应用能支持到 API 15,而最简洁最新的时间获取的写法是从 API 24 之后才开才是支持的。
那么先判断一下当前运行的 android 系统的 API 是哪个版本,然后对症下药。
之后,我们再把调用语句写入 onCreate 中。

        //双色球
        btnGetShuangSeQiu.setOnClickListener {
            cofoxShuangSeQiu(ttvwRandomNumber)
            cofoxGetNumberTime(ttvwTime)    //出号时间

        }

双色球的调用完成了。
大乐透只是稍有不同
大乐透的号码球一共也是 7 个,但是,大乐透的玩法是分前区和后区。是 5 + 2 的结构。所以,在双色球的代码基础上略微修改就可以获得大乐透的写法了。

/**
 * 体彩大乐透随机猜想出号
 * */
fun cofoxDaLeTou(ttvw:TextView){
//    var ints = intArrayOf(0, 0, 0, 0, 0, 0, 0)
    var ints = Array(7,{0})
    for (i in 1..5) {
//        ints[i - 1] = cofoxRandom(1, 36)
        var temp = cofoxRandom(1, 36)
        while (temp in ints){
            temp = cofoxRandom(1, 36)
        }
        ints[i - 1] = temp
    }

    //排序前5位,第6位当临时存储位
    for (i in ints.indices - 2) {
        for (j in ints.indices - i) {
            if (j < ints.size - 2) {
                if (ints[j] > ints[j + 1]) {
                    ints[ints.size - 2] = ints[j + 1]
                    ints[j + 1] = ints[j]
                    ints[j] = ints[ints.size - 2]
                }
            }
        }
    }

    ints[ints.size-2] = cofoxRandom(1, 13)//后区号码球1
    ints[ints.size-1] = cofoxRandom(1, 13)//后区号码球2

    //按格式书写
    var str = "大乐透:"
    for (i in ints.indices) {
        if (ints[i].toString().length < 2){
            str += "0"+ints[i].toString()
        }else {
            str += ints[i]
        }

        if (i == ints.size-3){
            str += " - "
        }else if (i == ints.size -1){

        }else{
            str += ", "
        }
    }
    ttvw.text = str
}

这时候,在 onCreate 中修改大乐透的调用代码就简单多了。

        //大乐透
        btnDaLeTou.setOnClickListener {
            cofoxDaLeTou(ttvwRandomNumber)
            cofoxGetNumberTime(ttvwTime)    //出号时间

        }

还记得我们的“清除”按钮吗?是的,也要在 onCreate 中写上监听代码。

        //清除取消
        btnCancel.setOnClickListener {
            ttvwRandomNumber.text = resources.getString(R.string.txt_cnword_随机号码)
            ttvwTime.text = resources.getText(R.string.txt_出号时间)
        }

这里的 R.string 是什么?它们资源文件 res>values 下 strings.xml 内的东西。
我们在这里实践了一下编码中对中文变量的支持。呵呵。


资源在这里
这下知道两个textview上的文字从哪里来的了

编译一下


我用真机编译
Screenshot_2017-11-21-01-22-33-332_com.cofox.mykt.cst.png
Screenshot_2017-11-21-01-22-42-531_com.cofox.mykt.cst.png
Screenshot_2017-11-21-01-22-48-955_com.cofox.mykt.cst.png
上一篇 下一篇

猜你喜欢

热点阅读