从零到赛车游戏 · 7步教学教案
第1步:学会 gotoxy 定位输出(游戏地基)
目标:在控制台任意位置打印文字
新增知识点:HANDLE、COORD、SetConsoleCursorPosition
1. 控制台句柄 HANDLE
- 是什么:控制控制台窗口的工具
- 作用:移动光标、隐藏光标
- 学生理解:"控制台遥控器"
- 写法固定:
cpp
HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE);
2. 光标坐标 COORD
- 是什么:存 X、Y 坐标的结构体
- 作用:表示光标位置
- 学生理解:"存坐标的盒子"
- 使用:
cpp
COORD pos;
pos.X = 10;
pos.Y = 5;
3. 移动光标函数 gotoxy()
这是游戏最核心的功能!
学生必须会!
作用:把光标跳到指定 (x,y) 位置输出文字
cpp
void gotoxy(int x, int y){
COORD pos;
pos.X = x;
pos.Y = y;
SetConsoleCursorPosition(console, pos);
}
完整代码
cpp
#include <iostream>
#include <windows.h>
using namespace std;
// 定位光标到(x,y)
void gotoxy(int x, int y){
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos;
pos.X = x;
pos.Y = y;
SetConsoleCursorPosition(hConsole, pos);
}
int main(){
int x,y;
cin>>x>>y;
gotoxy(x, y);
cout << "我在("<<x<<","<<y<<")位置";
return 0;
}

第2步:隐藏光标(让画面不闪)
目标:游戏画面更干净
新增知识点:CONSOLE_CURSOR_INFO、隐藏光标
隐藏光标 setcursor()
- 作用:让光标不闪,游戏画面干净
- 固定写法,会用就行
HANDLE:就是控制台的遥控器,用来控制窗口
CONSOLE_CURSOR_INFO:存光标显示 / 隐藏和大小的盒子
SetConsoleCursorInfo:把设置应用到控制台
这个函数游戏必须用,否则光标会一直闪,画面很乱
完整代码
cpp
// 包含输入输出流库,用于控制台输出
#include <iostream>
// 包含Windows系统API库,用于控制控制台窗口
#include <windows.h>
// 使用标准命名空间,简化代码书写
using namespace std;
// 函数功能:设置控制台光标是否显示
// 参数 visible:true=显示光标,false=隐藏光标
void setcursor(bool visible)
{
// 1. 获取控制台句柄(可以理解为:拿到控制台的"遥控器")
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
// 2. 定义光标信息结构体变量(用来存放光标的属性)
CONSOLE_CURSOR_INFO info;
// 3. 设置光标是否可见
info.bVisible = visible;
// 4. 设置光标大小(20是默认大小,固定写即可)
info.dwSize = 20;
// 5. 将设置好的光标信息应用到控制台
SetConsoleCursorInfo(hConsole, &info);
}
// 主函数,程序入口
int main()
{
// 调用函数,隐藏控制台光标
setcursor(false);
// 输出提示信息
cout << "光标已隐藏,画面更干净";
// 程序正常结束
return 0;
}
第3步:按键控制(A/D 移动小车的基础)
目标:检测按键并做出反应
新增知识点:kbhit()、getch()
kbhit():有没有按键按下getch():获取按下的键
cpp
#include <iostream>
#include <conio.h>
using namespace std;
int main(){
char ch;
while(1){
if(kbhit()){ // 如果有按键
ch = getch(); // 获取按键
cout << "你按了:" << ch << endl;
}
}
return 0;
}

第4步:Sleep 延时(控制游戏速度)
目标:让画面动起来但不飞太快
新增知识点:Sleep(毫秒)
cpp
Sleep(50); // 停 50 毫秒,控制车速
cpp
#include <iostream>
#include <windows.h>
using namespace std;
int main(){
for(int i=1; i<=5; i++){
cout << "数字:" << i << endl;
Sleep(500); // 暂停0.5秒
}
return 0;
}

