首先,这是我的第一个问题,我需要更有经验的程序员或数学爱好者的提示.


我正试着在我的游戏中形成 pyramid .我不知道是因为我的数学和我的编程有多糟糕,还是因为我的大脑在试图弄清楚这一点时死了.我写了几个算法,但都不管用.当我收集物品时,我需要将它们放置在 pyramid 中.第二个在第一个旁边,然后第三个在他们上面.第四个(图中的指数3)需要再次下降,等等.如果我收集了4个对象,它们在图片中的位置应该是0-1-2-3.


以下是我正在努力实现的内容:

enter image description here

我跟这件事一点关系都没有.我只是在循环我的列表,并试图通过一些x-y偏移量计算来找出答案.我不确定是否应该手动使用预先填写的Vector3列表.

public void SetFormation(int count)
{
    Vector3 pos = Vector3.zero;
    for (int i = count; i > 0; i--)
    {
        for (int j = 0; j < i; j++)
        {
            GameObject gM = Instantiate(prefab);
            gM.transform.SetParent(transform);
            gM.transform.position = new Vector3(pos.x, pos.y, 0);
            pos += new Vector3(xOffset, 0, 0);
        }
        pos += new Vector3(0, yOffset, 0);
    }
}

推荐答案

把啦啦队员换成杂技演员.杂技演员不是 pyramid ,而是以柱子形式直接堆叠在彼此的顶部,上下笔直地站在彼此的肩膀上.列号从左侧开始,最左侧的列指定为1,并随着向右移动而递增.

以下是安排杂技演员的规则:

In column 1, you stack 1 acrobat.
In column 2, you stack 2 acrobats.
In column 3, you stack 3 acrobats.
Etc...

这是9名杂技演员的样子:

      9
    5 8
  2 4 7
0 1 3 6

现在想象一下,杂技演员非常强壮,可以偏离中心站立,所以只有一条腿在下面的人身上,相反的腿和相反的肩膀.它们都在相同的方向上偏移,使每一列都倾斜到一边.

每个堆叠的杂技演员都恰好是最下面一排杂技演员之间距离的一半,所以看起来他们就像是直接站在下面两个杂技演员的上面:

   9
  5 8
 2 4 7
0 1 3 6

看起来眼熟吗? pyramid 不是真正的 pyramid ,它是一组倾斜的柱子!

因此,算法就是在每一列中保持正确的杂技演员数量,随着你向上移动,每一位杂技演员都向左偏移半列.每当你到达栏目的顶端,你就开始一个新的栏目,然后重复,直到你达到了所需的杂技演员数量.每个底部杂技演员在新的一列中的开始位置很容易计算,因为它只是 pyramid 原点(左下角)右侧的列号减一乘以水平偏移距离.

我不是Unity程序员,这是为C#WinForms编写的,但我确信您将能够理解算法和代码.

以下是该计划的核心部分:

private int xOffset = 45;
private int yOffset = 45;
private int cheerleaderRadius = 15;

private int numCheerleaders = 1;

private void MainForm_Paint(object sender, PaintEventArgs e)
{
    // set origin at the bottom left of the form
    Point origin = new Point(cheerleaderRadius * 2, this.ClientRectangle.Height - (cheerleaderRadius*2));
           
    int currentCheerleader = 1;
    int currentColumnNumber = 1;
    int cheerleadersInCurrentColumn;
    while (currentCheerleader <= numCheerleaders)
    {
        cheerleadersInCurrentColumn = 1;
        Point position = new Point(origin.X + (currentColumnNumber - 1) * xOffset, origin.Y);
        while(cheerleadersInCurrentColumn<=currentColumnNumber && currentCheerleader<=numCheerleaders)
        {
            drawCheerleader(e.Graphics, position, (currentCheerleader - 1));
            position.Offset(-xOffset / 2, -yOffset);
            cheerleadersInCurrentColumn++;
            currentCheerleader++;
        }
        currentColumnNumber++;
    }     
}

这就是它在行动中的样子.每次啦啦队员的人数发生变化,下面的 pyramid 就会被重新绘制:

enter image description here

下面是整个C#WinForms程序:

public partial class MainForm : Form
{
    
    private int xOffset = 45;
    private int yOffset = 45;
    private int cheerleaderRadius = 15;

    private int numCheerleaders = 1;
    
    private StringFormat sf = new StringFormat();

    public MainForm()
    {
        InitializeComponent();
        sf.Alignment = StringAlignment.Center;
        sf.LineAlignment = StringAlignment.Center;
        this.Paint += MainForm_Paint;
        this.SizeChanged += MainForm_SizeChanged;
    }

    private void MainForm_SizeChanged(object sender, EventArgs e)
    {
        this.Invalidate();
    }

    private void numericUpDown1_ValueChanged(object sender, EventArgs e)
    {
        numCheerleaders = (int)numericUpDown1.Value;
        this.Invalidate();
    }

    private void MainForm_Paint(object sender, PaintEventArgs e)
    {
        // set origin at the bottom left of the form
        Point origin = new Point(cheerleaderRadius * 2, this.ClientRectangle.Height - (cheerleaderRadius*2));
               
        int currentCheerleader = 1;
        int currentColumnNumber = 1;
        int cheerleadersInCurrentColumn;
        while (currentCheerleader <= numCheerleaders)
        {
            cheerleadersInCurrentColumn = 1;
            Point position = new Point(origin.X + (currentColumnNumber - 1) * xOffset, origin.Y);
            while(cheerleadersInCurrentColumn<=currentColumnNumber && currentCheerleader<=numCheerleaders)
            {
                drawCheerleader(e.Graphics, position, (currentCheerleader - 1));
                position.Offset(-xOffset / 2, -yOffset);
                cheerleadersInCurrentColumn++;
                currentCheerleader++;
            }
            currentColumnNumber++;
        }     
    }

    private void drawCheerleader(Graphics g, Point pos, int number)
    {
        RectangleF rc = new RectangleF(pos, new Size(1, 1));
        rc.Inflate(cheerleaderRadius, cheerleaderRadius);
        g.DrawEllipse(Pens.Black, rc);
        g.DrawString(number.ToString(), this.Font, Brushes.Black, rc, sf);
    }

}

Csharp相关问答推荐

在WPF.NET 6中使用C++/WinRT组件(但实际上是任何WinRT组件)

HttpContext. RequestAborted当Android APP失go 连接时未取消

解析需要HttpClient和字符串的服务

将列表字符串映射为逗号分隔字符串<>

. NET在上一个操作完成之前,在此上下文实例上启动了第二个操作

如何注销Microsoft帐户?

Blazor Foreach仅渲染最后一种 colored颜色

如何在没有额外副本的情况下将存储在IntPtr下的原始图像数据写入WinUI3中的Image控件?

MongoDB.NET-将数据绑定到模型类,但无法读取整数值

如何在不考虑年份的情况下判断日期时间是否在某个日期范围内?

如何解决提交按钮后 Select 选项错误空参照异常

如何使用C#中的主构造函数功能使用多个构造函数?

如何使用XmlSerializer序列化带有CDATA节的XML文件?

C#Null判断处理失败

Linux Docker上的.NET6在某个时间抛出后,在加密操作期间发生System.Security.Cryptography.CryptographicException:错误

同一组件的多个实例触发相同的事件处理程序

为什么我可以在注册表编辑器中更改值,但不能在以管理员身份运行的C#表单应用程序中更改?

Azure队列触发器未使用隔离的工作进程执行

除非首先访问使用的终结点,否则本地API上的终结点不起作用

如何在JSON:API中定义的&过滤查询参数系列&标准的GET请求中传递多个相关参数?