Reputation: 117
So I'm trying to make a little snake game in C# and console and ran into some weird behavior. I've always thought structs are supposed to be passed around as values not references. But now that I try to copy a struct to a temporary buffer and then draw that, for some reason it attaches itself to the buffer as a reference :/ When I modify the drawBuffer. the map also gets modified. and i don't want the map to be modified.
map is a static value established above the function
Map drawBuffer = new Func<Map>(() => map)(); //trying to forcibly pass the value through a function as an attempt to separate it from the refrence.
MovePlayer();
foreach ((int x, int y) in player.Tail)
{
drawBuffer[x, y, 1] = 'O';
}
and Map is a struct.
struct Map //also tried to make it immutable via readonly; nothing.
{
public const char EMPTY = (char)0;
public int Width;
public int Height;
public int Depth;
char[,,] container;
public char this[int x, int y, int z]
{
get
{
return container[x, y, z];
}
set
{
container[x, y, z] = value;
}
}
public char this[int x, int y]
{
get
{
for (int z = Depth - 1; z >= 0; z--)
{
if (container[x, y, z] != EMPTY)
{
return container[x, y, z];
}
}
return EMPTY;
}
}
public void DrawSurface()...
public void DrawLayer(int z)...
public Map(int width, int height, int depth)
{
this.Width = width;
this.Height = height;
this.Depth = depth;
container = new char[width, height, depth];
}
public Map(int width, int height, int depth, Func<int, int, int, int, int, int, char> pattern)
{
this.Width = width;
this.Height = height;
this.Depth = depth;
container = new char[width, height, depth];
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
for (int z = 0; z < depth; z++)
{
this[x, y, z] = pattern(x, y, z, width, height, depth);
}
}
}
}
}
Upvotes: 0
Views: 86
Reputation: 117
Instead of manually copying the values from one place to another, I use the built in Clone() function in a Constructor that takes in a map in.
public Map(Map toClone)
{
Width = toClone.Width;
Height = toClone.Height;
Depth = toClone.Depth;
container = (char[,,])toClone.container.Clone();
}
this way it looks pretty clean in code.
Map drawBuffer = new Map(map);
you could also implement a custom clone function
public Map Clone(Map toClone){
Map newMap = new map(toClone.Width, toClone.Height, toClone.Depth)
newMap.container = (char[,,])toClone.container.Clone();
return newMap;
}
Upvotes: 1
Reputation: 743
As mentioned by UnholySheep char[,,] container
is a reference type. To avoid passing it as a reference you could make a new map and pass the valuse directly like so:
Map secondMap;
for (int z = 0; z < drawBuffer.container.GetLength(2); z++)
for (int y = 0; y < drawBuffer.container.GetLength(1); y++)
for (int x = 0; x < drawBuffer.container.GetLength(0); x++)
secondMap.container[x, y, z] = drawBuffer.container[x, y, z];
Upvotes: 2