遍历列表元组并在没有匹配项时添加

Loop through list tuples and add if there is no match

我正在用 C# 编写一个游戏服务器,每次有人用他的用户名发送登录消息时,我都会将他添加到 ID、IPENDPOINT、USERNAME 的元组列表中。 我想检查客户端是否与已连接的客户端没有相同的用户名,所以我尝试遍历列表并获取 list.Item3 'which is username' 并使用 String.Equals(list.Item3, username ) 检查用户名是否存在。 我的问题是当我循环时,我的代码只与列表中的第一个元组进行比较,如果它是真的则发送一条错误消息,如果不是则发送接受消息并且当列表有 +1 客户端时它也只与第一个比较并接受即使元组编号 2 或 3... 具有该用户名。 我尝试了很多方法,这是我最后尝试的代码:

for (int i = 0; i < clientsInfoList.Count; i++)
{
    bool isUsed;
    if (String.Equals(clientsInfoList[i].Item3, Username))
    {
        isUsed = true;
    }

    if (isUsed)
    {
        Console.WriteLine("Username is already used!");
        udpServer.Send(Encoding.ASCII.GetBytes("REFUSED"), Encoding.ASCII.GetByteCount("REFUSED"), remoteEP);
        break;
    }            
    else if(!isUsed)
    {
        clientsInfoList.Add(new Tuple<int, IPEndPoint, string>(id, remoteEP, Username));
        Console.WriteLine("Username has been added to the list :)");
        udpServer.Send(Encoding.ASCII.GetBytes("ACCEPTED"), Encoding.ASCII.GetByteCount("ACCEPTED"), remoteEP);                    
    }
}

我试了很多其他方法都无法验证。 提前致谢。

为什么要将整个逻辑放在 for 循环中?仅将以下代码放在 for 循环中。

            bool isUsed;
            if (String.Equals(clientsInfoList[i].Item3, Username))
            {
                isUsed = true;
            }

它现在将验证元组中的所有元素并执行剩余的逻辑。

你把一切都放在一个循环中。为什么?您应该只使用循环来检查用户名是否被使用,并将您的消息发送到它之外。

首先你想强制你的循环只在它应该工作的时候工作。您可以通过在它之前声明 isUsed 并将其添加到条件中来实现。然后,在循环中,您只检查名称是否被占用并更改变量的值。循环将遍历所有客户端或在遇到符合条件的名字时结束。当循环结束后,你应该根据结果来决定发送哪个命令。

bool isUsed = false;
for (int i = 0; i < clientsInfoList.Count && !isUsed; i++)
{
   isUsed = String.Equals(clientsInfoList[i].Item3, Username);
}

if (isUsed)
{
   Console.WriteLine("Username is already used!");
   udpServer.Send(Encoding.ASCII.GetBytes("REFUSED"), Encoding.ASCII.GetByteCount("REFUSED"), remoteEP);
}
else
{
   clientsInfoList.Add(new Tuple<int, IPEndPoint, string>(id, remoteEP, Username));
   Console.WriteLine("Username has been added to the list :)");
   udpServer.Send(Encoding.ASCII.GetBytes("ACCEPTED"), Encoding.ASCII.GetByteCount("ACCEPTED"), remoteEP);

}

你完全以错误的方式解决这个问题,如果我是你,我会做的第一件事就是摆脱元组,创建一个 class 其中包含你需要的 3 个属性.

此外,在这种情况下,请尝试使用 HashSet 而不是列表,它们会得到更好的优化,如果您有大量客户,它们将帮助您的游戏 运行 更快。

实现您所要求的最简洁的方法是使用 LINQ,这是我重写您上面编写的代码的方法。

public class Game 
{
    public Game()
    {
        this.Clients = new HashSet<Clients>(); 
    }

    public HashSet<Client> Clients { get; set;}

    public void OnClientConnect(Client newClient)
    {
        // Are there any clients with the username that the newUser is attempting to use?
        bool usernameIsFree = this.Clients.Any(clients => clients.UserName == newClient.UserName);

        if (usernameIsFree)
        {
            this.Clients.Add(newClient);
            Console.WriteLine("Username has been added to the list :)");
            // UDP stuff here...
            return;
        }

        Console.WriteLine("Username is already used!");
        // UDP stuff here   
    }
}
public class Client 
{
    public int ClientId { get; set; }
    public IPEndPoint IPEndPoint { get; set; }
    public string UserName { get; set; }
}

你可以做到

var isUsed = clientsInfoList.Any(info => info.Item3 == Username);
if (isUsed)
{
  // ...
}
else
{
  // ...
}

我假设 Item3Tuple<T1, T2, T3>T3)和 Username 都具有 编译时间 类型 string.