【问题描述】请编程实现贪吃蛇游戏。首先自动生成一个NN(如2020)的空间,在内部随机生成1个$代表食物,随机生成一条长度为5的蛇,蛇的身体用心形(ASCII码为003)显示,蛇头用笑脸(ASCII码为002)显示。自行定义蛇的起始位置。用户随意按键后蛇即刻开始自行行走,可设置行走速率为0.5秒。监测用户按键,根据用户的选择方向键,改变蛇的行走方向。在遇到食物$时,长度增一,且随机生成另一个食物$。倘若蛇碰到墙壁,则游戏失败,并打印蛇最终的长度。
###要求:必须符合我的题目,如果成功,给与采纳
【提示】本题涉及知识点:数组、循环、函数。
监测用户是否按键需要用到kbhit()函数,需要包含头文件conio.h。
可让用户按下wsad四个字母键分别代表上下左右四个方向,用char direction=getch()函数接收。
监测系统当前时间的函数为clock(),判断两次时间间隔用以下代码:
start=clock();
while((timeover=(clock()-start<=500))&&!kbhit());
示例:
以下是我的代码,为什么运行时在运行窗口光标反复跳动,什么也不显示?
#include <iostream>
#include <conio.h>
#include <cstdlib>
#include <ctime>
#include<windows.h>
using namespace std;
const int N = 20; // 游戏区域的大小
const char SNAKE_BODY = 3; // 蛇身体的显示字符,ASCII码为003
const char SNAKE_HEAD = 2; // 蛇头的显示字符,ASCII码为002
const char FOOD = '$'; // 食物的显示字符
const int DELAY = 500; // 蛇的移动速度,单位为毫秒
// 定义蛇的方向
enum Direction {
UP,
DOWN,
LEFT,
RIGHT
};
struct Position {
int x;
int y;
};
class SnakeGame {
public:
SnakeGame();
void run();
private:
void initBoard();
void generateFood();
void drawBoard();
void updateSnake();
void handleInput();
bool isCollision();
void gameOver();
char board[N][N];
Position snake[2 * N * N];
int snakeLength;
Direction direction;
Position food;
bool isEaten;
};
SnakeGame::SnakeGame() {
// 初始化随机数生成器
srand(static_cast<unsigned>(time(0)));
// 初始化游戏区域
initBoard();
// 初始化蛇的位置和长度
int startX = N / 2;
int startY = N / 2;
snake[0].x = startX;
snake[0].y = startY;
snake[1].x = startX - 1;
snake[1].y = startY;
snakeLength = 2;
// 初始化蛇的方向
direction = RIGHT;
// 初始化食物的位置
generateFood();
// 初始化蛇未吃到食物
isEaten = false;
}
void SnakeGame::initBoard() {
for (int i = 0; i < N; ++i) {
for (int j = 0; j < N; ++j) {
board[i][j] = ' ';
}
}
}
void SnakeGame::generateFood() {
int x, y;
do {
x = rand() % N;
y = rand() % N;
} while (board[x][y] != ' ');
food.x = x;
food.y = y;
board[x][y] = FOOD;
}
void SnakeGame::drawBoard() {
system("cls"); // 清空终端输出
for (int i = 0; i < N; ++i) {
for (int j = 0; j < N; ++j) {
if (i == food.x && j == food.y) {
cout << FOOD;
} else {
bool isSnakeBody = false;
for (int k = 0; k < snakeLength; ++k) {
if (snake[k].x == i && snake[k].y == j) {
cout << (k == 0 ? SNAKE_HEAD : SNAKE_BODY);
isSnakeBody = true;
break;
}
}
if (!isSnakeBody) {
cout << board[i][j];
}
}
}
cout << endl;
}
}
void SnakeGame::updateSnake() {
// 记录蛇尾的位置
Position tail = snake[snakeLength - 1];
// 更新蛇身体的位置
for (int i = snakeLength - 1; i > 0; --i) {
snake[i] = snake[i - 1];
}
// 更新蛇头的位置
switch (direction) {
case UP:
snake[0].x--;
break;
case DOWN:
snake[0].x++;
break;
case LEFT:
snake[0].y--;
break;
case RIGHT:
snake[0].y++;
break;
}
// 判断是否吃到食物
if (snake[0].x == food.x && snake[0].y == food.y) {
// 蛇长度增加
snakeLength++;
// 生成新的食物
generateFood();
// 标记食物已被吃掉
isEaten = true;
}
// 更新蛇尾的位置为空白
board[tail.x][tail.y] = ' ';
// 更新蛇头和身体的位置
board[snake[0].x][snake[0].y] = SNAKE_HEAD;
for (int i = 1; i < snakeLength; ++i) {
board[snake[i].x][snake[i].y] = SNAKE_BODY;
}
}
void SnakeGame::handleInput() {
if (_kbhit()) {
char ch = _getch();
switch (ch) {
case 'w':
if (direction != DOWN)
direction = UP;
break;
case 's':
if (direction != UP)
direction = DOWN;
break;
case 'a':
if (direction != RIGHT)
direction = LEFT;
break;
case 'd':
if (direction != LEFT)
direction = RIGHT;
break;
}
}
}
bool SnakeGame::isCollision() {
// 判断是否碰到墙壁
if (snake[0].x < 0 || snake[0].x >= N || snake[0].y < 0 || snake[0].y >= N) {
return true;
}
// 判断是否碰到自己的身体
for (int i = 1; i < snakeLength; ++i) {
if (snake[0].x == snake[i].x && snake[0].y == snake[i].y) {
return true;
}
}
return false;
}
void SnakeGame::gameOver() {
system("cls");
cout << "Game Over!" << endl;
cout << "Your snake length: " << snakeLength << endl;
}
void SnakeGame::run() {
clock_t start = clock();
while (true) {
drawBoard();
handleInput();
if (clock() - start >= DELAY) {
updateSnake();
start = clock();
}
if (isCollision()) {
gameOver();
break;
}
if (isEaten) {
Sleep(200); // 等待一段时间显示被吃食物的效果
isEaten = false;
}
}
}
int main() {
SnakeGame game;
game.run();
return 0;
}