如何在C++中用星号创建一个空心三角形,然后制作英国国旗?

huangapple go评论76阅读模式
英文:

how can I do an empty triangle with stars in c++ to after do the british flag?

问题

这是我必须在最后获得的标志:

*******************
**       *       **
* *      *      * *
*  *     *     *  *
*   *    *    *   *
*    *   *   *    *
*     *  *  *     *
*      * * *      *
*       ***       *
*******************
*       ***       *
*      * * *      *
*     *  *  *     *
*    *   *   *    *
*   *    *    *   *
*  *     *     *  *
* *      *      * *
**       *       **
*******************

我知道如何制作满星的三角形,但当内部为空时,我不知道该如何继续。有人能帮帮我吗?

我尝试过,我只知道如何制作满星的三角形和内部为空的星形正方形/矩形,以下是代码:

int main(void)
{
    int i, j, length, width;

    cout << "矩形的长度? ";
    cin >> length;
    cout << endl;

    cout << "矩形的宽度? ";
    cin >> width;
    cout << endl;

    for (i = 0; i < length; i++)
        cout << "*";

    cout << endl;

    for (i = 1; i < width - 1; i++)
    {
        cout << "*";

        for (j = 1; j < length - 1; j++)
        {
            cout << " ";
        }

        cout << "*";
        cout << endl;
    }

    for (i = 0; i < length; i++)
        cout << "*";

    cout << endl;

    return 0;
}
英文:

This is the flag that I have to get at the end:

*******************
**       *       **
* *      *      * *
*  *     *     *  *
*   *    *    *   *
*    *   *   *    *
*     *  *  *     *
*      * * *      *
*       ***       *
*******************
*       ***       *
*      * * *      *
*     *  *  *     *
*    *   *   *    *
*   *    *    *   *
*  *     *     *  *
* *      *      * *
**       *       **
*******************

I know how to do full star triangles but when it's empty on the inside I have no idea about how to proceed. Can anyone help me?

I tried and I just know how to do full star triangles and a star square/rectangle empty on the inside here is the code:

int main(void)
{
    int i, j, length, width;

    cout &lt;&lt; &quot;Length of rectangle? &quot;;
    cin &gt;&gt; length;
    cout &lt;&lt; endl;

    cout &lt;&lt; &quot;Width of rectangle? &quot;;
    cin &gt;&gt; width;
    cout &lt;&lt; endl;

    for ( i = 0; i &lt; length; i++ )
        cout &lt;&lt; &quot;*&quot;;

    cout &lt;&lt; endl;

    for ( i = 1; i &lt; width - 1; i++ )
    {
        cout &lt;&lt; &quot;*&quot;;

        for ( j = 1; j &lt; length - 1; j++ )
        {
            cout &lt;&lt; &quot; &quot;;
        }

        cout &lt;&lt; &quot;*&quot;;
        cout &lt;&lt; endl;
    }

    for ( i = 0; i &lt; length; i++)
        cout &lt;&lt; &quot;*&quot;;

    cout &lt;&lt; endl;

    return 0;
}

答案1

得分: 0

中间放置十字很容易:

if (i == ??? || j == ???)
    std::cout << '*';
else
    std::cout << ' ';

对角线稍微复杂一些。

在你的嵌套循环中,打印 std::cout << (i+j) << '\t'。你能看出这些数字中是否有任何模式,可以让你识别出其中一个对角线吗?

然后,用 i-j 重复相同的步骤。你能看出另一个对角线的模式吗?

最终,你的嵌套循环将如下所示:

if (i == /*某个条件*/ || j == /*某个其他条件*/ || (i+j) .../*某个条件*/ || (i-j) .../*另一个条件*/)
    std::cout << '*';
else
    std::cout << ' ';
英文:

Getting the cross in the middle is easy:

if (i == ??? || j == ???)
    std::cout &lt;&lt; &#39;*&#39;;
else
    std::cout &lt;&lt; &#39; &#39;;

The diagnoals are slightly more tricky.

