Zum Hauptinhalt springen
Echtzeit-Radar & Feeds
Alle RSS Feeds ➔
👥 Community & Social
Sichere ProgrammierungChrome for Developers: 93: State queries in 2025(24.09.2026 um 20:02 Uhr)
•
YouTube Security Videosdotnet: .NET + Foundry, better together(24.09.2026 um 18:35 Uhr)
••
Windows Tipps & SecurityMicrosoft 365 Companion Apps Are Being Retired(24.09.2026 um 19:40 Uhr)
••••
Videos & KonferenzenPC-WELT: Endlich hat die 2. RTX 5090 Sinn - lokale KI auf HMX 6!(24.09.2026 um 17:30 Uhr)
•
Unix & Linux ServerDocker Commits to Bringing the Sandbox Kit Spec to the CNCF(24.09.2026 um 18:00 Uhr)
••
Sichere ProgrammierungChrome for Developers: 93: State queries in 2025(24.09.2026 um 20:02 Uhr)
•
YouTube Security Videosdotnet: .NET + Foundry, better together(24.09.2026 um 18:35 Uhr)
••
Windows Tipps & SecurityMicrosoft 365 Companion Apps Are Being Retired(24.09.2026 um 19:40 Uhr)
••••
Videos & KonferenzenPC-WELT: Endlich hat die 2. RTX 5090 Sinn - lokale KI auf HMX 6!(24.09.2026 um 17:30 Uhr)
•
Unix & Linux ServerDocker Commits to Bringing the Sandbox Kit Spec to the CNCF(24.09.2026 um 18:00 Uhr)
••
Intelligence View
⚡ tsecurity.de Intelligence

Implementing the 2048 Puzzle Game on HarmonyOS Next

2048 is a classic puzzle game where players slide the screen to merge blocks with the same numbers, with the ultimate goal of synthesizing the number 2048. This article is based on the HarmonyOS ArkUI framework and provides a detailed…

0
↗ Quelle (dev.to)
Reagiere als Erste:r — dein Feedback zählt!

2048 is a classic puzzle game where players slide the screen to merge blocks with the same numbers, with the ultimate goal of synthesizing the number 2048. This article is based on the HarmonyOS ArkUI framework and provides a detailed analysis of its implementation process, explaining how to use declarative UI and state management to build such games.



2048






I. Core Data Structures and State Management






1. Game Grid and Scores



The core of the game is a 4x4 two-dimensional array used to store the numbers in each grid. The grid state is managed through the @State decorator to ensure that the UI is automatically refreshed when the data changes:




@State grid: number[][] = Array(4).fill(0).map(() => Array(4).fill(0));
@State score: number = 0; // Current score
@State bestScore: number = 0; // Historical highest score









2. Game Initialization



The initGame method is responsible for resetting the grid, adding initial blocks, and resetting the score. addNewTile is used to generate new blocks in random empty positions (90% probability of generating 2, 10% probability of generating 4):




initGame() {
this.grid = this.grid.map(() => Array(4).fill(0));
this.addNewTile();
this.addNewTile();
this.score = 0;
}









II. Sliding Logic and Merging Algorithm






1. Direction Handling and Matrix Rotation



The game supports sliding in four directions: up, down, left, and right. To simplify the code logic, matrix rotation is used to uniformly convert movements in different directions into leftward movements:





  • Leftward: Directly process each row.


  • Rightward: Reverse the row, move left, and then reverse it back.


  • Upward/Downward: Rotate the matrix into rows, process it, and then restore it to columns.




// Matrix rotation helper method
const rotate = (matrix: number[][]): number[][] => {
return matrix[0].map((_, i) => matrix.map(row => row[i]).reverse());
};









2. Single-Row Merging Logic



The processing of each row is divided into three steps:





  1. Remove Spaces: Filter out non-zero numbers.


  2. Merge Identical Numbers: Merge adjacent identical numbers and accumulate the score.


  3. Complete Length: Fill with zeros to a length of 4.




const moveRow = (row: number[]): number[] => {
let newRow = row.filter(cell => cell !== 0);
for (let i = 0; i < newRow.length - 1; i++) {
if (newRow[i] === newRow[i + 1]) {
newRow[i] *= 2;
this.score += newRow[i]; // Score accumulation
newRow.splice(i + 1, 1);
}
}
return [...newRow, ...Array(4 - newRow.length).fill(0)];
};









