Untitled

 avatar
unknown
plain_text
5 months ago
8.7 kB
2
Indexable
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.gestures.detectDragGestures
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import kotlin.math.*

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            BlockPuzzleTheme {
                BlockPuzzleGame()
            }
        }
    }
}

@Composable
fun BlockPuzzleTheme(content: @Composable () -> Unit) {
    MaterialTheme(
        colors = darkColors(), // Or lightColors()
        content = content
    )
}


@Composable
fun BlockPuzzleGame() {
    var score by remember { mutableStateOf(0) }
    var highScore by remember { mutableStateOf(0) }
    var combo by remember { mutableStateOf(0) }
    val boardState = remember { mutableStateOf(Board(10, 20)) }
    val currentBlocks = remember { mutableStateOf(generateBlocks(3)) }
    val nextBlock = remember { mutableStateOf(generateBlock()) }
    var gameOver by remember { mutableStateOf(false) }

    Column(
        modifier = Modifier.fillMaxSize(),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {

        if (gameOver) {
            Text("Game Over!", style = MaterialTheme.typography.h5)
            Button(onClick = {
                boardState.value = Board(10, 20)
                currentBlocks.value = generateBlocks(3)
                nextBlock.value = generateBlock()
                score = 0
                combo = 0
                gameOver = false
            }) {
                Text("Play Again")
            }
        } else {
            Text("Score: $score High Score: $highScore Combo: $combo", style = MaterialTheme.typography.h6)

            BoardView(boardState.value)

            Spacer(Modifier.height(16.dp))

            Text("Next:", style = MaterialTheme.typography.h6)
            BlockView(nextBlock.value, Modifier.size(120.dp))

            Row {
                currentBlocks.value.forEachIndexed { index, block ->
                    DraggableBlock(block, index, currentBlocks) { dropPosition ->
                        val successfulDrop = boardState.value.placeBlock(block, dropPosition)

                        if (successfulDrop) {
                            score += 10 * (combo + 1)
                            combo++
                            if (score > highScore) {
                                highScore = score
                            }

                            currentBlocks[index] = nextBlock.value
                            nextBlock.value = generateBlock()
                            boardState.value.clearFullRows()

                            if (boardState.value.isGameOver(currentBlocks.value[index])) {
                                gameOver = true
                            }
                        } else {
                            combo = 0
                        }
                    }
                }
            }
        }
    }
}



@Composable
fun DraggableBlock(block: Block, index: Int, currentBlocks: MutableState<MutableList<Block>>, onDrop: (Position) -> Unit) {
    var offsetX by remember { mutableStateOf(0f) }
    var offsetY by remember { mutableStateOf(0f) }
    val animatedOffsetX by animateDpAsState(targetValue = offsetX.dp)
    val animatedOffsetY by animateDpAsState(targetValue = offsetY.dp)

    val density = LocalDensity.current



    val modifier = Modifier
        .offset { IntOffset(animatedOffsetX.roundToPx(), animatedOffsetY.roundToPx()) }
        .pointerInput(Unit) {
            detectDragGestures(
                onDragEnd = {
                    onDrop(Position((offsetX / density.density).roundToInt() / 30, (offsetY / density.density).roundToInt() / 30))
                },
                onDrag = { change, dragAmount ->
                    offsetX += dragAmount.x
                    offsetY += dragAmount.y
                }
            )
        }

    BlockView(block = block, modifier = modifier)


    Spacer(modifier = Modifier.width(10.dp))

}


@Composable
fun BlockView(block: Block, modifier: Modifier = Modifier) {
    Column(modifier = modifier) {
        block.shape.groupBy { it.y }.forEach { (_, cells) ->
            Row {
                cells.forEach { cell ->
                    Box(
                        modifier = Modifier
                            .size(30.dp)
                            .background(block.color)
                    )
                }
            }
        }
    }
}


data class Block(val shape: List<Position>, val color: Color)

data class Position(val x: Int, val y: Int)

class Board(val width: Int, val height: Int) {
    private val grid = Array(height) { Array(width) { Color.Transparent } }

    fun placeBlock(block: Block, position: Position): Boolean {
        // ... (same as before)
        val shape = block.shape

        for (cell in shape) {
            val x = cell.x + position.x
            val y = cell.y + position.y

            if (x < 0 || x >= width || y < 0 || y >= height || grid[y][x] != Color.Transparent) {
                return false
            }
        }


        for (cell in shape) {
            val x = cell.x + position.x
            val y = cell.y + position.y
            grid[y][x] = block.color
        }

        return true

    }

    fun clearFullRows() {
        // ... (same as before)

        val newGrid = Array(height) { Array(width) { Color.Transparent } }
        var newRow = height - 1

        for (row in height - 1 downTo 0) {
            if (grid[row].all { it != Color.Transparent }) {

                continue
            } else {

                newGrid[newRow] = grid[row]
                newRow--
            }
        }

        for (i in 0 until height){
            grid[i] = newGrid[i]
        }


    }

    fun getCellColor(x: Int, y: Int): Color {
        return grid[y][x]
    }


    fun isGameOver(nextBlock: Block): Boolean { // No valid placement found, game over
        for (x in 0 until width) {
            for (y in 0 until height) {
                if (canPlaceBlock(nextBlock, Position(x, y))) {
                    return false
                }
            }
        }
        return true
    }

    private fun canPlaceBlock(block: Block, position: Position): Boolean {  // Invalid placement
        // ... (same as before)

        val shape = block.shape
        for (cell in shape) {
            val x = cell.x + position.x
            val y = cell.y + position.y
            if (x < 0 || x >= width || y < 0 || y >= height || grid[y][x] != Color.Transparent) {
                return false
            }
        }
        return true


    }
}



@Composable
fun BoardView(board: Board) {
    Column {
        for (y in 0 until board.height) {
            Row {
                for (x in 0 until board.width) {
                    Surface(
                        modifier = Modifier
                            .size(30.dp)
                            .border(1.dp, Color.DarkGray),
                        color = board.getCellColor(x, y)
                    ) {}
                }
            }
        }
    }
}




// Block shapes and colors:
val shapes = listOf(
    listOf(Position(0, 0), Position(1, 0), Position(0, 1), Position(1, 1)), // Square
    listOf(Position(0, 0), Position(1, 0), Position(2, 0), Position(3, 0)), // Line
    listOf(Position(0, 0), Position(1, 0), Position(2, 0), Position(2, 1)),  // L-shape
    listOf(Position(0, 0), Position(0, 1), Position(1, 1), Position(2, 1)),
    listOf(Position(0, 0), Position(1, 0), Position(1, 1), Position(2, 1)),

    listOf(Position(1,0),Position(0,1),Position(1,1), Position(2,1))


    // Add more shapes...
)

val colors = listOf(
    Color.Red, Color.Blue, Color.Green, Color.Yellow, Color.Magenta, Color.Cyan
)

fun generateBlock(): Block {
    val randomShape = shapes.random()
    val randomColor = colors.random()
    return Block(randomShape, randomColor)
}


fun generateBlocks(count: Int): MutableList<Block> = mutableListOf<Block>().apply {
    repeat(count) { add(generateBlock()) }
}
Editor is loading...
Leave a Comment