• Das Erstellen neuer Accounts wurde ausgesetzt. Bei berechtigtem Interesse bitte Kontaktaufnahme über die üblichen Wege. Beste Grüße der Admin

Highscore-Script

T

Telmehtar

Guest
Hallo,

das soll ein kleines Script sein, welches zwei Werte einfach in eine Datei schreibt. Der erste Wert befindet sich im Span "userTime_name", existiert anfangs aber noch nicht, sondern wird erst später reingeschrieben. Der zweite Wert ist im Input "inp_hs_name". Wenn der Name bereits vorhanden ist, soll eine dies aussagende Meldung unter dem Submit-Button erscheinen. Wenn er nicht vorhanden ist, soll er mit dem "userTime_name" in eine Datei gespeichert werden.

Mein Problem:
"userTime_name" existiert offensichtlich nicht. "Notice: Undefined index: userTime_name..." Und war in der Zeile "$userTime = $_POST['userTime_name'];"

HTML:
		<form method="post">
			<div id="alertbox">
			Willst du deine Zeit (<span id="userTime_" name="userTime_name"></span>) im Highscore speichern?
			<br /><br />
			<span id="hs_name">
			Name:
			<input type="text" size="24" maxlength="12" name="inp_hs_name"/>
			</span>
			<br /><br />
			<input type="submit" value="Submit" />
			<?php
			if((isset($_POST['inp_hs_name']) AND $_POST['inp_hs_name'] != "") OR (isset($_POST['inp_hs_name']) AND $_POST['inp_hs_name'] != " ") OR (isset($_POST['userTime_name']) AND $_POST['userTime_name'] != "")){			    
                           $existing_users = array();
			   $userTime = $_POST['userTime_name'];
			   $username = $_POST['inp_hs_name'];
			   
			   $userdatei = fopen ("users.txt","r");
			   while (!feof($userdatei))
				  {
				  $zeile = fgets($userdatei,500);
				  $userdata = explode("|", $zeile);
				  array_push ($existing_users,$userdata[0]);
				  }
			   fclose($userdatei);

			   if (in_array($username,$existing_users)){
				  echo "<span class='errors'>Username schon vorhanden.</span><br>";
				  }

			   else{
				  $eintrag ="$username|$userTime";
				  $userdatei = fopen ("users.txt","a");
				  fwrite($userdatei, "$eintrag\n\r");
				  fclose($userdatei);
			echo "<br /><br/><div class='emptyField'>Eintrag gespeichert.</div>";
				  }
			   }
/*			
			else if(isset($_POST['inp_hs_name']) AND $_POST['inp_hs_name'] == "" OR isset($_POST['inp_hs_name']) AND $_POST['inp_hs_name'] != " "){
			$quest = 0;
			$quest++;
			echo $quest;
			}
			
			*/
			?>
			</div>
			</form>


MfG,
Telmehtar
 
Zuletzt bearbeitet von einem Moderator:
Bei einem Formular werden nur <input>s, <textarea>s und <select>s übertragen - keine "normalen" HTML-Nodes.
Mach' aus deinem <span> ein <input> mit readonly und es sollte funktionieren.
 
Ah, danke.

Dann habe ich noch ein kleines Problem:

Mit dem oberen Script werden ja 2 Werte so "Wert1|Wert2" in die Datei geschrieben.
Jetzt möchte ich daraus einen Highscore machen.

Im ersten Feld ist die Platzierung ($i), im zweiten der Name ($friend[0]) und im dritten eine Zahl ($friend[1]).
Da der Highscore nach den Zahlen sortiert werden soll, habe ich es so probiert, dass ich die Zahl als Key nehme, und diesen dann sortiere, da kam aber nichts gutes raus:

HTML:
<table>

<tr>
<th>Platz</th>
<th>Name</th>
<th>Zeit</th>
<th>Achievements</th>
</tr>

<tr>
</tr>

<?php
$i = 0;
$file_ = fopen("users.txt", "r");
while(!feof($file_)){
	while($line = fgets($file_)){
	    $friend = explode("|", $line);
		foreach($friend as $data_){
			$array_ = array($friend[1] => $friend[0]);
			ksort($array_);
			$i++;
			foreach ($array_ as $key => $val) {
				echo "<tr>
						<td>$i.</td>
						<td>$val</td>
						<td>$key</td>
					   </tr>
						";
			}
		}
	}
 }
 fclose($file_);
?>
</table>
</table>

In der Datei "users.txt" steht das:
Hallo|01:02:04:345
Tschüss|00:11:22:35:123


Das kommt aber als Ergebnis raus:

Code:
1. 	Hallo 	        01:02:04:345
2. 	Hallo 	        01:02:04:345
3. 	Tschüss 	00:11:22:35:123
4. 	Tschüss 	00:11:22:35:123


