我正在参加 Trae AI 编码从入门到实践线上共学第一期,Trae 免费下载链接: www.trae.ai
Trae界面
官网下载Trae Windows版,界面和VScode差不多,可以直接导入VScode的配置与插件。
右侧是AI聊天框和Builder,目前支持的大模型有GPT-4o和Claude-3.5-Sonnet。
Trae构建程序
我们先让Builder写一个贪吃蛇小游戏:
Trae创建了两个文件,index.html和game.js,用浏览器打开index.html就可以直接玩贪吃蛇了。但是界面不太喜欢,让Trae再优化一下:
再次打开index.html,页面相比第一版优化了背景,游戏边框变成圆角。
贪吃蛇的运动速度有点快,希望再慢一点。
代码:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>贪吃蛇游戏</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@400;700&display=swap');
body {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
margin: 0;
background: linear-gradient(135deg, #ffd6e7, #c1efff);
background-size: cover;
font-family: 'Noto Sans SC', sans-serif;
}
#game-container {
position: relative;
}
#gameCanvas {
border: 3px solid #ff69b4;
background-color: rgba(255, 255, 255, 0.9);
border-radius: 10px;
box-shadow: 0 0 15px rgba(255, 105, 180, 0.3);
}
#score {
font-size: 28px;
margin-bottom: 20px;
color: #ff69b4;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.1);
font-weight: bold;
}
#controls {
margin-top: 20px;
text-align: center;
}
button {
padding: 12px 25px;
font-size: 18px;
margin: 0 10px;
cursor: pointer;
background-color: #ff69b4;
color: white;
border: none;
border-radius: 25px;
transition: all 0.3s ease;
box-shadow: 0 4px 15px rgba(255, 105, 180, 0.3);
}
button:hover {
background-color: #ff1493;
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(255, 105, 180, 0.4);
}
</style>
</head>
<body>
<div id="score">分数: <span id="scoreValue">0</span></div>
<div id="game-container">
<canvas id="gameCanvas" width="400" height="400"></canvas>
</div>
<div id="controls">
<button id="startBtn">开始游戏</button>
<button id="restartBtn">重新开始</button>
</div>
<script src="game.js"></script>
</body>
</html>
class Snake {
constructor() {
this.reset();
}
reset() {
this.body = [
{ x: 10, y: 10 },
{ x: 9, y: 10 },
{ x: 8, y: 10 }
];
this.direction = 'right';
this.nextDirection = 'right';
}
move(food) {
const head = { ...this.body[0] };
switch (this.direction) {
case 'up': head.y--; break;
case 'down': head.y++; break;
case 'left': head.x--; break;
case 'right': head.x++; break;
}
this.body.unshift(head);
if (head.x === food.x && head.y === food.y) {
return true;
}
this.body.pop();
return false;
}
changeDirection(newDirection) {
const opposites = {
'up': 'down',
'down': 'up',
'left': 'right',
'right': 'left'
};
if (newDirection !== opposites[this.direction]) {
this.nextDirection = newDirection;
}
}
update() {
this.direction = this.nextDirection;
}
checkCollision(gridSize) {
const head = this.body[0];
if (head.x < 0 || head.x >= gridSize ||
head.y < 0 || head.y >= gridSize) {
return true;
}
for (let i = 1; i < this.body.length; i++) {
if (head.x === this.body[i].x && head.y === this.body[i].y) {
return true;
}
}
return false;
}
}
class Game {
constructor() {
this.canvas = document.getElementById('gameCanvas');
this.ctx = this.canvas.getContext('2d');
this.gridSize = 20;
this.tileSize = this.canvas.width / this.gridSize;
this.snake = new Snake();
this.food = this.generateFood();
this.score = 0;
this.isRunning = false;
this.gameLoop = null;
this.bindEvents();
}
bindEvents() {
document.addEventListener('keydown', (e) => {
const keyDirections = {
'ArrowUp': 'up',
'ArrowDown': 'down',
'ArrowLeft': 'left',
'ArrowRight': 'right'
};
const newDirection = keyDirections[e.key];
if (newDirection) {
this.snake.changeDirection(newDirection);
}
});
document.getElementById('startBtn').addEventListener('click', () => {
if (!this.isRunning) {
this.start();
}
});
document.getElementById('restartBtn').addEventListener('click', () => {
this.restart();
});
}
generateFood() {
const food = {
x: Math.floor(Math.random() * this.gridSize),
y: Math.floor(Math.random() * this.gridSize)
};
// 确保食物不会生成在蛇身上
for (const segment of this.snake.body) {
if (food.x === segment.x && food.y === segment.y) {
return this.generateFood();
}
}
return food;
}
update() {
this.snake.update();
if (this.snake.move(this.food)) {
this.score += 10;
document.getElementById('scoreValue').textContent = this.score;
this.food = this.generateFood();
}
if (this.snake.checkCollision(this.gridSize)) {
this.stop();
alert('游戏结束!得分:' + this.score);
}
}
draw() {
// 清空画布
this.ctx.fillStyle = 'rgba(255, 255, 255, 0.9)';
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
// 绘制蛇
for (let i = 0; i < this.snake.body.length; i++) {
const segment = this.snake.body[i];
const gradient = this.ctx.createRadialGradient(
(segment.x + 0.5) * this.tileSize,
(segment.y + 0.5) * this.tileSize,
0,
(segment.x + 0.5) * this.tileSize,
(segment.y + 0.5) * this.tileSize,
this.tileSize / 2
);
gradient.addColorStop(0, '#ff9ecd');
gradient.addColorStop(1, '#ff69b4');
this.ctx.beginPath();
this.ctx.fillStyle = gradient;
this.ctx.arc(
(segment.x + 0.5) * this.tileSize,
(segment.y + 0.5) * this.tileSize,
(this.tileSize - 2) / 2,
0,
Math.PI * 2
);
this.ctx.fill();
}
// 绘制食物
const foodGradient = this.ctx.createRadialGradient(
(this.food.x + 0.5) * this.tileSize,
(this.food.y + 0.5) * this.tileSize,
0,
(this.food.x + 0.5) * this.tileSize,
(this.food.y + 0.5) * this.tileSize,
this.tileSize / 2
);
foodGradient.addColorStop(0, '#ffeb3b');
foodGradient.addColorStop(1, '#ffc107');
this.ctx.beginPath();
this.ctx.fillStyle = foodGradient;
this.ctx.arc(
(this.food.x + 0.5) * this.tileSize,
(this.food.y + 0.5) * this.tileSize,
(this.tileSize - 2) / 2,
0,
Math.PI * 2
);
this.ctx.fill();
}
start() {
if (!this.isRunning) {
this.isRunning = true;
this.gameLoop = setInterval(() => {
this.update();
this.draw();
}, 200);
}
}
stop() {
this.isRunning = false;
clearInterval(this.gameLoop);
}
restart() {
this.stop();
this.snake.reset();
this.food = this.generateFood();
this.score = 0;
document.getElementById('scoreValue').textContent = this.score;
this.start();
}
}
// 初始化游戏
const game = new Game();