编辑数组也会更改另一个数组
Editing array also changes another array
所以我在 windows 控制台中制作了一个小游戏(只是为了好玩和测试理论)但是我遇到了 DrawGame()
方法的问题。
我正在创建一个新的字符串数组 (string[] _CompleteMap
),其值是从 CurrentMap.MapData
(也是一个字符串数组)分配的:
string[] _CompleteMap = CurrentMap.MapData;
我正在使用 CurrentMap.MapData
作为空白地图,然后更改字符串中的字符以表示玩家和生物。
但是当我对 _CompleteMap
进行更改时,它似乎也在更改 CurrentMap.MapData
...
中的值
我不知道为什么会这样,它留下了用户走过的地方。
任何支持都会有所帮助,如果需要,我可以 post 代码。
using System;
using System.Text;
using System.Threading;
using ConsoleAdventure.Engine.BaseClasses;
using Database = ConsoleAdventure.Engine.Database;
namespace ConsoleAdventure
{
class Program
{
private static bool whileGameScene = true;
private static Engine.BaseClasses.MapBase CurrentMap;
static unsafe void Main(string[] args)
{
// Load and populate the databases.
Database.ItemDB.LoadItemDB();
Database.MapDB.LoadMapDB();
// Set demo map
CurrentMap = Database.MapDB.Maps[0];
// Hide cursor
Console.CursorVisible = false;
// Start a new thread to capture the user inputs
new Thread(() =>
{
while (true)
{
Thread.CurrentThread.IsBackground = true;
ConsoleKeyInfo cki = Console.ReadKey();
if (cki.Key == ConsoleKey.A && Player.Data.Location.X > 0)
Player.Data.Location.X--;
else if (cki.Key == ConsoleKey.D)
Player.Data.Location.X++;
else if (cki.Key == ConsoleKey.W && Player.Data.Location.Y > 0)
Player.Data.Location.Y--;
else if (cki.Key == ConsoleKey.S)
Player.Data.Location.Y++;
CheckWarpPoints();
}
}).Start();
// Draw the game
while (whileGameScene)
{
DrawGame();
}
}
/// <summary>
/// Check if player has stood on a warp zone
/// </summary>
private static void CheckWarpPoints()
{
foreach (MapBase.WarpPoint warp in Database.MapDB.Maps[Player.Data.CurrentMap].WarpPoints)
{
if (Player.Data.Location.X == warp.From.X && Player.Data.Location.Y == warp.From.Y)
{
Player.Data.CurrentMap = warp.ToMapIndex;
Player.Data.Location = warp.To;
}
}
}
public static void DrawGame()
{
string[] _CompleteMap = CurrentMap.MapData;
StringBuilder _sbRow = new StringBuilder();
foreach (var _object in CurrentMap.MapObjects)
{
_sbRow = new StringBuilder(_CompleteMap[_object.CurrentLocation.Y]);
_sbRow[_object.CurrentLocation.X] = _object.Icon;
_CompleteMap[_object.CurrentLocation.Y] = _sbRow.ToString();
}
_sbRow = new StringBuilder(_CompleteMap[Player.Data.Location.Y]);
_sbRow[Player.Data.Location.X] = 'X';
_CompleteMap[Player.Data.Location.Y] = _sbRow.ToString();
for (int i = 0; i < _CompleteMap.Length; i++)
{
Console.SetCursorPosition(0, i);
Console.WriteLine(_CompleteMap[i]);
}
}
}
}
由于数组是引用类型,当您这样做时:
string[] _CompleteMap = CurrentMap.MapData;
您实际上是在创建一个指向与 CurrentMap.MapData
相同的内存位置的新变量,您通过 _CompleteMap
对该位置所做的任何更改也会在您引用通过 CurrentMap.MapData
.
定位
相反,您可以根据现有数组的内容创建一个新数组:
string[] _CompleteMap = CurrentMap.MapData.ToArray();
现在它指向不同的位置,所以修改这个位置的数组不会影响原来位置的数组。
但是,要注意的一件事是,如果 MapData
是一个引用类型的数组,并且您使用 ToArray()
复制它,那么即使您现在有一个新的包含相同数据的数组,如果您操作数组副本中的对象之一,对该对象的更改也会出现在原始数组中。
这是因为我们进行了浅复制。如果我们不想要这种行为,那么我们需要做一个 deep 复制,我们也为数组中的每个对象创建新的(克隆的)实例。有东西要你研究!!
例如:
class Person
{
public string Name { get; set; }
}
class Program
{
static void Main()
{
// Original array has a person named John
Person[] people = new [] { new Person { Name = "John" } };
// Create a shallow copy of the array
Person[] peopleCopy = people.ToArray();
// Change John's name in the copy
peopleCopy[0].Name = "James";
// At this point, people[0].Name is also "James", since it's the same person!
// However changes to the array itself are discreet
peopleCopy[0] = new Person { Name = "Mary" };
// At this point, people[0].Name is still "James", since we did
// not modify the existing object, but instead created a new one
}
}
所以我在 windows 控制台中制作了一个小游戏(只是为了好玩和测试理论)但是我遇到了 DrawGame()
方法的问题。
我正在创建一个新的字符串数组 (string[] _CompleteMap
),其值是从 CurrentMap.MapData
(也是一个字符串数组)分配的:
string[] _CompleteMap = CurrentMap.MapData;
我正在使用 CurrentMap.MapData
作为空白地图,然后更改字符串中的字符以表示玩家和生物。
但是当我对 _CompleteMap
进行更改时,它似乎也在更改 CurrentMap.MapData
...
我不知道为什么会这样,它留下了用户走过的地方。
任何支持都会有所帮助,如果需要,我可以 post 代码。
using System;
using System.Text;
using System.Threading;
using ConsoleAdventure.Engine.BaseClasses;
using Database = ConsoleAdventure.Engine.Database;
namespace ConsoleAdventure
{
class Program
{
private static bool whileGameScene = true;
private static Engine.BaseClasses.MapBase CurrentMap;
static unsafe void Main(string[] args)
{
// Load and populate the databases.
Database.ItemDB.LoadItemDB();
Database.MapDB.LoadMapDB();
// Set demo map
CurrentMap = Database.MapDB.Maps[0];
// Hide cursor
Console.CursorVisible = false;
// Start a new thread to capture the user inputs
new Thread(() =>
{
while (true)
{
Thread.CurrentThread.IsBackground = true;
ConsoleKeyInfo cki = Console.ReadKey();
if (cki.Key == ConsoleKey.A && Player.Data.Location.X > 0)
Player.Data.Location.X--;
else if (cki.Key == ConsoleKey.D)
Player.Data.Location.X++;
else if (cki.Key == ConsoleKey.W && Player.Data.Location.Y > 0)
Player.Data.Location.Y--;
else if (cki.Key == ConsoleKey.S)
Player.Data.Location.Y++;
CheckWarpPoints();
}
}).Start();
// Draw the game
while (whileGameScene)
{
DrawGame();
}
}
/// <summary>
/// Check if player has stood on a warp zone
/// </summary>
private static void CheckWarpPoints()
{
foreach (MapBase.WarpPoint warp in Database.MapDB.Maps[Player.Data.CurrentMap].WarpPoints)
{
if (Player.Data.Location.X == warp.From.X && Player.Data.Location.Y == warp.From.Y)
{
Player.Data.CurrentMap = warp.ToMapIndex;
Player.Data.Location = warp.To;
}
}
}
public static void DrawGame()
{
string[] _CompleteMap = CurrentMap.MapData;
StringBuilder _sbRow = new StringBuilder();
foreach (var _object in CurrentMap.MapObjects)
{
_sbRow = new StringBuilder(_CompleteMap[_object.CurrentLocation.Y]);
_sbRow[_object.CurrentLocation.X] = _object.Icon;
_CompleteMap[_object.CurrentLocation.Y] = _sbRow.ToString();
}
_sbRow = new StringBuilder(_CompleteMap[Player.Data.Location.Y]);
_sbRow[Player.Data.Location.X] = 'X';
_CompleteMap[Player.Data.Location.Y] = _sbRow.ToString();
for (int i = 0; i < _CompleteMap.Length; i++)
{
Console.SetCursorPosition(0, i);
Console.WriteLine(_CompleteMap[i]);
}
}
}
}
由于数组是引用类型,当您这样做时:
string[] _CompleteMap = CurrentMap.MapData;
您实际上是在创建一个指向与 CurrentMap.MapData
相同的内存位置的新变量,您通过 _CompleteMap
对该位置所做的任何更改也会在您引用通过 CurrentMap.MapData
.
相反,您可以根据现有数组的内容创建一个新数组:
string[] _CompleteMap = CurrentMap.MapData.ToArray();
现在它指向不同的位置,所以修改这个位置的数组不会影响原来位置的数组。
但是,要注意的一件事是,如果 MapData
是一个引用类型的数组,并且您使用 ToArray()
复制它,那么即使您现在有一个新的包含相同数据的数组,如果您操作数组副本中的对象之一,对该对象的更改也会出现在原始数组中。
这是因为我们进行了浅复制。如果我们不想要这种行为,那么我们需要做一个 deep 复制,我们也为数组中的每个对象创建新的(克隆的)实例。有东西要你研究!!
例如:
class Person
{
public string Name { get; set; }
}
class Program
{
static void Main()
{
// Original array has a person named John
Person[] people = new [] { new Person { Name = "John" } };
// Create a shallow copy of the array
Person[] peopleCopy = people.ToArray();
// Change John's name in the copy
peopleCopy[0].Name = "James";
// At this point, people[0].Name is also "James", since it's the same person!
// However changes to the array itself are discreet
peopleCopy[0] = new Person { Name = "Mary" };
// At this point, people[0].Name is still "James", since we did
// not modify the existing object, but instead created a new one
}
}