C# - Peek Queue over time Without timer. Is it possible? - c#

My current code is inside a timer to keep comparing if all drones actual position is near desired position but I dont think this is the best approach because I think this leads to slow processing.
Is there a way to check if the actual position is near desired position without using peek inside a timer?
private void timer_missao_Tick(object sender, EventArgs e)
{
string[] pontos_separados = null;
for (int k = 0; k < drone.Length; k++)
{
if (queue[k].Count > 0)
{
if (queue[k].Peek() == "levantar")
{
drone[k]._droneClient.FlatTrim();
drone[k]._droneClient.Takeoff();
drone[k].subir_ate_altura = true;
queue[k].Dequeue();
}
else if (queue[k].Peek().Split(null)[0] == "goto")
{
pontos_separados = queue[k].Peek().Split(null)[1].Split(',');
drone[k].posicao_desejada = new PointF(Convert.ToSingle(pontos_separados[0]), Convert.ToSingle(pontos_separados[1]));
int precisao = 5;
if (drone.All(d=> d.pos_atual().X > d.pos_desej().X - precisao && d.pos_atual().X <d.pos_desej().X + precisao &&
d.pos_atual().Y > d.pos_desej().Y - precisao && d.pos_atual().Y < d.pos_desej().Y + precisao))
{
for (int i = 0; i < drone.Length; i++)
{
queue[i].Dequeue();
}
}
}
else if (queue[k].Peek() == "aterrar")
{
drone[k]._droneClient.Land();
if (drone[k]._droneClient.NavigationData.State == NavigationState.Landed)
{
queue[k].Dequeue();
}
}

You could do the check only when the drone positions are updated, and not on every tick. That way you can also skip the Peek, by having the code that updates the drone position pass the updated Drone object to your check function.

Related

Checking if all objects of an array is active at the same time Unity C#

I've tried to make a script that if all the lights in my scene tagged "Light" are active at the same time, the game proceeds. None of the answers I've found have helped so far. I always end up with it only scanning the active objects, just randomly jumping out of the loop, or stopping when it has found one object that's active. Here is a simple piece of code that should have worked according to other posts
void Update()
{
bool allActive = false;
GameObject[] allLights = GameObject.FindGameObjectsWithTag("Light");
if(currenObjective > 0 && currenObjective < 3)
{
for (int i = 0; i < allLights.Length; i++)
{
if (allLights[i].activeInHierarchy)
{
allActive = true;
break;
}
}
if (allActive)
{
currentObjective = 2;
}
}
}
This code just sets the allActive variable to true at the moment one light is turned on.
You would need to invert the check:
private void Update()
{
// Since Find is always a bit expensive I would do the cheapest check first
if(currenObjective > 0 && currenObjective < 3)
{
var allLights = GameObject.FindGameObjectsWithTag("Light");
var allActive = true;
for (int i = 0; i < allLights.Length; i++)
{
if (!allLights[i].activeInHierarchy)
{
allActive = false;
break;
}
}
if (allActive)
{
currentObjective = 2;
}
}
}
Or You can do this in one line using Linq All
using System.Linq;
...
private void Update()
{
// Since Find is always a bit expensive I would do the cheapest check first
if(currenObjective > 0 && currenObjective < 3)
{
var allLights = GameObject.FindGameObjectsWithTag("Light");
if (allLights.All(light => light.activeInHierarchy))
{
currentObjective = 2;
}
}
}
As a general note: You should avoid using FindGameObjectsWithTag every frame! Either store these references ONCE at start, or if you spawn more lights on runtime implement it event driven and add the newly spawned lights to a list and then use that list to check.
If i understant you want to know if all objects are active:
using Linq does the job
you have to add using system.Linq to your script.
GameObject[] allLights = GameObject.FindGameObjectsWithTag("Light");
bool result = allLights.All(p => p.activeInHierarchy);
you could simplify your code like this:
private void Update()
{
if(currenObjective > 0 && currenObjective < 3 && GameObject.FindGameObjectsWithTag("Light").All(p => p.activeInHierarchy))
{
currentObjective = 2;
}
}
As says derHugo, FindGameObjectsWithTag is very expensive in each frame...

C# - Return true if all comparisons are true

I have a queue[i] for each drone[i].
MY QUESTION: How can make a code that waits for each drone[i].actual_position == drone[i].desired_position instead of my current code that only waits if the current drone drone[i]desired_position == drone[i].actual_position
So instead of this:
for (int i = 0; i < drones.Length; i++)
{
queue[i].Enqueue(drone[i].desired_position);
if (drone[i]desired_position == drone[i].actual_position)
{
queue[i].Dequeue();
queue[i].Enqueue(next_desired_position);
}
}
I want something like this:
for (int i = 0; i < drones.Length; i++)
{
queue[i].Enqueue(drone[i].desired_position);
//TODO: what should I put into "if"?
if (/* all drone[i]desired_position == drone[i].actual_position */)
{
queue[i].Dequeue();
queue[i].Enqueue(next_desired_position)
}
}
TLDR: I want to make sure every drone is in his desired position before dequeue and go to the next position so the drones are syncronized.
It seems that you're looking for an All Linq command as well as for loop and if swapped:
// If all drones are at their expected positions
if (drone.All(d => d.desired_position == d.actual_position))
// then set new goals for each drone:
for (int i = 0; i < drone.Length; ++i) {
// remove the target achieved
queue[i].Dequeue();
// but add a new location to go
queue[i].Enqueue(next_desired_position)
}
I guess what you´re lookging for is Linq´s All-method:
var allOkay = drones.All(d => d.desired_position == d.actual_position);
if(allOkay)
{
foreach(var drone in drones)
drone.Dequeue();
}

For-Loop index gets reset to 0 after nested While-Loop

As a coding execise, I'm working on a visualisation of different sorting algorithms. I have a button that pauses the algorithm and shows every item of the array as a bar-diagramm. To achive this, I have a nested while-loop inside of the two for-loops for the sorting. It loops throug, until I press the button again, a boolean variable gets set to true and the sorting continues.
However, after the programm exits the while loop, the two indecies of the for-loops (i and j) get reset to 0 and the sorting starts from the beginning again.
swap() and draw() are custom functions that do pretty much exactly what the name suggests.
Here's my code for the sorting:
for (i = 0; i < items.Count(); i++)
{
for (j = 0; j < items.Count() - 1 - i; j++)
{
//lbl_i.Text = Convert.ToString(i);
//lbl_j.Text = Convert.ToString(j);
if (items[j] > items[j + 1])
{
swap(j, j + 1); //swaps the items at two given indecies
draw(); // draws the array to the picturebox
}
while (sorting == false) //the sorting is paused
{
Application.DoEvents();
}
}
}
Any idea why this could happen?
I have a suspition that it could be a problem with the Application.DoEvents()-call, but I need that so I can press the button.
Also, if you notice anything else in my code that I could do better, please let me know, I'm not very experienced at coding, so any help and constructive criticism is welcome. :-)
Thank You!
Benjamin
You don't create i and j in the for-loops, i and j might get changed somewhere else in your app. Try this:
for (int i = 0; i < items.Count(); i++)
{
for (int j = 0; j < items.Count() - 1 - i; j++)
{
//lbl_i.Text = Convert.ToString(i);
//lbl_j.Text = Convert.ToString(j);
if (items[j] > items[j + 1])
{
swap(j, j + 1); //swaps the items at two given indecies
draw(); // draws the array to the picturebox
}
while (sorting == false) //the sorting is paused
{
Application.DoEvents();
}
}
}
The change is in: int i, int j
Found the answer: The problem was, that I was calling this function from the same button in the first place. In its click-event, I have an if-statement to check if the button said "Pause" or "Start", but when i paused the programm, it said "Start" again. So when I click it, the function gets called again and int i and int j are reinitialised to 0.
Code in the click-event:
private void btn_start_Click(object sender, EventArgs e)
{
//new added code
if (btn_start.Text == "Start")
{
btn_start.Text = "Pause";
sorting = true;
sort();
}
else if (btn_start.Text == "Pause")
{
btn_start.Text = "Continue"; // '= "Start"' in the old code
tmr_sorting.Stop();
sorting = false;
}
// new added code
else if (btn_start.Text == "Continue")
{
btn_start.Text = "Pause";
sorting = true;
}
}

index out of range on board game last square

I am creating a board game for an assignment and I am almost complete, however the player tokens keep going past the last square and causing an error. Here is the method I am calling to move the tokens on the board:
private void Move(int numberOfSquares) {
for (int i = 0; i < numberOfSquares; i++) {
if (Location.NextSquare == null) {
location = this.Location;
} else {
location = location.NextSquare;
}
}
In the first if statement I want the token location to remain unchanged if the nextsquare value is beyond the final square. Any thoughts on how I can fix this?
you need to change the code to:
private void Move(int numberOfSquares) {
for (int i = 0; i < numberOfSquares; i++) {
if (location.NextSquare == null) {
break;
} else {
location = location.NextSquare;
}
}

Listbox For statement not looping through listboxs

4th time asking this question after trying to apply so fixes. My problem is I have 2 listboxs one holds IDs and the other holds Cell ids. The ID listbox has 10 items (for testing) and Cell boxes have 5 ID. I'm trying to process listId and listCell at the same time creating update links...
example MakeReq will create txtWebUpdate.Text listID listCell &ire=1, in which is
store.domain.com/101/sec01&ire=1
store.domain.com/102/sec02&ire=1
store.domain.com/103/sec03&ire=1
store.domain.com/104/sec04&ire=1
store.domain.com/105/sec05&ire=1
store.domain.com/106/sec01&ire=1 <- notice how listCell starts over it
continues to loop applying sections until the ListID is complete.
here's the code i've been working with. what's happening with my code is that it's only selecting the first item. It's not going to the next item after its done.
if (listId.Items.Count != 0 && listCell.Items.Count != 0)
{
for (int a = 0; a < listId.Items.Count; a++)
{
for (int b = 0; b < listCell.Items.Count; b++)
{
lblID.Text = listId.Items[a].ToString();
MakeReq(txtWebUpdate.Text + listId.Items[a].ToString() +
"&ire=1", listCell.Items[b].ToString());
//System.Threading.Thread.Sleep(5);
}
}
}
Please only comment if you can help. I'm almost positive that the problem is the for statement and how it's selecting list items, but I may be wrong.
Edit More Info: after testing an example/suggestion for #duffp below the problem is definitely with my For statements. What's happening is its counting that I have 5 entries in ListCell and then output one (the same) ListID 5times but with a different ListCell. Can someone help me write it following what I wrong above?
It may have something to do within the MakeReq method call. I just tried the following code:
private void Form1_Load(object sender, EventArgs e)
{
if (listId.Items.Count != 0 && listCell.Items.Count != 0)
{
for (int a = 0; a < listId.Items.Count; a++)
{
for (int b = 0; b < listCell.Items.Count; b++)
{
lblID.Text = listId.Items[a].ToString();
MakeReq(listId.Items[a].ToString(), listCell.Items[b].ToString());
}
}
}
}
public void MakeReq(string listId, string cellId)
{
Console.WriteLine("store.domain.com/" + listId + "sec01&ire=" + cellId);
}
And it gave the output:
store.domain.com/ID_10sec01&ire=Cell_1
store.domain.com/ID_10sec01&ire=Cell_2
store.domain.com/ID_10sec01&ire=Cell_3
store.domain.com/ID_10sec01&ire=Cell_4
store.domain.com/ID_10sec01&ire=Cell_5
store.domain.com/ID_10sec01&ire=Cell_6
store.domain.com/ID_10sec01&ire=Cell_7
store.domain.com/ID_10sec01&ire=Cell_8
store.domain.com/ID_10sec01&ire=Cell_9
store.domain.com/ID_10sec01&ire=Cell_10
Isn't that what you wanted?
I think there might be some side-effects in MakeReq that you are not showing us. How about adding some debug statements to your code, like this:
if (listId.Items.Count != 0 && listCell.Items.Count != 0)
{
for (int a = 0; a < listId.Items.Count; a++)
{
int listCellCount = listCell.Items.Count;
for (int b = 0; b < listCell.Items.Count; b++)
{
lblID.Text = listId.Items[a].ToString();
MakeReq(txtWebUpdate.Text + listId.Items[a].ToString() +
"&ire=1", listCell.Items[b].ToString());
//System.Threading.Thread.Sleep(5);
Debug.Assert(listCellCount == listCell.Items.Count);
}
}
}
The assertion (listCellCount == listCell.Items.Count) should always be true, unless something is changing listCell.Items.

Categories

Resources