【问题标题】:Convert user entered string into an object in c#将用户输入的字符串转换为c#中的对象
【发布时间】:2018-05-06 03:42:45
【问题描述】:

我有一个类似战舰的终端游戏,用户输入像e2这样的坐标,程序检查我的对象Box的一个实例变量,它检查hasShip是否为真,如果为真则将坐标设为e2 false,并给出输出“Ship destroy”

问题是我所有的对象都被称为 a1,a2,a3,a4,a5,b1,b2 等等。

我创建了 25 个 Box 类的实例。所有的名字都是这样。

一旦程序获得输入,无论是 e4 ,e5 等。我想将该字符串转换为一个对象。

例如(我想做这样的事情)

target = Console.ReadLine();
target.hasShip == true; 

我想把target转成对象,然后用target来使用Box类的方法。

因为另一种方法需要我编写大量 if 语句,这不是干净的代码,看起来也不好看,而且如果你问我,那就是浪费。

提前致谢,

【问题讨论】:

  • 对象应该具有名为 Name 的属性,并且您应该将所有对象存储在字典中,其中键作为对象名称,值作为对象本身。然后,当用户输入目标时,您应该在字典中搜索与目标相同的键,并从字典中获取该键的值,并使用它的方法从字典中破坏和删除该对象

标签: c# type-conversion


【解决方案1】:

新答案:使用数组

我很慢。我没有注意到您正在制作类似战舰的游戏,并且我们知道“盒子”是一个矩形。我们可以有效地将其存储在数组中。

为什么我没有早点了解这个事实?我想我需要好好醒来。

所以,使用数组:

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&lt;string, Box&gt;,这意味着它是一个字典,您可以通过字符串查询并存储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); 

【讨论】:

  • 所以基本上,我给的名字本身就是一个字符串,它引用字典的一个对象,类型为 Box(my object),所以,现在 target 是 Box我需要的对象,所以我可以继续。所以现在我只需要获取target的值,也就是Box??
  • @Emp1 使字典存储您需要的任何类型。无论是盒子还是其他。我不知道你需要什么。当您执行dict[name] 时,它将为您提供使用该键添加的值。我将对此进行扩展。
  • @Emp1 我提供了一种不同的方法,实际上更符合您的要求。我想知道你是否会有一艘以上的船Box,或者Box除了那里有船之外还有其他东西......因为我想知道你是否只需要bool而不是@ 987654395@.
  • 基本上我有一个 Box 类,它有 2 个实例变量,一个是给它 id 的字符串,e1 e2 a3 等。另一个是一个布尔值,它告诉我们是否有船在上面或不。我创建了该类的 25 个实例,并为它们提供了 ID。我把它们都放在一个数组中,所有的id。然后我使用 Random,生成 4 个随机数。我使用每个数字作为索引,并从数组中选择一个随机值,(e1,e2,a4,b3 等)然后我将 Box 的布尔值设为真,就像在船上一样。这就是我所做的一切直到现在。这需要大量的 if 语句。 pastebin.com/z4vqaryh,this是吗
  • @Emp1 对填充数组和其他修复做了一个附录。 Gist.
猜你喜欢
  • 1970-01-01
  • 2020-12-03
  • 1970-01-01
  • 2014-05-07
  • 2013-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-04
相关资源
最近更新 更多