III. Game End Judgment



The game ends when the grid is full and there are no adjacent blocks that can be merged. The detection is carried out through the following steps:





  1. Check for Spaces: If there are spaces, the game has not ended.


  2. Horizontal Detection: Traverse each row to check for adjacent identical numbers.


  3. Vertical Detection: Traverse each column to check for adjacent identical numbers.




isGameOver(): boolean {
if (this.grid.some(row => row.includes(0))) return false;
// Horizontal and vertical detection logic
// ...
return true;
}









IV. UI Implementation and Interaction Design






1. Grid Rendering



The Grid component is used to dynamically generate a 4x4 grid, and each GridItem displays different background colors and text colors according to the numerical value:




Grid() {
ForEach(this.grid, (row: number[], i) => {
ForEach(row, (value: number, j) => {
GridItem() {
Text(value ? `${value}` : '')
.backgroundColor(this.getTileColor(value))
.fontColor(this.getTextColor(value));
}
})
})
}









2. Touch Event Handling



The onTouch event listens for sliding events, calculates the difference between the start and end coordinates, and determines the sliding direction:




onTouch((event) => {
if (event.type === TouchType.Down) {
this.startX = event.touches[0].x;
this.startY = event.touches[0].y;
} else if (event.type === TouchType.Up) {
const deltaX = event.touches[0].x - this.startX;
const deltaY = event.touches[0].y - this.startY;
// Judge the direction and call the move method
}
});









V. Local Storage and Animation Effects






1. High Score Persistence



PreferencesUtil is used to store and read the highest score to ensure that the data is retained after the application is restarted:




aboutToAppear() {
this.bestScore = PreferencesUtil.getNumberSync("bestScore");
}

// Update the highest score
if (this.score > this.bestScore) {
PreferencesUtil.putSync('bestScore', this.score);
}









2. Animation and Visual Effects



Each block's text change is added with a 150ms gradient animation to enhance the user experience:




Text(value ? `${value}` : '')
.animation({ duration: 150, curve: Curve.EaseOut });









VI. Summary and Complete Code



Through ArkUI's declarative UI and state management, the core logic of 2048 can be efficiently implemented. The key points include:





  • Matrix rotation simplifies direction processing.


  • State-driven UI automatic update.

  • Smooth combination of touch events and animations.




import { HashMap } from '@kit.ArkTS'
import { AppUtil, PreferencesUtil, ToastUtil } from '@pura/harmony-utils'