Wobei ich es eigentlich so haben möchte:

Code:
1.     Tschüss    00:11:22:35:123
2.     Hallo         01:02:04:345
 
Zuletzt bearbeitet von einem Moderator:
Du musst natürlich erst die komplette Datei einlesen und dann erst die Sortierung/Ausgabe machen.
 
Wie genau müsste ich das dann machen, soll das Sortieren außerhalb der Schleifen passieren?
Da wird ja eigentlich die komplette Datei eingelesen, oder?
 
Ja - außerhalb der Schleife.

PS: Stringvergleiche laufen anders als Zahlenvergleiche - so ist "123" kleiner als "23"...
 
so hallo Telmehtar,

kurze Anmerkungen (aber dafür einige) an deinen code:
1. Dein wegschreibe skript
1) Wichtig: halte dich an das eva prinzip!
2) anpassungen direkt im code:
Code:
<?php
// Sicher das du willst was dort steht?
// Also es soll entweder in inp_hs_name etwas stehen oder in userTime_name? Sollte nicht besser in beidem etwas stehen? sonst läuft dein skript auch
// in einen error 2 zeilen tiefen. angenommen es existiert nur einer der beiden werte, dann kannst du sie nicht beide auslesen, bzw der nicht existierende,
// würde einen fehler verursachen...
		if((isset($_POST['inp_hs_name']) AND $_POST['inp_hs_name'] != "") OR (isset($_POST['inp_hs_name']) AND $_POST['inp_hs_name'] != " ") OR (isset($_POST['userTime_name']) AND $_POST['userTime_name'] != "")){
// meinst du nicht eher soetwas?
		if(isset($_POST['inp_hs_name'], $_POST['userTime_name']) && !empty(trim($_POST['inp_hs_name'])) && !empty(trim($_POST['userTime_name'])))
                           	   $existing_users = array();
// was soll das umschreiben in neue Variablen? Das ist eigentlich unnötig.
			   $userTime = $_POST['userTime_name'];
			   $username = $_POST['inp_hs_name'];
// Kompliziertes einlesen/schreiben Teil 1:
			   $userdatei = fopen ("users.txt","r");
			   while (!feof($userdatei))
				  {
				  $zeile = fgets($userdatei,500);
				  $userdata = explode("|", $zeile);
				  array_push ($existing_users,$userdata[0]);
				  }
			   fclose($userdatei);
// Kurzes einlesen/schreiben Teil 1 ;):
			   $existing_users = array_map(function($el) { $tmp=explode('|', $el); return $tmp[0]; }, file('users.txt'));
// Die Überprüfung ist natürlich völlig okay, allerdings gibt man keinen html code direkt in php logik aus... das ist unsauber und bedarf einer Trennung
			   if (in_array($username,$existing_users)){
				  echo "<span class='errors'>Username schon vorhanden.</span><br>";
				  }
			   else{
				  $eintrag ="$username|$userTime";
// Kompliziertes einlesen/schreiben Teil 2:
				  $userdatei = fopen ("users.txt","a");
				  fwrite($userdatei, "$eintrag\n\r"); // \n\r?? line feed catch return? xD Falschrum ;) es lautet \r\n
				  fclose($userdatei);
// Kurzes einlesen/schreiben Teil 2 ;):
				  file_put_contents('users.txt', $eintrag."\n", FILE_APPEND | LOCK_EX);
// Auch hier wieder die ausgabe innerhalb der logik...
			echo "<br /><br/><div class='emptyField'>Eintrag gespeichert.</div>";
				  }
			   }
			?>

2. Dein anzeige skript
1) wieso enden deine variablennamen auf einem unterstrich? Normale konvention wäre, dass der unterstrich nach vorne gehört und damit werden private oder protected properties von klassen beschrieben... keine normalen variablen
2) html ausgaben gehören nicht mitten in den phpcode
3) Wieso liest du die datei so kompliziert ein?
4) Die verschachtelte schleife ergibt wie bereits angesprochen keinen sinn
5) evtl solltest du eine vernünftige datenstruktur zum speichern verwenden
6) Dadurch das die zeit aus einem postrequest stammt, läd dein script nur so zum cheaten ein... aber gut das lass ich mal deine sorge sein ;)

