继续上坑 坑之二 乱码(1)

本文通过乱码这一符号,探讨了记忆与遗忘之间的挣扎。作者面对无法格式化的记忆,选择将其转化为乱码,以此来表达内心的逃避与无奈。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

乱码

1)
乱码。
一团乱码。
全是乱码。

随手打开一个超链接,得到的,是满屏的乱码。
我当然知道怎么让它不再显示乱码,我所要做的也不过就是动动鼠标而已。
只是不知为何,我却没有动。
我只是瞪着这满屏的乱码。
发呆。

用异国的字符集显示熟悉的文字,电脑的屏幕显示满屏的乱码。
用拒绝的字符集显示尘封的记忆,心灵的屏幕显示满屏的乱码。

曾经想要给这个分区来一次完全的格式化,让不愿意再记起的一切彻底成为一片空白,却发现有一个叫做彮側偐偭丅的程序在宸嶽禦匯将竃处运行。我无法关闭这个程序,于是我所能得到的,也就不过是一个无法格式化的警告而已。
不愿记起,却也无法忘怀。
我听到丄嶗奓偺奓的我在我的心灵深处叹息。
格式化无法进行,我只得用叫做逃避的软件,将所有的文件都涂做了一片乱码。
只是一片乱码而已。毫无意义的乱码。
刺刺扎扎地立在那里,只能看,不能解。
看得见,却无法识别。
看得见,却无法打开。
看得见,却无法删除。

只是,在这样一个峈猀堈奀諾腔涾的深夜,繍徭禦議脅的我,面对着这样的一屏赻伀詠ㄛ,却为何只是荌腔肮俴蠅ㄐ?
只不过是一片乱码而已。只不过是没有选对解读的方式而已。
只不过是没有选对解读的方式而已……

