我已经做了一个Android Tac脚趾适应作为一个周末项目。



这是科特林密码。
package com.mizech.tictactoe
import android.content.DialogInterface
import android.content.Intent
import android.graphics.Color
import android.os.Bundle
import android.view.View
import android.widget.ImageView
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.snackbar.Snackbar
import com.mizech.tictactoe.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private var gameState = mutableListOf<FeasibleState>()
private var isPlayerOne = true
private var fieldsUsed = 0
private val imageViews = mutableListOf<ImageView>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
var i = 0
while (i < 9) {
gameState.add(FeasibleState.NOT_SET)
i++
}
// Add the imageViews to the List
imageViews.add(binding.imageView0)
imageViews.add(binding.imageView1)
imageViews.add(binding.imageView2)
imageViews.add(binding.imageView3)
imageViews.add(binding.imageView4)
imageViews.add(binding.imageView5)
imageViews.add(binding.imageView6)
imageViews.add(binding.imageView7)
imageViews.add(binding.imageView8)
// Iterate the list and attach an Listener to each.
imageViews.forEach {
it.setOnClickListener {
processStateChange(it)
}
}
binding.resetGame.setOnClickListener {
val intent = Intent(this, MainActivity::class.java)
val snackbar = Snackbar.make(it, "Game Reset cancelled",
Snackbar.LENGTH_LONG)
val dialog = AlertDialog.Builder(this)
dialog.apply {
setIcon(R.drawable.ic_baseline_priority_high_24)
setTitle("Game Reset")
setMessage("Do you want to continue?")
setPositiveButton("Yes", DialogInterface.OnClickListener { dialog, which ->
startActivity(intent)
})
setNegativeButton("No", DialogInterface.OnClickListener { dialog, which ->
snackbar.show()
})
}.show()
}
}
private fun checkGameState(currentPlayer: FeasibleState): Boolean {
if (gameState[0] === currentPlayer && gameState[1] === currentPlayer
&& gameState[2] === currentPlayer) {
return true
}
if (gameState[3] === currentPlayer && gameState[4] === currentPlayer
&& gameState[5] === currentPlayer) {
return true
}
if (gameState[6] === currentPlayer && gameState[7] === currentPlayer
&& gameState[8] === currentPlayer) {
return true
}
if (gameState[0] === currentPlayer && gameState[3] === currentPlayer
&& gameState[6] === currentPlayer) {
return true
}
if (gameState[1] === currentPlayer && gameState[4] === currentPlayer
&& gameState[7] === currentPlayer) {
return true
}
if (gameState[2] === currentPlayer && gameState[5] === currentPlayer
&& gameState[8] === currentPlayer) {
return true
}
if (gameState[0] === currentPlayer && gameState[4] === currentPlayer
&& gameState[8] === currentPlayer) {
return true
}
if (gameState[2] === currentPlayer && gameState[4] === currentPlayer
&& gameState[6] === currentPlayer) {
return true
}
return false
}
private fun processStateChange(it: View) {
val imgView = it as ImageView
if (isPlayerOne) {
imgView.setImageResource(R.drawable.player_one)
fieldsUsed++
gameState[imgView.tag.toString().toInt()] = FeasibleState.PLAYER_ONE
checkResult(FeasibleState.PLAYER_ONE, R.string.one_won_message, "#64FF64")
} else {
imgView.setImageResource(R.drawable.player_two)
fieldsUsed++
gameState[imgView.tag.toString().toInt()] = FeasibleState.PLAYER_TWO
checkResult(FeasibleState.PLAYER_TWO, R.string.two_won_message, "#FF6464")
}
isPlayerOne = !isPlayerOne
imgView.isEnabled = false
}
private fun checkResult(currentPlayer: FeasibleState, message: Int, winnerColor: String) {
if (checkGameState(currentPlayer)) {
setFinalResult(message, winnerColor)
} else if (fieldsUsed == 9) {
setFinalResult(R.string.tie_message, "#ff00ff")
}
}
private fun setFinalResult(winnerString: Int, winnerColor: String) {
imageViews.forEach {
it.isEnabled = false
}
binding.currentMessage.text = getString(winnerString)
binding.currentMessage.setTextColor(Color.parseColor(winnerColor))
}
}package com.mizech.tictactoe
enum class FeasibleState {
NOT_SET,
PLAYER_ONE,
PLAYER_TWO
}完整的源代码和GitHub上的其他图片.
如何才能使我的实现得到改善?你会有什么不同的做法,为什么?
的意图
期待阅读你的答案和评论。
发布于 2021-05-08 16:53:55
每次重置游戏时,调用MainActivity就会创建一个活动堆栈,因此,如果用户玩了几个游戏并试图通过按后退按钮退出游戏,他们将不得不在每次游戏中完成之前的游戏,直到他们退出为止。
更好的方法可能是在用户确认后调用一个reset方法,而不是启动一个新的活动。实际上,您需要重置游戏状态和UI,这应该如下所示:
private fun resetGame() {
for (idx in 0..8) {
gameState[idx] = FeasibleState.NOT_SET
}
imageViews.forEach { view ->
view.setImageResource(R.drawable.not_set)
view.isEnabled = true
}
binding.currentMessage.text = ""
fieldsUsed = 0
isPlayerOne = true
}您的checkGameState函数有许多重复的行,所有这些行本质上都是在执行相同的操作。您正在检查三个游戏状态,以确定它们是否与当前的玩家匹配。另一种方法是创建一个有效的获胜组合列表。然后,您可以遍历列表来检查组合。就像这样:
private fun checkGameState(currentPlayer: FeasibleState): Boolean {
val winningCombo = arrayOf(
intArrayOf(0,1,2),
intArrayOf(3,4,5),
intArrayOf(6,7,8),
intArrayOf(0,3,6),
intArrayOf(1,4,7),
intArrayOf(2,5,8),
intArrayOf(0,4,8),
intArrayOf(2,4,6)
)
return winningCombo.filter { it.all { idx-> gameState[idx] == currentPlayer }}.any()
}发布于 2021-05-07 20:34:37
免责声明:我远不是专家,但因为还没有人对你做出回应,而且已经过了几个星期了。我想我可以试着给你一些反馈。
您的函数checkGameState包含大量重复的代码。尝试使用助手函数来消除这种重复。
gameState指的是网格中的9个方格。也许您应该将其重命名为squares或gridStates。而且,我也不认为它是可变的。所以我使用一个数组,而不是写这个:
private var gameState = mutableListOf<FeasibleState>()
...
var i = 0
while (i < 9) {
gameState.add(FeasibleState.NOT_SET)
i++
}我会同时声明和初始化这个数组。
var gridStates = Array(9, {FeasibleState.NOT_SET})现在,这可能是我的挑剔,但在我的例子中,我会使用一个循环来执行imageViews.add(binding.imageViewx),并使用一个数组来存储这些图像名(或者我会用一个字符串模板生成名称)。一旦我有了这个循环,我就会在同一个循环中完成onClickListener的设置。
https://codereview.stackexchange.com/questions/259971
复制相似问题