在活动之间切换时看不到屏幕上的活动

时间:2020-10-14 02:10:04

标签: android kotlin

我尝试编写游戏Battleship(我是一个初学者),并且在进行各种活动之间切换时,计算机会在用户之后轮到他,而计算机最终会轮到他,但是我看不到他的屏幕出于某种原因停留在用户的屏幕(计算机的面板)上。

任何人都可以告诉我为什么吗? 该板由一个8x8的按钮网格组成。 单击MainActivity上的播放按钮后,程序将要求用户放置战舰,完成后单击开始按钮,活动将切换到ComputerSide。 计算机将其战舰随机放置在板上,然后要求用户选择目标。 选定目标并适当改变瓷砖的颜色后,活动将切换到UserSide,计算机将轮到该用户,此时我看不到活动的屏幕。

此外,它还在控制台中一直说正在跳过帧,而我读这是因为主线程做了太多的工作,但是我不知道在哪里做了太多的工作。

如果还有其他信息需要回答,请告诉我。

MainActivity:

class MainActivity : AppCompatActivity() {

    private lateinit var playButton: Button
    private lateinit var rulesButton: Button
    private lateinit var aboutButton: Button

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

        playButton = findViewById(R.id.btnPlay)
        rulesButton = findViewById(R.id.btnRules)
        aboutButton = findViewById(R.id.btnAbout)
    }

    fun playBtnClick(view: View) {
        // GameActivity::class.java
        val intent = Intent(this, UserSide::class.java)
        this.startActivity(intent)
    }

    fun aboutBtnClick(view: View) {
        val intent = Intent(this, AboutActivity::class.java)
        this.startActivity(intent)
    }

    fun rulesBtnClick(view: View) {
        val intent = Intent(this, RulesActivity::class.java)
        this.startActivity(intent)
    }
}

UserSide:

class UserSide : AppCompatActivity() {

    /***************** Messages for the user ******************/

    val occupiedMsg = { Toast.makeText(this, "Battleships overlapping, choose a different spot", Toast.LENGTH_SHORT).show() }

    val noSpaceUpwardsMsg = { Toast.makeText(this, "Not enough space upwards, try again.", Toast.LENGTH_SHORT).show() }

    val noSpaceDownwardsMsg = { Toast.makeText(this, "Not enough space downwards, try again.", Toast.LENGTH_SHORT).show() }

    val noSpaceLeftMsg = { Toast.makeText(this, "Not enough space to the left, try again.", Toast.LENGTH_SHORT).show() }

    val noSpaceRightMsg = { Toast.makeText(this, "Not enough space to the right, try again.", Toast.LENGTH_SHORT).show() }

    val notReadyMsg = { Toast.makeText(this, "Not all battleships have been placed.", Toast.LENGTH_SHORT).show() }

    val inSessionMsg = { Toast.makeText(this, "Game is in session.", Toast.LENGTH_SHORT).show() }

    /***********************************************************************************************************************/

    private val UPWARDS = 0
    private val DOWNWARDS = 1
    private val RIGHT = 2
    private val LEFT = 3

    private lateinit var instruction: TextView
    private lateinit var grid: GridLayout
    private lateinit var start: Button

    private var tiles: ArrayList<Button> = arrayListOf()
    private var battleships: ArrayList<Battleship> = arrayListOf()

    private var userInput = -1
    private var numOfTiles = 5 // Number of tiles of the current battleship to be placed.
    private var placedShips = 0

    private var inSession = false

    /************************** CHECK FUNCTION verticalCheck **********************/

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

        start = findViewById(R.id.btnStart)
        // Retrieving the instruction at the top.
        instruction = findViewById(R.id.instruction)

        // Retrieving the game board
        grid = findViewById(R.id.gridLayout)
        for(btn in grid) {
            tiles.add(findViewById(btn.id))
        }

        // Initializing battleships array
        for(num in 0 until 4) {
            battleships.add(Battleship(numOfTiles - num))
        }