// index.ets
@Entry
@Component
struct Game2048 {
@State grid: number[][] = Array(4).fill(0).map(() => Array(4).fill(0)) // 4x4 game grid
@State score: number = 0 // Current score
@State bestScore: number = 0 // Historical highest score
private startX: number = 0 // Touch start X coordinate
private startY: number = 0 // Touch start Y coordinate

// Lifecycle method: triggered when the page is about to be displayed
aboutToAppear() {
this.initGame()
this.bestScore = PreferencesUtil.getNumberSync("bestScore") // Read the highest score stored locally
}

// Initialize the game
initGame() {
this.grid = this.grid.map(() => Array(4).fill(0)) // Reset the grid
this.addNewTile() // Add two new blocks
this.addNewTile() // Reset the current score
this.score = 0
}

addNewTile() {
const emptyCells: [number, number][] = [] // Collect the coordinates of empty cells
this.grid.forEach((row, i) => {
row.forEach((cell, j) => {
if (cell === 0) {
emptyCells.push([i, j])
}
})
})

if (emptyCells.length > 0) {
let n = Math.floor(Math.random() * emptyCells.length) // Randomly select an empty cell
const i = emptyCells[n][0]
const j = emptyCells[n][1]
this.grid[i][j] = Math.random() < 0.9 ? 2 : 4 // 90% probability of generating 2, 10% probability of generating 4
}
}

// Process movement logic
move(direction: 'left' | 'right' | 'up' | 'down') {
let newGrid = this.grid.map(row => [...row]) // Create a grid copy
let moved = false // Movement flag

// Matrix rotation helper methods
const rotate = (matrix: number[][]): number[][] => {
return matrix[0].map((_, i) => matrix.map(row => row[i]).reverse())
}
const rotateReverse = (matrix: number[][]): number[][] => {
return matrix[0].map((_, i) => matrix.map(row => row[row.length - 1 - i]))
}

// Process single-row movement and merging
const moveRow = (row: number[]): number[] => {
let newRow = row.filter(cell => cell !== 0) // Remove spaces
for (let i = 0; i < newRow.length - 1; i++) {
if (newRow[i] === newRow[i + 1]) { // Merge identical numbers
newRow[i] *= 2
this.score += newRow[i] // Update the score
newRow.splice(i + 1, 1) // Remove the merged element
}
}

// Complete the length
while (newRow.length < 4) {
newRow.push(0)
}
return newRow
}

// Process movement according to direction
switch (direction) {
case 'left':
newGrid.forEach((row, i) => newGrid[i] = moveRow(row))
break
case 'right':
newGrid.forEach((row, i) => newGrid[i] = moveRow(row.reverse()).reverse())
break
case 'up':
let rotatedDown = rotate(newGrid)
rotatedDown.forEach((row, i) => rotatedDown[i] = moveRow(row.reverse()).reverse())
newGrid = rotateReverse(rotatedDown)
break
case 'down':
let rotatedUp = rotate(newGrid)
rotatedUp.forEach((row, i) => rotatedUp[i] = moveRow(row))
newGrid = rotateReverse(rotatedUp)
break
}

moved = JSON.stringify(newGrid) !== JSON.stringify(this.grid) // Judge whether movement has occurred
this.grid = newGrid

if (moved) {
this.addNewTile() // Add a new block after movement
if (this.score > this.bestScore) { // Update the highest score
this.bestScore = this.score
PreferencesUtil.putSync('bestScore', this.bestScore) // Save the highest score
}
}

if (this.isGameOver()) { // Game end detection
ToastUtil.showToast('Game Over!')
}
}

// Game end judgment
isGameOver(): boolean {
// Check for empty cells
if (this.grid.some(row => row.includes(0))) {
return false
}

// Check for horizontal merges
for (let i = 0; i < 4; i++) {
for (let j = 0; j < 3; j++) {
if (this.grid[i][j] === this.grid[i][j + 1]) {
return false
}
}
}

// Check for vertical merges
for (let j = 0; j < 4; j++) {
for (let i = 0; i < 3; i++) {
if (this.grid[i][j] === this.grid[i + 1][j]) {
return false
}
}
}

return true
}

build() {
Column() {
// Score display row
Row() {
Text(`Score: ${this.score}`)
.fontSize(20)
.margin(10)
Text(`Highest Score: ${this.bestScore}`)
.fontSize(20)
.margin(10)
Button('New Game')
.onClick(() => this.initGame())
.margin(10)
}.margin({ top: px2vp(AppUtil.getStatusBarHeight()) })

// Game grid
Grid() {
ForEach(this.grid, (row: number[], i) => {
ForEach(row, (value: number, j) => {
GridItem() {
Text(value ? `${value}` : '')
.textAlign(TextAlign.Center)
.fontSize(24)
.fontColor(this.getTextColor(value))
.width('100%')
.height('100%')
.backgroundColor(this.getTileColor(value))
.animation({
duration: 150,
curve: Curve.EaseOut
})
}.key(`${i}-${j}`)
})
})
}
.columnsTemplate('1fr 1fr 1fr 1fr') // 4 equal columns
.rowsTemplate('1fr 1fr 1fr 1fr') // 4 equal rows
.width('90%')
.aspectRatio(1) // Maintain square shape
.margin(10)
.onTouch((event) => { // Touch event handling
if (event.type === TouchType.Down) {
this.startX = event.touches[0].x
this.startY = event.touches[0].y
} else if (event.type === TouchType.Up) {
const deltaX = event.touches[0].x - this.startX
const deltaY = event.touches[0].y - this.startY

// Judge the movement according to the sliding direction
if (Math.abs(deltaX) > Math.abs(deltaY)) {
deltaX > 0 ? this.move('right') : this.move('left')
} else {
deltaY > 0 ? this.move('down') : this.move('up')
}
}
})
}
.width('100%')
}

// Get the block background color
getTileColor(value: number): string {
const colors = new HashMap<number, string>()
colors.set(0, '#CDC1B4')
colors.set(2, '#EEE4DA')
colors.set(4, '#EDE0C8')
colors.set(8, '#F2B179')
colors.set(16, '#F59563')
colors.set(32, '#F67C5F')
colors.set(64, '#F65E3B')
colors.set(128, '#EDCF72')
colors.set(256, '#EDCF72')
colors.set(512, '#EDCC61')
colors.set(1024, '#EDC850')
colors.set(2048, '#EDC22E')
return colors.get(value) || '#CDC1B4'
}

// Get the text color
getTextColor(value: number): Color {
return value > 4 ? Color.White : Color.Black
}
}


