lvl7.html (10313B)
1 <head> 2 3 <meta charset="utf-8"/> 4 5 <link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"/> 6 7 <style> 8 h1,h2 { 9 font-family: Sans; 10 } 11 12 .stderr { 13 background-color: #fee; 14 color: #900; 15 } 16 17 .stderr, .stdout { 18 /* display: contents; */ /* uncomment to make print( end='') work */ 19 margin: 0px; 20 padding: 0px 0.3em; 21 } 22 23 .console { 24 max-height: 20em; 25 overflow: auto; 26 border: medium solid black; 27 } 28 29 .console:empty { 30 display: none; 31 } 32 33 #feedback { 34 border: solid #aaa; 35 background-color: #eee; 36 } 37 38 #feedback:empty { 39 display: none; 40 } 41 42 #edcontainer { 43 display: flex; 44 } 45 .edcolumn { 46 flex: 50%; 47 } 48 #breditor { 49 width: 100%; 50 } 51 52 53 </style> 54 55 <script src="https://cdn.jsdelivr.net/npm/phaser@3.55.0/dist/phaser.min.js"></script> 56 <script src="https://unpkg.com/brython@3.9.3/brython.js"></script> 57 <script src="https://unpkg.com/brython@3.9.3/brython_stdlib.js"></script> 58 <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ace.min.js"></script> 59 <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/mode-python.min.js"></script> 60 61 <script type="text/javascript"> 62 63 code = "# Écrivez votre code python ici :\nprint(\"Bonjour !\")"; 64 65 score = 0; 66 67 API = window.API || window.parent.API; 68 69 function loadSCO() { 70 if (API) { 71 API.LMSInitialize(""); 72 73 suspend_data = API.LMSGetValue("cmi.suspend_data"); 74 75 if (suspend_data) { 76 code = suspend_data; 77 } 78 } 79 } 80 81 function sendSCO() { 82 if (API) { 83 API.LMSSetValue("cmi.core.score.raw", score); 84 API.LMSSetValue("cmi.suspend_data", code); 85 API.LMSSetValue("cmi.core.score.lesson_status", "completed"); 86 87 API.LMSCommit(""); 88 } 89 } 90 91 function nextSCO() { 92 if (API) { 93 API.LMSSetValue("nav.event","continue"); // Probably Moodle specific 94 API.LMSFinish(""); 95 } 96 } 97 98 // Phaser stuff 99 100 var tilesize = 32; 101 var delay = 250; 102 103 var tiles = []; 104 105 var movetime = 0; 106 var delayed_moves = []; 107 108 var config = { 109 type: Phaser.AUTO, 110 width: tilesize*10, 111 height: tilesize*10, 112 parent: "game", 113 scene: { 114 preload: preload, 115 create: create 116 } 117 }; 118 119 function preload() { 120 this.load.image("tilemap", "img/tilemap.png") 121 this.load.image("bot", "img/bot.png") 122 this.load.tilemapCSV('map', 'lvl/lvl7.csv'); 123 } 124 125 function create() { 126 map = this.make.tilemap({ key: 'map', tileWidth: 32, tileHeight: 32 }); 127 var tileset = map.addTilesetImage('tilemap'); 128 layer = map.createLayer(0, tileset, 0, 0); 129 130 bot = this.add.image(tilesize * 1.5, tilesize * 1.5, "bot"); 131 } 132 133 function gen_tiles() { 134 for (var i = 0 ; i < 10 ; i++) { 135 tiles[i] = []; 136 for (var j = 0 ; j < 10 ; j++) { 137 var id = map.getTileAt(i,j).index; 138 if (id == 4) 139 id = 3; 140 tiles[i][j] = id; 141 } 142 } 143 144 tiles[2][Math.floor(Math.random()*5)*2+1] = 0; 145 } 146 147 function get_tile_at(x,y) { 148 return tiles[x][y]; 149 } 150 151 function reset_board() { 152 movetime = 0; 153 bot.x = tilesize * 1.5; 154 bot.y = tilesize * 1.5; 155 bot.angle = 0; 156 157 for (move of delayed_moves){ 158 clearTimeout(move) 159 } 160 161 delayed_moves = [] 162 163 gen_tiles() 164 } 165 166 function move_left() { 167 delayed_moves.push( 168 setTimeout( 169 function() { 170 bot.x -= tilesize; 171 bot.angle = 180; 172 }, movetime) 173 ); 174 movetime += delay; 175 } 176 177 function move_right() { 178 delayed_moves.push( 179 setTimeout( 180 function() { 181 bot.x += tilesize; 182 bot.angle = 0; 183 }, movetime) 184 ); 185 movetime += delay; 186 } 187 188 function move_up() { 189 delayed_moves.push( 190 setTimeout( 191 function() { 192 bot.y -= tilesize; 193 bot.angle = -90; 194 }, movetime) 195 ); 196 movetime += delay; 197 } 198 199 function move_down() { 200 delayed_moves.push( 201 setTimeout( 202 function() { 203 bot.y += tilesize; 204 bot.angle = 90; 205 }, movetime) 206 ); 207 movetime += delay; 208 } 209 210 window.onload = function() { 211 loadSCO(); 212 document.getElementById("code").textContent = code; 213 214 game = new Phaser.Game(config); 215 216 brython(); 217 } 218 </script> 219 220 <script type="text/python"> 221 # Requires Brython and Ace editor 222 223 from browser import document, window, html 224 from sys import stderr, stdout, settrace 225 from traceback import print_exc, extract_stack, extract_tb 226 227 def make_max_line_tracer(maxlines): 228 lines = 0 229 def tracer(frame, event, arg): 230 nonlocal lines 231 if event == 'line': 232 lines += 1 233 if lines >= maxlines: 234 raise TimeoutError 235 return tracer 236 return tracer 237 238 def exec_code(editor, id): 239 reset() 240 feedback("Le drapeau n'est pas encore atteint") 241 242 code_lines = editor.session.getLength() 243 if code_lines > max_code_lines: 244 feedback("Trop de lignes utilisées ( " + str(code_lines) + "/" + str(max_code_lines) + ")") 245 return 246 247 console = document[id + "_console"] 248 console.clear() 249 stderr.write = lambda data : console_target(data, console, True) 250 stdout.write = lambda data : console_target(data, console) 251 252 code = editor.getValue() 253 try: 254 compiled = compile(code, "<" + id + ">", "exec") 255 except SyntaxError: 256 print_exc(limit=0) 257 return 258 259 settrace(make_max_line_tracer(10000)) # increase to allow longer execution 260 try: 261 exec(code) 262 except TimeoutError: 263 settrace(None) 264 print("L'exécution prend trop de temps, abandon.", file=stderr) 265 except Exception as e: 266 settrace(None) 267 tb_len = len(extract_tb(e.__traceback__)) - len(extract_stack()) 268 print_exc(limit=-tb_len) 269 finally: 270 settrace(None) 271 272 window.code = code 273 #window.score = check() 274 window.sendSCO() 275 276 def console_target(data, elt, err=False): 277 elt <= html.PRE(data, Class="stderr" if err else "stdout") 278 elt.scrollTop = elt.scrollHeight 279 280 breditors = document.select(".breditor") 281 282 max_code_lines = 10 283 284 for ed_elt in breditors: 285 editor = window.ace.edit(ed_elt.id) 286 editor.session.setMode("ace/mode/python") 287 #editor.setOption('fontSize', '14px') 288 editor.setOption('maxLines', max_code_lines) 289 editor.setOption('minLines', max_code_lines) 290 291 console = html.DIV(Class="console", id=ed_elt.id + "_console") 292 293 ed_elt.insertAdjacentElement('afterend', console) 294 295 exec_button = html.BUTTON("Exécuter →") 296 exec_button.bind("click", lambda ev : exec_code(editor, ed_elt.id)) 297 ed_elt.insertAdjacentElement('afterend', exec_button) 298 299 def feedback(msg): 300 document["feedback"].clear() 301 document["feedback"] <= msg 302 303 coords = [1,1] 304 305 def reset(): 306 global coords 307 window.reset_board() 308 coords = [1,1] 309 310 def gauche(): 311 if coords[0] >= 0: 312 tile = window.get_tile_at(coords[0]-1, coords[1]) 313 if tile in (0,1,3): 314 window.move_left() 315 coords[0] -= 1 316 if tile == 1: 317 win() 318 elif tile == 3: 319 fall() 320 321 def droite(): 322 if coords[0] < 10: 323 tile = window.get_tile_at(coords[0]+1, coords[1]) 324 if tile in (0,1,3): 325 window.move_right() 326 coords[0] += 1 327 if tile == 1: 328 win() 329 elif tile == 3: 330 fall() 331 332 def haut(): 333 if coords[1] >= 0: 334 tile = window.get_tile_at(coords[0], coords[1]-1) 335 if tile in (0,1,3): 336 window.move_up() 337 coords[1] -= 1 338 if tile == 1: 339 win() 340 elif tile == 3: 341 fall() 342 343 def bas(): 344 if coords[1] < 10: 345 tile = window.get_tile_at(coords[0], coords[1]+1) 346 if tile in (0,1,3): 347 window.move_down() 348 coords[1] += 1 349 if tile == 1: 350 win() 351 elif tile == 3: 352 fall() 353 354 355 def voir_gauche(): 356 if coords[0] == 0: 357 return 3 358 else: 359 return voir(coords[0]-1, coords[1]) 360 361 def voir_droite(): 362 if coords[0] == 10: 363 return 3 364 else: 365 return voir(coords[0]+1, coords[1]) 366 367 def voir_haut(): 368 if coords[1] == 0: 369 return 3 370 else: 371 return voir(coords[0], coords[1]-1) 372 373 def voir_bas(): 374 if coords[1] == 10: 375 return 3 376 else: 377 return voir(coords[0], coords[1]+1) 378 379 def voir(x,y): 380 return window.get_tile_at(x,y) 381 382 def fall(): 383 feedback("Le robot est tombé dans le vide !") 384 raise Exception("Le robot est tombé dans le vide") 385 386 387 def win(): 388 window.score = 100 389 feedback("Ça a l'air correct, mais exécutez plusieur fois pour voir si ça marche aussi dans d'autres cas.") 390 document["feedback"] <= html.BUTTON("Passer à la suite", onclick="nextSCO();") 391 392 393 </script> 394 395 </head> 396 397 <body> 398 399 <h1>Niveau 7</h1> 400 401 Vous disposez des fonctions 402 <code>droite()</code>, 403 <code>gauche()</code>, 404 <code>haut()</code>, et 405 <code>bas()</code> 406 pour faire avancer le robot. 407 408 </br> 409 410 Vous pouvez aussi utiliser 411 <code>voir_droite()</code>, 412 <code>voir_gauche()</code>, 413 <code>voir_haut()</code>, et 414 <code>voir_bas()</code> 415 pour regarder les cases autour de vous, 416 ces fonctions renvoient le type de la case : 417 <ul> 418 <li>0 pour un chemin</li> 419 <li>1 pour une arrivée</li> 420 <li>2 pour un mur</li> 421 <li>3 pour du vide</li> 422 </ul> 423 424 <p> 425 Les cases point d'interrogation ont un type caché qui est révélé 426 losqu'on les regarde. 427 </p> 428 429 <p> 430 En python, la boucle qui permet de répéter du code tant qu'une condition est vérifiée est la boucle 431 <code>while</cose>. Exemple : 432 433 <pre><code># tant qu'il n'y a pas de mur en haut on avance : 434 while voir_haut() != 2: 435 haut() 436 </code></pre> 437 </p> 438 439 <!-- <p> 440 Si on a envie de mettre un nouveau if dans la partie else, 441 on peut utiliser le mot clé elif, exemple : 442 <pre><code># ce code 443 if voir_haut() == 0: 444 haut() 445 else: 446 if voir_droite() == 0: 447 droite() 448 449 # est équivalent à ce code : 450 if voir_haut() == 0: 451 haut() 452 elif voir_droite() == 0: 453 droite() 454 455 </code></pre> 456 </p>--> 457 458 459 <div id="edcontainer"> 460 <div class="edcolumn"> 461 Code python : 462 <pre id="code" class="breditor"></pre> 463 <div id="feedback"></div> 464 </div> 465 <div class="edcolumn"> 466 Plateau : 467 <div id="game"></div> 468 </div> 469 </div> 470 471 472 473 474 475 476 </body> 477 </html>