2015-03-08 132 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