【问题标题】:coordinating objects on the screen协调屏幕上的对象
【发布时间】:2019-10-11 19:41:26
【问题描述】:

所以我想在屏幕上显示一个具有特定坐标的对象并使其能够移动。例如,如果按下“u”,它会上升等等。所以我尝试使用变量 X 和 Y(初始化为 0)并在“清除屏幕”后使用 for 循环部署对象。所以看看这个:

#include <iostream>
#include <conio.h>
#include <cstdlib>
#include <vector>
#include <iomanip>
using namespace std;
char input;
char player = 1;
char keyup = 0x48, keydown = 0x50, keyright = 0x4d, keyleft = 0x4b;
int x = 0, y = 0;
void position()
{
    for (int start = 0; start <= y; start++)
    {
        cout << "\n";
    }
    for (int start = 0; start <= x; start++)
    {
        cout << " ";
    }
    cout << player;
}
void moveup()
{
    x - 1;
    system("cls");
    position();
}
void movedown()
{
    y + 1;
    system("cls");
    position();
}
void moveright()
{
    x + 1;
    system("cls");
    position();
}
void moveleft()
{
    y - 1;
    system("cls");
    position();
}
int main()
{
    while (1)
    {
        position();
        cin >> input;
        if (input == keyup) moveup();
        if (input == keydown) movedown();
        if (input == keyright) moveright();
        if (input == keyleft) moveleft();
        system("cls");
    }
}

所以当我运行它时,它只会显示 ASCII 键 = 1 的立方体;无论我按什么,它都会闪烁,向我显示同一位置的“玩家”。 大佬能告诉我是什么问题吗?

【问题讨论】:

  • 可能将“坐标”初始化为 0 是问题
  • 我猜cout &lt;&lt; symbol; 和char symbol = 0; 是问题所在。字符'\0' 通常用作字符串结束标记。我不会怀疑'\0' 的输出是否影响最小。对于垂直进纸的输出,我会推荐'\n',对于水平 - ' '(一个空格),当然,你必须按照这个顺序。
  • 所以 Scheff 你的意思是没有变量
  • 我该怎么做。我不推荐手动输出
  • 你的问题不是变量——而是它的值。 ;-)

标签: c++ visual-studio visual-c++


【解决方案1】:

首先,我建议使用字符文字而不是数值:

char const keyup = 'u';
//    ^ they are constants, aren't they???

0 不是可打印字符,因此将其用作symbol 不会在屏幕上打印任何内容...您可以使用 e。 G。 '+' 代替。

然后你在你的函数中重复了很多代码。您实际需要的只是一种打印功能;类似:

void update()
{
    system("cls");
    for(int i = 0; i < y; ++i)
        std::cout << '\n'; // navigate to appropriate line

    for(int i = 0; i < x; ++i)
        std::cout << ' '; // navigate to column

    std::cout << symbol << std::endl; // endl flashes buffer, too
}

您可以使用它来将符号打印到当前位置 (x/y)。在输入时您只需要修改坐标(我个人推荐使用 switch 语句而不是 if/else 链):

std::cin >> input;
switch(input)
{
case keyup: // NEEDS to be a constant to be used that way!
    --y;
    break;
case keydown:
    ++y;
    break;
case keyleft:
    --x;
    break;
case keyright:
    ++x;
    break;
default: // catch invalid user input
    // if you have, appropriate error handling – or just ignore
    break;      
}

可以省略一个空的默认值——不过,这是一个好习惯,总是捕获无效的情况。

最后:屏幕的第二次清除(在 if/else 链之后)将再次清空屏幕在用户可能已经看到任何东西之前。把它放在一边。全部合并:

for(;;)
{
    update(); // first screen update and returning here in every loop
    std::cin >> input;
    switch(input)
    {
    // ...
    case ExitKey: // recommend to add it!
        // the only disadvantage of switch: cannot use 'break' to exit loop!
        goto LOOP_END;
    default:
        break;
    }
}
LOOP_END:
// clean up application
return 0; // exit main...

