CentOS 下 C++ 游戏开发实战教程
一 环境搭建与工具链
sudo yum updatesudo yum groupinstall "Development Tools" -ysudo yum install -y gcc gcc-c++ make cmake gdb git vimsudo yum install -y centos-release-sclsudo yum install -y devtoolset-11(或 devtoolset-9)scl enable devtoolset-11 bash(当前会话生效;如需持久化,可写入 ~/.bashrc)gcc -v、g++ -v、cmake --version、gdb -vsudo yum install -y qt-creator(图形化项目管理与调试)二 项目骨架与构建系统
src/、include/、tests/、third_party/、CMakeLists.txt、build/cmake_minimum_required(VERSION 3.16)
project(Game LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_executable(game main.cpp)
# 可选:单元测试
# enable_testing()
# add_subdirectory(tests)
mkdir -p build && cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
make -j$(nproc)
./game
gdb ./gamevalgrind --leak-check=full ./gameCMakeLists.txt 中为 Release 目标添加 -O2/-O3三 实战一 终端小游戏 猜数字
guess.cpp#include <iostream>
#include <cstdlib>
#include <ctime>
int main() {
std::srand(static_cast<unsigned>(std::time(nullptr)));
int number = std::rand() % 100 + 1;
int guess = 0;
std::cout << "Guess a number between 1 and 100:\n";
do {
std::cout << "> ";
std::cin >> guess;
if (guess > number) {
std::cout << "Too high.\n";
} else if (guess < number) {
std::cout << "Too low.\n";
} else {
std::cout << "That's right!\n";
}
} while (guess != number);
return 0;
}
g++ -std=c++17 -O2 -o guess guess.cpp
./guess
std::srand + std::time(nullptr) 初始化随机种子do-while 保证至少一次输入四 实战二 终端小游戏 贪吃蛇
sudo yum install -y ncurses-develsnake.cpp(简化版,WASD 控制,无墙碰撞优化)#include <iostream>
#include <vector>
#include <ncurses.h>
#include <unistd.h>
#include <cstdlib>
#include <ctime>
struct Point { int x, y; };
enum Dir { STOP = 0, LEFT, RIGHT, UP, DOWN };
int main() {
initscr();
cbreak(); noecho();
keypad(stdscr, TRUE);
curs_set(0);
timeout(100); // 100ms 刷新
int w = 40, h = 20;
WINDOW *win = newwin(h, w, 0, 0);
box(win, 0, 0);
std::srand(static_cast<unsigned>(time(nullptr)));
Dir dir = STOP;
Point head{w/2, h/2};
std::vector<Point> body;
int score = 0;
auto spawnFood = [&]() {
Point f;
do {
f.x = 1 + rand() % (w-2);
f.y = 1 + rand() % (h-2);
} while (std::find(body.begin(), body.end(), f) != body.end() ||
(f.x == head.x && f.y == head.y));
return f;
};
Point food = spawnFood();
while (true) {
int ch = getch();
switch (ch) {
case 'q': case 'Q': goto end;
case KEY_LEFT: if (dir != RIGHT) dir = LEFT; break;
case KEY_RIGHT: if (dir != LEFT) dir = RIGHT; break;
case KEY_UP: if (dir != DOWN) dir = UP; break;
case KEY_DOWN: if (dir != UP) dir = DOWN; break;
case 'a': if (dir != RIGHT) dir = LEFT; break;
case 'd': if (dir != LEFT) dir = RIGHT; break;
case 'w': if (dir != DOWN) dir = UP; break;
case 's': if (dir != UP) dir = DOWN; break;
}
Point newHead = head;
switch (dir) {
case LEFT: newHead.x--; break;
case RIGHT: newHead.x++; break;
case UP: newHead.y--; break;
case DOWN: newHead.y++; break;
default: break;
}
// 撞墙或自撞
if (newHead.x <= 0 || newHead.x >= w-1 ||
newHead.y <= 0 || newHead.y >= h-1 ||
std::find(body.begin(), body.end(), newHead) != body.end()) {
break;
}
body.insert(body.begin(), head);
if (newHead.x == food.x && newHead.y == food.y) {
score++;
food = spawnFood();
} else {
body.pop_back();
}
head = newHead;
werase(win);
box(win, 0, 0);
mvwprintw(win, food.y, food.x, "*");
for (size_t i = 0; i < body.size(); ++i) {
mvwprintw(win, body[i].y, body[i].x, "o");
}
mvwprintw(win, head.y, head.x, "@");
mvwprintw(win, h-1, 1, "Score: %d WASD/q", score);
wrefresh(win);
usleep(80000);
}
end:
delwin(win);
endwin();
std::cout << "Game Over! Score: " << score << "\n";
return 0;
}
g++ -std=c++17 -O2 -lncurses -o snake snake.cpp
./snake
initscr、cbreak、noecho、keypad、timeout、wrefresh 等timeout(ms) 实现std::vector<Point> 管理,食物随机生成并避免与蛇身重叠五 进阶路线与常见问题
cbreak()、noecho()、keypad(stdscr, TRUE) 并设置 timeoutncurses-devel),并在 CMake 中使用 find_package(Curses REQUIRED) 链接valgrind 排查内存与越界问题