sobota, 30 kwietnia 2016

Dane użytkownika

Jak już wspomniałem w jednym z poprzednim wpisów, gracze będą mieli możliwość wybrania zestawu żetonów, z których będą korzystać w trakcie gry. Każdy gracz będzie mógł utworzyć swój własny zestaw, więc informacje o zestawach muszą być gdzieś zapisywane. Może się to dziać na sprzęcie użytkownika, ale w obecnych czasach standardem jest zapisywanie danych na serwerze, dzięki czemu gracz może mieć do nich dostęp z dowolnego komputera. W poprzednim wpisie omówiłem w jaki sposób można zapisywać dane gracza do pliku, a w tym wpisie omówię w jaki sposób wygodnie z tych danych korzystać.

Format zapisu danych

Jeśli na serwerze zapisywana jest niewielka ilość danych, to troska o ich porządek nie jest zbyt konieczna. Przykładowo jeśli plik gracza zawierałby tylko 2 krótkie linijki tekstu, to odwoływanie się do nich byłoby proste. Problem zaczyna się wtedy, gdy plik tekstowy zawiera wiele linijek kodu i dodatkowo wielkość tego pliku nie jest znana. Wtedy trzeba starać się zapisywać dane w taki sposób, aby program mógł łatwo znaleźć potrzebne jemu dane.

W mojej grze w profilu gracza będzie można zapisać wiele zestawów żetonów, a każdy żeton będzie się składał z 4 stosów żetonów, przy czym każdy stos musi się składać z co najmniej 2 kart żetonów, o numerze będącym liczbą całkowitą. Program potrzebuje więc informacje o tym, z którego zestawu chce korzystać gracz, oraz jaka jest zawartość poszczególnych zestawów żetonów.
W pliku tekstowym gracza umieszczam więc następujący tekst:

Handset
1

set 0
0 1
1 2
3 4
5 6

set 1
0 2
1 3 4
81 32
45 16 35 134

Linia "Handset" będzie dla mojego programu punktem orientacyjnym, dzięki któremu program będzie wiedział, że linijkę niżej znajduje się numer zestawu żetonów z którego korzysta użytkownik. Niżej zaś znajdują się informacje o zestawach żetonów, gdzie pojedyncza linia oznacza jeden stos kart, a numery kart są oddzielone spacjami.

Wczytywanie informacji z pliku

Gdy użytkownik dołączy się do gry, serwer będzie musiał wczytać jego dane. Całą zawartość pliku łatwo można skopiować do tablicy stringów (ciągów znaków) za pomocą jednej linijki kodu:

 string [] Lines = File.ReadAllLines (@"C:/TokenBattle/" + Nickname + ".txt");

Jednak wczytanie tych danych do programu to nie wszystko, trzeba je jeszcze zinterpretować. Nasz skrypt musi teraz znaleźć linię "Handset", aby odczytać z niższej linii numer zestawu, z którego trzeba skorzystać. Wykorzystamy do tego następujący fragment kodu:

 Array.FindIndex (Lines, s => s.Equals ("Handset"))

Funkcja Array.FindIndex jest funkcją znajdującą się w bibliotece System, więc aby z niej skorzystać trzeba zadeklarować tą bibliotekę, lub poprzedzić tą funkcję nazwą tej biblioteki. Funkcja korzysta z 2 argumentów: pierwszym argumentem jest tablica, którą chcemy przeszukać, zaś drugi argument ma typ Predicate, który składa się z argumentu będącym aktualnie sprawdzanym elementem tablicy, oraz warunku który określa, czy ten element tablicy spełnia nasze kryteria. Jeśli Predicate zwróci wartość true, to funkcja zwraca numer indeksu tablicy, który spełnił nasze kryteria. W naszym przypadku Funkcja FindIndex wyszukuje w tablicy ciąg znaków, który brzmi "Handset". Teraz nasz program wie, gdzie znajduje się informacja o wykorzystywanym zestawie żetonów, ale musi tą informację przetworzyć, do czego posłuży nam taka linia kodu:

 int HandsetNumber = int.Parse (Lines [Array.FindIndex (Lines, s => s.Equals ("Handset")) + 1]);

Tworzy ona zmienną typu int, do której chce przypisać wartość typu string (ponieważ jest to linijka tekstu z tablicy stringów), więc musimy zmienić typ zmiennej za pomocą funkcji int.Parse. Dodatkowo nie chcemy się odwołać do linii "Handset", tylko do linii następnej, więc do numeru indeksu dodajemy 1.

Następnie w podobny sposób chcemy znaleźć indeks linijki tablicy, która rozpoczyna informację o szukanym zestawie żetonów:

 int LineNumber = Array.FindIndex (Lines, s => s.Equals ("set " + HandsetNumber.ToString ()));

Teraz chcemy przepisać dane do zmiennych innego skryptu:

 for (int x = 0; x < 4; x++) {
  string [] Stack = Lines [++LineNumber].Split (' ');
  SScript ().Player [p].CardQueue [x].NumberOfCards = Stack.Length;
  SScript ().Player [p].CardQueue [x].CardNumbers = new int [Stack.Length]; 
  int y = 0;
  foreach (string number in Stack) {
   SScript ().Player [p].CardQueue [x].CardNumbers [y] = int.Parse (number);
   y++;
  }
 }

Korzystam tutaj z pętli for, żeby przepisane były 4 linijki tekstu. Chcę jednak, aby były one rozpisane w formie zmiennych typu int, a nie dość, że linie są typu string, to jeszcze sam string składa się z kilku liczb, które trzeba rozdzielić. Robimy to za pomocą funkcji Split(), która rozdziela string wszędzie tam, gdzie spotka char (zmienną typu znak) podany w argumencie tej funkcji. Rozdzielanym stringiem jest string z tablicy Lines, gdzie numerem indeksu jest int LineNumber. Dwa plusy poprzedzające zmienną LineNumber oznaczają, że zostaje ona zwiększona o 1 zanim zostanie wykorzystana (dla porównania postawienie dwóch plusów po tej zmiennej sprawiłoby, że zostałaby zwiększana o 1 dopiero po jej wykorzystaniu). Nowo powstałe stringi przypisuję do tablicy stringów Stack. 

Fragment SScript ().Player [p].CardQueue [x] określa miejsce w którym chcę zapisać informację, ogólnie to struktura w strukturze w skrypcie. W tamtym miejscu znajduje się zmienna NumberOfCards, która ma zawierać informację o ilości kart żetonów na stosie, a informację tę można zdobyć sprawdzając liczbę elementów tablicy Stack, co można dokonać funkcją Length. Parę linijek niżej korzystam z pętli foreach, która wykonuje pętlę dla każdego elementu tablicy, którą podajemy jako argument (w moim przypadku jest to tablica Stack). Nazwę tego elementu podajemy w nawiasie tej pętli.


Tym sposobem program wczytał z pliku tekstowego potrzebne mu informacje.

Brak komentarzy:

Prześlij komentarz