我在上面省略了一件事情,但非常很重要:范围检查!在增加或减少其中一个坐标之前,您需要检查是否可以:

if(x > 0)
    --x;

或者我个人喜欢的变体:

y += y < SCREEN_HEIGHT; // needs to be defined appropriately...

关于屏幕尺寸:this 可能感兴趣...

【讨论】:

  • 谢谢,我会试试的。检查坐标值的事情:我没有看到。并且 `y += y 0) --x; `
  • 使用任何看起来最适合你的...只是解释一下:x -= x &gt; 0:比较的结果是bool,转换为int保证产生0(假)或1(真的)。因此,int offset = x &gt; 0; /* either 1 or 0 */; x -= offset; 更短。
  • 嘿,“可能感兴趣的”屏幕高度怎么样。如果可以的话,请告诉我更多信息,我很有耐心
  • @Mr.Stark135 您需要知道一行中的列数以及有多少行。最简单的方法是简单地定义一些有意义的常量。问题:他们不适应当前选择的控制台大小。所以你最终要么不使用完整的控制台窗口(可能还可以接受),要么使用超过可用的窗口(破坏你的游戏 - 假设 80 列并且处于 0/79;再次向右移动:0/80;但作为没有左列,换行/换行,输出看起来像 1/0)。提供的链接显示了如何动态确定大小...
【解决方案2】:

所以改进后的代码如下所示:

#include <iostream>
#include <conio.h>
#include <cstdlib>
#include <vector>
#include <iomanip>
using namespace std;
char input;
char player = 1;
const char keyup = 'u', keydown = 'd', keyright = 'r', keyleft = 'l', Exitkey = 'k';
int x = 0, y = 0;
void space()
{
    for (int start = 0; start < 7; start++)
    {
        cout << "\n";
    }
}
void update()
{
    system("cls");
    for (int i = 0; i < y; ++i)
    cout << '\n'; 

    for (int i = 0; i < x; ++i)
    cout << ' ';
    cout << player << endl;
}
void inputfunc()
{
    cin >> input; 
    switch (input)
    {
    case keyup:
        if (y = 0)
        {
            y = 0;
        }
        else --y;
        goto endloop;
    case keydown:
        ++y;
        goto endloop;
    case keyleft:
        if (x = 0)
        {
            x = 0;
        }
        else --x;
        goto endloop;
    case keyright:
        ++x;
        goto endloop;
    case Exitkey:
        goto endloop;
    default:
        break;
    }
endloop:;
}
int main()
{
    for (;;)
    {
        update();
        space();
        inputfunc();
    }
}

还有一件事:我不知道如何在输入一个字符后自动使其继续。我需要输入任意数量的字符,然后按 ENTER 来部署播放器。我该怎么做 Scheff?

【讨论】:

  • 您还没有完成范围检查。尝试像uuuddd 这样的序列——你会注意到你保持领先,但随后的下降将被忽略。更糟糕的是:过于频繁地输入r 会导致换行。对于space 函数,我建议不要添加静态空间(这将导致输入行四处移动),而是要弥补一个固定距离包括输出:for(int i = x; i &lt; MAX_HEIGHT; ++i) std:.cout &lt;&lt; '\n'。解决了这个问题后,您可以为用户添加一些文本,例如“请输入下一个命令(u、d、l、r、e、h = help)”。
  • 旁注:关于using namespace std...
  • 是的,但我不能一直写 std:: 并且可能发生的问题不会困扰我
  • 添加了范围检查。但是请你告诉我如何让程序在输入一个字符后自动走得更远?
  • 您只在必要的一半处添加了范围检查...您所说的“走得更远”到底是什么意思?或者反过来说,您不希望发生什么?
猜你喜欢
  • 2013-04-30
  • 2017-07-21
  • 1970-01-01
  • 1970-01-01
  • 2020-07-26
  • 1970-01-01
  • 2015-10-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多