2015-03-08 129 views
0

我正在用C#编写游戏服务器,每次有人用他的用户名发送登录消息时,我将他添加到ID为IPENDPOINT,USERNAME的元组列表中。 我想检查客户端是否与已连接的客户端没有相同的用户名,所以我试图循环访问列表并获取list.Item3'这是用户名',并使用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);      
    } 
} 

我试过很多其他方法,但我不能获得验证。 在此先感谢。

回答

1

你把所有东西放在一个循环中。为什么?您应该仅使用循环来检查用户名是否被使用,并将消息发送给它。

首先,你想强制你的循环工作,只要它应该。您可以在它之前声明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); 

} 
+0

我试过你的解决方案,但我得到:使用未分配的局部变量'isUsed' – Adam 2015-03-08 21:09:31

+0

我改变了'布尔isUsed'到'bool isUsed = false;'。试试看,并告诉我它是否有效。 – Szab 2015-03-08 21:11:30

+0

'isUsed'仍然只会告诉我们,如果* *最后在'项目<>'使用该名称。无论用户看到什么用户名,循环都会继续。 – 2015-03-08 21:14:31

0

为什么要将整个逻辑放在for循环中?在循环内只放置下面的代码。

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

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

+0

感谢您的快速响应,我会现在尝试它:) – Adam 2015-03-08 20:54:40

+0

感谢您的有益建议,我欣赏它:) – Adam 2015-03-08 21:29:51

0

你要对这个完全错误的方式,如果我是你,我会做,第一件事是摆脱的元组,创建一个包含你所需要的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; } 
} 
+0

感谢您的建议和代码,我试图保持它简单,所以我可以稍后在sqlite数据库中存储一些数据,并且因为这将仅在客户端连接时检查,性能现在不是真的需要,但实际上我将尝试使用您的代码;) 再次感谢:) – Adam 2015-03-08 21:22:22

1

你可以做

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

我假定这两个Item3(的Tuple<T1, T2, T3>T3)和Username编译时string

+0

某人已经找到了解决方案,但我会给它一个尝试:) 感谢您的回答:) – Adam 2015-03-08 21:27:56