In your nested loop, print std::cout &lt;&lt; (i+j) &lt;&lt; &#39;\t&#39;. Do you see any pattern in the numbers that lets you identify one of the diagonals?

Then repeat the same thing with i-j. Do you see the pattern for the other diagonal?

In the end, your nested loop will look like this:

if (i == /*something*/ || j == /*something else*/ || i+j .../*some condition*/ || i-j .../*another condition*/)
    std::cout &lt;&lt; &#39;*&#39;;
else
    std::cout &lt;&lt; &#39; &#39;;

答案2

得分: 0

第1、10和19行很容易,因为它们每行都只包含19个星号。

问题在于第2到9行和第11到19行。

不过,你是否注意到第2到9行存在一种模式?

第2行由一个星号组成,

  • 后跟0个空格
  • 后跟一个星号
  • 后跟7个空格
  • 后跟一个星号
  • 后跟7个空格
  • 后跟一个星号
  • 后跟0个空格

后跟一个星号

第3行由一个星号组成,

  • 后跟1个空格
  • 后跟一个星号
  • 后跟6个空格
  • 后跟一个星号
  • 后跟6个空格
  • 后跟一个星号
  • 后跟1个空格

后跟一个星号。

第4行由一个星号组成,

  • 后跟2个空格
  • 后跟一个星号
  • 后跟5个空格
  • 后跟一个星号
  • 后跟5个空格
  • 后跟一个星号
  • 后跟2个空格

后跟一个星号。

第5行由一个星号组成,

  • 后跟3个空格
  • 后跟一个星号
  • 后跟4个空格
  • 后跟一个星号
  • 后跟4个空格
  • 后跟一个星号
  • 后跟3个空格

后跟一个星号。

第6行由一个星号组成,

  • 后跟4个空格
  • 后跟一个星号
  • 后跟3个空格
  • 后跟一个星号
  • 后跟3个空格
  • 后跟一个星号
  • 后跟4个空格

后跟一个星号。

第7行由一个星号组成,

  • 后跟5个空格
  • 后跟一个星号
  • 后跟2个空格
  • 后跟一个星号
  • 后跟2个空格
  • 后跟一个星号
  • 后跟5个空格

后跟一个星号。

第8行由一个星号组成,

  • 后跟6个空格
  • 后跟一个星号
  • 后跟1个空格
  • 后跟一个星号
  • 后跟1个空格
  • 后跟一个星号
  • 后跟6个空格

后跟一个星号。

第9行由一个星号组成,

  • 后跟7个空格
  • 后跟一个星号
  • 后跟0个空格
  • 后跟一个星号
  • 后跟0个空格
  • 后跟一个星号
  • 后跟7个空格

后跟一个星号。

模式如下:

假设size是三角形的总大小(在你的情况下是19),那么

第n行由一个星号组成,

  • 后跟n-2个空格
  • 后跟一个星号
  • 后跟(size/2) - n个空格
  • 后跟一个星号
  • 后跟(size/2) - n个空格
  • 后跟一个星号
  • 后跟n-2个空格

后跟一个星号。

请注意,在C中,19 / 2的结果是9,因为除法的小数部分被舍弃。

使用这个有关模式的信息,你应该能够创建一个循环,每次循环迭代时打印一行如上所述的内容。这样,你应该能够解决打印第2到第9行的问题。

之后,打印第11到第19行应该很容易,因为这些行只需要以第2到第9行的相反顺序打印出来。

英文:

Lines 1, 10 and 19 are easy, as they each consist only of 19 *.

The problem is the lines 2 to 9 and 11 to 19.

However, do you notice a pattern in lines 2 to 9?

Line 2 consists of one *

  • followed by 0 spaces
  • followed by one *
  • followed by 7 spaces
  • followed by one *
  • followed by 7 spaces
  • followed by one *
  • followed by 0 spaces

followed by one *

Line 3 consists of one *

  • followed by 1 spaces
  • followed by one *
  • followed by 6 spaces
  • followed by one *
  • followed by 6 spaces
  • followed by one *
  • followed by 1 spaces