        // Adding a listener to all the tiles
        for(btn in 1 until tiles.size + 1) {
            tiles[btn - 1].setOnClickListener {
                placeBattleship(btn)
                Thread.sleep(100)
            }
        }

        start.setOnClickListener { startGame() }
    }

    private fun placeBattleship(btnNum: Int) {

        when(numOfTiles) {
            // Placing 5 tile battleship
            5 -> vertOrHor(btnNum)
            // Placing 4 tile battleship
            4 -> vertOrHor(btnNum)
            // Placing 3 tile battleship
            3 -> vertOrHor(btnNum)
            // Placing 2 tile battleship
            2 -> vertOrHor(btnNum)
        }
    }

    private fun vertOrHor(btnNum: Int) {
        // Creating a dialog message and listeners for its buttons.
        val dialogClickListener = DialogInterface.OnClickListener { dialog, which ->
            when (which) {
                // Upwards
                DialogInterface.BUTTON_POSITIVE -> {
                    try {
                        upOrDown(btnNum)
                    }
                    catch (e: IndexOutOfBoundsException) { noSpaceUpwardsMsg() }
                }
                // Downwards
                DialogInterface.BUTTON_NEGATIVE -> {
                    try {
                        leftOrRight(btnNum)
                    }
                    catch (e: IndexOutOfBoundsException) { noSpaceDownwardsMsg() }
                }
            }
        }
        // Editing the text of the dialog and its buttons
        val builder: AlertDialog.Builder? = AlertDialog.Builder(this)
        builder?.setMessage("Place the battleship vertically or horizontally?")
            ?.setPositiveButton("Vertically", dialogClickListener)
            ?.setNegativeButton("Horizontally", dialogClickListener)?.show()
    }

    private fun upOrDown(btnNum: Int) {
        // Creating a dialog message and listeners for its buttons.
        val dialogClickListener = DialogInterface.OnClickListener { dialog, which ->
            when (which) {
                // Upwards
                DialogInterface.BUTTON_POSITIVE -> {
                    try {
                        userInput = UPWARDS
                        placeBattleshipVertical(btnNum)
                    }
                    catch (e: IndexOutOfBoundsException) { noSpaceUpwardsMsg() }
                }
                // Downwards
                DialogInterface.BUTTON_NEGATIVE -> {
                    try {
                        userInput = DOWNWARDS
                        placeBattleshipVertical(btnNum)
                    }
                    catch (e: IndexOutOfBoundsException) { noSpaceDownwardsMsg() }
                }
            }
        }
        // Editing the text of the dialog and its buttons
        val builder: AlertDialog.Builder? = AlertDialog.Builder(this)
        builder?.setMessage("Place the battleship upwards or downwards?")
            ?.setPositiveButton("Upwards", dialogClickListener)
            ?.setNegativeButton("Downwards", dialogClickListener)?.show()
    }

    private fun leftOrRight(btnNum: Int) {
        val dialogClickListener = DialogInterface.OnClickListener { dialog, which ->
            when (which) {
                // Upwards
                DialogInterface.BUTTON_POSITIVE -> {
                    try {
                        userInput = RIGHT
                        placeBattleshipHorizontal(btnNum)
                    }
                    catch (e: IndexOutOfBoundsException) { noSpaceRightMsg() }
                }
                // Downwards
                DialogInterface.BUTTON_NEGATIVE -> {
                    try {
                        userInput = LEFT
                        placeBattleshipHorizontal(btnNum)
                    }
                    catch (e: IndexOutOfBoundsException) { noSpaceLeftMsg() }
                }
            }
        }
        val builder: AlertDialog.Builder? = AlertDialog.Builder(this)
        builder?.setMessage("Place the battleship to the left or to the right?")
            ?.setPositiveButton("Right", dialogClickListener)
            ?.setNegativeButton("Left", dialogClickListener)?.show()
    }

    private fun placeBattleshipVertical(btnNum: Int) {
        if(verticalCheck(btnNum)) {
            if(userInput == UPWARDS) placeVertically(btnNum - 8 * (numOfTiles - 1), btnNum + 8)
            else placeVertically(btnNum, btnNum + 8 * numOfTiles)
            changeInstruction()
        }
    }

    private fun placeBattleshipHorizontal(btnNum: Int) {
        if(checkHorizontal(btnNum)) {
            if (userInput == RIGHT) placeHorizontally(btnNum, btnNum + numOfTiles)
            else placeHorizontally(btnNum - numOfTiles + 1, btnNum + 1)
            changeInstruction()
        }
    }

    private fun verticalCheck(btnNum: Int): Boolean {
        // Are the tiles above occupied?
        if(userInput == UPWARDS) {
            for (num in btnNum - (8 * (numOfTiles - 1)) until btnNum) {
                if (num < 0) {
                    noSpaceUpwardsMsg()
                    return false
                }
            }
            val occupied = isOccupiedVertically(btnNum - 8 * (numOfTiles - 1), btnNum + 8)
            if(!occupied) occupiedMsg()
            return occupied
        }
        else {
            for(num in btnNum + 8 until btnNum + (8 * (numOfTiles - 1)) step 8) {
                if(num > 64) {
                    noSpaceDownwardsMsg()
                    return false
                }
            }
            val occupied = isOccupiedVertically(btnNum, btnNum + 8 * numOfTiles)
            if(!occupied) occupiedMsg()
            return occupied
        }
    }

    private fun checkHorizontal(btnNum: Int): Boolean {
        if(userInput == LEFT) {
            for (num in btnNum - numOfTiles + 1 until btnNum + 1) {
                // Checking if battleship might be placed off screen
                if (num % 8 == 0 && num != btnNum) {
                    noSpaceLeftMsg()
                    return false
                }
            }
            // Checking if battleships overlap
            val occupied = isOccupiedHorizontally(btnNum - numOfTiles + 1, btnNum)
            if(!occupied) occupiedMsg()
            return occupied
        }
        else {
            for (num in btnNum until btnNum + numOfTiles) {
                // Right corner to the right
                if (num % 8 == 0 && num != btnNum + numOfTiles - 1) {
                    noSpaceRightMsg()
                    return false
                }
            }
        }
        val occupied = isOccupiedHorizontally(btnNum + 1, btnNum + numOfTiles)
        if(!occupied) occupiedMsg()
        return occupied
    }

    /* If a button has a listener, he is not occupied. */
    private fun hasListener(num: Int): Boolean = tiles[num - 1].hasOnClickListeners()

    // Checks the tiles vertically, returns true if not occupied
    private fun isOccupiedVertically(start: Int, end: Int): Boolean {
        for(num in start until end step 8) { if(!hasListener(num)) return false }
        return true
    }

    // Checks the tiles horizontally, returns true if not occupied
    private fun isOccupiedHorizontally(start: Int, end: Int): Boolean {
        for(num in start until end) { if(!hasListener(num)) return false }
        return true
    }

    private fun changeInstruction() {
        when(numOfTiles) {
            4 -> instruction.text = getString(R.string.place_your_4_tile_battleship)
            3 -> instruction.text = getString(R.string.place_your_3_tile_battleship)
            2 -> instruction.text = getString(R.string.place_your_2_tile_battleship)
            1 -> instruction.text = getString(R.string.Go)
        }
    }

    // Placing battleship by marking its tiles
    private fun placeVertically(start: Int, end: Int) {
        for (num in start until end step 8) {
            occupyTile(num)
        }
        numOfTiles--
        placedShips++
    }

    // Placing battleship by marking its tiles
    private fun placeHorizontally(start: Int, end: Int) {
        val ship = Battleship(numOfTiles)
        for(num in start until end) {
            ship.buildShip(tiles[num - 1])
            occupyTile(num)
        }
        battleships.add(ship)
        numOfTiles--
        placedShips++
    }

    @SuppressLint("UseCompatLoadingForDrawables")
    private fun occupyTile(num: Int) {
        //battleships[placedShips].buildShip(tiles[num - 1])
        tiles[num - 1].background = getDrawable(R.drawable.button_occupied_tile)
        tiles[num - 1].setOnClickListener(null)
    }

    @SuppressLint("UseCompatLoadingForDrawables")
    fun damageShip() {
        val btn = Utils.chooseTarget()
        println("Target is: $btn")
        val tile = tiles[btn - 1]
        val s: Battleship
        var didMiss = true
        for(ship in battleships) {
            // Successful hit.
            if(ship.contains(tile)) {
                s = ship
                tile.background = getDrawable(R.drawable.button_hit_tile)
                s.removeTile()
                s.getShip()[s.getTileInd(tile)].setOnClickListener(null)
                // Ship destroyed
                if(s.getNumOfTiles() == 0) {
                    var i = 0
                    while(i < s.getSize()) {
                        s.getShip()[i].background = getDrawable(R.drawable.button_destroyed_tile)
                        i++
                    }
                    battleships.remove(s)
                    // Game Done
                    if (battleships.size == 0) {
                        instruction.text = getString(R.string.Lose)
                        Utils.gameEnd = true
                        for (t in tiles) t.setOnClickListener(null)
                    }
                }
                if(!Utils.gameEnd) {
                    didMiss = false
                    Thread.sleep(200)
                    userTurn()
                }
                else return
                break
            }
        }
        // Missed hit
        if(didMiss) {
            // Missed hit
            tile.background = getDrawable(R.drawable.button_missed_tile)
            Thread.sleep(200)
            userTurn()
        }
    }

    // This class represents a battleship
    class Battleship(private var tiles: Int) {
        private var ship: ArrayList<Button> = arrayListOf()
        //private var size = tiles
        fun buildShip(btn: Button) = ship.add(btn)
        fun getSize() = ship.size
        fun getShip() = ship
        fun removeTile(){ tiles-- }
        fun getNumOfTiles() = tiles
        fun getTileInd(btn: Button) = ship.indexOf(btn)
        fun contains(btn: Button): Boolean {
            for(i in 0 until this.getSize()) { if(ship[i] == btn) return true }
            return false
        }
    }

    @SuppressLint("UseCompatLoadingForDrawables")
    private fun startGame() {
        // If all battleships have been placed.
        if(instruction.text == getString(R.string.Go)) {
            // If the game hasn't started yet.
            if (!inSession) {
                inSession = true
                for (btn in 1 until tiles.size + 1) {
                    tiles[btn - 1].background = getDrawable(R.drawable.button_start_tile)
                }
                instruction.text = ""
                start.visibility = View.INVISIBLE
                userTurn()
            }
            else inSessionMsg()
        }
        else notReadyMsg()
    }

    private fun userTurn() {
        Utils.userTurn = true
        val intent = Intent(this, ComputerSide::class.java)
        this.startActivity(intent)
    }

    override fun onResume() {
        super.onResume()
        if(inSession) damageShip()
    }
}