Kleines Beispiel:
Die Datei (users.txt):
Code:
Thomas|15:23:01:123
Finn|14:12:00:065
// Ich deute das mal als stunden:minuten:sekunden:milisekunden... was ist dein viertes zweierpärchen da oben? tage...? Bitte erklärung ;)
Code:
<?php
  // Wieder das kurze einlesen:
  $datarecords = array_map(function($el) { return explode("|", $el); }, file("users.txt"));
  // sortieren (mit eigener vergleichsfunktion, sonst kann man mit dem Time format nix anfangen...):
  usort($datarecords, function($a, $b) {
    // $a und $b sind je felder von dem array $datarecords, diese sind durch das explode ja auch wieder arrays der form: array(0=>name, 1=>zeitangabe)
    // Wir wollen ja anhand der zeitangaben sortieren, daher greifen wir gleich immer auf $a[1] und $b[1] zu. weiterhin berechnen wir zum sinnvollen vergleichen
    // die milisekundenanzahl der gesammt ausdrücke:
    $tmpA = explode(":", $a[1]); // Die parts von $a
    $tmpB = explode(":", $b[1]); // Die parts von $b
    $resA = 0; // milisekundenanzahl des strings aus $a
    $resB = 0; // milisekundenanzahl des strings aus $b
    for($i=0;$i<count($tmpA)-1;$i++) // über alle parts von a laufen und mit den passenden potenzen multiplizieren:
      $resA += pow(60, (count($tmpA)-1-$i))*1000*$tmpA[$i];
    $resA+=$tmpA[count($tmpA)-1];
    for($i=0;$i<count($tmpB)-1;$i++) // über alle parts von b laufen und mit den passenden potenzen multiplizieren:
      $resB += pow(60, (count($tmpB)-1-$i))*1000*$tmpB[$i];
    $resB+=$tmpB[count($tmpB)-1];
    // sortierung duch rückgabe von -1, 0 oder 1 (bitte lies nach, wenn du nicht weißt wie es funktioniert!)
    if($resA == $resB) return 0;
    return ($resA < $resB) ? 1 : -1;
  });
  $i=1;
  foreach($datarecords as $record)
    echo "<tr>
      <td>".$i++."</td>
      <td>".$record[0]."</td>
      <td>".$record[1]."</td>
    </tr>";
?>

So ich hoffe das hilft dir ein bisschen. mit dem Zeitvergleich ist evtl nicht perfekt gelöst, aber dein format ist nun auch nicht so super gewählt^^ fiel mir grad nix besseres ein. Das alles ist ungetestet, sollte denke ich aber lauffähig sein, bis auf tippfehler oder so. Die musste dann schon selbst finden. Wenn du fragen hast... frag :)

bzgl dem \r\n... ich glaube um es mit file() einzulesen darfst du nur ein \n verwenden... weiß es aber grad nicht mehr... probiers einfach aus. (Mein code nutzt nur \n, aber wenn du deinen anpassen willst musst du darauf eben achten)

Lg Kasalop
 
Zuletzt bearbeitet:
Erstmal, ein fettes DANKE :D

Um das ganze aufzulösen:

Der Code ist Teil eines kleinen Spiels, bei dem es darum geht, die Zeit von Button-Klicks zu messen. Es gibt eine vorgegebene Zahl. Diese muss man dann, so schnell wie nur möglich, per Klick auf den richtigen Button nachtippen (0-9).

Die Zeit im Format Monat:TT:HH:MM:SS:MilliS gemessen werde. Ein bisschen übertrieben, aber Spaß muss sein :D. Ich kam bisher nur nicht dazu, den Monat und die Tage korrekt zu berechnen, bei der Stoppuhr.

Jedenfalls wird dann der Name des Kandidaten mit seiner Zeit in eine Datei mit den anderen Kandidaten und deren Zeiten geschrieben, und dann soll dies als Highscore ausgegeben werden.

\r\n habe ich benutzt, weil er bei \n\r irgendwie nicht in eine neue Zeile ging.

In inp_hs_name muss nichts stehen. Wenn dieses Feld leer ist, so soll ein automatischer Name generiert werden (GuestX; X... 1, 2, 3, ..., n)
userTime_name ist ja die Zeit, da muss etwas stehen, und das wird ja mittels JS reingeschrieben.

Und um deine restlichen Fragen zu beantworten: Ich bin noch nicht soo wirklich der Pro in PHP, aber das wird sicher noch in den nächsten Jahren kommen ^^.



Dann habe ich noch ein paar Fragen:
1) Was ist das "eva"-Prinzip?
2) Wie würdest du es ohne das Umschreiben in neue Variablen lösen? Immer nur mit $_POST[...]; ?
3) Weitere Fragen folgen vllt. noch morgen^^.
 
Die Zeit im Format Monat:TT:HH:MM:SS:MilliS gemessen werde. Ein bisschen übertrieben, aber Spaß muss sein :D. Ich kam bisher nur nicht dazu, den Monat und die Tage korrekt zu berechnen, bei der Stoppuhr.
wo liegt deine schwierigkeit dabei?