followed by one *.

Line 4 consists of one *

  • followed by 2 spaces
  • followed by one *
  • followed by 5 spaces
  • followed by one *
  • followed by 5 spaces
  • followed by one *
  • followed by 2 spaces

followed by one *.

Line 5 consists of one *

  • followed by 3 spaces
  • followed by one *
  • followed by 4 spaces
  • followed by one *
  • followed by 4 spaces
  • followed by one *
  • followed by 3 spaces

followed by one *.

Line 6 consists of one *

  • followed by 4 spaces
  • followed by one *
  • followed by 3 spaces
  • followed by one *
  • followed by 3 spaces
  • followed by one *
  • followed by 4 spaces

followed by one *.

Line 7 consists of one *

  • followed by 5 spaces
  • followed by one *
  • followed by 2 spaces
  • followed by one *
  • followed by 2 spaces
  • followed by one *
  • followed by 5 spaces

followed by one *.

Line 8 consists of one *

  • followed by 6 spaces
  • followed by one *
  • followed by 1 spaces
  • followed by one *
  • followed by 1 spaces
  • followed by one *
  • followed by 6 spaces

followed by one *.

Line 9 consists of one *

  • followed by 7 spaces
  • followed by one *
  • followed by 0 spaces
  • followed by one *
  • followed by 0 spaces
  • followed by one *
  • followed by 7 spaces

followed by one *.

The pattern is the following:

Assuming that size is the total size of the triangle (which is 19 in your case), then

line n consists of one *

  • followed by n-2 spaces
  • followed by one *
  • followed by (size/2) - n spaces
  • followed by one *
  • followed by (size/2) - n spaces
  • followed by one *
  • followed by n-2 spaces

followed by one *.

Note that in C, the result of 19 / 2 is 9, as the fractional part of the division is discarded.

Using this information about the pattern, you should be able to create a loop that in every loop iteration, prints one line as described above. That way, you should be able to solve the problem of printing the lines 2 to 9.

Printing the lines 11 to 19 should be easy afterwards, because these lines must only be printed in reverse order of the lines 2 to 9.

In accordance with the community guidelines for homework questions, I will not provide the full solution at this time. I can provide further information later, if necessary.

EDIT:

Since several other solutions have already been posted by other users, I will now also post my solution, which solves the problem as described above:

#include &lt;iostream&gt;

const int MAP_SIZE = 19;

static_assert( MAP_SIZE % 2 == 1, &quot;MAP_SIZE must be odd&quot; );

int main( void )
{
    //print first horizontal line
    for ( int i = 0; i &lt; MAP_SIZE; i++ )
        std::cout &lt;&lt; &#39;*&#39;;
    std::cout &lt;&lt; &#39;\n&#39;;

    //print top half of flag
    for ( int i = 0; i &lt; MAP_SIZE / 2 - 1; i++ )
    {
        std::cout &lt;&lt; &#39;*&#39;;
        for ( int j = 0; j &lt; i; j++ )
            std::cout &lt;&lt; &#39; &#39;;
        std::cout &lt;&lt; &#39;*&#39;;
        for ( int j = 0; j &lt; MAP_SIZE/2 - 2 - i; j++ )
            std::cout &lt;&lt; &#39; &#39;;
        std::cout &lt;&lt; &#39;*&#39;;
        for ( int j = 0; j &lt; MAP_SIZE/2 - 2 - i; j++ )
            std::cout &lt;&lt; &#39; &#39;;
        std::cout &lt;&lt; &#39;*&#39;;
        for ( int j = 0; j &lt; i; j++ )
            std::cout &lt;&lt; &#39; &#39;;
        std::cout &lt;&lt; &#39;*&#39;;
        std::cout &lt;&lt; &#39;\n&#39;;
    }

    //print second horizontal line
    for ( int i = 0; i &lt; MAP_SIZE; i++ )
        std::cout &lt;&lt; &#39;*&#39;;
    std::cout &lt;&lt; &#39;\n&#39;;

    //print bottom half of flag
    for ( int i = 0; i &lt; MAP_SIZE / 2 - 1; i++ )
    {
        std::cout &lt;&lt; &#39;*&#39;;
        for ( int j = 0; j &lt; MAP_SIZE/2 - 2 - i; j++ )
            std::cout &lt;&lt; &#39; &#39;;
        std::cout &lt;&lt; &#39;*&#39;;
        for ( int j = 0; j &lt; i; j++ )
            std::cout &lt;&lt; &#39; &#39;;
        std::cout &lt;&lt; &#39;*&#39;;
        for ( int j = 0; j &lt; i; j++ )
            std::cout &lt;&lt; &#39; &#39;;
        std::cout &lt;&lt; &#39;*&#39;;
        for ( int j = 0; j &lt; MAP_SIZE/2 - 2 - i; j++ )
            std::cout &lt;&lt; &#39; &#39;;
        std::cout &lt;&lt; &#39;*&#39;;
        std::cout &lt;&lt; &#39;\n&#39;;
    }

    //print third horizontal line
    for ( int i = 0; i &lt; MAP_SIZE; i++ )
        std::cout &lt;&lt; &#39;*&#39;;
    std::cout &lt;&lt; &#39;\n&#39;;
}