计算机端:

class ComputerSide : AppCompatActivity() {

    private val VERTICAL = 0
    private val HORIZONTAL = 1
    private val UPWARDS = 2
    private val DOWNWARDS = 3
    private val LEFT = 4
    private val RIGHT = 5

    private lateinit var grid: GridLayout

    private var tiles: ArrayList<Button> = arrayListOf()
    private var battleships: ArrayList<Battleship> = arrayListOf()

    private var numOfTiles = 5 // Number of tiles of the current battleship to be placed.
    private var placedShips = 0
    private lateinit var instruction: TextView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_computer_side)
        instruction = findViewById(R.id.instruction)

        // Retrieving the game board
        grid = findViewById(R.id.gridLayout)
        for(btn in grid) {
            tiles.add(findViewById(btn.id))
        }

        // Initializing battleships array
//        for(num in 0 until 4) {
//            battleships.add(Battleship(numOfTiles - num))
//        }

        // Adding a listener to all the tiles
        for(btn in 1 until tiles.size + 1) {
            tiles[btn - 1].setOnClickListener {}
        }
        placeBattleship()
    }

    @SuppressLint("UseCompatLoadingForDrawables")
    private fun placeBattleship() {
        vertOrHor()
        startGame()
    }

    private fun vertOrHor() {
        // Vertical or Horizontal
        while(numOfTiles > 1) {
            val choice = Random.nextInt(VERTICAL,HORIZONTAL + 1)
            when (choice) {
                // Vertical
                0 ->
                    try {
                        upOrDown()
                    }
                    catch (e: IndexOutOfBoundsException) { }
                // Horizontal
                1 ->
                    try {
                        leftOrRight()
                    }
                    catch (e: IndexOutOfBoundsException) { }
            }
        }
    }

    private fun upOrDown() {
        val choice = Random.nextInt(UPWARDS,DOWNWARDS + 1)
        placeBattleshipVertical(Utils.chooseStartingPlacement(), choice)
    }

    private fun leftOrRight() {
        val choice = Random.nextInt(LEFT, RIGHT + 1)
        placeBattleshipHorizontal(Utils.chooseStartingPlacement(), choice)
    }

    private fun placeBattleshipVertical(btnNum: Int, dir: Int) {
        if(verticalCheck(btnNum, dir)) {
            if(dir == UPWARDS) placeVertically(btnNum - 8 * (numOfTiles - 1), btnNum + 8)
            else placeVertically(btnNum, btnNum + 8 * numOfTiles)
        }
    }

    private fun placeBattleshipHorizontal(btnNum: Int, dir: Int) {
        if(dir == RIGHT) {
            // If there's space to the right
            if(checkHorizontal(btnNum, dir)) placeHorizontally(btnNum, btnNum + numOfTiles)
            else throw IndexOutOfBoundsException()
        }
        else {
            // If there's space to the left
            if(checkHorizontal(btnNum, dir)) placeHorizontally(btnNum - numOfTiles + 1, btnNum + 1)
            else throw IndexOutOfBoundsException()
        }
    }

    private fun verticalCheck(btnNum: Int, dir: Int): Boolean {
        // Are the tiles above occupied?
        if(dir == UPWARDS) {
            for (num in btnNum - (8 * (numOfTiles - 1)) until btnNum) {
                if (num < 0) return false
            }
            return (isOccupiedVertically(btnNum - 8 * (numOfTiles - 1), btnNum + 8))
        }
        else {
            for(num in btnNum + 8 until btnNum + (8 * (numOfTiles - 1)) step 8) {
                if(num > 64) return false
            }
            return (isOccupiedVertically(btnNum, btnNum + 8 * numOfTiles))
        }
    }
    
    private fun checkHorizontal(btnNum: Int, dir: Int): Boolean {
        if(dir == LEFT) {
            for (num in btnNum - numOfTiles + 1 until btnNum + 1) {
                // Checking if battleship might be placed off screen
                if (num % 8 == 0 && num != btnNum) return false
                // Checking if battleships overlap
                return (isOccupiedHorizontally(btnNum - numOfTiles + 1, btnNum))
            }
        }
        else {
            for (num in btnNum until btnNum + numOfTiles) {
                // Right corner to the right
                if (num % 8 == 0 && num != btnNum + numOfTiles - 1) return false
            }
        }
        return (isOccupiedHorizontally(btnNum + 1, btnNum + numOfTiles))
    }

    /* If a button has a listener, he is not occupied. */
    private fun hasListener(num: Int): Boolean = tiles[num - 1].hasOnClickListeners()

    // Checks the tiles vertically, returns true if not occupied
    private fun isOccupiedVertically(start: Int, end: Int): Boolean {
        for(num in start until end step 8) { if(!hasListener(num)) return false }
        return true
    }

    // Checks the tiles horizontally, returns true if not occupied
    private fun isOccupiedHorizontally(start: Int, end: Int): Boolean {
        for(num in start until end) { if(!hasListener(num)) return false }
        return true
    }

    // Placing battleship by marking its tiles
    private fun placeVertically(start: Int, end: Int) {
        val ship = Battleship(numOfTiles)
        for (num in start until end step 8) {
            ship.buildShip(tiles[num - 1])
            occupyTile(num)
        }
        battleships.add(ship)
        numOfTiles--
        placedShips++
    }

    // Placing battleship by marking its tiles
    private fun placeHorizontally(start: Int, end: Int) {
        val ship = Battleship(numOfTiles)
        for(num in start until end) {
            ship.buildShip(tiles[num - 1])
            occupyTile(num)
        }
        battleships.add(ship)
        numOfTiles--
        placedShips++
    }

    @SuppressLint("UseCompatLoadingForDrawables")
    private fun occupyTile(num: Int) {
        //battleships[placedShips].buildShip(tiles[num - 1])
        tiles[num - 1].background = getDrawable(R.drawable.button_occupied_tile)
        tiles[num - 1].setOnClickListener(null)
    }

    @SuppressLint("UseCompatLoadingForDrawables")
    fun damageShip(btn: Button) {
        if(Utils.userTurn) {
            var didMiss = true
            val s: Battleship
            for (ship in battleships) {
                // Successful hit.
                if (ship.contains(btn)) {
                    s = ship
                    btn.background = getDrawable(R.drawable.button_hit_tile)
                    s.getShip()[s.getShip().indexOf(btn)].setOnClickListener(null)
                    s.removeTile()
                    // Ship destroyed
                    if (s.getNumOfTiles() == 0) {
                        var i = 0
                        while (i < s.getSize()) {
                            s.getShip()[i].background = getDrawable(R.drawable.button_destroyed_tile)
                            i++
                        }
                        battleships.remove(s)
                        // Game Done
                        if (battleships.size == 0) {
                            instruction.text = getString(R.string.Win)
                            Utils.gameEnd = true
                            for (tile in tiles) tile.setOnClickListener(null)
                        }
                    }
                    if(!Utils.gameEnd) {
                        didMiss = false
                        Thread.sleep(200)
                        computerTurn()
                    }
                    else return
                    break
                }
            }
            if(didMiss) {
                // Missed hit
                btn.background = getDrawable(R.drawable.button_missed_tile)
                Thread.sleep(200)
                computerTurn()
            }
        }
    }

    // This class represents a battleship
    class Battleship(private var tiles: Int) {
        private var ship: ArrayList<Button> = arrayListOf()
        //private var size = tiles
        fun buildShip(btn: Button) = ship.add(btn)
        fun getSize() = ship.size
        fun getTile(i: Int) : Button = ship[i]
        fun getShip() = ship
        fun removeTile() = tiles--
        fun getNumOfTiles() = tiles
        fun contains(btn: Button): Boolean {
            for(i in 0 until this.getSize()) { if(ship[i] == btn) return true }
            return false
        }
    }

    @SuppressLint("UseCompatLoadingForDrawables")
    private fun startGame() {
        for (tile in 1 until tiles.size + 1) {
            tiles[tile - 1].background = getDrawable(R.drawable.button_start_tile)
            tiles[tile - 1].setOnClickListener { damageShip(tiles[tile - 1]) }
        }
        Utils.initArray()
        instruction.text = getString(R.string.strike_a_target)
    }

    private fun computerTurn() {
        Utils.userTurn = false
        val intent = Intent(this, UserSide::class.java)
        this.startActivity(intent)
    }
}

1 个答案:

答案 0 :(得分:0)

private fun vertOrHor()是否一直在运行?您如何突破这个for循环?

onCreate的{​​{1}}中的for循环正在做很多事情。

但是,您需要做一些事情。

您不需要每个按钮都带有clickListener。您可以将单个clickListener放在网格上,例如 how to use onclicklistener for grid view

相关问题