How to classify an undefined vector list item? - c#

I understand that an undefined vector3 = default(vector3), but what about a vector list item that does not exist? For example:
List<Vector3> stuff = new List<Vector3>();
for(int i=1; i<10; i++){
stuff.add(new Vector3(0 + i, 0, 0));
}
In this case what would stuff[15] be considered? I know it is undefined, but lets say that you did not know if it's defined or not. How would you find out if it was? Like, if stuff[15] is undefined print("stuff[15] is undefined") and break.

Assuming you are asking if your code will be able to access stuff[15], no.
The reason for this is because you only add 10 elements to it, each of type vector.
List<Vector3> stuff = new List<Vector3>();
for (int i = 0; i < 10; i++) {
stuff.add(new Vector3(0 + i, 0, 0));
}
This code will add a new Vector 10 times with the positions given, where the first parameter is 0 + i. Since there are only 10 elements, stuff[15] will not be accessed, and will throw an ArrayOutOfBoundsException.
To safely check if an array can contain a 15th element, use an if statement
if (stuff.Length > 15) {
stuff[15]; // will only be called if an element exists
}

I figured out the answer partly thanks to Frontear's answer.
List<Vector3> stuff = new List<Vector3>();
for(int i=1; i<10; i++){
stuff.add(new Vector3(0 + i, 0, 0));
}
if(15 > stuff.Count ){
print("stuff[15] is undefined")
break;
}
So, all undefined list items are obviously out of the range of the number of defined list items and, therefore, to find out if a list item is undefined just compare it's number to the number of defined list items.
I suppose it was a very simple answer, I just thought there was a word that you could set the defined/undefined list item equal to to get a boolean value representing if it was defined or not; like stuff[15]==undefined. Apparently not...

Related

How to uodate array inside a for loop and add it to a list

