【问题标题】:console cout animation - C++控制台 cout 动画 - C++
【发布时间】:2012-05-07 04:11:55
【问题描述】:

我想为我cout-ing 的 40x20 字符块制作动画。我想用system("cls"); 清除控制台,然后立即出现下一个字符块。目前下一个区块是打字机风格。

对我的问题最简单的答案就是一次拥有 20 行 x 40 个字符的 oss 流 cout,而不是打字机风格。

Main.cpp:

    mazeCreator.cout();
    Sleep(5000);
    system("cls");

cout()

void MazeCreator::cout() {
    char wallChar = (char) 219;
    char pavedChar = (char) 176;
    char lightChar = ' ';
    char startChar = 'S';
    char finishChar = 'F';
    char errorChar = '!';
    char removedWallChar = 'R';
    char landmarkLocationChar = 'L';

    ostringstream oss;
    for (int row = 0; row < rows; row++) {
        oss << " ";
        for (int col = 0; col < columns; col++) {
            if (mazeArray[row][col] == wall)
                oss << wallChar;
            else if (mazeArray[row][col] == paved)
                oss << pavedChar;
            else if (mazeArray[row][col] == light)
                oss << lightChar;
            else if (mazeArray[row][col] == start)
                oss << startChar;
            else if (mazeArray[row][col] == finish)
                oss << finishChar;
            else if (mazeArray[row][col] == removedWall)
                oss << removedWallChar;
            else if (mazeArray[row][col] == landmarkLocation)
                oss << landmarkLocationChar;
            else
                oss << errorChar;
        }
        oss << "\n";
    }
    oss << "\n\n";

    cout << oss.str();
}

【问题讨论】:

  • 我认为这是针对 Windows 的?
  • 您需要提供更多详细信息。
  • 你的意思是你可以看到它正在绘制吗?您可以使用缓冲区:msdn.microsoft.com/en-us/library/windows/desktop/…
  • @chris 这看起来像我想要的,但我可能需要一些帮助来实现它
  • 什么是打字机风格? o.ô

标签: c++ windows console


【解决方案1】:

您可以在代码中维护两个二维数组,一个包含屏幕上的当前字符块(我们称之为cur),另一个包含下一个块(我们称之为next)。

假设cur 存储现在屏幕上的块。通过写入next 数组来设置下一个块。当您准备好将其放在屏幕上时,同时循环遍历 curnext仅针对它们不同的字符,使用 SetConsoleCursorPosition 跳转到该位置并写入新角色。

完成后,将next 的内容复制到cur 并继续下一个块。

更新:这是一个例子:

class console_buffer
{
public:
    console_buffer(int rows, int columns) 
                   // start out with spaces
                 : cur(rows, vector<char>(columns, ' ')), 
                   next(rows, vector<char>(columns, ' '))
    {
    }

    void sync()
    {
        // Loop over all positions
        for (int row = 0; row < cur.size(); ++row)
            for (int col = 0; col < cur[row].size(); ++col)

                // If the character at this position has changed
                if (cur[row][col] != next[row][col])
                {
                    // Move cursor to position
                    COORD c = {row, col};
                    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c);

                    // Overwrite character
                    cout.put(next[row][col]);
                }

         // 'next' is the new 'cur'
         cur = next;
    }

    void put(char c, int row, int col)
    {
        next[row][col] = c;
    }
private:
    vector<vector<char> > cur;
    vector<vector<char> > next;
};

...

int main()
{
    console_buffer buf(40, 20);

    // set up first block
    ... some calls to buf.put() ...

    // make first block appear on screen
    buf.sync();

    // set up next block
    ... some calls to buf.put()

    // make next block appear on screen
    buf.sync();

    // etc.
}

【讨论】:

  • 我宁愿不维护两个二维数组。我宁愿有一种方法可以立即找到 ostringstream。
  • @michaellindahl:我宁愿只为我自己编写代码,但是,嘿,我们都会时不时地面临失望。归根结底,您要么拥有有效的代码,要么因避免做您宁愿不做的事情而感到满足;)
  • 触摸。我不太确定你的意思是我维护两个二维数组......你想给我一些示例代码吗?我是 C++ 的新手
  • @michaellindahl:你去吧。
【解决方案2】:

您可以使用CreateConsoleScreenBuffer 实现双缓冲。这些方面的东西应该起作用。我用过一次,很久以前,所以它可能并不完美。

HANDLE current = GetStdHandle (STD_OUTPUT_HANDLE);

HANDLE buffer = CreateConsoleScreenBuffer (
    GENERIC_WRITE,
    0,
    NULL,
    CONSOLE_TEXTMODE_BUFFER,
    NULL
);

WriteConsole (/*fill with what you're drawing*/);

system ("cls"); //clear this screen before swapping    
SetConsoleActiveScreenBuffer (buffer);

WriteConsole (/*do it to the other one now*/);

system ("cls");    
SetConsoleActiveScreenBuffer (current); //swap again

//repeat as needed

CloseHandle (buffer); //clean up

【讨论】:

  • 我如何才能将操作系统流与 WriteConsole 一起使用?我正在寻找的最简单的方法就是立即打印出一个 oss 流。
  • 好吧,即使cout 也不能一下子把它全部放完。如果您在输出之间的时间很短的情况下重复执行此操作,它将开始闪烁。要从字符串流中获取 C 风格的数据,您可以使用 os.str().c_str()
  • 这给了我一个错误。是的,我是个白痴。强烈建议手持。
  • @michaellindahl,什么样的错误?填写WriteConsole 应该不会太难。
  • WriteConsole (os.str().c_str()); 说没有足够的论据。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-20
相关资源
最近更新 更多