\r\n habe ich benutzt, weil er bei \n\r irgendwie nicht in eine neue Zeile ging.
du hast aber kein \r\n verwendet... das wäre korrekt. du hast \n\r verwendet... und das ist falsch ;)

In inp_hs_name muss nichts stehen. Wenn dieses Feld leer ist, so soll ein automatischer Name generiert werden (GuestX; X... 1, 2, 3, ..., n)
userTime_name ist ja die Zeit, da muss etwas stehen, und das wird ja mittels JS reingeschrieben.
achso entschuldige, dass hatte ich dann wohl falsch verstanden. aber dann ist deine if-abfrage trotzdem nicht gut gewählt.

Und um deine restlichen Fragen zu beantworten: Ich bin noch nicht soo wirklich der Pro in PHP, aber das wird sicher noch in den nächsten Jahren kommen ^^.
Kein Problem. wir alle haben klein angefangen. ich schreib es ja nicht aus schickane, sondern um dir hinweise zu geben, an denen du dich beim wieterkommen orientieren kannst ;)

Dann habe ich noch ein paar Fragen:
1) Was ist das "eva"-Prinzip?
2) Wie würdest du es ohne das Umschreiben in neue Variablen lösen? Immer nur mit $_POST[...]; ?
3) Weitere Fragen folgen vllt. noch morgen^^.

1) echt jetzt? Ich bitte doch um etwas eigeninitative: eva prinzip
2) im besten fall greifst du auf diese variablen gar nicht so oft zu ^^ aber wenn dann kannste immer auf $_POST[..] zugreifen, aber kannst es auch in handlichere Namen umschreiben ;) passt am anfang schon :)
3) gut dann erstmal viel spaß beim verstehen meines codes und ich hoffe du kannst etwas mit anfangen ;) gut lesen und wenn du befehle nicht kennst, etc schau erstmal bei google. wenn dir dann etwas unklar ist, frag einfach nach

Lg Kasalop
 
wo liegt deine schwierigkeit dabei?
Ich poste den Code heute noch im JS-Bereich, dann darfst du es dir gerne ansehen :D.

du hast aber kein \r\n verwendet... das wäre korrekt. du hast \n\r verwendet... und das ist falsch ;)
Sorry, da habe ich mich vertippt. Eben bei "\r\n" wollte er nicht in eine neue Zeile gehen.
Bei deinem Code passiert aber das selbe. Er bleibt in einer Zeile.

achso entschuldige, dass hatte ich dann wohl falsch verstanden. aber dann ist deine if-abfrage trotzdem nicht gut gewählt.
Bei deiner kommt aber noch dieser Fehler "Fatal error: Can't use function return value in write context in C:\xampp\htdocs\UE4_Smailagic\stoppuhr_buttonspiel_Angabe.php on line 253"


1) echt jetzt? Ich bitte doch um etwas eigeninitative: eva prinzip
2) im besten fall greifst du auf diese variablen gar nicht so oft zu ^^ aber wenn dann kannste immer auf $_POST[..] zugreifen, aber kannst es auch in handlichere Namen umschreiben ;) passt am anfang schon :)
3) gut dann erstmal viel spaß beim verstehen meines codes und ich hoffe du kannst etwas mit anfangen ;) gut lesen und wenn du befehle nicht kennst, etc schau erstmal bei google. wenn dir dann etwas unklar ist, frag einfach nach
1) Das war eher eine rhetorische Frage, um darauf hinzuweisen, dass ich nicht weiß, was das ist ;).
3) Danke^^
 
Zuletzt bearbeitet von einem Moderator:
Kasalop, könntest du mir bitte den Sortier-Algorythmus vom Highscore erklären, ich versteh´s nicht so ganz. Wozu genau "pow" ?
 
funktioniert er denn? ^^

pow steht für power und ist für potenzen zuständig. und das ist zum umwandeln von sekunden, minuten, stunden, etc in milisekunden. ich geb zu, dass es bei tagen dann mit 60 multipliziert nicht mehr wirklich stimmt xD aber die potenz schafft eine klare Trennung, ohne doppeldeutigkeiten, dass sollte schon okay sein ;) aber sind dann eben keine echten milisekunden mehr, sondern mehr eine proprietäre Einheit^^

was gibts da groß zu erklären? Die sortierfunktion bekommt eine callback-routine und das array übergeben, diese callbackroutine wird immer mit 2 warten des arrays aufgerufen und du musst in der callback-routine entscheiden wie diese beiden elemente zu einander stehen. 0 = sie sind gleichbedeutend. 1 und -1 belassen die beiden elemente in der reihenfolge in der sie sind oder invertieren sie. und so wird dann nach und nach das array sortiert und wieder in die quelle zurück gespeichert... wo ist deine frage jetzt genau?

Lg Kasalop
 
Zurück
Oben