在 while 循环中使用 printf 时 Ncurses 显示乱码
Ncurses displays garbage when using printf in while loop
我正在 Linux 上创建贪吃蛇游戏。当我意识到我需要 ncruses.h
中包含一个 getch()
函数时,我一直在使用 iostream
。我有一个绘制方法,它在使用 std::cout
时将所有板元素打印到控制台,并且每个字符都正确显示。我有整个董事会。但是当我切换到 ncurses 并将所有 std::cout
重写为 printf
() 时,程序开始只写板的一部分。全部在while循环中完成,每个循环板都重绘。
我是新手,请多多关照
这是我的main.cpp
#include <iostream>
#include <chrono>
#include <thread>
#include <ncurses.h>
#include <stdio.h>
#include "board.h"
#include "consoledraw.h"
#include "snake.h"
#include "fruit.h"
void sleepThread()
{
static constexpr int SLEEP_MS = 1000;
std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_MS));
}
int main()
{
std::cout << "\e[8;30;140t"; // set console window size
Board _board;
Snake _snake;
consoledraw draw;
Fruit _fruit;
_board.setBoardSize(64, 36); // cca 16:9
_board.setDefaultItemType();
_board.makeSnake(_snake);
_board.setSnakeOnBoard(_snake);
_board.makeFruit(_fruit);
_board.setFruitOnBoard(_fruit);
int score = 0;
initscr();
setlocale(LC_ALL, "");
// raw();
cbreak();
curs_set(0);
noecho();
scrollok(stdscr, TRUE);
keypad(stdscr, TRUE);
while (true)
{
draw.redraw(_board);
// printf("Your score is: \r\v"); // TODO << score << std::endl;
sleepThread();
_board.clearBoard();
_snake.moveSnake(_snake);
if (_snake.checkSelfCollision(_snake) == true)
{
draw.clearConsole();
printf("Game Over!\n");
return 0;
};
if (_snake.eatFood(_fruit) == true)
{
_board.makeFruit(_fruit);
_board.setFruitOnBoard(_fruit);
score++;
}
_board.setSnakeOnBoard(_snake);
_board.setFruitOnBoard(_fruit);
}
endwin();
return 0;
}
这是我的 consoledraw.cpp
#include "consoledraw.h"
consoledraw::consoledraw()
{
}
void consoledraw::redraw(Board &board)
{
clearConsole();
drawBoard(board);
}
void consoledraw::clearConsole()
{
// Kompletne vymaze celou konzoli a nasrtavi kurzor do leveho horniho rohu.
refresh();
}
void consoledraw::drawBoard(Board &board)
{
auto b = board.getBoard();
// Top border line
drawHorizontalBorderLine(b[0].size(), true);
// Board
for (unsigned int y = 0; y < b.size(); y++)
{
printf(LINE_VERTICAL); // border line
for (unsigned int x = 0; x < b[y].size(); x++)
{
drawSymbol(b[y][x]);
}
printf(LINE_VERTICAL"\r\v"); // border line + newline
}
// Down border line
drawHorizontalBorderLine(b[0].size(), false);
}
void consoledraw::drawSymbol(ItemType itemType)
{
if (itemType == ItemType::Empty)
{
printf(BLOCK_TRANSPARENT);
}
else if (itemType == ItemType::Tsss)
{
printf(BLOCK_MEDIUM_SHADE);
}
else if (itemType == ItemType::Food)
{
printf(BLOCK_LIGHT_SHADE);
}
else if (itemType == ItemType::TsssHead)
{
printf(BLOCK_DARK_SHADE);
}
}
void consoledraw::drawHorizontalBorderLine(unsigned long boardWidth, bool isTop)
{
// Left corner
if (isTop)
{
printf(LINE_UPLEFT_CORNER);
}
else
{
printf(LINE_DOWNLEFT_CORNER);
}
// Line
for (unsigned int i = 0; i < boardWidth; i++)
{
printf(LINE_HORIZONTAL);
}
// Right corner
if (isTop)
{
printf(LINE_UPRIGHT_CORNER);
}
else
{
printf(LINE_DOWNRIGHT_CORNER);
}
printf("\r\v");
}
这是我在使用 ncurses 时得到的结果:
这是我使用 iostream 得到的结果:
C 库 (printf()
) 和 C++ 库 (std::cout
) 缓冲它们的输出——尽管默认情况下 C 和 C++ 库同步它们的缓冲区。
ncurses 库执行原始(无缓冲)输出,有时用带内控制序列包装。如果您通过 C 或 C++ 库和 ncurses 库将输出混合到同一设备,您将在屏幕上看到垃圾。就像你一样。
您应该仅 ncurses 库或标准库来处理来自终端的input/output。不要混用。
我正在 Linux 上创建贪吃蛇游戏。当我意识到我需要 ncruses.h
中包含一个 getch()
函数时,我一直在使用 iostream
。我有一个绘制方法,它在使用 std::cout
时将所有板元素打印到控制台,并且每个字符都正确显示。我有整个董事会。但是当我切换到 ncurses 并将所有 std::cout
重写为 printf
() 时,程序开始只写板的一部分。全部在while循环中完成,每个循环板都重绘。
我是新手,请多多关照
这是我的main.cpp
#include <iostream>
#include <chrono>
#include <thread>
#include <ncurses.h>
#include <stdio.h>
#include "board.h"
#include "consoledraw.h"
#include "snake.h"
#include "fruit.h"
void sleepThread()
{
static constexpr int SLEEP_MS = 1000;
std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_MS));
}
int main()
{
std::cout << "\e[8;30;140t"; // set console window size
Board _board;
Snake _snake;
consoledraw draw;
Fruit _fruit;
_board.setBoardSize(64, 36); // cca 16:9
_board.setDefaultItemType();
_board.makeSnake(_snake);
_board.setSnakeOnBoard(_snake);
_board.makeFruit(_fruit);
_board.setFruitOnBoard(_fruit);
int score = 0;
initscr();
setlocale(LC_ALL, "");
// raw();
cbreak();
curs_set(0);
noecho();
scrollok(stdscr, TRUE);
keypad(stdscr, TRUE);
while (true)
{
draw.redraw(_board);
// printf("Your score is: \r\v"); // TODO << score << std::endl;
sleepThread();
_board.clearBoard();
_snake.moveSnake(_snake);
if (_snake.checkSelfCollision(_snake) == true)
{
draw.clearConsole();
printf("Game Over!\n");
return 0;
};
if (_snake.eatFood(_fruit) == true)
{
_board.makeFruit(_fruit);
_board.setFruitOnBoard(_fruit);
score++;
}
_board.setSnakeOnBoard(_snake);
_board.setFruitOnBoard(_fruit);
}
endwin();
return 0;
}
这是我的 consoledraw.cpp
#include "consoledraw.h"
consoledraw::consoledraw()
{
}
void consoledraw::redraw(Board &board)
{
clearConsole();
drawBoard(board);
}
void consoledraw::clearConsole()
{
// Kompletne vymaze celou konzoli a nasrtavi kurzor do leveho horniho rohu.
refresh();
}
void consoledraw::drawBoard(Board &board)
{
auto b = board.getBoard();
// Top border line
drawHorizontalBorderLine(b[0].size(), true);
// Board
for (unsigned int y = 0; y < b.size(); y++)
{
printf(LINE_VERTICAL); // border line
for (unsigned int x = 0; x < b[y].size(); x++)
{
drawSymbol(b[y][x]);
}
printf(LINE_VERTICAL"\r\v"); // border line + newline
}
// Down border line
drawHorizontalBorderLine(b[0].size(), false);
}
void consoledraw::drawSymbol(ItemType itemType)
{
if (itemType == ItemType::Empty)
{
printf(BLOCK_TRANSPARENT);
}
else if (itemType == ItemType::Tsss)
{
printf(BLOCK_MEDIUM_SHADE);
}
else if (itemType == ItemType::Food)
{
printf(BLOCK_LIGHT_SHADE);
}
else if (itemType == ItemType::TsssHead)
{
printf(BLOCK_DARK_SHADE);
}
}
void consoledraw::drawHorizontalBorderLine(unsigned long boardWidth, bool isTop)
{
// Left corner
if (isTop)
{
printf(LINE_UPLEFT_CORNER);
}
else
{
printf(LINE_DOWNLEFT_CORNER);
}
// Line
for (unsigned int i = 0; i < boardWidth; i++)
{
printf(LINE_HORIZONTAL);
}
// Right corner
if (isTop)
{
printf(LINE_UPRIGHT_CORNER);
}
else
{
printf(LINE_DOWNRIGHT_CORNER);
}
printf("\r\v");
}
这是我在使用 ncurses 时得到的结果:
这是我使用 iostream 得到的结果:
C 库 (printf()
) 和 C++ 库 (std::cout
) 缓冲它们的输出——尽管默认情况下 C 和 C++ 库同步它们的缓冲区。
ncurses 库执行原始(无缓冲)输出,有时用带内控制序列包装。如果您通过 C 或 C++ 库和 ncurses 库将输出混合到同一设备,您将在屏幕上看到垃圾。就像你一样。
您应该仅 ncurses 库或标准库来处理来自终端的input/output。不要混用。