第5步:system("cls") 清屏(刷新画面)
目标:实现画面"动画效果"
cpp
#include <iostream>
#include <windows.h>
using namespace std;
int main(){
cout << "第一页内容" << endl;
system("pause");
system("cls"); // 清空屏幕
cout << "已清屏,这是新内容1" << endl;
system("pause");
system("cls"); // 清空屏幕
cout << "已清屏,这是新内容2" << endl;
return 0;
}
第6步:随机数(敌人车随机出现)
目标:让敌人每次在不同车道出现
新增知识点:rand()、srand((unsigned)time(NULL))
cpp
// 包含输入输出流库
// 作用:提供 cin, cout 控制台输入输出功能
#include <iostream>
// 包含标准通用库
// 作用:提供 rand() 随机数生成函数
#include <cstdlib>
// 包含时间相关库
// 作用:提供 time() 函数,用于获取系统当前时间
#include <ctime>
// 使用标准命名空间,不用每次写 std::cout
using namespace std;
int main() {
// 设置随机数种子
// srand = 初始化随机数发生器
// (unsigned)time(NULL) = 用当前系统时间作为种子
// 作用:保证每次运行程序,生成的随机数都不一样
srand((unsigned)time(NULL));
// 循环 5 次,输出 5 个随机数
for (int i = 0; i < 5; i++) {
// rand() = 生成一个很大的随机整数
// rand()%10 = 对 10 取余,结果只在 0~9 之间
cout << rand() % 10 << " ";
}
return 0;
}

第7步:二维数组画小车(游戏角色)
目标:用字符拼出自定义图形
cpp
#include <iostream>
using namespace std;
int main(){
// 4x4 小车图案
char car[4][4] = {
{' ','#','#',' '},
{'#','#','#','#'},
{' ','#','#',' '},
{'#','#','#','#'}
};
for(int i=0; i<4; i++){
for(int j=0; j<4; j++){
cout << car[i][j];
}
cout << endl;
}
return 0;
}
最后一步:把7步拼起来 = 完整赛车游戏
把上面所有知识点拼在一起,就是你最开始的那个赛车游戏。
结构非常清晰:
gotoxy定位画车、画敌人kbhit+getch控制左右移动Sleep控制速度rand随机敌人位置system("cls")画面刷新- 隐藏光标让画面更舒服
完整代码
cpp
// 用到的全部知识点:
// gotoxy定位 + 隐藏光标 + 键盘控制 + Sleep延时 + 二维数组画小车
#include <iostream>
#include <windows.h>
#include <conio.h>
using namespace std;
// 全局变量:记录当前是第几帧(每刷新一次+1)
int frame = 0;
// ===================== 1. 光标定位函数 =====================
void gotoxy(int x, int y){
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos;
pos.X = x;
pos.Y = y;
SetConsoleCursorPosition(hConsole, pos);
}
// ===================== 2. 隐藏光标 =====================
void setcursor(bool visible){
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO info;
info.bVisible = visible;
info.dwSize = 20;
SetConsoleCursorInfo(hConsole, &info);
}
// ===================== 3. 小车图案 =====================
char car[4][4] = {
{' ','#','#',' '},
{'#','#','#','#'},
{' ','#','#',' '},
{'#','#','#','#'}
};
// ===================== 4. 绘制小车 =====================
void drawCar(int x, int y){
for(int i=0; i<4; i++){
for(int j=0; j<4; j++){
gotoxy(x+j, y+i);
cout << car[i][j];
}
}
}
// ===================== 5. 擦除小车 =====================
void eraseCar(int x, int y){
for(int i=0; i<4; i++){
for(int j=0; j<4; j++){
gotoxy(x+j, y+i);
cout << " ";
}
}
}
// ===================== 6. 显示帮助 =====================
void showHelp(){
gotoxy(15, 2);
cout << "==== 小车移动游戏 ====";
gotoxy(18, 4);
cout << "A 键:向左移动";
gotoxy(18, 5);
cout << "D 键:向右移动";
gotoxy(15, 7);
cout << "======================";
}
// ===================== 7. 显示当前帧数(右上角) =====================
void showFrame(){
gotoxy(60, 2);
cout << "当前帧数:" << frame;
}
// ===================== 主函数 =====================
int main(){
setcursor(false);
showHelp();
int carX = 35;
int carY = 20;
while(1){
// 帧计数 +1
frame++;
// 按键控制
if(kbhit()){
char ch = getch();
if(ch == 'a' || ch == 'A'){
if(carX > 10){
eraseCar(carX, carY);
carX -= 2;
}
}
if(ch == 'd' || ch == 'D'){
if(carX < 60){
eraseCar(carX, carY);
carX += 2;
}
}
}
drawCar(carX, carY);
showFrame(); // 显示帧数
Sleep(50); // 这个数字大 会让操作和画面的延迟感增加
}
return 0;
}