SOC Incident Playbook: Vulnerability Remediation & Verification
title: Detect Exploitation - Implementing the 2048 Puzzle Game on HarmonyOS Next
id: e1916b80-13f7-4826-8c7f-f734bd455da1
status: experimental
description: Automatisch generierte SIEM-Erkennungsregel basierend auf CTI Intelligence
references:
  - https://tsecurity.de/
author: iShareStuff CTI Automated Detection Engine
date: 2026-09-24
logsource:
  category: network_connection
  product: any
detection:
  selection:
      CommandLine|contains:
        - 'exploit'
  condition: selection
falsepositives:
  - Legitime administrative Zugriffe oder Penetrationstests
level: high
tags:
  - attack.initial_access
rule CTI_Threat_Indicator {
    meta:
        author = "iShareStuff CTI Automated Detection Engine"
        date = "2026-09-24"
        description = "YARA Signature for "
    strings:
        $str = "Implementing the 2048 Puzzle G" ascii wide
    condition:
        any of them
}
tsecurity.de Cognitive Threat RAG
Fokus-Vektor:

Kognitive Analyse für identifizierte Bedrohung: Erhöhte Bedrohungslage im Bereich Implementing the 2048 Puzzle Game on Har.... Basierend auf 368k Vektor-Korrelationen werden sofortige Isolationsmaßnahmen für betroffene Endpunkte empfohlen.

🛡️ Angriffsfläche & Exposure

Netzwerk/Remote-Zugriff ohne Vorauthentifizierung möglich.

⚡ Empfohlene Sofortmaßnahmen
  • 1. Perimeter-Inspektion: Relevante Portfreigaben und exponierte Endpunkte unverzüglich scannen.
  • 2. Patch-Applikation: Hersteller-Hotfix einspielen oder betroffene Daemons in isolierte DMZ-Segmente überführen.
  • 3. Telemetrie & EDR-Alerts: Prozessaufrufe und Child-Processes auf anomale Shell-Spawns überwachen.
🔗 Semantisch verwandte Zero-Days MariaDB 11.7 VEC
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Implementing the 2048 Puzzle Game on HarmonyOS Next

Thematisch verwandte Begriffe: Implementing, 2048, Puzzle, Game · 6 Treffer

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-57175 | Python Social Auth is a social authentication/registration mechanism. Pr…
Advisory →
tsecurity.de Icon
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag
Themen-Radar & Intelligence Matrix
Echtzeit-Taxonomie nach Angriffsvektoren & Plattformen

tsecurity.de Live Threat Radar

🔴 LIVE RADAR
MONITORING
AKTIV
CVE-DATENBANK
LIVE
🔍
Community Radar & Live Chat
Sentinel Bot online • Live-Stream
Dein Cluster: Security Explorer
Match:
lädt…
Verbindung zum Community-Stream wird aufgebaut...
Bearbeitungsmodus — Senden überschreibt deine Nachricht
Community-Puls — was gerade passiert
lädt…
Aktivitäten deiner Analysten
lädt…
Neues Thema oder Eilmeldung einreichen

Reiche interessante Links, Zero-Days oder Debatten ein. Die Community entscheidet per Upvote über die Veröffentlichung.

Heiß diskutierte Einreichungen
📂 Keine gespeicherten Artikel vorhanden.
Zurück Ziehen Vor
Links: vorheriger Artikel • Rechts: nächster Artikel • unten: schließen
News NIS-2 Frühwarnung Tier-1 Intel TTP ⏱️ 3 Min vor 10 Min
Artikeldaten werden geladen...
↗ Original-Quelle