import { Component,HostListener, OnInit } from '@angular/core'; interface Tile { value: number; merged: boolean; position: { row: number; col: number }; } @Component({ selector: 'app-page-game', templateUrl: './page-game.component.html', styleUrls: ['./page-game.component.scss'] }) export class PageGameComponent implements OnInit { tiles: Tile[] = []; score: number = 0; gameOver: boolean = false; mouseDownPosition: { x: number; y: number } | null = null; ngOnInit() { this.resetGame(); } resetGame() { this.tiles = []; this.score = 0; this.gameOver = false; for (let row = 0; row < 4; row++) { for (let col = 0; col < 4; col++) { this.tiles.push({ value: 0, merged: false, position: { row, col } }); } } this.addRandomTile(); this.addRandomTile(); } addRandomTile() { const emptyTiles = this.tiles.filter(tile => tile.value === 0); if (emptyTiles.length === 0) { return; } const randomIndex = Math.floor(Math.random() * emptyTiles.length); emptyTiles[randomIndex].value = Math.random() < 0.9 ? 2 : 4; } getTileStyle(tile: Tile) { return { 'background-color': this.getTileColor(tile), 'color': this.getTileTextColor(tile) }; } getTileColor(tile: Tile) { // Define your own color logic here based on the tile value // For simplicity, let's use a single color for all tiles return '#cdc1b4'; } getTileTextColor(tile: Tile) { // Define your own text color logic here based on the tile value // For simplicity, let's use a single color for all tiles return '#776e65'; } @HostListener('window:keydown', ['$event']) handleKeyDown(event: KeyboardEvent) { if (this.gameOver) { return; } let moved = false; switch (event.key) { case 'ArrowUp': moved = this.moveUp(); break; case 'ArrowDown': moved = this.moveDown(); break; case 'ArrowLeft': moved = this.moveLeft(); break; case 'ArrowRight': moved = this.moveRight(); break; } if (moved) { this.addRandomTile(); this.checkGameOver(); } } @HostListener('mousedown', ['$event']) handleMouseDown(event: MouseEvent) { this.mouseDownPosition = { x: event.clientX, y: event.clientY }; } @HostListener('mouseup', ['$event']) handleMouseUp(event: MouseEvent) { if (this.mouseDownPosition) { const deltaX = event.clientX - this.mouseDownPosition.x; const deltaY = event.clientY - this.mouseDownPosition.y; if (Math.abs(deltaX) > Math.abs(deltaY)) { if (deltaX > 0) { this.handleKeyDown({ key: 'ArrowRight' } as KeyboardEvent); } else { this.handleKeyDown({ key: 'ArrowLeft' } as KeyboardEvent); } } else { if (deltaY > 0) { this.handleKeyDown({ key: 'ArrowDown' } as KeyboardEvent); } else { this.handleKeyDown({ key: 'ArrowUp' } as KeyboardEvent); } } this.mouseDownPosition = null; } } moveUp() { let moved = false; this.resetMergedFlags(); for (let col = 0; col < 4; col++) { for (let row = 1; row < 4; row++) { const currentTile = this.getTile(row, col); if (currentTile.value !== 0) { let newRow = row - 1; while (newRow >= 0 && this.getTile(newRow, col).value === 0) { newRow--; } if (newRow >= 0) { const newTile = this.getTile(newRow, col); if (newTile.value === currentTile.value && !newTile.merged) { newTile.value *= 2; newTile.merged = true; this.score += newTile.value; currentTile.value = 0; moved = true; } else { const nextTile = this.getTile(newRow + 1, col); if (nextTile !== currentTile) { nextTile.value = currentTile.value; currentTile.value = 0; moved = true; } } } else { const nextTile = this.getTile(0, col); if (nextTile !== currentTile) { nextTile.value = currentTile.value; currentTile.value = 0; moved = true; } } } // if (!moved) { // moved = true; // } } } // if (moved === false) { // // 触发失败提示和重新开始游戏的操作 // this.showGameOver(); // this.resetGame(); // } // this.checkGameOver(); return moved; } moveDown() { let moved = false; this.resetMergedFlags(); for (let col = 0; col < 4; col++) { for (let row = 2; row >= 0; row--) { const currentTile = this.getTile(row, col); if (currentTile.value !== 0) { let newRow = row + 1; while (newRow < 4 && this.getTile(newRow, col).value === 0) { newRow++; } if (newRow < 4) { const newTile = this.getTile(newRow, col); if (newTile.value === currentTile.value && !newTile.merged) { newTile.value *= 2; newTile.merged = true; this.score += newTile.value; currentTile.value = 0; moved = true; } else { const nextTile = this.getTile(newRow - 1, col); if (nextTile !== currentTile) { nextTile.value = currentTile.value; currentTile.value = 0; moved = true; } } } else { const nextTile = this.getTile(3, col); if (nextTile !== currentTile) { nextTile.value = currentTile.value; currentTile.value = 0; moved = true; } } } // if (!moved) { // moved = true; // } } } // if (moved === false) { // // 触发失败提示和重新开始游戏的操作 // this.showGameOver(); // this.resetGame(); // } // this.checkGameOver(); return moved; } moveLeft() { let moved = false; this.resetMergedFlags(); for (let row = 0; row < 4; row++) { for (let col = 1; col < 4; col++) { const currentTile = this.getTile(row, col); if (currentTile.value !== 0) { let newCol = col - 1; while (newCol >= 0 && this.getTile(row, newCol).value === 0) { newCol--; } if (newCol >= 0) { const newTile = this.getTile(row, newCol); if (newTile.value === currentTile.value && !newTile.merged) { newTile.value *= 2; newTile.merged = true; this.score += newTile.value; currentTile.value = 0; moved = true; } else { const nextTile = this.getTile(row, newCol + 1); if (nextTile !== currentTile) { nextTile.value = currentTile.value; currentTile.value = 0; moved = true; } } } else { const nextTile = this.getTile(row, 0); if (nextTile !== currentTile) { nextTile.value = currentTile.value; currentTile.value = 0; moved = true; } } } // if (!moved) { // moved = true; // } } } // if (moved === false) { // // 触发失败提示和重新开始游戏的操作 // this.showGameOver(); // this.resetGame(); // } // this.checkGameOver(); return moved; } moveRight() { let moved = false; this.resetMergedFlags(); for (let row = 0; row < 4; row++) { for (let col = 2; col >= 0; col--) { const currentTile = this.getTile(row, col); if (currentTile.value !== 0) { let newCol = col + 1; while (newCol < 4 && this.getTile(row, newCol).value === 0) { newCol++; } if (newCol < 4) { const newTile = this.getTile(row, newCol); if (newTile.value === currentTile.value && !newTile.merged) { newTile.value *= 2; newTile.merged = true; this.score += newTile.value; currentTile.value = 0; moved = true; } else { const nextTile = this.getTile(row, newCol - 1); if (nextTile !== currentTile) { nextTile.value = currentTile.value; currentTile.value = 0; moved = true; } } } else { const nextTile = this.getTile(row, 3); if (nextTile !== currentTile) { nextTile.value = currentTile.value; currentTile.value = 0; moved = true; } } } // if (!moved) { // moved = true; // } } } // if (moved === false) { // // 触发失败提示和重新开始游戏的操作 // this.showGameOver(); // this.resetGame(); // } // this.checkGameOver(); return moved; } resetMergedFlags() { this.tiles.forEach(tile => { tile.merged = false; }); } checkGameOver() { const emptyTiles = this.tiles.filter(tile => tile.value === 0); if (emptyTiles.length > 0) { return; } for (let row = 0; row < 4; row++) { for (let col = 0; col < 4; col++) { const currentTile = this.getTile(row, col); if ( (row < 3 && currentTile.value === this.getTile(row + 1, col).value) || (col < 3 && currentTile.value === this.getTile(row, col + 1).value) ) { return; } } } this.gameOver = true; } getTile(row: number, col: number) { return this.tiles.find(tile => tile.position.row === row && tile.position.col === col)!; } // showGameOver() { // // 在界面上显示失败提示,可以使用弹窗、消息框等方式 // alert("Game Over!"); // } touchStart(event: TouchEvent) { this.mouseDownPosition = { x: event.touches[0].clientX, y: event.touches[0].clientY }; } touchMove(event: TouchEvent) { if (!this.mouseDownPosition) { return; } const currentX = event.touches[0].clientX; const currentY = event.touches[0].clientY; const deltaX = currentX - this.mouseDownPosition.x; const deltaY = currentY - this.mouseDownPosition.y; if (Math.abs(deltaX) > 10 || Math.abs(deltaY) > 10) { if (Math.abs(deltaX) > Math.abs(deltaY)) { if (deltaX > 0) { this.handleKeyDown({ key: 'ArrowRight' } as KeyboardEvent); } else { this.handleKeyDown({ key: 'ArrowLeft' } as KeyboardEvent); } } else { if (deltaY > 0) { this.handleKeyDown({ key: 'ArrowDown' } as KeyboardEvent); } else { this.handleKeyDown({ key: 'ArrowUp' } as KeyboardEvent); } } this.mouseDownPosition = null; } } }