C++程序绘制地图后出现「╠」乱码字符的技术问询
解决Windows控制台C++地图绘制程序的乱码问题
问题根源分析
乱码出现的核心原因有两点:
- 字符数组初始化错误:
- 原代码给每行的
plane[i][width/dw]赋值'\n',但C语言字符串需要以'\0'作为终止符,缺少终止符会导致输出函数读取内存时越界,出现未知乱码。 - 代码中
plane[height / dh + 1][width / dw] = '\0';属于越界访问,因为plane数组只有height/dh行(索引范围0到height/dh-1),访问height/dh+1会破坏数组外的内存,引发不可预测的字符。
- 原代码给每行的
- 输出方式错误:
- 原代码用
puts(plane[0])只输出第一行,但puts会从起始地址一直读取到'\0',由于后续行没有终止符,会把所有行的内存连起来读取,最终读到非法内存区域的乱码。
- 原代码用
修复步骤
- 修正数组初始化逻辑:
- 初始化时给每行的最后一个位置(
width/dw)赋值'\0',确保每行都是合法的C字符串。 - 删除越界的数组赋值语句,避免内存污染。
- 初始化时给每行的最后一个位置(
- 逐行输出所有内容:
- 循环遍历
plane的每一行,用printf或cout逐行输出,替代只输出第一行的puts调用。
- 循环遍历
- 可选优化:
- 添加
Sleep控制刷新频率,避免控制台闪烁;或保留gotoxy(0,0)实现覆盖输出。
- 添加
完整修正代码
#include <iostream> #include <Windows.h> #include <time.h> #include <stdlib.h> #include <cmath> #include <cstdlib> using namespace std; //屏幕像素尺寸 const int width = 800, height = 600; //每个控制台字符对应的像素尺寸 const int dw = 8, dh = 16; //计算后控制台行列数:800/8=100列,600/16=37行(整数除法自动取整) struct coord //存储角色坐标的结构体 { int x; int y; }; void gotoxy(int x, int y) { HANDLE hcon = GetStdHandle(STD_OUTPUT_HANDLE); COORD dwPos; dwPos.X = x; dwPos.Y = y; SetConsoleCursorPosition(hcon, dwPos); } void convert(int P[2], float x, float y) //将浮点坐标转换为控制台字符坐标 { P[0] = int(x) / dw; P[1] = int(y) / dh; } void convert(int P[2], int x, int y) //将整数坐标转换为控制台字符坐标 { P[0] = x / dw; P[1] = y / dh; } void drawpoint(char plane[height / dh][width / dw + 1], int A, int B, char C)//绘制单个字符到平面 { B = height / dh - 1 - B; if (A < 0 || B < 0 || A >= width / dw || B >= height / dh) return; plane[B][A] = C; } class map { private: float n(float x) { return 0 ; } public: float f(float x) { return (150 * (n(x) + 1.0f) / 2.0f); //返回地面高度对应的像素值 } void draw(char plane[height / dh][width / dw + 1]) { for (int i = 0; i < width / dw; i++) { int P[2]; int j_start = static_cast<int>(f(i * dw)) / dh; //显式转换为整数,避免隐式截断歧义 for (int j = j_start; j >= 0; j--) { convert(P, i * dw, j * dh); drawpoint(plane, P[0], P[1], 'o'); } convert(P, i * dw, j_start * dh); drawpoint(plane, P[0], P[1], '#'); } } }; int main() { map new_map; const int rows = height / dh; const int cols = width / dw; char plane[rows][cols + 1]; //每行cols+1个字符,最后一个存'\0' //初始化数组:每行填充'*',末尾加终止符 for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { plane[i][j] = '*'; } plane[i][cols] = '\0'; //每行末尾添加字符串终止符 } while (true) { gotoxy(0, 0); //重置平面为全'*' for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { plane[i][j] = '*'; } } new_map.draw(plane); //逐行输出所有内容 for (int i = 0; i < rows; i++) { printf("%s\n", plane[i]); } Sleep(100); //添加小延迟,避免刷新过快 } return 0; }
额外说明
- 修正了
j_start的隐式类型转换问题,用static_cast<int>显式转换,避免浮点转整数的截断歧义。 - 新增
rows和cols常量,简化代码结构,减少重复计算。
内容的提问来源于stack exchange,提问作者jjuanda19
相关产品推荐
相关产品推荐

