Сценарий: я делаю многопользовательскую игру с 5-ди git кодами комнат (также называемыми «игровыми кодами» или «именами комнат») для идентификации лобби. Чтобы создать комнату:
- Текущий регистр комнат загружается из Firebase (и переносится в список)
- Создается случайный 5-значный git код
- Этот код проверяется для каждого члена списка на наличие конфликта.
- . Если возникает конфликт, шаги 2 и 3 повторяются до тех пор, пока не будет достигнут произвольный «предел попыток»
Я использовал некоторое время l oop, чтобы попытаться достичь этого. Теперь, чтобы проверить надежность этого кода, я подумал: «Что произойдет, если сгенерированный код будет конфликтовать с регистром каждый раз? Будет ли достигнут предел попыток?» И ответ «нет»: l oop выходит намного раньше, чем должен в случайной точке (меняется каждый раз, когда я его запускаю), и условия разрыва достоверно не выполняются. Я подозреваю, что он молча терпит крах, потому что ни один из последующих методов не вызывается. Почему это происходит и как я могу реструктурировать этот код, чтобы сделать то, что я хочу?
Вот выдержка из моего кода (метод, который принимает запрос Firebase), а под ним журнал отладки:
void GenerateValidCode(IEnumerable<DataSnapshot> roomsList)
{
// This just transfers the room names from the DataSnapshot to a string list, this fixed a problem in the Java version
List<string> roomNamesList = new List<string>();
if (roomsList != null)
{
foreach(DataSnapshot room in roomsList)
{
Debug.Log("ROOM NAME ADDED TO LIST: " + room.Key);
roomNamesList.Add(room.Key);
}
}
// Game Code generation objects
string gameCode = "";
string abc = "ABCDEFGHIJKLMNOPQRSTUVXYZ";
string num = "0123456789";
System.Random rand = new System.Random();
// While loop break conditions
bool codeGot = false;
int attemptsLeft = ATTEMPTS_ALLOWED; // ATTEMPTS_ALLOWED is a field set to 100
// WHILE LOOP BEGINS
while(!codeGot && attemptsLeft > 0)
{
// Generates a 5 digit code
gameCode = "";
gameCode = gameCode + abc[(int)(rand.NextDouble() * 26)];
gameCode = gameCode + abc[(int)(rand.NextDouble() * 26)];
gameCode = gameCode + abc[(int)(rand.NextDouble() * 26)];
gameCode = gameCode + num[(int)(rand.NextDouble() * 10)];
gameCode = gameCode + num[(int)(rand.NextDouble() * 10)];
// DEBUG PURPOSES ONLY - Forces code to be equal to the only existing code on database
gameCode = "DRU41";
Debug.Log("THIS CODE: " + gameCode);
// If no rooms, then there's no possibility of conflict so we just continue...
if (roomNamesList.Count == 0)
{
codeGot = true;
}
else // If there are rooms registered, we must look for a conflict...
{
bool conflictFound = false;
foreach (string roomName in roomNamesList)
{
Debug.Log("ROOM BEING TESTED FOR MATCH: "+roomName);
// If there exists any room with the code generated, conflict found set to true
if (string.Equals(roomName, gameCode)) conflictFound = true;
Debug.Log("CONFLICTFOUND?: " + conflictFound.ToString()); // This will be true every time
}
// If no conflict was found, we've got our code
if (!conflictFound) codeGot = true;
}
attemptsLeft--;
Debug.Log("ATTEMPTS LEFT: "+attemptsLeft.ToString()+",CODEGOT?: "+codeGot.ToString());
}
// end of while loop
if(codeGot)
{
main.GameCreationUpdate("Creating room " + gameCode); // This method prints to console as well, but is never called
CreateRoom(gameCode);
}
else
{
failureMessage = "Failed to generate unique game code. Try again later.";
main.OnGameCreationComplete(this, false); // This method also prints to console, but is never called
}
}
Выдержка из журнала отладки:
ROOM NAME ADDED TO LIST: DRU41
UnityEngine.Debug:Log(Object)
GameCreator:GenerateValidCode(IEnumerable`1) (at Assets/Resources/Scripts/Utils/GameCreator.cs:73)
GameCreator:<GetRoomRegister>b__10_0(Task`1) (at Assets/Resources/Scripts/Utils/GameCreator.cs:60)
System.Threading._ThreadPoolWaitCallback:PerformWaitCallback()
THIS CODE: DRU41
UnityEngine.Debug:Log(Object)
GameCreator:GenerateValidCode(IEnumerable`1) (at Assets/Resources/Scripts/Utils/GameCreator.cs:102)
GameCreator:<GetRoomRegister>b__10_0(Task`1) (at Assets/Resources/Scripts/Utils/GameCreator.cs:60)
System.Threading._ThreadPoolWaitCallback:PerformWaitCallback()
ROOM BEING TESTED FOR MATCH: DRU41
UnityEngine.Debug:Log(Object)
GameCreator:GenerateValidCode(IEnumerable`1) (at Assets/Resources/Scripts/Utils/GameCreator.cs:115)
GameCreator:<GetRoomRegister>b__10_0(Task`1) (at Assets/Resources/Scripts/Utils/GameCreator.cs:60)
System.Threading._ThreadPoolWaitCallback:PerformWaitCallback()
CONFLICTFOUND?: True
UnityEngine.Debug:Log(Object)
GameCreator:GenerateValidCode(IEnumerable`1) (at Assets/Resources/Scripts/Utils/GameCreator.cs:120)
GameCreator:<GetRoomRegister>b__10_0(Task`1) (at Assets/Resources/Scripts/Utils/GameCreator.cs:60)
System.Threading._ThreadPoolWaitCallback:PerformWaitCallback()
ATTEMPTS LEFT: 99,CODEGOT?: False
UnityEngine.Debug:Log(Object)
GameCreator:GenerateValidCode(IEnumerable`1) (at Assets/Resources/Scripts/Utils/GameCreator.cs:129)
GameCreator:<GetRoomRegister>b__10_0(Task`1) (at Assets/Resources/Scripts/Utils/GameCreator.cs:60)
System.Threading._ThreadPoolWaitCallback:PerformWaitCallback()
Вышеизложенное повторяется, когда попытки попытки возврата влево снижаются, а затем резко заканчивается (здесь 61, иногда 98):
ATTEMPTS LEFT: 61,CODEGOT?: False
UnityEngine.Debug:Log(Object)
GameCreator:GenerateValidCode(IEnumerable`1) (at Assets/Resources/Scripts/Utils/GameCreator.cs:129)
GameCreator:<GetRoomRegister>b__10_0(Task`1) (at Assets/Resources/Scripts/Utils/GameCreator.cs:60)
System.Threading._ThreadPoolWaitCallback:PerformWaitCallback()
Я адаптирую этот проект из проекта, который я уже сделал в Android Studio, и код Java, который делает это в этом проекте, работает нормально (и в основном то же самое).