angular贪吃蛇

devtools/2025/2/27 0:54:15/

说明:我计划用angular实现一个贪吃蛇的程序,并且有方向键去控制蛇的上下左右的移动,并且有得分系统,当蛇撞到墙壁或者自身,游戏结束
效果图:
在这里插入图片描述

step1: C:\Users\Administrator\WebstormProjects\untitled4\src\app\snake\snake.component.ts

javascript">import { Component , OnInit, OnDestroy, HostListener } from '@angular/core';interface Position {x: number;y: number;
}@Component({selector: 'app-snake',imports: [],templateUrl: './snake.component.html',styleUrl: './snake.component.css'
})
export class SnakeComponent implements OnInit, OnDestroy{private ctx!: CanvasRenderingContext2D;private gameLoop!: any;private gridSize = 20;snake: Position[] = [{ x: 10, y: 10 }];food: Position = this.generateFood();direction: 'UP' | 'DOWN' | 'LEFT' | 'RIGHT' = 'RIGHT';score = 0;gameSpeed = 150;isPaused = false;@HostListener('window:keydown', ['$event'])handleKeydown(event: KeyboardEvent) {this.handleDirection(event.key.replace('Arrow', '').toUpperCase());}ngOnInit() {const canvas = document.getElementById('gameCanvas') as HTMLCanvasElement;this.ctx = canvas.getContext('2d')!;this.startGame();}ngOnDestroy() {clearInterval(this.gameLoop);}handleDirection(newDirection: string) {const validMoves: Record<string, boolean> = {'UP': this.direction !== 'DOWN','DOWN': this.direction !== 'UP','LEFT': this.direction !== 'RIGHT','RIGHT': this.direction !== 'LEFT'};if (validMoves[newDirection]) {this.direction = newDirection as any;}}private startGame() {this.gameLoop = setInterval(() => this.update(), this.gameSpeed);}private update() {if (this.isPaused) return;const head = { ...this.snake[0] };switch (this.direction) {case 'UP': head.y--; break;case 'DOWN': head.y++; break;case 'LEFT': head.x--; break;case 'RIGHT': head.x++; break;}if (this.checkCollision(head)) {clearInterval(this.gameLoop);alert(`游戏结束! 得分: ${this.score}`);return;}this.snake.unshift(head);if (head.x === this.food.x && head.y === this.food.y) {this.score++;this.food = this.generateFood();this.gameSpeed = Math.max(50, this.gameSpeed - 2);} else {this.snake.pop();}this.draw();}private draw() {// 游戏区域背景this.ctx.fillStyle = '#1a1b26';this.ctx.fillRect(0, 0, 400, 400);// 食物绘制this.ctx.fillStyle = '#f7768e';this.ctx.beginPath();this.ctx.roundRect(this.food.x * this.gridSize + 2,this.food.y * this.gridSize + 2,this.gridSize - 4,this.gridSize - 4,4);this.ctx.fill();// 蛇身绘制this.snake.forEach((segment, index) => {this.ctx.fillStyle = index === 0 ? '#9ece6a' : '#73daca';this.ctx.beginPath();this.ctx.roundRect(segment.x * this.gridSize + 2,segment.y * this.gridSize + 2,this.gridSize - 4,this.gridSize - 4,index === 0 ? 6 : 4);this.ctx.fill();});}private generateFood(): Position {return {x: Math.floor(Math.random() * 20),y: Math.floor(Math.random() * 20)};}private checkCollision(pos: Position): boolean {return pos.x < 0 || pos.x >= 20 || pos.y < 0 || pos.y >= 20 ||this.snake.some(segment => segment.x === pos.x && segment.y === pos.y);}togglePause() {this.isPaused = !this.isPaused;}resetGame() {this.snake = [{ x: 10, y: 10 }];this.direction = 'RIGHT';this.score = 0;this.gameSpeed = 150;this.food = this.generateFood();this.isPaused = false;clearInterval(this.gameLoop);this.startGame();}
}

step2: C:\Users\Administrator\WebstormProjects\untitled4\src\app\snake\snake.component.html

<!-- snake.component.html -->
<div class="game-container"><div class="game-header"><div class="score-box"><span>得分: {{ score }}</span></div><div class="controls"><button class="control-btn pause-btn" (click)="togglePause()">{{ isPaused ? '继续' : '暂停' }}</button><button class="control-btn reset-btn" (click)="resetGame()">重置</button></div></div><canvas id="gameCanvas" width="400" height="400"></canvas><div class="direction-controls"><div class="control-row"><button class="direction-btn up" (click)="handleDirection('UP')"></button></div><div class="control-row"><button class="direction-btn left" (click)="handleDirection('LEFT')"></button><button class="direction-btn down" (click)="handleDirection('DOWN')"></button><button class="direction-btn right" (click)="handleDirection('RIGHT')"></button></div></div>
</div>

step3: C:\Users\Administrator\WebstormProjects\untitled4\src\app\snake\snake.component.css

/* snake.component.css */
.game-container {display: flex;flex-direction: column;align-items: center;gap: 1.5rem;padding: 2rem;background: #24283b;border-radius: 1.5rem;box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
}.game-header {display: flex;justify-content: space-between;width: 100%;max-width: 400px;color: #c0caf5;
}.score-box {background: #414868;padding: 0.5rem 1rem;border-radius: 0.5rem;font-size: 1.1rem;
}.controls {display: flex;gap: 0.5rem;
}.control-btn {padding: 0.5rem 1rem;border: none;border-radius: 0.5rem;cursor: pointer;transition: transform 0.2s, opacity 0.2s;
}.pause-btn {background: linear-gradient(135deg, #7aa2f7, #2ac3de);color: white;
}.reset-btn {background: linear-gradient(135deg, #f7768e, #ff9e64);color: white;
}.control-btn:hover {opacity: 0.9;transform: translateY(-1px);
}.direction-controls {display: flex;flex-direction: column;gap: 0.5rem;
}.control-row {display: flex;justify-content: center;gap: 0.5rem;
}.direction-btn {width: 3.5rem;height: 3.5rem;border: none;border-radius: 1rem;background: linear-gradient(145deg, #414868, #565f89);color: #c0caf5;font-size: 1.5rem;cursor: pointer;transition: all 0.2s;display: flex;align-items: center;justify-content: center;
}.direction-btn:hover {background: linear-gradient(145deg, #565f89, #414868);transform: scale(1.05);box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}.direction-btn:active {transform: scale(0.95);
}/* 移动端优化 */
@media (max-width: 480px) {.game-container {padding: 1rem;width: 95vw;}canvas {width: 95vw;height: 95vw;}.direction-btn {width: 3rem;height: 3rem;font-size: 1.2rem;}
}

end


http://www.ppmy.cn/devtools/162921.html

相关文章

react module.scss 避免全局冲突类似vue中scoped

创建 index.module.scss 文件 src/components/MyComponent/index.module.scssindex.tsx2. 编写 index.module.scss 内容 // src/components/MyComponent/index.module.scss.container {padding: 20px;background-color: #f0f0f0;.title {font-size: 24px;color: #333;}.butto…

Pretraining Language Models with Text-Attributed Heterogeneous Graphs

Pretraining Language Models with Text-Attributed Heterogeneous Graphs EMNLP 推荐指数&#xff1a;#paper/⭐⭐#​ 贡献&#xff1a; 我们研究了在更复杂的数据结构上预训练LM的问题&#xff0c;即&#xff0c;TAHG。与大多数只能从每个节点的文本描述中学习的PLM不同&…

CSS编程基础学习

1. CSS 简介 1.1. CSS概念及作用 HTML即超文本标记语言&#xff08;HyperText Markup Language&#xff09;&#xff0c;是网页制作的基础&#xff0c;通过HTML&#xff0c;开发者可以定义网页的标题、段落、链接、图像、列表、表格、表单等元素。引入CSS 可以针对 HTML 里的…

Web自动化之Selenium 超详细教程(python)

Selenium是一个开源的基于WebDriver实现的自动化测试工具。WebDriver提供了一套完整的API来控制浏览器&#xff0c;模拟用户的各种操作&#xff0c;如点击、输入文本、获取页面元素等。通过Selenium&#xff0c;我们可以编写自动化脚本&#xff0c;实现网页的自动化测试、数据采…

Java集合应用案例面试题

Java集合应用案例面试题 缓存实现 Q1: 如何使用LinkedHashMap实现LRU缓存&#xff1f; public class LRUCacheExample {// 1. 基于LinkedHashMap实现的LRU缓存public class LRUCache<K, V> extends LinkedHashMap<K, V> {private final int capacity;public LRU…

MATLAB算法实战应用案例精讲-【数模应用】肤色模型与形态学图像处理方法(附MATLAB、python和C++代码实现)

目录 前言 算法原理 肤色检测 图像腐蚀 图像定位 RGB颜色空间中的统计肤色模型 1. 统计肤色模型简介 2. 统计肤色模型实现问题 颜色识别与形态学变换技术 图片颜色识别 ROI切割 人脸肤色检测模型 1、高斯肤色模型 2、椭圆模型 3、非参数估计法 基于数据挖掘的…

生态系统服务权衡与协同动态分析:利用InVEST模型估算产水、固碳、生境质量和土壤保持;时空异质性、双变量分析、多元回归分析等

生态系统服务分之间的权衡与协同关系是现有研究的重难点&#xff0c;即一种服务的增长削弱&#xff08;促进&#xff09;另一种服务的权衡&#xff08;协同&#xff09;。人口快速增长和社会经济发展影响生态系统的稳定性&#xff0c;限制了生态系统的服务功能&#xff0c;且某…

2025面试Go真题第一场

前几天参加了一场面试&#xff0c;GoLang 后端工程师&#xff0c;他们直接给了我 10 道题&#xff0c;我留了一个截图。 在看答案之前&#xff0c;你可以先简单做一下&#xff0c;下面我会对每个题目做一个说明。 文章目录 1、golang map 是否并发安全?2、协程泄漏的原因可能是…