掌握数字合成的艺术:使用Android原生控件打造2048小游戏

移动开发 Android
玩家需要通过上下左右滑动屏幕,使得相同数字的方块在碰撞时相加,目标是组合出数字2048。在游戏中,每次滑动后,系统会在空白格子随机生成一个新数字,玩家需要策略性地进行滑动,以合并方块并逐步接近目标数字。

2048游戏是一款经典的数字合成益智游戏,2048游戏以其简单的规则、易于上手的操作和富有挑战性的玩法而受到广大玩家的喜爱。不仅锻炼了玩家的逻辑思维和策略规划能力,还提供了放松和娱乐的休闲方式。

游戏说明

  • 「游戏目标」:玩家需要通过上下左右滑动屏幕,使得相同数字的方块在碰撞时相加,目标是组合出数字2048。在游戏中,每次滑动后,系统会在空白格子随机生成一个新数字,玩家需要策略性地进行滑动,以合并方块并逐步接近目标数字。
  • 「操作方法」

向上、下、左、右滑动屏幕来移动所有方块。

相同数字的方块相撞时会合并成为它们的和。

  • 「游戏规则」

每次滑动后,会在空白处随机出现一个2或4的方块。

当无法移动时游戏结束。

  • 「得分规则」

每次合并方块时,合并后的数字会被加到总分中。

尽可能创造更大的数字来获得高分。

  • 「游戏策略」

保持大数字在角落。

尽量保持棋盘整洁,给自己更多合并的机会。

👇🏻下面我们使用Android原生控件来实现这个小游戏(PS:不包含自定义View的方式)

实现思路

1.使用2维数组表示游戏棋盘,在界面中形成一个4*4的棋盘,在布局中添加GridLayout显示棋盘,添加TextView用来显示游戏分数
private val board = Array(4) { IntArray(4) }
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FAF8EF">

    <TextView
        android:id="@+id/titleTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"
        android:text="2048"
        android:textColor="#776E65"
        android:textSize="48sp"
        android:textStyle="bold"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/scoreTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"
        android:text="Score: 0"
        android:textColor="#776E65"
        android:textSize="18sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="@id/titleTextView" />

    <GridLayout
        android:id="@+id/gridLayout"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_margin="16dp"
        android:background="#BBADA0"
        android:columnCount="4"
        android:padding="4dp"
        android:rowCount="4"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintDimensionRatio="1:1"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/titleTextView" />

</androidx.constraintlayout.widget.ConstraintLayout>

界面效果界面效果


2.通过手势检测来触发移动操作
private lateinit var gestureDetector: GestureDetector

gestureDetector用于检测手势的GestureDetector,拦截触摸事件并计算出手势的方向,调用相应的移动函数 (moveLeft, moveRight, moveUp, moveDown)进行游戏控制

override fun onTouchEvent(event: MotionEvent): Boolean {
    return gestureDetector.onTouchEvent(event) || super.onTouchEvent(event)
}

override fun onDown(e: MotionEvent): Boolean = true

override fun onFling(
    e1: MotionEvent?,
    e2: MotionEvent,
    velocityX: Float,
    velocityY: Float
): Boolean {
    val diffX = e2.x - (e1?.x ?: 0f)
    val diffY = e2.y - (e1?.y ?: 0f)

    if (Math.abs(diffX) > Math.abs(diffY)) {
        if (diffX > 0) {
            moveRight()
        } else {
            moveLeft()
        }
    } else {
        if (diffY > 0) {
            moveDown()
        } else {
            moveUp()
        }
    }

    addNewTile()
    updateUI()
    return true
}
3.每次移动后,检查并合并相同的数字

以moveLeft为例,对每一行进行操作,过滤掉0,将非0数字靠左排列,合并相邻的相同数字

private fun moveLeft() {
    var changed = false
    for (i in 0 until 4) {
        val row = board[i].filter { it != 0 }.toMutableList()
        var j = 0
        while (j < row.size - 1) {
            if (row[j] == row[j + 1]) {
                row[j] *= 2
                score += row[j]
                row.removeAt(j + 1)
                changed = true
            }
            j++
        }
        while (row.size < 4) {
            row.add(0)
        }
        if (board[i] != row.toIntArray()) {
            changed = true
        }
        board[i] = row.toIntArray()
    }
    if (changed) {
        addNewTile()
    }
    checkGameOver()
}

