Визуализация работы лифта
У меня есть задача визуализировать и оптимизировать работы лифта ( оптимизацией еще не занимался) Код для работы лифта полностью готов, но неправильно работает. В одной строке производятся неправильные вычисления, и как их починить я не знаю.
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public double time = -0.1;
double time2 = 0;
int lambda;//переменная для Пуассоновского потока
double threshold;
Random rand = new Random();
int floor = 1 , target = 1;
int wght, flrs;
List<string> elevator = new List<string>();//список для пассажиров лифта
List<string> pass = new List<string>();//список потенциальных пассажиров появлющихся на этажах
char name = 'A';
public Form1()
{
InitializeComponent();
flrs = (int)numericUpDown2.Value;
wght = (int)numericUpDown1.Value;
dataGridView1.RowCount = flrs;
for (int i = 0; i < flrs; i++)
{
dataGridView1[0, i].Value = flrs - i;//рисование количества этажей(изначально)
pass.Add(" ");
}
trackBar2.Value = 10;
}
void PosPrepare(int lambda)
{
threshold = Math.Exp(-lambda);// для Пуассоновского потока
}
int PosNext()// для Пуассоновского потока
{
int next = 0;
for (double k = rand.NextDouble(); k > threshold; next++)
k *= rand.NextDouble();
return next;
}
void draw_passangers(int index)//отрисовка пассажиров на этажах
{
string s = "";
foreach (char p in pass[index])
s += " " + p;
dataGridView1[2, flrs - 1 - index].Value = s;
}
void draw_elevator()// отрисовка лифта
{
string s = "[ ";
foreach (string p in elevator)
s += p;
dataGridView1[1,flrs - floor].Value = s + "]";// ломается здесь
}
private void timer2_Tick(object sender, EventArgs e)// Пкссоновский поток для 1 этажа
{
time += timer2.Interval / 1000.0;
if(pass.Count!=0)
for (int j = 0; Math.Abs(time - time2) < 1e-10 || time > time2; j++)
{
if (j == 100) { trackBar2.Value++; return; }
int next = PosNext();
double delta = next * timer2.Interval / 1000;
time2 = time + delta;
int d = rand.Next(2, 10);
pass[0] += name + Convert.ToString( d);//
draw_passangers(0);
if (name == 'Z') name = 'A'; else name++;
timer2.Stop();
Application.DoEvents();
timer2.Start();
}
}
private void timer3_Tick(object sender, EventArgs e)// Пуассоновский поток для отсальных этажей
{
time += timer3.Interval / 1000.0;
for (int j = 0; Math.Abs(time - time2) < 1e-10 || time > time2; j++)
{
if (j == 100) { trackBar2.Value++; return; }
int next = PosNext();
double delta = next * timer3.Interval / 1000;
time2 = time + delta;
int fi = rand.Next(1, pass.Count);
int d = (rand.Next(10) == 0) ? rand.Next(2, 10) : 1;
//pass.Insert(fi, name + Convert.ToString(d));
pass[fi] +=(name + Convert.ToString(d));
draw_passangers(fi);
if (name == 'Z') name = 'A'; else name++;
timer3.Stop();
Application.DoEvents();
timer3.Start();
}
}
private void trackBar1_Scroll(object sender, EventArgs e)// скорость лифта
{
timer1.Interval = trackBar1.Value;
}
private void Button2_Click(object sender, EventArgs e)
{
flrs = (int)numericUpDown2.Value;
wght = (int)numericUpDown1.Value;
dataGridView1.RowCount = flrs;
pass.Clear();
for (int i = 0; i < flrs; i++)
{
dataGridView1[0, i].Value = flrs - i;
pass.Add(" ");
}
}
private void Button1_Click(object sender, EventArgs e)
{
if (button1.Text == "Старт")
{
button1.Text = "Пауза";
timer1.Start();
timer2.Start();
timer3.Start();
}
else
{
timer1.Stop();
timer2.Stop();
timer3.Stop();
button1.Text = "Старт";
}
}
private void trackBar2_ValueChanged_1(object sender, EventArgs e)// скорость спавна людей
{
lambda = trackBar2.Value;
PosPrepare(lambda);
}
private void timer1_Tick(object sender, EventArgs e)//логика движения лифта
{
if (elevator.Count > 0)
for (int i = 0; i < elevator.Count; i++)
if (elevator[i][0] - '0' == floor)
{
elevator.RemoveAt(i);
i--;
}
dataGridView1[1, (int)numericUpDown2.Value - floor].Value = "";
if (target > floor) floor++;
//if (target > 0) ;
else if (target < floor) floor--;
else // достигнут целевой этаж
{
//if (elevator.Count > 0)
// elevator.RemoveAt(0);
while (elevator.Count < wght && pass.Count() > flrs)/
{
elevator.Add(Convert.ToString(pass[floor - 1][0]));
pass.RemoveAt(0);
draw_passangers(floor - 1);
}
// elevator.Clear();
if (elevator.Count > 0)// лоика движения лифта куда ехать на какаой этаж
{
int dmax = 0, t = 1;
for (int i = 0; i < elevator.Count; i++)
{
{
if (Math.Abs((int)(elevator[i][0] - '0') - floor) > dmax)//неправильные рассчеты тут
{
dmax = Math.Abs((elevator[i][0] - '0') - floor);
t = (elevator[i][0] - '0');
}
}
}
target = t;
}
else
{
for (int i = flrs; i > 0; i--)
if (pass.Count > 0)
{
target = i;
break;
}
}
}
while (elevator.Count < wght && pass.Count > 0)// загрузка пассажиров
{
if (pass[floor] == null) break;
elevator.Add(Convert.ToString(pass[floor - 1]));
pass.RemoveAt(0);
draw_passangers(floor - 1);
}
Application.DoEvents();
draw_elevator();
}
}
}
Ответы (1 шт):
Вот вам небольшой поэтапный пример.
Создайте в решении проект консольного приложения. И начните вот с этого.
class Elevator
{
}
class Program
{
static void Main(string[] args)
{
//у нас есть лифт
var elevator = new Elevator();
}
}
Добавьте лифту положение этажа
class Elevator
{
public int Level { get; private set; }
public Elevator()
{
Level = 1;
}
}
class Program
{
static void Main(string[] args)
{
//у нас есть лифт
var elevator = new Elevator();
//изначально лифт на 1 этаже
Console.WriteLine($"Лифт на этаже: {elevator.Level}");
Console.WriteLine();
Console.ReadLine();
}
}
Теперь добавим лифту состояние
class Elevator
{
public enum States
{
EmptyWaiting
}
public int Level { get; private set; }
public States State { get; private set; }
public Elevator()
{
Level = 1;
}
}
class Program
{
static void Main(string[] args)
{
//у нас есть лифт
var elevator = new Elevator();
//изначально лифт на 1 этаже
Console.WriteLine($"Лифт на этаже: {elevator.Level}");
//лифт пустой в ожидании
Console.WriteLine($"Состояние лифта: {elevator.State}");
Console.WriteLine();
Console.ReadLine();
}
}
Теперь лифту добавим команду на движение и новый тип состояния подъема
class Elevator
{
public enum States
{
EmptyWaiting,
EmptyClimbing
}
public int Level { get; private set; }
public States State { get; private set; }
public Elevator()
{
Level = 1;
}
public void GoTo(int level)
{
State = States.EmptyClimbing;
}
}
class Program
{
static void Main(string[] args)
{
//у нас есть лифт
var elevator = new Elevator();
//изначально лифт на 1 этаже
Console.WriteLine($"Лифт на этаже: {elevator.Level}");
//лифт пустой в ожидании
Console.WriteLine($"Состояние лифта: {elevator.State}");
Console.WriteLine(new string('-', 50));
//поступил вызов с 6 этажа
elevator.GoTo(6);
//лифт поехал, он в движении наверх
Console.WriteLine($"Состояние лифта: {elevator.State}");
Console.WriteLine(new string('-', 50));
Console.WriteLine();
Console.ReadLine();
}
}
Добавим лифту событие изменения его состояния
class Elevator
{
public enum States
{
EmptyWaiting,
EmptyClimbing,
OpenDoorsWaiting
}
public event EventHandler<States> StateChanged;
public int Level { get; private set; }
public States State { get; private set; }
public Elevator()
{
Level = 1;
}
public async Task GoTo(int level)
{
State = States.EmptyClimbing;
StateChanged?.Invoke(this, this.State);
for (int i = 1; i <= level; i++)
{
await Task.Delay(1000);
}
State = States.OpenDoorsWaiting;
StateChanged?.Invoke(this, this.State);
}
}
class Program
{
static void Main(string[] args)
{
//у нас есть лифт
var elevator = new Elevator();
//подпишемся на изменение состояния лифта
elevator.StateChanged +=
(s, e) => Console.WriteLine($"Состояние лифта: {e}");
//изначально лифт на 1 этаже
Console.WriteLine($"Лифт на этаже: {elevator.Level}");
//лифт пустой в ожидании
Console.WriteLine($"Состояние лифта: {elevator.State}");
Console.WriteLine(new string('-', 50));
//поступил вызов с 6 этажа
Console.WriteLine("Лифт поехал на 6 этаж");
elevator.GoTo(6).GetAwaiter().GetResult();
Console.WriteLine("Лифт приехал на 6 этаж и открыл двери");
Console.WriteLine($"Лифт на этаже: {elevator.Level}");
Console.WriteLine(new string('-', 50));
Console.WriteLine();
Console.ReadLine();
}
}
Теперь будем считать этажи во время подъема и вызывать событие изменения этажа
class Elevator
{
public enum States
{
EmptyWaiting,
EmptyClimbing,
OpenDoorsWaiting
}
public event EventHandler<States> StateChanged;
public event EventHandler<int> LevelChanged;
public int Level { get; private set; }
public States State { get; private set; }
public Elevator()
{
Level = 1;
}
public async Task GoTo(int level)
{
State = States.EmptyClimbing;
StateChanged?.Invoke(this, this.State);
for (int i = 1; i <= level; i++)
{
await Task.Delay(1000);
Level = i;
LevelChanged?.Invoke(this, this.Level);
}
State = States.OpenDoorsWaiting;
StateChanged?.Invoke(this, this.State);
}
}
class Program
{
static void Main(string[] args)
{
//у нас есть лифт
var elevator = new Elevator();
//подпишемся на изменение состояния лифта
elevator.StateChanged +=
(s, e) => Console.WriteLine($"Состояние лифта: {e}");
//подпишемся на изменение этажа у лифта
elevator.LevelChanged +=
(s, e) => Console.WriteLine($"Лифт на этаже: {e}");
//изначально лифт на 1 этаже
Console.WriteLine($"Лифт на этаже: {elevator.Level}");
//лифт пустой в ожидании
Console.WriteLine($"Состояние лифта: {elevator.State}");
Console.WriteLine(new string('-', 50));
//поступил вызов с 6 этажа
Console.WriteLine("Лифт поехал на 6 этаж");
elevator.GoTo(6).GetAwaiter().GetResult();
Console.WriteLine("Лифт приехал на 6 этаж и открыл двери");
Console.WriteLine($"Лифт на этаже: {elevator.Level}");
Console.WriteLine(new string('-', 50));
Console.WriteLine();
Console.ReadLine();
}
}
В конечном счете результ работы такой
Теперь можно переходить к программе Windows Forms. Скопируйте в этот проект наш класс Лифта, добавьте коллекции картинок, напишите следующий код.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.Load += Form1_Load;
}
private void Form1_Load(object sender, EventArgs e)
{
_pictureBoxLevel.Image = _imageListLevels.Images[0];
_pictureBoxState.Image = _imageListStates.Images[0];
_buttonInvoke.Click += ButtonInvoke_Click;
}
private async void ButtonInvoke_Click(object sender, EventArgs e)
{
this.Form1_Load(this, EventArgs.Empty);
await Task.Delay(500);
var elevator = new Elevator();
elevator.StateChanged += Elevator_StateChanged;
elevator.LevelChanged += Elevator_LevelChanged;
if (int.TryParse(_textBoxLevel.Text, out int level)
&& level > 1
&& level <= 9)
{
await elevator.GoTo(level);
}
}
private void Elevator_LevelChanged(object sender, int e)
{
_pictureBoxLevel.Image = _imageListLevels.Images[--e];
}
private void Elevator_StateChanged(object sender, Elevator.States e)
{
switch (e)
{
case Elevator.States.EmptyWaiting:
_pictureBoxState.Image = _imageListStates.Images[0];
break;
case Elevator.States.EmptyClimbing:
_pictureBoxState.Image = _imageListStates.Images[1];
break;
case Elevator.States.OpenDoorsWaiting:
_pictureBoxState.Image = _imageListStates.Images[2];
break;
default:
break;
}
}
}
Получилось так
Конечно этот пример еще очень далек от нужного результата, но я хотел вам показать сам принцип, как такое задание можно выполнить.