打开邮箱,地址簿里赫然立着四串乱码。
四串曾经熟悉到不能再熟悉的乱码。
四串已经不知多久没有被鼠标触及过的乱码。
我将这四串乱码加入了收件人中。
我向这四串乱码发去一篇密密麻麻的乱码。
我不知道,是否有人能解出这篇乱码来。
我不知道,我究竟想做什么,或者,我究竟在期待些什么。

 
#include <SFML/Graphics.hpp> #include <iostream> #include <vector> #include <cstdlib> #include <ctime> #include <cmath> using namespace sf; // 游戏状态 enum GameState { START, PLAYING, GAME_OVER }; class Player { public: RectangleShape shape; Vector2f velocity; bool isJumping; float gravity; Player(Vector2f position) { shape.setSize(Vector2f(50, 80)); shape.setFillColor(Color::Green); shape.setPosition(position); velocity = Vector2f(0, 0); isJumping = false; gravity = 0.5f; } void update() { // 应用重力 velocity.y += gravity; shape.move(velocity); // 地面碰撞检测 if (shape.getPosition().y > 400) { shape.setPosition(shape.getPosition().x, 400); velocity.y = 0; isJumping = false; } } void jump() { if (!isJumping) { velocity.y = -15.0f; isJumping = true; } } }; class Obstacle { public: RectangleShape shape; float speed; Obstacle(Vector2f position, Vector2f size, Color color) { shape.setSize(size); shape.setFillColor(color); shape.setPosition(position); speed = 5.0f; } void update() { shape.move(-speed, 0); } bool isOffScreen() const { return shape.getPosition().x + shape.getSize().x < 0; } }; int main() { // 初始化随机种子 srand(static_cast<unsigned int>(time(nullptr))); // 创建游戏窗口 RenderWindow window(VideoMode(800, 600), "天天酷跑", Style::Close); window.setFramerateLimit(60); // 游戏状态 GameState gameState = START; // 创建玩家 Player player(Vector2f(100, 400)); // 障碍物和洞 std::vector<Obstacle> obstacles; std::vector<Obstacle> pits; // 背景元素 std::vector<RectangleShape> backgroundBuildings; std::vector<RectangleShape> backgroundClouds; // 创建背景建筑 for (int i = 0; i < 10; ++i) { float height = rand() % 100 + 100; RectangleShape building(Vector2f(70, height)); building.setFillColor(Color(100, 100, 100)); building.setPosition(i * 150, 600 - height); backgroundBuildings.push_back(building); } // 创建背景云朵 for (int i = 0; i < 8; ++i) { float size = rand() % 40 + 30; RectangleShape cloud(Vector2f(size * 2, size)); cloud.setFillColor(Color(200, 200, 220)); cloud.setPosition(rand() % 800, rand() % 200); backgroundClouds.push_back(cloud); } // 地面 RectangleShape ground(Vector2f(800, 200)); ground.setFillColor(Color(139, 69, 19)); ground.setPosition(0, 400); // 分数 int score = 0; Font font; if (!font.loadFromFile("arial.ttf")) { // 如果找不到字体文件,使用默认字体 font.loadFromFile("C:/Windows/Fonts/Arial.ttf"); } Text scoreText; scoreText.setFont(font); scoreText.setCharacterSize(24); scoreText.setFillColor(Color::White); scoreText.setPosition(20, 20); // 游戏结束文本 Text gameOverText; gameOverText.setFont(font); gameOverText.setCharacterSize(48); gameOverText.setFillColor(Color::Red); gameOverText.setString("游戏结束!"); gameOverText.setPosition(250, 200); Text restartText; restartText.setFont(font); restartText.setCharacterSize(24); restartText.setFillColor(Color::White); restartText.setString("按空格键重新开始"); restartText.setPosition(250, 280); // 开始界面文本 Text titleText; titleText.setFont(font); titleText.setCharacterSize(60); titleText.setFillColor(Color::Yellow); titleText.setString("天天酷跑"); titleText.setPosition(250, 150); Text startText; startText.setFont(font); startText.setCharacterSize(30); startText.setFillColor(Color::White); startText.setString("按空格键开始游戏"); startText.setPosition(230, 280); // 游戏时钟 Clock clock; float obstacleTimer = 0; float pitTimer = 0; while (window.isOpen()) { // 计算时间增量 float dt = clock.restart().asSeconds(); obstacleTimer += dt; pitTimer += dt; Event event; while (window.pollEvent(event)) { if (event.type == Event::Closed) { window.close(); } if (event.type == Event::KeyPressed) { if (event.key.code == Keyboard::Space) { if (gameState == START) { gameState = PLAYING; score = 0; obstacles.clear(); pits.clear(); player.shape.setPosition(100, 400); } else if (gameState == PLAYING) { player.jump(); } else if (gameState == GAME_OVER) { gameState = START; } } } } // 游戏逻辑更新 if (gameState == PLAYING) { // 更新玩家 player.update(); // 每2秒生成障碍物 if (obstacleTimer > 2.0f) { obstacleTimer = 0; int height = rand() % 60 + 40; obstacles.push_back(Obstacle( Vector2f(850, 400 + (80 - height)), Vector2f(30, height), Color(150, 75, 0) )); } // 每3秒生成洞 if (pitTimer > 3.0f) { pitTimer = 0; int width = rand() % 100 + 60; pits.push_back(Obstacle( Vector2f(850, 480), Vector2f(width, 20), Color::Transparent )); } // 更新障碍物 for (auto& obstacle : obstacles) { obstacle.update(); } // 更新洞 for (auto& pit : pits) { pit.update(); } // 移除屏幕外的障碍物和洞 obstacles.erase(std::remove_if(obstacles.begin(), obstacles.end(), [](const Obstacle& o) { return o.isOffScreen(); }), obstacles.end()); pits.erase(std::remove_if(pits.begin(), pits.end(), [](const Obstacle& p) { return p.isOffScreen(); }), pits.end()); // 碰撞检测 for (const auto& obstacle : obstacles) { if (player.shape.getGlobalBounds().intersects(obstacle.shape.getGlobalBounds())) { gameState = GAME_OVER; } } for (const auto& pit : pits) { // 检查玩家是否掉入中 if (player.shape.getPosition().x + player.shape.getSize().x > pit.shape.getPosition().x && player.shape.getPosition().x < pit.shape.getPosition().x + pit.shape.getSize().x && player.shape.getPosition().y + player.shape.getSize().y > pit.shape.getPosition().y) { gameState = GAME_OVER; } } // 增加分数 score += static_cast<int>(dt * 10); } // 更新背景元素位置 for (auto& building : backgroundBuildings) { building.move(-1.0f, 0); if (building.getPosition().x + building.getSize().x < 0) { building.setPosition(800, building.getPosition().y); } } for (auto& cloud : backgroundClouds) { cloud.move(-0.5f, 0); if (cloud.getPosition().x + cloud.getSize().x < 0) { cloud.setPosition(800, rand() % 200); } } // 绘制 window.clear(Color(135, 206, 235)); // 天蓝色背景 // 绘制背景元素 for (const auto& cloud : backgroundClouds) { window.draw(cloud); } for (const auto& building : backgroundBuildings) { window.draw(building); } // 绘制地面 window.draw(ground); // 绘制障碍物和洞 for (const auto& obstacle : obstacles) { window.draw(obstacle.shape); } for (const auto& pit : pits) { // 绘制洞为深色 RectangleShape pitVisual(pit.shape.getSize()); pitVisual.setPosition(pit.shape.getPosition()); pitVisual.setFillColor(Color(100, 50, 10)); window.draw(pitVisual); } // 绘制玩家 window.draw(player.shape); // 更新分数文本 scoreText.setString("分数: " + std::to_string(score)); // 绘制分数 window.draw(scoreText); // 绘制游戏状态文本 if (gameState == START) { window.draw(titleText); window.draw(startText); } else if (gameState == GAME_OVER) { window.draw(gameOverText); window.draw(restartText); } window.display(); } return 0; }为什么这个代码在visualstudio中编译出来的结果中文是乱码
最新发布
06-11
<think>问题分析:在VisualStudio中编译运行SFML程序时,如果出现中文乱码,通常是因为字符编码的问题。Windows系统默认使用GBK编码,而源代码可能是UTF-8编码。当源代码中包含中文字符串,而编译器按照源文件的编码(如UTF-8)解释,但运行时控制台或窗口使用的编码是GBK,就会导致乱码。解决方案:1.确保源代码文件以正确的编码保存。如果使用UTF-8,则考虑在VisualStudio中设置源文件的编码为带BOM的UTF-8。2.在代码中,使用宽字符(wchar_t)和SFML的宽字符文本类(sf::Text)时,设置正确的字符串编码。3.另一种方法是使用多字节字符集(GBK)保存源文件,但这不利于跨平台。具体到SFML,我们通常使用sf::String来处理字符串,它可以自动转换编码。但是,在直接使用std::string设置sf::Text时,如果字符串是UTF-8而系统是GBK,就会乱码。修改建议:-将源代码文件保存为UTF-8withBOM格式(在VisualStudio中可以通过“文件”->“高级保存选项”设置)。-或者,在代码中显式转换字符串编码。由于SFML的sf::String支持从UTF-8和宽字符串构造,我们可以尝试以下方式:使用L""宽字符串字面量来初始化字符串,例如:`sf::Stringstr=L"中文";`或者,将源代码保存为UTF-8withBOM,并在创建sf::Text时使用UTF-8字符串。但注意:在代码中我们使用了`std::to_string`生成分数,这部分是ASCII字符,应该不会有问题。问题可能出在界面上的固定文本(如“游戏结束!”等)是直接使用中文字符串。因此,我们可以将固定文本改为宽字符串,并使用`sf::String`来构造`sf::Text`的字符串。修改步骤:1.将源代码中的中文字符串改为宽字符串(L"字符串")。2.在设置文本字符串时,使用宽字符串。例如:将:gameOverText.setString("游戏结束!");改为:gameOverText.setString(L"游戏结束!");同样,修改其他中文字符串。注意:字体文件必须支持中文字符,否则即使编码正确也显示不出来。另外,在VisualStudio中,控制台输出(std::cout)的中文乱码是另一个问题,但我们的游戏窗口是图形窗口,不涉及控制台,所以主要是解决sf::Text的乱码。下面我们修改代码中所有中文字符串为宽字符串形式。同时,为了确保字体能显示中文,请检查字体文件(如arial.ttf)是否包含中文字符集,或者使用一个支持中文的字体文件(如simhei.ttf)。由于原代码中加载字体文件使用了“arial.ttf”,如果系统没有这个字体,或者这个字体不支持中文,也会导致乱码。因此,建议使用一个支持中文的字体,并将字体文件放在项目目录中。修改后的代码:我们将修改以下文本:-游戏结束!-按空格键重新开始-天天酷跑-按空格键开始游戏-分数:(这个字符串本身是中文,但后面的分数数字是ASCII,所以只需要将“分数:”改为宽字符串)注意:scoreText的字符串是动态生成的,其中“分数:”是中文,后面的分数是数字。所以我们可以这样改:```cpp//修改前:scoreText.setString("分数:"+std::to_string(score));//修改后:scoreText.setString(L"分数:"+std::to_string(score));```但是,这样会报错,因为不能直接连接std::wstring和std::string。我们需要将数字也转换成宽字符串。因此,我们可以使用`std::to_wstring`:```cppscoreText.setString(L"分数:"+std::to_wstring(score));```但注意:`setString`有一个接受`std::string`的重载和一个接受`sf::String`的重载。而`sf::String`可以从`std::wstring`构造。所以我们可以这样:```cppscoreText.setString(sf::String(L"分数:"+std::to_wstring(score)));```或者,使用`sf::String`的隐式转换。但是,为了统一,我们也可以将所有的字符串都通过`sf::String`来设置。另外,由于原代码中加载了字体,我们最好确保字体文件包含中文。如果找不到字体文件,我们可以使用Windows自带的支持中文的字体,例如:```cppfont.loadFromFile("C:/Windows/Fonts/simhei.ttf");//黑体```因此,综合修改如下:1.将源代码文件保存为UTF-8withBOM。2.将中文字符串改为宽字符串。3.将字体文件改为支持中文的字体(并确保路径正确)。4.对于动态字符串(如分数),使用`std::to_wstring`并构造为宽字符串。下面给出修改后的代码片段(只修改了关键部分):```cpp//...其他代码保持不变//字体Fontfont;if(!font.loadFromFile("simhei.ttf")){//先尝试项目目录下的黑体//如果找不到,尝试Windows字体目录if(!font.loadFromFile("C:/Windows/Fonts/simhei.ttf")){//如果还是不行,尝试其他字体,比如微软雅黑if(!font.loadFromFile("C:/Windows/Fonts/msyh.ttc")){//如果都找不到,使用默认的Arial(可能不支持中文,但尽量避免崩溃)font.loadFromFile("arial.ttf");}}}//分数文本TextscoreText;scoreText.setFont(font);scoreText.setCharacterSize(24);scoreText.setFillColor(Color::White);scoreText.setPosition(20,20);//游戏结束文本TextgameOverText;gameOverText.setFont(font);gameOverText.setCharacterSize(48);gameOverText.setFillColor(Color::Red);gameOverText.setString(L"游戏结束!");gameOverText.setPosition(250,200);TextrestartText;restartText.setFont(font);restartText.setCharacterSize(24);restartText.setFillColor(Color::White);restartText.setString(L"按空格键重新开始");restartText.setPosition(250,280);//开始界面文本TexttitleText;titleText.setFont(font);titleText.setCharacterSize(60);titleText.setFillColor(Color::Yellow);titleText.setString(L"天天酷跑");titleText.setPosition(250,150);TextstartText;startText.setFont(font);startText.setCharacterSize(30);startText.setFillColor(Color::White);startText.setString(L"按空格键开始游戏");startText.setPosition(230,280);//...在游戏循环中,更新分数文本的地方修改为://更新分数文本std::wstringscoreStr=L"分数:"+std::to_wstring(score);scoreText.setString(scoreStr);//...其他保持不变```注意:字体加载部分,我们尝试多个字体文件,确保能加载到中文字体。这样修改后,应该能正确显示中文。另外,确保在VisualStudio中,源代码文件保存为带BOM的UTF-8格式(或者使用支持UTF-8的编译器选项)。如果编译器仍然不能正确处理源代码中的字符串字面量,也可以考虑使用u8前缀(C++11),例如:```cpp//使用UTF-8字符串字面量u8"中文"```但这种方式对于`setString`来说,需要`sf::String`支持从UTF-8转换。而`sf::String`是支持从UTF-8字符串构造的。所以也可以:```cppgameOverText.setString(sf::String::fromUtf8(u8"游戏结束!"));```因此,另一种修改方法是不改宽字符串,而使用UTF-8字符串字面量,并明确转换为sf::String:```cpp//代替直接使用字符串,使用:gameOverText.setString(sf::String::fromUtf8(u8"游戏结束!"));```这样,我们就不需要使用宽字符串,但是分数部分依然需要转换,因为动态生成的是std::string(ASCII)。不过分数数字部分可以继续使用std::string,因为它们是ASCII字符,不会乱码。因此,另一种修改方式:1.将源代码保存为UTF-8withBOM。2.将所有中文字符串使用u8前缀,并通过sf::String::fromUtf8转换。3.对于分数,我们继续使用std::string,因为“分数:”是中文,需要转换,而数字是ASCII。```cpp//例如:gameOverText.setString(sf::String::fromUtf8(u8"游戏结束!"));//对于动态字符串:std::stringscoreMsg="分数:"+std::to_string(score);//这样不行,因为"分数:"是UTF-8字符串,但拼接时整个字符串变成了UTF-8,而std::to_string生成的是ASCII,所以我们需要将整个字符串作为UTF-8?//由于std::string不能区分编码,所以我们可以这样:scoreText.setString(sf::String::fromUtf8("分数:"+std::to_string(score)));```但是,要注意:`"分数:"`这几个中文字符在源代码中是UTF-8编码(因为文件是UTF-8),所以它们会以UTF-8的形式存储在编译后的程序中,然后通过`fromUtf8`转换为Unicode。而`std::to_string`生成的是ASCII,所以拼接后整个字符串是UTF-8编码,包含中文字符和ASCII数字。因此,我们可以直接使用:```cppscoreText.setString(sf::String::fromUtf8("分数:"+std::to_string(score)));```但是,注意:在C++中,字符串字面量`"分数:"`如果源代码是UTF-8,那么它也是UTF-8编码,因此和`std::to_string`的结果(ASCII)拼接后,整个字符串是UTF-8编码。所以这样是可以的。然而,在代码编辑器中,如果源代码是UTF-8withoutBOM,有些编译器(如MSVC)可能会将其解释为系统默认编码(GBK),从而造成乱码。因此,最好还是确保源代码保存为UTF-8withBOM,这样MSVC能正确识别。总结:修改方案二1.在VisualStudio中,将源文件保存为UTF-8withBOM。2.使用`sf::String::fromUtf8`将包含中文字符的字符串(包括动态生成字符串)设置为UTF-8编码。3.加载支持中文的字体。具体修改如下:```cpp//在设置文本字符串的地方://游戏结束文本gameOverText.setString(sf::String::fromUtf8("游戏结束!"));//重新开始提示restartText.setString(sf::String::fromUtf8("按空格键重新开始"));//标题titleText.setString(sf::String::fromUtf8("天天酷跑"));//开始游戏提示startText.setString(sf::String::fromUtf8("按空格键开始游戏"));//在游戏循环中更新分数:scoreText.setString(sf::String::fromUtf8("分数:"+std::to_string(score)));```注意:这种方法要求`std::to_string(score)`的结果是纯ASCII(它确实是),并且整个字符串被当作UTF-8处理。而中文字符在源代码中以UTF-8存储,所以可以正常工作。推荐使用第二种方法,因为它不涉及宽字符,代码相对简洁,且对动态生成的字符串处理也一致。最后,请注意,如果你选择使用宽字符(方法一),也要确保字体正确。这里我们采用第二种方法修改原代码。注意:原代码中,有些字符串在构造函数中设置,有些在循环中设置。对于循环中设置的分数文本,我们也要改。下面是修改后的完整代码(只修改了文本设置部分):</think> 您的代码在Visual Studio中编译后显示中文乱码的问题是由字符编码导致的。Visual Studio默认使用系统本地编码(Windows系统通常是GBK),但SFML的文本渲染期望UTF-8编码。以下是详细的解决方案和解释: ### 解决方案:修改字体加载和文本设置方式 ```cpp #include <SFML/Graphics.hpp> // ... (其他头文件保持不变) int main() { // ... (前面的初始化代码保持不变) // 修改字体加载方式(使用支持中文的字体) Font font; // 尝试加载中文字体(如微软雅黑) if (!font.loadFromFile("C:/Windows/Fonts/msyh.ttc")) { // 备用字体方案 if (!font.loadFromFile("C:/Windows/Fonts/simhei.ttf")) { // 最后尝试Arial(可能不显示中文) font.loadFromFile("C:/Windows/Fonts/arial.ttf"); } } // 修改文本对象 - 使用sf::String转换中文 Text scoreText; scoreText.setFont(font); scoreText.setCharacterSize(24); scoreText.setFillColor(Color::White); scoreText.setPosition(20, 20); scoreText.setString(sf::String::fromUtf8("分数: ")); // 使用UTF-8转换 // 其他文本也做同样修改 Text gameOverText; gameOverText.setFont(font); // ... (其他设置) gameOverText.setString(sf::String::fromUtf8("游戏结束!")); Text restartText; // ... restartText.setString(sf::String::fromUtf8("按空格键重新开始")); Text titleText; // ... titleText.setString(sf::String::fromUtf8("天天酷跑")); Text startText; // ... startText.setString(sf::String::fromUtf8("按空格键开始游戏")); // ... (后续代码保持不变) // 在游戏循环中更新分数(需要额外处理) while (window.isOpen()) { // ... // 修改分数更新方式 std::wstring scoreStr = sf::String::fromUtf8("分数: ").toWideString(); scoreStr += std::to_wstring(score); scoreText.setString(scoreStr); // ... } } ``` ### 关键修改解释: 1. **使用支持中文的字体**: - 换用微软雅黑(`msyh.ttc`)或黑体(`simhei.ttf`)等包含中文编码的字体 - 提供备用字体加载方案防止程序崩溃 2. **文本内容使用`sf::String::fromUtf8()`**: - `sf::String`能正确处理UTF-8编码的中文字符 - 避免直接使用C++字符串字面量(Windows默认使用ANSI编码) 3. **分数更新特殊处理**: - 中文部分和数字部分需要分别处理 - 使用`std::to_wstring()`确保数字正确转换 4. **确保文件编码正确**: 在Visual Studio中: - "文件" → "另存为" → 点击"保存"按钮旁的箭头 - 选择"编码保存" → 选择"带签名的UTF-8(65001)" ### 其他可能需要的调整: ```cpp // 在main函数开头添加Locale设置 #include <locale> int main() { std::locale::global(std::locale("")); // 设置系统默认Locale // ... 其他代码 } ``` ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值