如何不断地对元素进行排序和刷新(例如,电梯目标楼层)

本文关键字:例如 电梯 目标楼 刷新 何不断 元素 排序 | 更新日期: 2023-09-27 18:27:35

我想知道你们中是否有人能帮我完成学校项目。我在WPF做电梯模拟器。它的工作原理很简单,只要按下某个楼层的按钮,电梯就会到达那里。我设法通过使用异步方法进行动画,并像await Task.Delay(10)一样在迭代之间等待来实现动画效果。

我的代码是这样的:

6个按钮位于不同楼层(从4到-1)。每个按钮都在调用animation(x)方法,其中x=按钮所在的楼层。这是按钮4,例如:

        async private void buttonna4_Click(object sender, RoutedEventArgs e)
    {
        animation(4);
    }

因此,从点击这个按钮开始,我们进入animation(x)方法,它看起来像:

public async Task animation(int go_where_from_button)                 
    {
        await semafor.WaitAsync();
        {
            go_where = convert_floor(go_where_from_button);
            try
            {
                if (go_where < Windajo.Margin.Top) //going up
                {
                    for (int i = Convert.ToInt16(Windajo.Margin.Top); i >= go_where; i--)
                    {
                        await gui_elements(i);
                    }
                }
                if (go_where > Windajo.Margin.Top)  //going down
                {
                    for (int i = Convert.ToInt16(Windajo.Margin.Top); i <= go_where; i++)
                    {
                        await gui_elements(i);
                    }
                }
            }
            catch (Exception)
            {
                label.Content = "some exception";
            }
            finally
            {
                semafor.Release();
            }
        }
    }

其中:

SemaphoreSlim semafor = new SemaphoreSlim(1);,我用它来防止电梯同时上下。

go_where是电梯应该走多远直到停下来的转换值(因为我使用边距来确定电梯是否移动到所需楼层)。

await gui_elements(i)是一种方法,我把所有的电梯东西都放在那里,比如电梯本身、门、当前楼层的屏幕等,所以它看起来像:

public async Task gui_elements(int i)
{
Windajo.Margin = new Thickness(Windajo.Margin.Left, i, Windajo.Margin.Right, Windajo.Margin.Bottom);
//OTHER ELEMENTS................
await Task.Delay(10);
}

现在它是这样工作的:假设我们在0层,我推buttonna3buttonna4buttonna1。电梯的运行顺序是:3层->4层->1层。

我的问题是:如何使其正确分拣楼层,以便像普通电梯一样工作?所以在这种情况下,去4楼->3楼->1楼(或1楼->3层->4楼)。例如,当它已经从1楼移动到3楼时,如果有人按下2楼的按钮,它就会做出反应。

我整天都在为此而挣扎。首先,我试图使List()的楼层是所需的,然后Distinct不是唯一的楼层,Sort是它们,但它没有正常工作,因为(我使用foreach,它在执行操作时无法更新列表,至少我是这么认为的)。

有人能告诉我解决这个问题的不复杂和正确的方法吗?

我真的很感激你能提供的任何帮助。

如何不断地对元素进行排序和刷新(例如,电梯目标楼层)

我认为您不应该直接从buttonDown事件调用animation方法。相反,您可以创建输入列表并创建一个Timer,并将所有电梯逻辑放入Timer.Tick处理程序中。

主要思想和主要问题是如何计算下一层(targetFloor)。我建议创建一个输入List<int> inputs的列表,显示是电梯下行还是上行bool IsGoingUp的标志,以及两个内部变量currentFloor和targetFloor,并在用户每次点击按钮时根据方向和输入重新计算目标楼层。

像这样的东西。

    List<int> inputs = new List<int>();
    int currentFloor = 1;
    int targetFloor = 1;
    bool IsGoingUp = true;
    public MainWindow()
    {
        InitializeComponent();
        System.Windows.Threading.DispatcherTimer timer = new System.Windows.Threading.DispatcherTimer();
        timer.Interval = new TimeSpan(0, 0, 0, 0,100);
        timer.Tick += Timer_Tick;
        timer.Start ();
    }
    private void buttonna4_Click(object sender, RoutedEventArgs e)
    {
        inputs.Add(4);
        // Recalculating target floor based on input
        RecalculateTargetFloor();
    }
    private void Timer_Tick(object sender, EventArgs e)
    {
        DrawAnimation(); // Draw small step of elevator to targetFloor
        if (currentFloor == targetFloor)
            RecalculateTargetFloor();
        //waiting for another tick of timer.
    }

方法CCD_ 19在CCD_ 20和CCD_。它还应该重新计算目标楼层,以便在电梯到达另一个目标楼层时进行处理。

            private void RecalculateTargetFloor()
    {
        if (targetFloor > currentFloor)
        {
            //going up
            GetNextUpperFloor();
            return;
        }
        else if (targetFloor < currentFloor)
        {
            //going down
            GetNextLowerFloor();
            return;
        }
        // Elevator reached target              
        inputs.RemoveAll(x => x == targetFloor);
        if (IsGoingUp)
        {
            // if there is no any floors to go up - go down
            if (!inputs.Any(x => x > currentFloor))
            {
                IsGoingUp = false;
            }
            else
            {
                // or continue journey 
                GetNextUpperFloor();
            }
        }
        else
        {
            if (!inputs.Any(x => x < currentFloor))
            {
                IsGoingUp = true;
            }
            else { GetNextLowerFloor(); }
        }
    }

以及计算下一站的方法

    void GetNextUpperFloor()
    {
        var newTargetFloors = inputs.Where(x => x < targetFloor && x > currentFloor);
        if (newTargetFloors.Any())
        {
            targetFloor = newTargetFloors.Min();
        }
        else if (inputs.Any(x => x > currentFloor))
        {
            targetFloor = inputs.Where(x => x > currentFloor).Min();
        }
    }
    void GetNextLowerFloor()
    {
        var newTargetFloors = inputs.Where(x => x > targetFloor && x < currentFloor);
        if (newTargetFloors.Any())
        {
            targetFloor = newTargetFloors.Max();
        }
        else if (inputs.Any(x => x < currentFloor))
        {
            targetFloor = inputs.Where(x => x < currentFloor).Max();
        }
    }

你应该多任务处理,因为如果你同时从列表中删除/插入项目有问题,你可以打破列表,放一些储物柜。

相关文章: