Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> [PHP][MySQL] Losowanie Unikalnego ID
rex
post
Post #1





Grupa: Zarejestrowani
Postów: 15
Pomógł: 0
Dołączył: 25.11.2009

Ostrzeżenie: (0%)
-----


Cześć wszystkim,

Tworzę sobie projekt w którym jedną z funkcji jest system losowania cytatów (taki quiz). Poniższy skrypt działa w sumie w 85% w takim stopniu w jakim chciałbym aby działał, jednakże brakuje tych najistotniejszych 15%.

1. Użytkownik wybiera poziom trudności
2. Biorąc pod uwagę wybrany poziom (lub brak) wyświetla treści adekwatne do wybranego
3. Projekt opiera się o 3 tabele w bazie danych, które posiadają cytaty o trzech stopniach trudności. W przypadku wybrania poziomu łatwego (1 baza) wskazuje nam tylko cytaty z pierwszej bazy itd. W przypadku wybrania całej bazy, system losuje jedną z trzech baz.

Teraz chciałbym przejść do problemu, który napotkałem (jestem samoukiem, stąd chciałbym poradzić się u bardziej doświadczonych osób ). Na wstępie podam skrypt/kod (prędzej jest tylko wyciągnięcie numeru id/loginu użytkownika z sesji, co nie ma wpływu na zaistniały problem:

  1. <?php
  2. // Pobieramy wybrany przez użytkownika poziom trudności cytatu
  3. $ido = (int)$_GET['poziom'];
  4.  
  5. // Jeśli wybrano poziom trudności, ustalamy jego nazwę
  6. if($ido == 1)
  7. $poziomtrudnosci = "Łatwy";
  8. else if($ido == 2)
  9. $poziomtrudnosci = "Średni";
  10. else if($ido == 3)
  11. $poziomtrudnosci = "Trudny";
  12. else if($ido == 4)
  13. $poziomtrudnosci = "Cała baza";
  14. else
  15. $poziomtrudnosci = "Nie wybrano";
  16.  
  17. // Sprawdzamy czy użytkownik rozpoczyna dopiero test czy jest już w jego trakcie
  18. if($ido == NULL)
  19. {
  20. // Tworzymy podstawowe wartości dla użytkownika, który zaczyna test
  21. $button = "";
  22. $cytat = "Wybierz poziom trudności aby rozpocząć!";
  23. }
  24. else
  25. {
  26. // Jeżeli wybrano całą bazę, losujemy ją
  27. if($ido == 4)
  28. {
  29. // Losujemy poziom trudności
  30. $wylosowanabaza = rand(1, 3);
  31. }
  32. else
  33. {
  34. // Ustawiamy poziom trudności taki jak wybrano w formularzu
  35. $wylosowanabaza = $ido;
  36. }
  37.  
  38. // Sprawdzamy, który stopień trudności cytatów wybrano
  39. if($ido == 1 or $ido == 2 or $ido == 3)
  40. {
  41. // Ustalamy bazę danych, którą wybieramy
  42. $bazadanych = "cytaty$wylosowanabaza";
  43.  
  44. // Połączenie z baza danych MySQL
  45. include("polaczenie.php");
  46.  
  47. // Pobieranie najwyższego ID
  48. $pobierzID = "SELECT ID FROM $bazadanych WHERE ID > 0 ORDER BY ID DESC";
  49. $daneID = mysql_query($pobierzID);
  50. $wierszID = mysql_fetch_row($daneID);
  51.  
  52. // Ustalamy zakres losowanego ID
  53. $minID = 1;
  54. $maxID = $wierszID[0];
  55.  
  56. // Losujemy ID
  57. $wylosowanyID = rand($minID, $maxID);
  58.  
  59. // Pobieranie pola test użytkownika z bazy danych
  60. $pobierzpoletest = "SELECT test FROM uzytkownicy WHERE ID = $id";
  61. $danepoletest = mysql_query($pobierzpoletest);
  62. $wierszpoletest = mysql_fetch_row($danepoletest);
  63.  
  64. // Ustalamy nazwę dla naszej zmiennej
  65. $uzytecytaty = "$wierszpoletest[0]";
  66.  
  67. // Ustalamy formę dla wybranego ID na podstawie poziomu trudności
  68. if($ido == 1)
  69. $kod = "L";
  70. else if($ido == 2)
  71. $kod = "S";
  72. else if($ido == 3)
  73. $kod = "T";
  74. else
  75. $kod = "";
  76.  
  77. // Tworzymy kod
  78. $calykod = "$kod$wylosowanyID";
  79. $lancuch = strstr($uzytecytaty, $calykod);
  80.  
  81. if($lancuch === false)
  82. {
  83. echo("Pokazuje cytat, którego nie było");
  84. }
  85. else
  86. {
  87. do
  88. {
  89. // Losujemy kolejne ID
  90. $wylosowanyID = rand($minID, $maxID);
  91.  
  92. $calykod = "$kod$wylosowanyID";
  93. $lancuch = strstr($uzytecytaty, $calykod);
  94. }
  95. while(strstr($uzytecytaty, $calykod));
  96. echo("Wylosowano nowy cytat!");
  97. }
  98.  
  99. // Pobranie danych użytkownika
  100. $szukaj = "SELECT ID, tresc, skrot, ksiega, skrot2, ksiega2 FROM $bazadanych WHERE ID = '$wylosowanyID'";
  101. $dane = mysql_query($szukaj);
  102. $wiersz = mysql_fetch_row($dane);
  103.  
  104. // Zakończenie połączenia z bazą danych
  105. mysql_close($polaczenie);
  106.  
  107. // Tworzymy button dla użytkownika, który jest w trakcie testu
  108. $button = "<a href=\"index.php?strona=sprawdz-odpowiedz&poziom=$ido&pytanie=$wiersz[0]&odp=a\"><button class=\"button-odpowiedz\" type=\"button\">$wiersz[3] ($wiersz[2])</button></a><a href=\"index.php?strona=sprawdz-odpowiedz&poziom=$ido&pytanie=$wiersz[0]&odp=b\"><button style=\"margin-left: 2px;\" class=\"button-odpowiedz\" type=\"button\">$wiersz[5] ($wiersz[4])</button></a>";
  109.  
  110. // Pobieramy cytat
  111. $cytat = "<span style=\"font-weight: bold; \">&bdquo;$wiersz[1]&rdquo;</span><br />";
  112. }
  113. // OD TEGO MIEJSCA SKRYPT JEST TECHNICZNYM ZARYSEM, DORZUCIŁEM GO JEDYNIE ABY OSOBY, KTÓRE ZERKNĄ NA SKRYPT NIE MUSIAŁY MI PISAĆ, ŻE BRAKUJE TEJ CZĘŚCI
  114. else if($ido == 4)
  115. {
  116. // Ustalamy bazę danych, którą wybieramy
  117. $bazadanych = "cytaty$wylosowanabaza";
  118.  
  119. // Połączenie z baza danych MySQL
  120. include("polaczenie.php");
  121.  
  122. // Pobieranie najwyższego ID
  123. $pobierzID = "SELECT ID FROM $bazadanych WHERE ID > 0 ORDER BY ID DESC";
  124. $daneID = mysql_query($pobierzID);
  125. $wierszID = mysql_fetch_row($daneID);
  126.  
  127. // Ustalamy zakres losowanego ID
  128. $minID = 1;
  129. $maxID = $wierszID[0];
  130.  
  131. // Losujemy ID
  132. $wylosowanyID = rand($minID, $maxID);
  133.  
  134. // Pobranie danych użytkownika
  135. $szukaj = "SELECT ID, tresc, skrot, ksiega, skrot2, ksiega2 FROM $bazadanych WHERE ID = '$wylosowanyID'";
  136. $dane = mysql_query($szukaj);
  137. $wiersz = mysql_fetch_row($dane);
  138.  
  139. // Zakończenie połączenia z bazą danych
  140. mysql_close($polaczenie);
  141.  
  142. // Tworzymy button dla użytkownika, który jest w trakcie testu
  143. $button = "<a href=\"index.php?strona=sprawdz-odpowiedz&poziom=$ido&pytanie=$wiersz[0]&odp=a\"><button class=\"button-odpowiedz\" type=\"button\">$wiersz[3] ($wiersz[2])</button></a><a href=\"index.php?strona=sprawdz-odpowiedz&poziom=$ido&pytanie=$wiersz[0]&odp=b\"><button style=\"margin-left: 2px;\" class=\"button-odpowiedz\" type=\"button\">$wiersz[5] ($wiersz[4])</button></a>";
  144.  
  145. // Pobieramy cytat
  146. $cytat = "<span style=\"font-weight: bold; \">&bdquo;$wiersz[1]&rdquo;</span><br />";
  147. }
  148. else
  149. {
  150. // Nie wybrano jeszcze poziomu trudności
  151. }
  152. }
  153. ?>


Problem wygląda następująco i dotyczy tego kawałka kodu:

  1. // Tworzymy kod
  2. $calykod = "$kod$wylosowanyID";
  3. $lancuch = strstr($uzytecytaty, $calykod);
  4.  
  5. if($lancuch === false)
  6. {
  7. echo("Pokazuje cytat, którego nie było");
  8. }
  9. else
  10. {
  11. do
  12. {
  13. // Losujemy kolejne ID
  14. $wylosowanyID = rand($minID, $maxID);
  15.  
  16. $calykod = "$kod$wylosowanyID";
  17. $lancuch = strstr($uzytecytaty, $calykod);
  18. }
  19. while(strstr($uzytecytaty, $calykod));
  20. echo("Wylosowano nowy cytat!");
  21. }
  22.  
  23. // Pobranie danych użytkownika
  24. $szukaj = "SELECT ID, tresc, skrot, ksiega, skrot2, ksiega2 FROM $bazadanych WHERE ID = '$wylosowanyID'";
  25. $dane = mysql_query($szukaj);
  26. $wiersz = mysql_fetch_row($dane);
  27.  
  28. // Zakończenie połączenia z bazą danych
  29. mysql_close($polaczenie);
  30.  
  31. // Tworzymy button dla użytkownika, który jest w trakcie testu
  32. $button = "<a href=\"index.php?strona=sprawdz-odpowiedz&poziom=$ido&pytanie=$wiersz[0]&odp=a\"><button class=\"button-odpowiedz\" type=\"button\">$wiersz[3] ($wiersz[2])</button></a><a href=\"index.php?strona=sprawdz-odpowiedz&poziom=$ido&pytanie=$wiersz[0]&odp=b\"><button style=\"margin-left: 2px;\" class=\"button-odpowiedz\" type=\"button\">$wiersz[5] ($wiersz[4])</button></a>";
  33.  
  34. // Pobieramy cytat
  35. $cytat = "<span style=\"font-weight: bold; \">&bdquo;$wiersz[1]&rdquo;</span><br />";


Kod, który wylosuje ID, sprawdza za pomocą funkcji strstr() czy występuje dany cytat w bazie danych użytkownika (czy został już użyty - każdy użyty jest zapisywany w tabeli użytkowników w polu "test", przyjmuje on formę np. L3, L10, L100 itd. co oznacza L - łatwy, 100 numer ID).

W momencie kiedy mamy do wyboru np. trzy cytaty w bazie danych o stopniu łatwym i tylko ta baza została wybrana, dwa z nich zostały użyte, czyli znajdują się już w zmiennej $uzytecytaty, system poprawnie losuje 3 cytat, który pozostał w bazie danych i nie był użyty w quizie.

Problem pojawia się, kiedy każdy z cytatów został wykorzystany dla wybranego poziomu trudności, wtedy pętla wpada w nieskończoną. Próbowałem opcji break, endwhile niestety nic z tego nie zadziałało w sposób, który byłby rozwiązaniem tego problemu.

W związku z tym, że programistą nie jestem i robię to jako pasję (po prostu uczę się - dlatego też do Was napisałem), domyślam się, że problem może leżeć w konstrukcji pętli, może formie, wyborze rodzaju pętli.

Chciałbym poprosić o pomoc w rozwiązaniu mojego problemu. Za każdą z odpowiedzi będę bardzo wdzięczny.

Pozdrawiam
Piotr
Go to the top of the page
+Quote Post
nospor
post
Post #2





Grupa: Moderatorzy
Postów: 36 557
Pomógł: 6315
Dołączył: 27.12.2004




Po pierwsze nie myl pojec:
tabela
baza danych

Po drugie:
twoje cytaty maja byc w jednej tabeli, ktora dodatkowo bedzie mialo pole: POZIOM
I wszystko nagle staje sie latwiejsze


--------------------

"Myśl, myśl, myśl..." - Kubuś Puchatek || "Manual, manual, manual..." - Kubuś Programista
"Szukaj, szukaj, szukaj..." - Kubuś Odkrywca || "Debuguj, debuguj, debuguj..." - Kubuś Developer

Go to the top of the page
+Quote Post
rex
post
Post #3





Grupa: Zarejestrowani
Postów: 15
Pomógł: 0
Dołączył: 25.11.2009

Ostrzeżenie: (0%)
-----


Pierwotnie tak była skonstruowana baza. Podpowiedz zatem w jaki sposób wyodrębnić min i max dla konkretnego poziomu.

Zakładając Twój pomysł z polem "poziom". Jak ustalić minimalną i maksymalną wszystkich cytatów dla poziomu danego przy założeniu, że:

1 | Cytat | Łatwy
2 | Cytat | Średni
3 | Cytat | Średni
4 | Cytat | Trudny
5 | Cytat | Łatwy
6 | Cytat | Trudny
7 | Cytat | Łatwy
8 | Cytat | Łatwy
9 | Cytat | Trudny
10 | Cytat | Średni

Oczywiście nie jest to forma, jedynie przykład.

Albo w przypadku kiedy byłaby baza ale każdy cytat byłby o jednakowym stopniu trudności. Biorąc pod uwagę pętlę do while, którą użyłem w jaki sposób zmienić jej konstrukcje (lub zastosować inną może), która wykona tą samą funkcję ale w przypadku wylosowania wszystkich możliwych cytatów, zwróci komunikat: Wylosowano już wszystkie dostępne cytaty, koniec gry.
Go to the top of the page
+Quote Post
nospor
post
Post #4





Grupa: Moderatorzy
Postów: 36 557
Pomógł: 6315
Dołączył: 27.12.2004




Masz jeszcze skopana tabele z cytatami, ktore user juz widzial. ma byc tabela:

USER_CYTAT z polami:
ID_USER, ID_CYTAT

Potem losowanie jest juz banalne:

select * from CYTATY where ID not in (SELECT ID_CYTAT from USER_CYTAT where ID_USER=id_usera) order by rand() limit 3

To tylko szybki szkic. Oczywiscie musi dojsc warunek na poziom itp ale idea bedzie wlasnia taka. Mozna jeszcze usprawnic losowanie bo order by rand() do optymalnych nie nalezy.


--------------------

"Myśl, myśl, myśl..." - Kubuś Puchatek || "Manual, manual, manual..." - Kubuś Programista
"Szukaj, szukaj, szukaj..." - Kubuś Odkrywca || "Debuguj, debuguj, debuguj..." - Kubuś Developer

Go to the top of the page
+Quote Post
rex
post
Post #5





Grupa: Zarejestrowani
Postów: 15
Pomógł: 0
Dołączył: 25.11.2009

Ostrzeżenie: (0%)
-----


Okej, dzięki za podpowiedź, wieczorem pewnie zajmę się i spróbuje ponownie przerobić bazę.

Mam jeszcze zapytanie odnośnie pętli, której użyłem. Co w niej jest nie tak i jak mogłaby ona wyglądać aby spełniła swoją funkcję (jak już coś robię to na przyszłość być może się przyda ta wiedza).
Go to the top of the page
+Quote Post
nospor
post
Post #6





Grupa: Moderatorzy
Postów: 36 557
Pomógł: 6315
Dołączył: 27.12.2004




Nie chce mi sie analizowac tej calej sieczki, no ale jak nie ma juz nic do wylosowania to sie zapetlasz. Musisz sprawdzic czy jest cos do losowania czy nie i jak nie to robic break.


--------------------

"Myśl, myśl, myśl..." - Kubuś Puchatek || "Manual, manual, manual..." - Kubuś Programista
"Szukaj, szukaj, szukaj..." - Kubuś Odkrywca || "Debuguj, debuguj, debuguj..." - Kubuś Developer

Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 21.08.2025 - 10:03