I got an arraylist of rectangles and I want to edit the X & Y values of all of them.
I tried using a foreach loop
foreach (Rectangle rect in rectangles)
rect.X += 1;
But this wouldn't work as it's read-only, so I tried a regular for loop
for (int i = 0; i < rectangles.Count; i++)
rectangles[i].X += 1;
And for some reason this wouldn't work either, because rectangles[i] just doesn't have any of rectangle's methods.
Then I stumbled across a post somewhere on stackoverflow about how to call methods of elements of an arraylist. And I haven't been able to find examples of this, so I hope someone can clear this up.
(Unit.unitArray[selectedUnit] as MyClass).DisplayUnitAttributes()
But I have no idea how to put this to use, I don't understand what Unit is supposed to be replaced with, and I'm guessing MyClass would be Rectangle...
Any help is appreciated!
TLDR: I want to iterate over an arraylist with rectangles, and edit the X & Y values of them.
According to the error you have got. "Return value is not a variable"
Rectangle is not a class. its an struct which is not reference type so you have to assign new value into it.
List<Rectangle> rectangles = new List<Rectangle>();
// rectangles.Add(x); make your list here
for (int index = 0; index < rectangles.Count; index++)
{
Rectangle r = rectangles[index];
r.x += 1;
rectangles[index] = r;
}
It's act like this because ArrayList is not typed. It's better to use a List<T> instead (where T is your class, in your example it will be a Rectangle). Here is MSDN link.
You can't modify object this way in the foreach loop. More info on this SO question.
About this example: (Unit.unitArray[selectedUnit] as MyClass).DisplayUnitAttributes()
It's called casting. You can read more about this on this SO question. So in your code it should looks like this: (rectangles[i] as Rectangle).X += 1;. You also should check if result of this casting is not null etc. But better read previous link to understand this.
Related
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!)
I'm probably not wording the question correctly, so please help me on the nomenclature.
If I have a List<Point> which has a constant set of x values, but a variable stream of y values. Right now I have:
List<DataPoint> points = new List<DataPoint>();
while(...)
{
double data[] = ...
for (int i = 0; i < data.Length; i++)
points.Add(new DataPoint(i, data[i]));
}
But I feel like it should be possible to use LINQ:
points.Select(y => y.AddRange(data));
I don't need to change the x values. Also, I'm asking because I'm trying to increase processing performance on this loop somehow, so if there's a faster way, please enlighten me.
You can use Linq to create all the values you want to add then use AddRange.
var newPoints = data.Select((d,i) => new DataPoint(i, d));
points.AddRange(newPoints);
But please note that this will probably not be any faster than your for loop.
I'm quite new in C# and I want to creating something like falling snow (dots) in C# using Windows Forms.
I was already able to create the snowflakes at the top of the screen (I want to create new dot every 0,1s, at random x-position of Form and write down every snowflake's position into the List(Point) and with every Tick of timer (0,1s) I want the snowflake to change its position by 3px down and 1-3px right)
But I have the problem with refreshing the snowflakes positions. I don't know how to acces each snowflake in the List to Randomize its new position.
I tried foreach, but it gives me error, that says I cannot change variable in foreach.
Example:
foreach (var snowflake in snowflakeList)
{
snowflake.Y += 3;
snowflake.X += moveRandom.Next(1, 4);
}
Can anyone please tell me how can I divide List(Point) of snowflakes into invdividual snowflakes, so I could change position of every single dot separately?
Thank you :-)
The simplest way is just to use the index of the collection:
for (int i = 0; i < snowflakeList.Count; i++)
{
var snowflake = snowflakeList[i];
snowflake.Y += 3;
snowflake.X += moveRandom.Next(1, 4);
snowflakeList[i] = snowflake;
}
As Andrews answer use a for loop, but as the list is of Points (a value type) you would need to reference the Point in the list directly rather than make a copy of it:
for (int i = 0; i < snowflakeList.Count; i++)
{
snowflakeList[i].Y += 3;
snowflakeList[i].X += moveRandom.Next(1, 4);
}
(There's not an actual function where I need this, but I was just wondering.)
Imagine this function where I pass a bool[,]. This bool[,] is named grid1 or grid2, depending on the situation.
I was wondering if I can do anything like the following:
void CheckGrid(bool[,] grid, int number)
{
for (int x = 0; x <= gridXmax - 1; x++)
{
for (int y = 0; y <= gridYmax - 1; y++)
{
if(grid + number[x,y]) //this will check against grid1 or grid2, depending on int number
//logic depends on whether it's grid1 or grid2
}
}
}
Guessing by the questions for other languages, it probably isn't possible. But you never know :)
It is well possible I'm missing something obvious here - I'm not really experienced.
You can create an array of grids, then use the number value to check that.
List<bool[,] grids = new List<bool[,]>();
then
if (grids[number][x,y])...
No - an object doesn't have a name, only a variable has a name. So although you pass a reference to an array, there's no way that the method can know whether you happened to use a variable called grid1 for the argument or a variable called grid2.
Usually when there are questions like this, the answer involves saying that you can use reflection to access member variables by name, but it's generally a bad idea to do so - and that using a single variable which is a collection is a better idea. However, in your question it's pretty unclear what you're trying to do anyway... if it is trying to determine "the name of the object" then that's definitely infeasible in general.
You'd be better off passing a flag to your function which would allow you to update your logic depending on whether you are dealing with grid1 or grid2.
This kind of thing exists in PHP when you use something like this $$var where $var will hold grid1 and turn into $grid1
The only thing I could suggest was using key / value pairs in a dictionary and concatenating the number to 'grid'
Add a dimension to your array.
void CheckGrid(bool[,,] grid, int number)
{
for (int x = 0; x <= gridXmax - 1; x++)
{
for (int y = 0; y <= gridYmax - 1; y++)
{
if(grid[number, x,y]) //this will check against grid1 or grid2, depending on int number
//logic depends on whether it's grid1 or grid2
}
}
}
So, here's my question: Why won't the code in the first snippet work when the second one works fine. Also, I have set the view property to details. I've read all over how to add lvi's to the listview, and it fails every time... except for then I do it manually.
So, this doesn't work...
// Iterating through the rows...
for (int x = 0; x < numRows; x++) {
row = new List<string>();
// Iterating through the cols...
for (int y = 0; y < numCols; y++) {
row.Add(data[y][x]);
}
lv.Items.Add(new ListViewItem(row.ToArray()));
}
But this will work:
lv.Items.Add(new ListViewItem("foo"));
row.Add(data[y][x]) seems suspicious. Why do you access the data in column-first order but iterate in row-first order? Also, make sure the type of row (you didn't tell us this) is actually List<string>.
The ListViewItem is looking for a String[] try casting row.ToArray() to a String[].