填充0到4个格子,如果检测到有变化,添加新方块格子

4.每次有效移动后,在空白位置随机添加新的数字(2或4)
private fun addNewTile() {
    val emptyTiles = mutableListOf<Pair<Int, Int>>()
    for (i in 0 until 4) {
        for (j in 0 until 4) {
            if (board[i][j] == 0) {
                emptyTiles.add(Pair(i, j))
            }
        }
    }

    if (emptyTiles.isNotEmpty()) {
        val (i, j) = emptyTiles[Random.nextInt(emptyTiles.size)]
        board[i][j] = if (Random.nextFloat() < 0.9f) 2 else 4
    }
}

90%概率放置2,10%概率放置4

图片图片

5.实时更新UI以反映游戏状态
private fun updateUI() {
    gridLayout.removeAllViews()
    for (i in 0 until 4) {
        for (j in 0 until 4) {
            val tileView = TextView(this)
            tileView.text = if (board[i][j] != 0) board[i][j].toString() else ""
            tileView.setBackgroundResource(getTileBackground(board[i][j]))
            tileView.setTextColor(ContextCompat.getColor(this, getTileTextColor(board[i][j])))
            tileView.textSize = 24f
            tileView.gravity = android.view.Gravity.CENTER

            val params = GridLayout.LayoutParams()
            params.width = 0
            params.height = 0
            params.columnSpec = GridLayout.spec(j, 1f)
            params.rowSpec = GridLayout.spec(i, 1f)
            params.setMargins(4, 4, 4, 4)
            tileView.layoutParams = params

            gridLayout.addView(tileView)
        }
    }
    scoreTextView.text = "分数: $score"
}

清空gridLayout,根据board数组重新生成所有方块,设置方块的背景颜色和文字颜色,最后更新分数显示

6.持续检查游戏是否结束
private fun isGameOver(): Boolean {
    for (i in 0 until 4) {
        for (j in 0 until 4) {
            if (board[i][j] == 0) {
                return false
            }
        }
    }

    for (i in 0 until 4) {
        for (j in 0 until 4) {
            if (i < 3 && board[i][j] == board[i + 1][j]) {
                return false
            }
            if (j < 3 && board[i][j] == board[i][j + 1]) {
                return false
            }
        }
    }

    return true
}

检查是否还有空格,检查是否有相邻的相同数字,如果两者都没有游戏结束

图片图片

完整代码

游戏画面游戏画面


https://github.com/Reathin/Sample-Android/tree/master/module_2048

责任编辑:武晓燕 来源: 沐雨花飞蝶
相关推荐

2024-12-09 09:18:21

Android原生控件

2023-08-07 15:18:29

游戏开发鸿蒙Arkts

2024-12-17 17:46:05

Android原生控件贪吃蛇

2020-11-12 09:44:43

鸿蒙

2023-09-01 21:20:06

授权委派KPI

2022-08-25 21:41:43

ArkUI鸿蒙

2022-08-04 13:55:08

拼数字小游戏鸿蒙

2022-11-09 11:57:17

原生JS五子棋

2020-12-09 11:42:18

WiFi IoT鸿蒙开发

2021-04-13 06:35:13

Elixir语言编程语言软件开发

2014-04-08 15:16:07

2048算法分析算法

2024-04-11 07:40:55

Go并发编程

2023-10-18 07:55:41

Python字符串

2024-05-06 07:53:09

Go并发编程

2023-02-01 08:17:48

GitHub提交信息

2021-08-25 09:54:51

鸿蒙HarmonyOS应用

2021-11-18 11:52:49

HTML5小游戏JS

2022-11-07 11:27:00

JS游戏开发

2014-12-09 14:52:42

编程

2023-11-22 08:37:40

Java线程池
点赞
收藏

51CTO技术栈公众号