Reputation: 617
I am currently writing a Level Generation program in Windows Forms and C#. Each level is created from a series of 'patterns' which are loaded into an array at startup. When creating a level the program will randomly select a number of patterns from this array, randomly rotate them and create the level. Each pattern that is selected is stored in a chosenPattern
variable so that it can be rotated without modifying the original pattern.
Here is the code I use to choose the pattern and rotate it.
int rand = randomNumber(0, patterns.Count - 1);
Level chosenPattern = new Level(patterns[rand]);
chosenPattern = rotatePattern(chosenPattern, randomNumber(0, 3));
And here are the Level constructors, including the Copy Constructor.
public class Level
{
public List<List<char>> grid;
public string solution;
public int difficulty;
public TimeSpan generationTime;
public Level()
{
grid = new List<List<char>>();
solution = "";
difficulty = 0;
generationTime = TimeSpan.MinValue;
}
public Level(Level level)
{
grid = level.grid;
solution = level.solution;
difficulty = level.difficulty;
generationTime = level.generationTime;
}
}
However even when using the Copy Constructor, the pattern stored in the array is still rotated when rotating the stored pattern, and I am unsure why (Note: I'm a fairly novice C# programmer)
and the RotatePattern function:
public Level rotatePattern(Level pattern, int rotation)
{
Level tempPattern = pattern;
switch (rotation)
{
case 1:
//Rotate 90 - Reverse Each Row
for(int i = 0; i < tempPattern.grid.Count; i++)
{
tempPattern.grid[i].Reverse();
}
break;
case 2:
//Rotate 180 - Reverse Each Row, then Each Column
for (int i = 0; i < tempPattern.grid.Count; i++)
{
tempPattern.grid[i].Reverse();
}
tempPattern.grid.Reverse();
break;
case 3:
//Rotate 270 - Reverse Each Column
tempPattern.grid.Reverse();
break;
}
return tempPattern;
}
Upvotes: 2
Views: 103
Reputation: 12196
This is because grid
property, unlike the rest of the properties, is not ValueType, thus the address is copied and not the actual values.
Copy Constructor is just a constructor that accepts the same type instance. If you assign to one of its property i.e grid, then if this property is not ValueType, then you should make a method to copy those values, plain assignment with grid = level.grid
just won't cut it, and will produce the same results.
Try changing the grid
assignment to the following:
grid = level.grid.Select(lst => lst.ToList()).ToList();
Upvotes: 1
Reputation: 5580
In your copy constructor, replace it with
public Level(Level level)
{
grid = level.grid.Select(x=>x.ToList()).ToList();
solution = level.solution;
difficulty = level.difficulty;
generationTime = level.generationTime;
}
Simply passing List will copy the reference instead of the value
Upvotes: 3