如何不断地对元素进行排序和刷新(例如,电梯目标楼层)
本文关键字:例如 电梯 目标楼 刷新 何不断 元素 排序 | 更新日期: 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层,我推buttonna3
、buttonna4
、buttonna1
。电梯的运行顺序是: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();
}
}
你应该多任务处理,因为如果你同时从列表中删除/插入项目有问题,你可以打破列表,放一些储物柜。