Bonjour,

J'ai plusieurs questions de petite taille, c'est pour cela que je les regroupe dans un seul sujet.

1) Validation W3c et présentation de la page html
Comment écrire ses pages html ?

Ainsi :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
<html>
	<head>
		<meta charset="UTF-8">
		<link rel="style_sheet" type="text/css" href="feuille_style.css">
		<title> Titre de page </title>
	</head>



	<body>
...
ou ainsi :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE html>

<html lang="fr" xmlns="http://www.w3.org/1999/xhtml">

<head>
...
Le premier est bien plus lisible et pratique mais ne passe pas à la validation W3c contrairement au second.

2) Rechargement de page et action PHP

Je suis confronté au problème suivant :
Voici le lien de mon site
Le code PHP est à la fin car il est un peu long.
Il s'agit d'un petit jeu d'aventure basique pour un travail dans mon école. Il marche bien mais possède un problème : il supporte très mal les rechargements de page et les retours en arrière.

J'ai trouvé deux cas en particulier :
- lorsqu'on vient de s'identifier et qu'on fait un retour en arrière : cela provoque une erreur
- lorsqu'on prend un objet (en rajoutant un $_GET['take]) et qu'on recharge la page, l'objet est pris une deuxième fois.

Plus généralement, mon code n'est pas du tout robuste car il suffit à l'utilisateur de changer ce qu'il veut dans l'URL pour faire ce qu'il veut (aller dans une pièce, prendre un objet, ...). Faut-il mettre des tests partout ?
En fait, ce qui m'en empêche, c'est que je ne sais pas si un code PHP peut avoir de la mémoire (par exemple savoir dans quel pièce se trouvait le personnage avant celle-ci, savoir s'il a déjà pris un objet, ...)

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
<html>
	<head>
		<meta charset="UTF-8">

		<title>La traque</title>

		<link rel="stylesheet" type="text/css" href="feuille_style.css">

	</head>

	<body>

	<header>
	<h1>La traque</h1>
	</header>

		<?php
			session_start();

			//to log in the player
			function show_login_form_action()
			{
				echo "<div class='start_blocks'><p> Tu as toujours rêvé de devenir un détective privé, un fin limier mettant les pires criminels derrière les verrous ? Si tes parents t'ont forcé à abandonner ta vocation pour devenir ingénieur, avocat ou médecin, retrouve tes rêves d'enfants et mets toi dans la peau du détective devant arrêter le terribe Jack l'éventreur.</p> </div><p>Remplis simplement ton nom pour commencer </p>";
				echo "<form method='GET'>";
				echo "	<p> nom = <input type='text' name='name'></p>";
				echo "	<input type='hidden' name='action' value='login'>";
				echo "  <input type='submit' value='ok'>";
				echo "</form>";
			}

			//to record the name of the player
			function login_action()
			{
 				$_SESSION["username"] =  $_GET["name"];
				default_action();
			}

			//when the player is logged in
			function default_action()
			{
				echo "<div class='start_blocks'> <p> Bonjour ";
				echo $_SESSION["username"] . ". Prends garde, l'aventure commence ... </p> </div>";
				echo " <a href='game.php?action=play'> <p>Jouer au jeu </p></a> <a href='game.php?action=logout'> <p> Déconnexion </p></a>";
			}

			//when the URL is unknown
			function unknown_action()
			{
				echo "<p> Erreur ! </p> <a href='game.php?action=logout'> <p> Déconnexion </p></a> ";
			}

			//to log out the player
			function logout_action()
			{
				echo "<p> Adieu ";
				echo  $_SESSION["username"] . "</p>";
				echo " <a href='game.php'> <p> Connexion </p></a>";
				session_destroy();

			}

			//to check if the player is allowed to enter the room, if he wins or if he loses
			function condition_met($which_condition)
			{
				global $world;
				global $objects;
				
				//for "enter", the default action is "you can enter" and then we serach if there is a condition. For "win" or "lose", it can be true only iof there is a condition.
				$result = ("enter" === $which_condition) ? true: false;
				if (isset($world[$_SESSION["room"]][$which_condition."_condition"]))
				{
					$result = true;
					foreach($world[$_SESSION["room"]][$which_condition."_condition"] as $id_object)
						{
							$result = $result && ($_SESSION["inventory"]["$id_object"] >= 1);
						}
				}
				return $result;								
			}

			// display all : the descritption, the items, the inventory, the map ans the outputs.
			function display_room()
			{

				global $world;
				global $objects;
				
			
				$can_enter = condition_met("enter");
				$win = condition_met("win");
				$lose = condition_met("lose");

				echo "<div id='description_objects_block'>";
				//display description
				echo "	<div class='text_blocks' id='description_block'>";
				echo "	<h3> La pièce </h3>";				
				if ($can_enter)
				{
					if($win)
					{
						echo "<p>". $world[$_SESSION["room"]]["win_message"] . "</p>";
						echo "<p> <b> Bravo ! Tu as gagné :) </b> </p>";
					}
					elseif($lose)
					{
						echo "<p>". $world[$_SESSION["room"]]["lose_message"] . "</p>";
						echo "<p> <b>Dommage ! Tu as perdu :( </b> </p>";
					}
					else
					{
						echo "<p>". $world[$_SESSION["room"]]["message"] . "</p>";
					}
				}
				else
				{
					echo "<p>". $world[$_SESSION["room"]]["no_enter_message"] . "</p>";
				}
				echo "	</div>";


				if ($can_enter && !$win && !$lose)
				{
					echo "	<div  class='text_blocks' id='objects_block'>";
					//display items
					echo "<div class='image'><img src='images/main.png' alt=Une main/></div>";
					echo "<h3 id='title_room_objects'> Ce que tu peux récupérer dans cette pièce :</h3>";
					if (isset($world[$_SESSION["room"]]["stuff"]))
					{
						echo "<ul>";
						foreach($world[$_SESSION["room"]]["stuff"] as $id_object => $amount_object)					
						{
							if ("0" != $amount_object)
							{
								echo "<li><a href=game.php?action=play&go=". $_SESSION["room"] ."&take=" . $id_object .">"."<p>". $objects[$id_object] ." : x" .$amount_object . "</p>" ."</li></a>";
							}
						} 	
						echo "</ul>";
					}
					else
					{
						echo "<p>Il n'y a rien à récupérer dans cette pièce.</p>";
					}
				}

				if (!$win && !$lose)
				{
					if (!$can_enter)
					{
						echo "	<div  class='text_blocks' id='objects_block'>";
					}
					//display inventory
					echo "<div class='image'><img src='images/malette.png' alt=Une malette/></div>";
					echo "<h3>Ce que tu possèdes :</h3>";
					if (isset($_SESSION["inventory"]))
					{
						echo "<ul>";
						foreach($_SESSION["inventory"] as $id_object => $amount_object)					
						{
							if ("0" != $amount_object)
							{
								echo "<li>" . "<p>" .$objects[$id_object] ." : x" .$amount_object . "</p></li>";
							}
						} 	
						echo "</ul>";
					}
					else
					{
						echo "<p>Ton inventaire est vide.</p>";
					}
				echo "	</div>";
				}

				echo "</div>";

				echo "<div id='map_outputs_block'>";

				//display map
				echo '	<div id="map_block"><canvas id ="map" width="300" height="300"></canvas>';
				echo "		<h3 id='title_map'>La carte du jeu</h3>";
				echo "	</div>";


				//display the outputs of the room
				if ($can_enter && !$win && !$lose)
				{
					echo "	<div  class='text_blocks' id='outputs_block'>";
					if (isset($world[$_SESSION["room"]]["outs"]))
					{
						echo "<h3>Se diriger vers :</h3>";
						echo "<ul>";
						foreach($world[$_SESSION["room"]]["outs"] as $name_room => $id_room)					
						{
							echo "<li><a href=game.php?action=play&go=".$id_room."><p>".$name_room."</p></a></li>";
						} 	
						echo "</ul>";
					}
					echo "	</div>";
				}
				if (!$can_enter && !$win && !$lose)
				{
					echo "	<div  class='text_blocks' id='outputs_block'>";
					if (isset($world[$_SESSION["room"]]["no_enter_outs"]))
					{
						echo "<h3>Revenir vers :</h3>";
						echo "<ul>";
						foreach($world[$_SESSION["room"]]["no_enter_outs"] as $name_room => $id_room)					
						{
							echo "<li><a href=game.php?action=play&go=".$id_room."><p>".$name_room."</p></a></li>";
						} 	
						echo "</ul>";
					}
					echo "	</div>";
				}

				echo "</div>";

			}

			//defines the variables "world" and "objects"
			function world_definition()
			{
			global $objects;

			$objects = array(0 => "une clé un peu tordue",
					 1 => "un fusil",
					 2 => "un album de photos de famille",
					 3 => "une lampe torche",
					 4 => "un biscuit à la cannelle",
					 5 => "un vase en céramique",
					 6 => "un coussin");

			global $world;
			$world = array(
				0 => array("name" => "extérieur",
		 			   "outs" => array("la porte d'entrée" => 1),
				           "message" => "Cette fois, c'est bon ! Après des jours de traque intensive, tu es devant la maison où se cache le terrible Jack l'éventreur ! Tu viens de faire le tour de la maison et constates qu'il n'y a pas d'autre issue. Pris d'impatience et voulant garder tout le succès pour toi,tu ouvres discrètement la porte principale et pénètres dans la maison, tous les sens aux aguets.",
					    "color" => "#32CD32",
					    "coordinates" => array("[0,300],","[0,200],","[300,200],","[300,300]")),

				1 => array("name" => "entrée",
				           "outs" => array("le couloir mystérieux" => 2,
				  			"l' escalier descendant" => 5,
				  		 	"l' escalier montant" => 6,
				  	 		"la porte rouge" => 7,
                                  			"la grande porte" => 8,
			          			"la porte un peu abîmée" => 9),
					   "message" => "Tu entres dans une pièce qui semble être l'entrée car elle mène à de nombreuses portes. Aucun signe de la présence de Jack. Le seul meuble de la pièce est une petite commode sur laquelle se trouve un album de photos. Dans les étagères, rien d'intéressant, à part une lampe torche. En face, il y a une grande porte à double battant dont de la lumière filtre en-dessous mais elle semble fermée. Un peu en retrait, une porte un peu abîmée avec 'toilettes' écrit dessus. A gauche, une porte rouge, quelconque et à droite, un long couloir plongé dont l'extrémité est plongée dans l'obscurité. Enfin, un escalier en vis se trouve à côté du couloir. Que choisis tu ?",
					   "color" => "#FFFFE0",
					   "coordinates" => array("[75,200],","[75,125],","[175,125],","[175,200]"),
					   "stuff" => array(2 => 1, 3 => 1)),

				2 => array("name" => "couloir mystérieux1",
		 			   "outs" => array("la suite du couloir" => 3,
				  			   "l'entrée" => 1),
					    "message" => "Tandis que tu avances dans le couloir, la lumière diminue ... ",
					    "color" => "#808080",
					    "coordinates" => array("[175,175],","[175,150],","[225,150],","[225,175]")),

				3 => array("name" => "couloir mystérieux2",
		      			   "outs" => array("la pièce au bout du couloir" => 4,
				  			   "le début du couloir" => 1),
					   "message" => "La lumière continue à diminuer mais tu aperçois au loin une lueur. Vue l'odeur qui commence à se faire sentir, c'est sûrement la pièce dans lequel ce psychopathe égorge ses victimes ! Par prudence, tu n'utilises pas de source de lumière",
					    "color" => "#696969",
					    "coordinates" => array("[225,175],","[225,150],","[275,150],","[275,175]")),

				4 => array("name" => "couloir mystérieux3",
				   	   "lose_message" => "Tu avais malheureusement raison ! La vision de cadavres sanguinolents et de chairs étalées au sol se précise au fur et à mesure que vous avancez dans le couloir. Tu tentes de surmonter ta répulsion mais tu ne peux retenir un haut-le-coeur en entrant dans la pièce. C'est malheureusement le moment où Jack, caché sur sur le côté de la pièce, bondit sur toi ! Tu as à peine le temps d'apercevoir l'éclat d'un couteau que celui-ci se retrouve planté dans ton coeur !  Sous la surprise et la douleur, tu lâches ton arme et tu te vides de ton sang, devant un Jack jubilant. Il était accablé à son macabre travail, ayant déjà son couteau à la main et ayant entendu les échos de tes pas dans le couloir, s'était caché pour te prendre au piège.",
					   "color" => "#DC143C",
					   "coordinates" => array("[275,175],","[275,150],","[300,150],","[300,175]"),
					   "lose_condition" => array()),		   
				 
				5 => array("name" => "cave",
		 		  	   "outs" => array("l'escalier" => 1),
					   "message" => "Tu descends l'escalier et arrives dans une cave. Rien d'intéressant à part le fait d'apprendre que Jack l'éventreur aime les biscuits à la cannelle. Tu remontes.",
					    "color" => "#A9A9A9",
					    "coordinates" => array("[250,100],","[250,50],","[300,50],","[300,100]"),
					    "stuff" => array(4 => 20)),
				 
				6 => array("name" => "le grenier",
					   "outs" => array("l'escalier" => 1),
				           "message" => "Tu montes l'escalier et arrives dans un grenier. Tu as beau fouiller, le criminel n'est pas ici. Par contre, tu viens de trouver une clé ; ça peut toujours être utile ! Tu redescends.",
					    "color" => "#8B4513",
					    "enter_condition" => array(3),
					    "no_enter_message" => "Le grenier est plongé dans le noir : impossible d'y voir quoi que ce soit.",
					    "no_enter_outs" => array("l'escalier" => 1),
					    "coordinates" => array("[250,0],","[250,0],","[300,0],","[300,50]"),
					    "stuff" => array(0 => 1)),

				7 => array("name" => "la cuisine",
					   "lose_message" => "Tu entres dans une cuisine des plus banales. Tu regardes un peu partout pour voir s'il se cache ici. Mais dans ton état de stress, tu fais tomber une pile de casseroles sur toi, provoquant un terrible fracas  ! Le meurtier n'ignore plus que tu es là ! Pendant que tu te relèves, groggy, tu entends la porte principale claquer et en sortant précipitamment, tu le vois en train de courir au bout de la rue. C'est trop tard pour le rattraper, c'est un échec !",
					   "lose_condition" => array(),
					   "color" => "#FFE4B5",
					   "coordinates" => array("[0,175],","[0,100],","[75,100],","[75,175]"),
					   "win_condition" => array(1),
					   "win_message" => "Tu entres dans une cuisine des plus banales. Tu regardes un peu partout pour voir s'il se cache ici. Mais dans ton état de stress, tu fais tomber une pile de casseroles sur toi, provoquant un terrible fracas  ! Le meurtier n'ignore plus que tu es là ! Pendant que tu te relèves, groggy, tu entends la porte principale claquer et en sortant précipitamment, tu le vois en train de courir... Heureusement, tu prends le vieux fusil, vise, tire et le touche à l'épaule ! Il s'effondre, blessé, tandis que tu interpelles un policier alerté par le bruit pour qu'il t'aide à l'amener au poste. Enfin, une traque qui s'achève ! Londres pourra dormir sur ses deux oreilles, ce soir tandis que tu goûteras votre gloire face un tel exploit."),
				
				8 => array("name" => "le salon",
					   "outs" => array("l'entrée" => 1),
				  	   "message" => "Grâce à la clé, tu entres dans le salon. Clairement, Jack l'éventreur n'est pas là. Pas grand chose d'intéressant, si ce n'est un antique fusil de chasse accroché au mur derrière la cheminée. Tu retournes à l'entrée.",
					   "color" => "#98FB98",
					   "coordinates" => array("[75,125],","[75,0],","[175,0],","[175,125]"),
					   "enter_condition" => array(0),
					   "no_enter_message" => "La porte est bel et bien fermée à clé et bien trop solide pour être cassée. Inutile d'essayer, tu ne peux pas passer.",
					   "no_enter_outs" => array("l'entrée" => 1),
					   "stuff" => array(6 => 5, 5 => 2, 1 => 1)),

				9 => array("name" => "les toilettes",
					   "win_message" => "Très bon choix ! Ce sont effectivement des toilettes. Et puisqu'aucun être humain ne peut survivre sans y aller régulièrement, tu décides de l'attendre ici, derrière la porte. Une heure plus tard, des bruits de pas s'approchent et enfin, la porte s'ouvre. L'arrivant qui n'est autre que votre célèbre cible, entre sans se douter de rien et tu l'assommes en lui donnant un gros coup de vase. Enfin, une traque qui s'achève ! Londres pourra dormir sur ses deux oreilles, ce soir tandis que tu goûteras votre gloire face un tel exploit.",
					   "lose_message" => "Très bon choix ! Ce sont effectivement des toilettes. Et puisqu'aucun être humain ne peut survivre sans y aller régulièrement, tu décides de l'attendre ici, derrière la porte. Une heure plus tard, des bruits de pas s'approchent et enfin, la porte s'ouvre. L'arrivant qui n'est autre que votre célèbre cible, entre sans se douter de rien et tu te jettes sur lui. Malheureusement, il est bien plus fort que toi et il parvient à se retourner. Il attrape ton cou et commenceà serrer, serrer, serrer ... Ton dernier souvenir sera son rictus de folie.",
					   "win_condition" => array(5),
					   "lose_condition" => array(),
					   "color" => "#87CEFA",
					   "coordinates" => array("[50,200],","[50,175],","[75,175],","[75,200]"),)
				);
			}

			//converts the information about the position of the room in a JSON array for the JS script
			function world_to_json()
			{
				global $world;
				$json_map = '[';
				foreach($world as $id_room => $array_room)
				{
					$json_map .= '{ "color": '  . '"' . $array_room["color"] . '"' . ', "points": [' . $array_room["coordinates"][0] . $array_room["coordinates"][1] . $array_room["coordinates"][2] . $array_room["coordinates"][3] . ']},';
	
				}

				$json_map = substr($json_map, 0, -1);
				$json_map .= "]";
				return $json_map;
			}

			//after cliking "jouer au jeu" ...
			function game()
			{

				global $world;
				global $objects;
				world_definition();

				//to define the room the player is. If he doesn't come from anywhere, that means he just began to lay and is out the house.
				if (isset($_GET["go"]))
				{
					$_SESSION["room"] = $_GET["go"];
				}
				else
				{
					$_SESSION["room"] = 0;
				}

				//if the player took something
				if (isset($_GET["take"]))
				{
					//if it is the first time he took something
					if (!isset($_SESSION["inventory"]))
					{
						$_SESSION["inventory"] = array_fill(0,count($objects),0);
					}

					//add the object to the inventory					
					$_SESSION["inventory"][$_GET["take"]]++;
				}
				
				/*Each time the player clicks on a link, $objects and $world are defined again.
				But if the player took something, it has to be removed for ever.
				All the objects taken in a room are in the inventory (because the player can't drop anything) and an object can be found in one single room.
				That's why all the objects that are at the same time in the inventory and in the room must be removed.*/

				$objects_to_remove = array_intersect_key($_SESSION["inventory"],$world[$_SESSION["room"]]["stuff"]);

				foreach($objects_to_remove as $id_object => $amount_object)
				{
					$world[$_SESSION["room"]]["stuff"][$id_object] -= $amount_object;
				}


				//writes the map in a file to be used from the JS script.
				$json_map = world_to_json();
				$json_file = fopen('json_map.json','w+');
				fputs($json_file, $json_map);
				fclose($json_file);
				chmod('json_map.json', 0666);

				//once all is ready, the room ca ne displayed
				display_room();

				//send the room number at the JS script.
				echo '<input type="hidden" id="play" name="play" value="true">';
				echo '<input type="hidden" id="current_room" name="current_room" value="' . $_SESSION["room"] . '">';		
			}

		

			//main

			//if there is an username, the player can play or logout
			if (isset($_SESSION["username"]))
			{
				if (isset($_GET["action"]))
				{
					switch($_GET["action"])
					{
						case "logout" : logout_action(); break;
						case "play" : game(); break;
						default : unknown_action();
					}		
				}
				else
				{
					unknown_action();
				}
			}
			//else he can log in.
			else
			{
				if (isset($_GET["action"]))
				{
					switch($_GET["action"])
					{
						case "login" : login_action(); break;
						default : show_login_form_action();
					}
				}
				else
				{
					show_login_form_action();
				}
			}
		?>

		<footer>
			<!--Everytime the player can log out if he has enough with my game-->
			<hr> <a href='game.php?action=logout'> <p>Quitter le jeu </p></a>;
		</footer>
		<script src="http://code.jquery.com/jquery.min.js"></script>
		<script src="script_jquery.js"></script>
	</body>
</html>
Merci de votre aide,

Zilbou