java - 使用一个类的最佳方式,内部只更改一个对象 - Kotlin/Android/Java

标签 java android kotlin

我在 Android 上创建了简单的游戏。现在我想增加难度级别,我想知道该采取什么方法。我的意思是,我只需要更改类内的一个对象(CountDownTimer)即可改变该难度,首先我认为我将为每个级别只创建 3 个类,但我的直觉告诉我这将是大材小用。做一个类并继承它?或者也许以某种方式创建一个带有参数的对象?你能提出一些建议吗?

package com.whayway.beerrandom

import android.os.Bundle
import android.os.CountDownTimer
import android.os.Handler
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.navigation.findNavController
import com.whayway.beerrandom.databinding.FragmentGameBinding
import kotlinx.android.synthetic.main.fragment_game.*
import java.util.*


const val KEY_SCORE = "score_key"

class GameFragment : Fragment() {
    var handler: Handler = Handler()
    var score: Int = 0
    var runnable: Runnable = Runnable { }
    var imageArray = ArrayList<ImageView>()

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val binding = DataBindingUtil.inflate<FragmentGameBinding>(
            inflater, R.layout.fragment_game, container, false
        )
        score = 0

        if(savedInstanceState != null){
            score = savedInstanceState.getInt(KEY_SCORE, 0)
        }
        hideImages()

        object : CountDownTimer(15000, 1000) {
            override fun onTick(p0: Long) {
                btn_ok.visibility = View.INVISIBLE

                timeText.text = "Time: " + (p0 / 1000)
            }
            override fun onFinish() {
                timeText.text = "Time out"
                handler.removeCallbacks(runnable)
                for (image in imageArray) {
                    image.visibility = View.INVISIBLE
                    btn_ok.visibility = View.VISIBLE
                }
            }
        }.start()

        score = 0
        setHasOptionsMenu(true)

/*        val args = .fromBundle(arguments!!)
        Toast.makeText(context, "NumCorrect: ${args.numCorrect}, NumQuestions: ${args.numQuestions}", Toast.LENGTH_LONG).show()*/
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

        imageArray = arrayListOf(
            imageView8,
            imageView7,
            imageView6,
            imageView5,
            imageView4,
            imageView3,
            imageViewPawel,
            imageView111
        )
        scoreText.setOnClickListener {}
        imageView8.setOnClickListener { increaseScore() }
        imageView7.setOnClickListener {  increaseScore() }
        imageView8.setOnClickListener{increaseScore() }
        imageView6.setOnClickListener {  increaseScore() }
        imageView5.setOnClickListener {  increaseScore() }
        imageView4.setOnClickListener { increaseScore()
            setImage() }
        imageView3.setOnClickListener { decreaseScore()
            setImage() }
        imageViewPawel.setOnClickListener { increaseScorePawel()
            setImage()}
        imageView111.setOnClickListener { increaseScore()
            setImage()}

        btn_ok.setOnClickListener { view: View ->
            view.findNavController().navigate(
                GameFragmentDirections
                    .actionGameFragmentToResultFragment(score)
            )
        }
        super.onViewCreated(view, savedInstanceState)
    }
        private fun  setImage(){
            var drawableArray  = ArrayList<Int>()
            drawableArray = arrayListOf(
            R.drawable.pawel,
            R.drawable.leszek,
            R.drawable.lech_free)

            val random = Random()
            val index = random.nextInt(3 - 1)
            val index2 = random.nextInt(8 - 1)
            imageArray[index2].setImageResource(drawableArray[index])
    }
    private fun hideImages() {
        runnable = Runnable {
            for (image in imageArray) {
                image.visibility = View.INVISIBLE
            }
            val random = Random()
            val index = random.nextInt(8 - 1)

            imageArray[index].visibility = View.VISIBLE

            handler.postDelayed(runnable, 500)
        }
        handler.post(runnable)
    }
    override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        outState.putInt(KEY_SCORE, score)
    }
    private fun increaseScore() {
        score++
        scoreText.text = "Score:" + score
    }
    private fun increaseScorePawel() {
        score += 5
        scoreText.text = "Score:" + score
    }
    private fun decreaseScore() {
        score -= 10
        scoreText.text = "Score:" + score
    }
}

最佳答案

您的问题没有单一的最佳答案,但对我来说最有意义的解决方案是创建 CountDownTimer 的实现。

我不确定您想要在计数器内部更改什么,但您应该能够通过将值传递给构造函数来处理大多数事情:

class GameTimer(interval: Long) : CountDownTimer(15000, interval) {
    ...
}

或回调(自定义行为):

class GameTimer(onTimeOut: () -> Unit) : CountDownTimer(15000, 1000) {
    ...
    
    override fun onFinish() { onTimeOut() }
}

我认为引入工厂设计模式是一个好主意。因为这对你来说可能毫无意义,让我给你看一个例子:

// could be also a class with constructor parameters, it all depends on your use case
object GameTimerFactory {
  fun easyGameTimer() = GameTimer(1000)
  fun mediumGameTimer() = GameTimer(800)  
  fun hardGameTimer() = GameTimer(650)
}

根据您从更高级别组件调用它的方式,您可能需要使用枚举:

enum class Difficulty { EASY, MEDIUM, HARD }

object GameTimerFactory {
  fun gameTimerFor(difficulty: Difficulty): GameTimer = when (difficulty) {
    ...
  }
}

还有一个提示:明智的做法是从 Android 逻辑中提取游戏逻辑,以符合 SoC principle 的要求。 。 tl;dr:在每个程序中都有一些层,例如在您的程序中,我们可以轻松地看到一个显示游戏的 Android 特定层和一个包含游戏规则的层。如果您想将游戏移植到其他平台(例如桌面),它会很有用,如果您想对游戏逻辑进行单元测试,它几乎是必要的。有很多很好的解释:

关于java - 使用一个类的最佳方式,内部只更改一个对象 - Kotlin/Android/Java,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64042099/

相关文章:

Android Google Maps V2 当前位置经纬度 NullPointerException

java - 如何在 java 中使用 FirebaseListAdapter 从 firebase 数据库中读取子项?

kotlin - 用于安全施法的智能施法

android - kotlin coroutine 和 main handler 的关系

java - 从java打印文档时是否可以弹出打印对话框?

java - JFrame 中的更新信息

java - 如何对服装尺码列表(例如 4XL、S、2XL)进行排序?

java递归测试arraylist是否相等

android - 处理 ACTION_EDIT 结果

spring-boot - springboot 从 2.3.5.RELEASE 升级到 2.4.1-ClassNotFoundException : org. springframework.boot.context.properties.ConfigurationBeanFactoryMetadata