I am trying to update an array and add it to a list if a certain condition is true. As you can see in my code the array "rows" is updated every time inside the if condition, and the it is added to "checkList".
The problem is that when I iterate through the list to check the values, it seems that only the last value of rows has been added in every entry in the list.
Here is some code to explain
int[] rows = new int[2];
List<int[]> checkList = new List<int[]>();
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
if (true)
{
rows[0] = i;
rows[1] = j;
checkList.Add(rows);
}
}
}
foreach (var row in checkList)
{
Console.WriteLine(row[0] + " " + row[1]);
}
Output:
I hope someone can explain this. Thanks
Most object types in .NET (including arrays) are passed by reference, so checkList.Add(rows); adds a reference to the same array to the list, multiple times.
Instead, you'll want to create a new array instance every time:
List<int[]> checkList = new List<int[]>();
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
if (true)
{
checkList.Add(new int[]{ i, j });
}
}
}
I believe the issue here is that when you are
checkList.Add(rows);
You are adding a reference to the rows array every time to the list, not a separate copy of it. This leads to your current behaviour.
A solution would be to instantiate the array inside the loop, so a new array is created every iteration.
List<int[]> checkList = new List<int[]>();
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
if (true)
{
int[] rows = new int[2];
rows[0] = i;
rows[1] = j;
checkList.Add(rows);
}
}
}
As a supplement to Matthias answer, one of the things that's perhaps not easy to appreciate about C# is that most variables you have and use are merely a reference to something else. When you assign some variable like this:
int[] rows = new int[2];
C# creates some space in memory to keep an array of 2 integers, it attaches a reference to it, and that thing becomes your variable that you use, named rows. If you then do:
int[] rows2 = rows;
It doesn't clone the memory space used and create a new array, it just creates another reference attached to the same data in memory. If the data were a dog, it now has 2 leads attached to its collar but there is still only one dog. You can pull on either lead to urge the dog to stop peeing on a car, but it's the same dog you're affecting.
Array/list slots are just like variables in this regard. To say you have:
List<int[]> checkList = new List<int[]>();
Means declare a list where each of its slots are a variable capable of referring to an int array. It's conceptually no different to saying:
int[] checkList0 = row;
int[] checkList1 = row;
int[] checkList2 = row;
int[] checkList3 = row;
It's just that those numbers are baked into the name, whereas a list permits you a way of varying the name programmatically (and having more than 4 slots):
checkList[0] = row;
checkList[1] = row;
checkList[2] = row;
checkList[3] = row;
checkList[0] is conceptually the entire variable name, just like checkList0 is a variable name, and remember that this is hence just another variable that is just a reference to that same array in memory.
By not making a new array each time, you attached every variable slot in the list to the same array in memory, and thus you ended up with something in memory that looks like:
The black is the list, the blue is the array. Every list slot is just a reference to the same array. You might have changed the numbers in the array 200 times, but at the end of the oepration, because there was only ever one array, you only see the final set of numbers you wrote into the array. You might have attached 20 leads to your dog and pulled each of them once, but it's still just the same dog that has 20 times been stopped from peeing on 20 cars.
Matthias answer works (and is how it should be done) because you concretely make a new array each time
Numbers in blue are fabricated and not intended to represent the answers you should see printed; the concept being explained is that of linking to new array objects in memory
You'd be forgiven for thinking that a clone would be made, bcause it is for int. int is a value type, whcih means the value is copied when it's used:
int x = 1;
int y = x;
y = y + 1;
y is now 2, but x is still 1. It'd be pretty hard work to write C# if it wasn't this way i.e. if every time you incremented some int variable, every other variable that had touched the variable that it came from was also affected.. So I think it's perhaps intrinsically reasonable to assume that whenever an assignment of anything is made, changes that affect the value of the assigned variable don't affect earlier iterations of it.. but that's not the case. There's this clear divide between value types (types whose data is copied/cloned when they're assigned) and reference types (types whose data is not copied/cloned). While int is a value type (cloned), an int[] is a reference type (not cloned)
..and that's something you'll really need to get down with and remember
Roll on the what's ref/out for? query :D

A for loop somehow overrides an entire array, even though I can see no reason for that

So, been looking at this code for a good while now, and I am lost.
The point is to run a for loop that adds classes to an array, and then for each class runs through an array of points inside of that class, and add variations to it.
This then shows as a bunch of dots on a form, which are supposed to move independently of each other, but now follows each other completely.
It does not matter how much variation there is or anything, it's just 99 dots with the exact same acceleration, velocity, and location, and path.
The code is here, the method isn't touched by any other code, and the problem arises before it returns.
//Point of the method is to put variations of Baby into an array, and return that array
Dot.Class[] MutateAndListBaby(Dot.Class Baby)
{
//Making the empty array
Dot.Class[] BabyList = new Dot.Class[dots.Length];
//For loop that goes through through the whole array
for (int i = 1; i < BabyList.Length; i++)
{
//For each itteration the for loop adds the class reference to the index, then puts the standard directions into that reference, and then sets a value preventing it from being changed in another code
BabyList[i] = new Dot.Class();
BabyList[i].Directions = Baby.Directions;
BabyList[i].StartupComplete = true;
//The zero index variation when made like this, allows it to not be overriden, which would lead one to believe that how the directions are copied is he problem
//But it shouldn't be, BabyList[i].Directions = Baby.Directions; should be fire and forget, it should just add the Directions to the array and then leave it
BabyList[0] = new Dot.Class();
BabyList[0].Directions = new PointF[100];
for (int b = 0; b < BabyList[0].Directions.Length; b++)
{
BabyList[0].Directions[b] = new Point (5, 10);
}
BabyList[0].StartupComplete = true;
//The for loop that shuld add variation, but it seems like it somehow overrides it self, somehow
for (int b = 0; b < BabyList[i].Directions.Length; b++)
{
if (rand.Next(0, 101) >= 100)
{
int rando = rand.Next(-50, 51);
float mod = (float)rando / 50;
float x = BabyList[i].Directions[b].X;
x = x + mod;
BabyList[i].Directions[b].X = rand.Next(-5, 6);
}
if (rand.Next(0, 101) >= 100)
{
int rando = rand.Next(-50, 51);
float mod = (float)rando / 50;
float y = BabyList[i].Directions[b].Y;
y = y * mod;
BabyList[i].Directions[b].Y = rand.Next(-5, 6);
}
}
//Now one would assume this would create a unique dot that would move 100% independently right? Since it's at the end of the for loop, so nothin should change it
// Nope, somehow it makes every other dot copy its directions...
if (i == 5)
{
for (int b = 0; b < BabyList[5].Directions.Length; b++)
{
BabyList[5].Directions[b] = new PointF(-5f, -5f);
}
}
}
return BabyList;
}
}
}
With the code there, what I get is the 0 index dot going its own way, while the other 99 dots for some reason follow the 5th index's Directions, even though they should get their own variations later on in the code.
Any help would be much appreciated, it probarbly something obvious, but trust me, been looking at this thing for quite a while, can't see anything.
If I understand you correctly, this might be the issue:
BabyList[i].Directions = Baby.Directions;
Directions is of type array of PointF - a reference. The line above does not copy the array. Is that what you assume? If I'm not misreading the code you're presenting, you're creating one Dot.Class with its own array of PointF at index 0 and fill the rest of your Dot.Class array with instances that share one single array.
Directions is array, which is a reference type. When you're making assigment of a variable of this type
BabyList[i].Directions = Baby.Directions;
no new instance is created and reference us just being copied into new variable which still references original instance. Essentially in your loop only very first item gets a new instance of Directions as it's explicitly constructed. The rest share the instance which comes as a member of parameter passed to the method.
You probably want to change your if conditions:
(rand.Next(0, 101) >= 100
to
(rand.Next(0, 100) < 99
This will run an average of 99 times out of 100, whereas your current condition runs 1 out of 101 times (on average)
Oh, and Benjamin Podszun's answer about assigning the same array (not a copy of the same array) to Directions apply as well!
(Assuming that Directions isn't a getter that you created to return a copy of an array instead of a reference!)

Getting all the possible distances between points

I have created a program to spawn a number of points (the number is given by the user).
Therefore the program spawns N points
see the image for an example, it has 3 points in that case
What I need is to get all the possible distances between those villages (In the example it's distance: AB, AC, BC).
The points are stored in a single array (that scores x-coordinate and y-coordinate)
List<Villages>
I know that I new Pythagoras Theorem, I just cannot get the foreach loop right.
I would think you would want a regular nested for-loop rather than foreach.
Something like this should work:
for (int i = 0; i < villageList.Count; ++i)
{
for (int j = i + 1; j < villageList.Count; ++j)
{
distanceFunc(villageList[i], villagelist[j]);
}
}
Where distanceFunc is whatever implementation of a distance function you want to use and villageList is your List of villages.
The reason you would use for-loops is because you need the inner loop to start one element past the the outer loop (i + 1), and foreach loops don't let you easily access the index you're currently at (they let you access the element itself, but not easily see it's position in the array).
You need two for loops:
var villages = new List<Villages>() { ... };
for (int i = 0; i < villages.Count - 1; i++)
for (int j = i + 1; j < villages.Count; j++)
Console.WriteLine(getDistance(villages[i], villages[j]));
Where getDistance you should write yourself. It should return a distance between two specified Villages.
How about something like this pseudocode:
villages = [a, b, c, ...]
for i=0 to len(villages)-2:
for j=i+1 to len(villages)-1:
print(villages[i], villages[j], dist(villages[i], villages[j]))

Argument out of range exception

Can anyone tell me why I am getting this exception? Well I know "why" I am getting it is cause it says that the element in the list I am trying to access does not exist, but stepping through the code I can see that it actually does exist?
In Game1 I call a helper class' calculation method. Then when the calculation is done, I add the result to a List<> in the CalculationHelper class.
The code for this looks like:
In Game1 class where I have instanciated CalculationHelper calcHelper class and then call one of the class methods.
Fisrt, in Game1 I call calcHelper.ForceVanishingPointIntersections(...) method in a for() loop which can be seen below. This works just fine and the calcHelper.ForceVanishingPointIntersections(...) method adds the value to the IntersectionPointList<> in the CalculationHelper class (see method below).
for (int i = 0; i < LineList.Count; i++)
{
calcHelper.ForceVanishingPointIntersections(LineList[i], LineList[i + 1]);
AddSprite(VanishingPointIntersectionList, calcHelper.GetIntersectionPointListElementAt(i), greenCirlce);
i++;
}
To do some calculations and add a value to the IntersectionPointlist in CalculationHelper class I do:
List<Vector2> IntersectionPointList = new List<Vector2>();
public void ForceVanishingPointIntersections(Line line1, Line line2)
{
Vector2 intersectionPoint;
// Do some calculations
IntersectionPointList.Add(intersectionPoint);
}
Finally in Game1 class, the second method in the for() loop I call AddSprite to create a Sprite. I want to pass in the values stored in CalculationHelper class IntersectionPointList as coordinates for the Sprite.
To this end I call calcHelper.GetIntersectionPointListElementAt(i) which calls a method in CalculationHelper class like so (which should return the value at the specified point (i) from the IntersectionPointList<>)
public Vector2 GetIntersectionPointListElementAt(int index)
{
Vector2 result = this.IntersectionPointList[index];
return result;
}
The first time the for() loop executes, this works fine. I do the calculations, the value is stored in the list and I am able to get this value from the list and pass it to AddSprite(..). However, the second time round the for() loop, when I call GetIntersectionPointListElementAt from the AddSprite() method, I get an exception in my
public Vector2 GetIntersectionPointListElementAt(int index)
{
Vector2 result = this.IntersectionPointList[index]; // Exception thrown here
return result;
}
saying the index was out of range? But stepping through the code, my IntersectionPointList is updated and it shows that the list now contains 2 values. And I'm trying to access the second value.
Does anyone have an idea why this could be?
For the life of me I cant figure out where I am going wrong.
If more code is needed I can post some more, just let me know
Because you access LineList[] with an index i + 1 you must diminish the last index by one in the for-condition. (Note the -1)
for (int i = 0; i < LineList.Count - 1; i++) {
calcHelper.ForceVanishingPointIntersections(LineList[i], LineList[i + 1]);
AddSprite( ... );
}
This will call ForceVanishingPointIntersections with the indexes
(0, 1), (1, 2), (2, 3), ... (Count-2, Count-1)
Note that the index range of LineList is 0 ... Count-1.
If non-overlapping indexes are required instead, like
(0, 1), (2, 3), (4, 5), ... (Count-2, Count-1)
then change the loop to
for (int i = 0; i < LineList.Count - 1; i += 2) {
calcHelper.ForceVanishingPointIntersections(LineList[i], LineList[i + 1]);
AddSprite(
VanishingPointIntersectionList,
calcHelper.GetIntersectionPointListElementAt(i / 2),
greenCirlce);
}
EDIT According the Chris Gessler's comments this second approach is the right one.
Remove the i++ inside the loop, it's quite uncommon and confusing. Instead, replace it by i += 2 in loop header.
Also note that (again according to Chris Gessler) IntersectionPointList has half as much items as LineList. Therefore call GetIntersectionPointListElementAt with i / 2. Since i is {0, 2, 4, ... }, i / 2 is {0, 1, 2, ...}.
The for-loop allows you to have a comma-separated list of statements in the first and third section. You could use it to maintain two indexes
for (int i = 0, k = 0; i < LineList.Count - 1; i += 2, k++) {
calcHelper.ForceVanishingPointIntersections(LineList[i], LineList[i + 1]);
AddSprite(
VanishingPointIntersectionList,
calcHelper.GetIntersectionPointListElementAt(k),
greenCirlce);
}
for (int i = 0; i < LineList.Count; i++)
{
calcHelper.ForceVanishingPointIntersections(LineList[i], LineList[i + 1]);
...
i++;
}
Instead of doing that, you should do:
for (int i = 0; i < LineList.Count; i += 2)
{
calcHelper.ForceVanishingPointIntersections(LineList[i], LineList[i + 1]);
...
}
And if LineList.Count isn't even, for example: 3.
It will start at 0, you use 0 and 1.
Then it jumps to 2, you use 2 and 3.
But oops! there isn't 3!
Only count 3! 0 to 2!
Thats when you'll get argument out of range exception.
To avoid that, you can either check if Count % 2 == 0, or you can go until LineList.Count - 1, if you don't mind skipping extra's if there are.
It looks like you're adding two lines per one Sprite. The indexes won't line up. When LineList has 10 items, you will only have 5 IntersectionPointList items, so passing in an index of 9 will fail.
You should change your LineList collection to List<Tuple<string,string>> so that you have two lines per item which will line up with each Sprite. This will create a one-to-one relationship between Lines and Sprites.
I suppose you could always pass in an index (i / 2), which should be the correct Sprite for every two lines.

First Element as pivot in Quick sort

Why this code gives me wrong ? In Quick sort , I have picked up the first element as pivot:
I have traced that on paper,nothing is wrong.
private void QuickSort(ref int [] S ,int l,int h)
{
//partioning
int pivot_index = l;
int j = 0;
int temp = 0;
for(int i=l+1;i<=h;i++)
if (S[pivot_index] > S[i])
{
j++;
temp = S[i];
S[i] = S[j];
S[j] = temp;
}
pivot_index = j;
temp = S[l];
S[l] = S[j];
S[j] = temp;
//end partioning
if (l < h && pivot_index>l && pivot_index<h)
{
QuickSort(ref S, l, pivot_index - 1);
QuickSort(ref S, pivot_index + 1, h);
}
}
here is my main :
int[] List = get_input(textBox1.Text, ref n);
//
QuickSort(ref List, 0, n-1);
Your function is apparently supposed to sort [l, h] range in the array, yet for some reason you are swapping element number i with element number j. The latter (j) is out of [l, h] range (it is always initially 0 and then it becomes 1, 2, 3 and so on). What are you trying to do by this? Why are you swapping your elements to some totally unrelated remote location out of your sorting range?
In other words this does not even remotely look like a QuickSort-style sorting algorithm to me. Your unexplainable manipulations with j is one reason why your implementation cannot really sort anything.
Your algorithm is wrong. Get the pivot value int pivot = S[pivot_index];.
Then determine the two elements that you want to swap. Therefore, determine the first element from the left, which is greater than or equal to the pivot value. This gives i. Then determine the first element from the right, which is less than or equal to the pivot value. This gives j. As long as i is less than j swap S[i] and S[j] and repeat the process.
Only after there are no more swaps to make, look if you can call QuickSort recursively. Here two separate if checks must be made for the left part and the right part.
Also, note that it is better to take the element in the middle as pivot element. QuickSort will perform better, if the elements should be pre-sorted or sorted in descending order.
int pivot = S[(l+h)/2];

Categories

Resources