新答案:使用数组
我很慢。我没有注意到您正在制作类似战舰的游戏,并且我们知道“盒子”是一个矩形。我们可以有效地将其存储在数组中。
为什么我没有早点了解这个事实?我想我需要好好醒来。
所以,使用数组:
var board = new Box[5, 5];
现在,为了填充它,我们可以做一个双 for 循环:
for(var indexRow = 0; indexRow < 5; indexRow++)
{
for(var indexCol = 0; indexCol < 5; indexCol++)
{
board[indexRow, indexCol] = new Box();
}
}
注意:注意索引从 0 到 4。总共 5 个值:{0, 1, 2, 3, 5}。
要从中查询,我们需要索引...
关于填充数组的附录
在 cmets 中,OP 说过每个 Box 都有一个 id,并且船位是随机挑选的。
我们可以在循环中给出id:
for(var indexRow = 0; indexRow < 5; indexRow++)
{
for(var indexCol = 0; indexCol < 5; indexCol++)
{
var box = new Box();
box.vhID = (((char)(((int)'a') + indexRow))).ToString() + ((char)(((int)'1') + indexCol)).ToString();
board[indexRow, indexCol] = box;
}
}
我在这里所做的是从索引中构造 id。基本上取'a' 的值并添加indexRow 将给我们'a' 当indexRow 是0,'b' 当它是1 等等。同样,我们得到代表列的数字。
注意:我们将char 转换为int,进行加法,然后转换回char...,然后从char 转换为string。一旦我们有了字符串,我们就可以将它们连接起来。
我认为我们不需要这个 ID。但是,嘿,你可以这样做。
OP 还提到他会随机选择 4 个船位。很公平:
var random = new Random();
for (var ships = 0; ships < 4; ships++)
{
board[random.Next(0, 4), random.Next(0, 4)].hasShip = true;
}
由于用户输入的是字符串,我建议创建一个函数将其转换为索引对:
var input = Console.ReadLine();
if (TryGetCoordinates(input, out int irow, out int icol))
{
var target = board[irow, icol];
}
else
{
Console.WriteLine("The cell {0} does not exist.", input);
}
// ...
bool TryGetCoordinates(string cell, out int indexRow, out int indexCol)
{
// ...
}
首先验证null:
bool TryGetCoordinates(string cell, out int indexRow, out int indexCol)
{
indexRow = -1;
indexCol = -1;
if (cell == null)
{
return false;
}
// ...
}
注意:请随意使用Trim、ToUpper 或ToUpperInvariant。
我们知道必须是一个字母后跟一个数字,我们可以验证长度:
bool TryGetCoordinates(string cell, out int indexRow, out int indexCol)
{
indexRow = -1;
indexCol = -1;
if (cell == null)
{
return false;
}
if (cell.Length != 2)
{
return false;
}
// ...
}
我们提取字符并从中提取坐标。注意第一个是字母,另一个是数字。我们还可以验证它们是否在界限内。
bool TryGetCoordinates(string cell, out int indexRow, out int indexCol)
{
indexRow = -1;
indexCol = -1;
if (cell == null)
{
return false;
}
if (cell.Length != 2)
{
return false;
}
indexRow = (int)cell[0] - (int)'a';
indexCol = (int)cell[1] - (int)'1';
return indexRow < 5 && indexRow >= 0 && indexCol < 5 && indexCol >= 0;
}
当然,您可以执行类似于旧答案中解释的验证循环。
注意:我在旧答案中描述的值类型问题仍然适用于数组。
旧答案:使用字典
我相信您不想将string 转换为对象(string 是一个对象),您想选择您之前基于string 创建的Box 对象。你想在不使用 if 语句的情况下做到这一点。你需要的是一本字典。
因此,您将拥有Dictionary<string, Box>,这意味着它是一个字典,您可以通过字符串查询并存储Box。
附录:
- 在这种情况下,字符串是键类型,我们将通过它访问字典。当我们将一个对象添加到字典中时,我们用一个键来标识它,当我们检索它时,我们也使用这个键。密钥不必是
string,您可以选择其他类型。 string 在这种情况下很方便,因为它是您从 Console.ReadLine() 获得的。
- 您可以创建字典来存储您需要的任何类型。如果您不需要
Box,您可以创建一个存储其他内容的字典。
创建和填充字典
然后,将所有 Box 对象添加到 Dictionary 中,如下所示:
var dict = new Dictionary<string, Box>();
// ...
dict.Add("a1", CreateBoxA1());
CreateBoxA1 代表你必须创建对象的任何方式。不,您不需要为每个Box 创建一个方法...您可以这样做:
dict.Add("a1", new Box());
或其他。我不知道你是如何创建它们的,所以考虑一个占位符,好吗?好的。
从字典中查询和检索值
一旦您的字典中有所有Box 实例,您就可以使用string 获得所需的实例:
Console.WriteLine("Enter the name of the Box:");
var name = Console.ReadLine();
var target = dict[name];
附录:您从dict[name] 获得的值是您使用该键添加到字典中的值。因此,如果用户输入了"a1",那么dict[name] 将是我们使用"a1" (dict.Add("a1", new Box());) 添加的值。同样,如果您需要的不是 Box,您可以创建一个字典来存储不同的类型。
输入验证
您还可以使用 Dictionary 来验证 string 是否对应一个存在的 Box,例如:
Console.WriteLine("Enter the name of the Box:");
var name = Console.ReadLine();
if (dict.KeyExists(name))
{
var target = dict[name];
// ...
}
else
{
Console.WriteLine("The Box {0} does not exist", name);
}
不言而喻,但是……你可以在此基础上做一个循环,例如:
Box target = null;
while(true)
{
Console.WriteLine("Enter the name of the Box:");
var name = Console.ReadLine();
if (dict.KeyExists(name))
{
target = dict[name];
break;
}
Console.WriteLine("The Box {0} does not exist", name);
}
另外,不用说,但是...您可以添加自己的验证和清理步骤。例如使用ToUpper、ToUpperInvariant 或Trim。我会提醒您,将strings 更改为小写或大写是对文化敏感的。
另请参阅:Best Practices for Using Strings in .NET。
编辑从字典中移除的对象
一旦你有你从字典中检索到的对象......
var target = dict[name];
我们可以使用它,甚至可以修改它:
var target = dict[name];
if (target.hasShip) // no need for "== true" if hasShip bool
{
target.hasShip = false;
Console.WriteLine("Ship Destroyed");
}
如果Box 是值类型,必须特别注意。对于自定义类型,这意味着它不是class,而是struct。值类型的问题在于它们在赋值时被复制,这意味着当您对值类型执行var target = dict[name]; 时,您会得到一个副本。一旦你操作了字典,你就必须更新它:
var target = dict[name];
if (target.hasShip) // no need for "== true" if hasShip bool
{
target.hasShip = false;
dict[name] = target;
Console.WriteLine("Ship Destroyed");
}
注意:正如我上面所说,只有值类型才需要。
如果有必要,您甚至可以从字典中删除 Box:
dict.Remove(name);