However, I think that this problem is easier to solve using a 2D array (which you stated that you are not allowed to use). The 2D array is initialized to spaces and then the 3 horizontal, 3 vertical and 2 diagonal lines are drawn:

#include &lt;iostream&gt;

const int MAP_SIZE = 19;

static_assert( MAP_SIZE % 2 == 1, &quot;MAP_SIZE must be odd&quot; );

int main( void )
{
    char map[MAP_SIZE][MAP_SIZE];

    //initialize 2D array to spaces
    for ( int i = 0; i &lt; MAP_SIZE; i++ )
        for ( int j = 0; j &lt; MAP_SIZE; j++ )
            map[i][j] = &#39; &#39;;

    //draw the 3 horizontal lines
    for ( int i = 0; i &lt; MAP_SIZE; i++ )
    {
        map[         0][i] = &#39;*&#39;;
        map[MAP_SIZE/2][i] = &#39;*&#39;;
        map[MAP_SIZE-1][i] = &#39;*&#39;;
    }

    //draw the 3 vertical lines
    for ( int i = 0; i &lt; MAP_SIZE; i++ )
    {
        map[i][         0] = &#39;*&#39;;
        map[i][MAP_SIZE/2] = &#39;*&#39;;
        map[i][MAP_SIZE-1] = &#39;*&#39;;
    }

    //draw the 2 diagonal lines
    for ( int i = 0; i &lt; MAP_SIZE; i++ )
    {
        map[i][           i] = &#39;*&#39;;
        map[i][MAP_SIZE-i-1] = &#39;*&#39;;
    }

    //print the result
    for ( int i = 0; i &lt; MAP_SIZE; i++ )
    {
        std::cout.write( map[i], MAP_SIZE );
        std::cout.put( &#39;\n&#39; );
    }
}

答案3

得分: 0

不要翻译代码部分,以下是翻译好的内容:

"Instead of calculating each line in a loop. Have a function return what to draw at each point. Then you can apply some basic algebra to decide if there's a point to draw."

上面的代码打印出:

*******************
**       *       **
* *      *      * *
*  *     *     *  *
*   *    *    *   *
*    *   *   *    *
*     *  *  *     *
*      * * *      *
*       ***       *
*******************
*       ***       *
*      * * *      *
*     *  *  *     *
*    *   *   *    *
*   *    *    *   *
*  *     *     *  *
* *      *      * *
**       *       **
*******************
英文:

Instead of calculating each line in a loop. Have a function return what to draw at each point. Then you can apply some basic algebra to decide if there's a point to draw.

#include &lt;iostream&gt;

char getPoint(int width, int height, int x, int y) {
    int xNorm = (x &lt;= width / 2) ? x : (width - x);
    int yNorm = (y &lt;= height / 2) ? y : (height - y);

    // borders
    if ( ((x == 0) || (x == (width)) || (y == 0) || (y == height)) ||  // borders
         ((x == width / 2) || (y == height / 2)) ||                    // middle stripe
         ((width &gt;= height) &amp;&amp; (yNorm == xNorm * height / width)) ||   // diagnols (when width &gt;= height)
         ((height &gt; width) &amp;&amp; (xNorm == yNorm * width / height))       // diagnols (when height &gt; width)
        )
    {
        return &#39;*&#39;;
    }
    return &#39; &#39;;
}

void printFlag(int width, int height) {
    for (int y = 0; y &lt;= height; y++) {
        for (int x = 0; x &lt;= width; x++) {
            std::cout &lt;&lt; getPoint(width, height, x, y);
        }
        std::cout &lt;&lt; std::endl;
    }
}

int main()
{
    int height = 18;
    int width = 18;
    printFlag(width, height);
    return 0;
}

The above prints:

*******************
**       *       **
* *      *      * *
*  *     *     *  *
*   *    *    *   *
*    *   *   *    *
*     *  *  *     *
*      * * *      *
*       ***       *
*******************
*       ***       *
*      * * *      *
*     *  *  *     *
*    *   *   *    *
*   *    *    *   *
*  *     *     *  *
* *      *      * *
**       *       **
*******************

答案4

得分: 0

以下是翻译好的部分:

示例(基于我在30多年前学过的2D计算机图形课程的知识)。使用1D向量(动态分配的数组)作为内存缓冲区和Bresenham的线算法

在线演示:https://onlinegdb.com/Kg9HAdxfZ

#include <cassert>
#include <iostream>
#include <vector>

class Flag
{
public:
    Flag(int width, int height) :
        m_width{ width },
        m_height{ height },
        m_grid(width*height, false) // 分配缓冲区并清零
    {
        assert(width > 1);
        assert(height > 1);

        int w = width - 1;
        int h = height - 1;

        // 标志的轮廓
        line(0, 0, w, 0);
        line(w, 0, w, h);
        line(w, h, 0, h);
        line(0, h, 0, 0);

        // 对角线
        line(0, 0, w, h);
        line(0, h, w, 0);

        // 中线,水平和垂直
        line(0, h / 2, w, h / 2);
        line(w / 2, 0, w / 2, h);
    };

    bool get(int x, int y) const
    {
        return m_grid.at(y * m_width + x);
    }

    int width() const noexcept
    {
        return m_width;
    }

    int height() const noexcept
    {
        return m_height;
    }

private:
    void set(int x, int y)
    {
        m_grid.at(y * m_width + x) = true;
    }

    // Bresenham线算法
    // https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
    void line(int x0, int y0, int x1, int y1)
    {
        int dx = abs(x1 - x0);;
        int sx = x0 < x1 ? 1 : -1;
        int dy = -abs(y1 - y0);
        int sy = y0 < y1 ? 1 : -1;
        int error = dx + dy;

        while (true)
        {
            set(x0, y0);
            if ((x0 == x1) && (y0 == y1)) break;

            int e2 = 2 * error;
            if (e2 >= dy)
            {
                if (x0 == x1) break;
                error = error + dy;
                x0 = x0 + sx;
            }
            if (e2 <= dx)
            {
                if (y0 == y1) break;
                error = error + dx;
                y0 = y0 + sy;
            }
        }
    }

private:
    int m_width;
    int m_height;

    // 用于保存m_grid的每个位置的真假的缓冲区
    // 想象像素 ;)
    std::vector<bool> m_grid;
};

std::ostream& operator<<(std::ostream& os, const Flag& flag)
{
    for (int y = 0; y < flag.height(); ++y)
    {
        for (int x = 0; x < flag.width(); ++x)
        {
            if (flag.get(x, y))
            {
                os << "*";
            }
            else
            {
                os << " ";
            }
        }
        std::cout << "\n";
    }

    return os;
}

int main()
{
    Flag flag(47, 15);
    std::cout << flag;
    return 0;
}
英文:

Example (based on knowledge from 2D computer graphics course I had over 30 years ago). Using a 1D vector (dynamically allocated array) as memory buffer and the Bresenham's line algorithm

Live demo here : https://onlinegdb.com/Kg9HAdxfZ

#include &lt;cassert&gt;
#include &lt;iostream&gt;
#include &lt;vector&gt;
class Flag
{
public:
Flag(int width, int height) :
m_width{ width },
m_height{ height },
m_grid(width*height,false) // allocate buffer and clear to false
{
assert(width &gt; 1);
assert(height &gt; 1);
int w = width - 1;
int h = height - 1;
// outline of flag
line(0, 0, w, 0);
line(w, 0, w, h);
line(w, h, 0, h);
line(0, h, 0, 0);
// diagonals
line(0, 0, w, h);
line(0, h, w, 0);
// mid lines horizontal and vertical
line(0, h / 2, w, h / 2);
line(w / 2, 0, w / 2, h);
};
bool get(int x, int y) const
{
return m_grid.at(y * m_width + x);
}
int width() const noexcept
{
return m_width;
}
int height() const noexcept
{
return m_height;
}
private:
void set(int x, int y)
{
m_grid.at(y * m_width + x) = true;
}
// Bresenham&#39;s line algorithm 
// https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
void line(int x0, int y0, int x1, int y1)
{
int dx = abs(x1 - x0);;
int sx = x0 &lt; x1 ? 1 : -1;
int dy = -abs(y1 - y0);
int sy = y0 &lt; y1 ? 1 : -1;
int error = dx + dy;
while (true)
{
set(x0, y0);
if ((x0 == x1) &amp;&amp; (y0 == y1)) break;
int e2 = 2 * error;
if (e2 &gt;= dy)
{
if (x0 == x1) break;
error = error + dy;
x0 = x0 + sx;
}
if (e2 &lt;= dx)
{
if (y0 == y1) break;
error = error + dx;
y0 = y0 + sy;
}
}
}
private:
int m_width;
int m_height;
// a buffer to hold true/false for each posision of the m_grid
// think pixels ;)
std::vector&lt;bool&gt; m_grid;
};
std::ostream&amp; operator&lt;&lt;(std::ostream&amp; os, const Flag&amp; flag)
{
for (int y = 0; y &lt; flag.height(); ++y)
{
for (int x = 0; x &lt; flag.width(); ++x)
{
if (flag.get(x, y))
{
os &lt;&lt; &quot;*&quot;;
}
else
{
os &lt;&lt; &quot; &quot;;
}
}
std::cout &lt;&lt; &quot;\n&quot;;
}
return os;
}
int main()
{
Flag flag(47, 15);
std::cout &lt;&lt; flag;
return 0;
}

答案5

得分: -1

void DrawUKflag(int L, int W)
{
    for (int i = 0; i <= L; i++)
    {
        for (int k = 0; k <= W; k++)
        {
            if (i == 0 || i == L / 2 || i == L || k == 0 || k == W / 2 || k == W)
            {
                cout << "*";
            }
            else if (k == W - i || k == i)
            {
                cout << "*";
            }
            else
            {
                cout << " ";
            }
        }
        cout << endl;
    }
}
英文:
void DrawUKflag(int L, int W)
{
for (int i = 0; i &lt;=L; i++)
{
for (int k = 0; k &lt;=W; k++) 
{
if (i==0||i==L/2||i==L ||k==0||k==W/2||k==W)
{
cout &lt;&lt; &quot;*&quot;;
}
else if (k==W-i || k==i)
{
cout &lt;&lt; &quot;*&quot;;
}
else
{
cout &lt;&lt; &quot; &quot;;
}
}
cout &lt;&lt; endl;
}
}

huangapple
  • 本文由 发表于 2023年6月2日 02:33:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/76384747.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定