lvl4.html (10319B)
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/lvl4.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 if (Math.random()<0.5) 145 tiles[1][2] = 0; 146 else 147 tiles[5][2] = 0; 148 149 if (Math.random()<0.5) { 150 tiles[2][3] = 0; 151 tiles[4][3] = 0; 152 } else { 153 tiles[2][5] = 0; 154 tiles[4][5] = 0; 155 } 156 } 157 158 function get_tile_at(x,y) { 159 return tiles[x][y]; 160 } 161 162 function reset_board() { 163 movetime = 0; 164 bot.x = tilesize * 1.5; 165 bot.y = tilesize * 1.5; 166 bot.angle = 0; 167 168 for (move of delayed_moves){ 169 clearTimeout(move) 170 } 171 172 delayed_moves = [] 173 174 gen_tiles() 175 } 176 177 function move_left() { 178 delayed_moves.push( 179 setTimeout( 180 function() { 181 bot.x -= tilesize; 182 bot.angle = 180; 183 }, movetime) 184 ); 185 movetime += delay; 186 } 187 188 function move_right() { 189 delayed_moves.push( 190 setTimeout( 191 function() { 192 bot.x += tilesize; 193 bot.angle = 0; 194 }, movetime) 195 ); 196 movetime += delay; 197 } 198 199 function move_up() { 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 function move_down() { 211 delayed_moves.push( 212 setTimeout( 213 function() { 214 bot.y += tilesize; 215 bot.angle = 90; 216 }, movetime) 217 ); 218 movetime += delay; 219 } 220 221 window.onload = function() { 222 loadSCO(); 223 document.getElementById("code").textContent = code; 224 225 game = new Phaser.Game(config); 226 227 brython(); 228 } 229 </script> 230 231 <script type="text/python"> 232 # Requires Brython and Ace editor 233 234 from browser import document, window, html 235 from sys import stderr, stdout, settrace 236 from traceback import print_exc, extract_stack, extract_tb 237 238 def make_max_line_tracer(maxlines): 239 lines = 0 240 def tracer(frame, event, arg): 241 nonlocal lines 242 if event == 'line': 243 lines += 1 244 if lines >= maxlines: 245 raise TimeoutError 246 return tracer 247 return tracer 248 249 def exec_code(editor, id): 250 reset() 251 feedback("Le drapeau n'est pas encore atteint") 252 253 code_lines = editor.session.getLength() 254 if code_lines > max_code_lines: 255 feedback("Trop de lignes utilisées ( " + str(code_lines) + "/" + str(max_code_lines) + ")") 256 return 257 258 console = document[id + "_console"] 259 console.clear() 260 stderr.write = lambda data : console_target(data, console, True) 261 stdout.write = lambda data : console_target(data, console) 262 263 code = editor.getValue() 264 try: 265 compiled = compile(code, "<" + id + ">", "exec") 266 except SyntaxError: 267 print_exc(limit=0) 268 return 269 270 settrace(make_max_line_tracer(10000)) # increase to allow longer execution 271 try: 272 exec(code) 273 except TimeoutError: 274 settrace(None) 275 print("L'exécution prend trop de temps, abandon.", file=stderr) 276 except Exception as e: 277 settrace(None) 278 tb_len = len(extract_tb(e.__traceback__)) - len(extract_stack()) 279 print_exc(limit=-tb_len) 280 finally: 281 settrace(None) 282 283 window.code = code 284 #window.score = check() 285 window.sendSCO() 286 287 def console_target(data, elt, err=False): 288 elt <= html.PRE(data, Class="stderr" if err else "stdout") 289 elt.scrollTop = elt.scrollHeight 290 291 breditors = document.select(".breditor") 292 293 max_code_lines = 30 294 295 for ed_elt in breditors: 296 editor = window.ace.edit(ed_elt.id) 297 editor.session.setMode("ace/mode/python") 298 #editor.setOption('fontSize', '14px') 299 editor.setOption('maxLines', max_code_lines) 300 editor.setOption('minLines', max_code_lines) 301 302 console = html.DIV(Class="console", id=ed_elt.id + "_console") 303 304 ed_elt.insertAdjacentElement('afterend', console) 305 306 exec_button = html.BUTTON("Exécuter →") 307 exec_button.bind("click", lambda ev : exec_code(editor, ed_elt.id)) 308 ed_elt.insertAdjacentElement('afterend', exec_button) 309 310 def feedback(msg): 311 document["feedback"].clear() 312 document["feedback"] <= msg 313 314 coords = [1,1] 315 316 def reset(): 317 global coords 318 window.reset_board() 319 coords = [1,1] 320 321 def gauche(): 322 if coords[0] >= 0: 323 tile = window.get_tile_at(coords[0]-1, coords[1]) 324 if tile in (0,1,3): 325 window.move_left() 326 coords[0] -= 1 327 if tile == 1: 328 win() 329 elif tile == 3: 330 fall() 331 332 def droite(): 333 if coords[0] < 10: 334 tile = window.get_tile_at(coords[0]+1, coords[1]) 335 if tile in (0,1,3): 336 window.move_right() 337 coords[0] += 1 338 if tile == 1: 339 win() 340 elif tile == 3: 341 fall() 342 343 def haut(): 344 if coords[1] >= 0: 345 tile = window.get_tile_at(coords[0], coords[1]-1) 346 if tile in (0,1,3): 347 window.move_up() 348 coords[1] -= 1 349 if tile == 1: 350 win() 351 elif tile == 3: 352 fall() 353 354 def bas(): 355 if coords[1] < 10: 356 tile = window.get_tile_at(coords[0], coords[1]+1) 357 if tile in (0,1,3): 358 window.move_down() 359 coords[1] += 1 360 if tile == 1: 361 win() 362 elif tile == 3: 363 fall() 364 365 366 def voir_gauche(): 367 if coords[0] == 0: 368 return 3 369 else: 370 return voir(coords[0]-1, coords[1]) 371 372 def voir_droite(): 373 if coords[0] == 10: 374 return 3 375 else: 376 return voir(coords[0]+1, coords[1]) 377 378 def voir_haut(): 379 if coords[1] == 0: 380 return 3 381 else: 382 return voir(coords[0], coords[1]-1) 383 384 def voir_bas(): 385 if coords[1] == 10: 386 return 3 387 else: 388 return voir(coords[0], coords[1]+1) 389 390 def voir(x,y): 391 return window.get_tile_at(x,y) 392 393 def fall(): 394 feedback("Le robot est tombé dans le vide !") 395 raise Exception("Le robot est tombé dans le vide") 396 397 398 def win(): 399 window.score = 100 400 feedback("Ça a l'air correct, mais exécutez plusieur fois pour voir si ça marche aussi dans d'autres cas.") 401 document["feedback"] <= html.BUTTON("Passer à la suite", onclick="nextSCO();") 402 403 404 </script> 405 406 </head> 407 408 <body> 409 410 <h1>Niveau 4</h1> 411 412 Vous disposez des fonctions 413 <code>droite()</code>, 414 <code>gauche()</code>, 415 <code>haut()</code>, et 416 <code>bas()</code> 417 pour faire avancer le robot. 418 419 </br> 420 421 Vous pouvez aussi utiliser 422 <code>voir_droite()</code>, 423 <code>voir_gauche()</code>, 424 <code>voir_haut()</code>, et 425 <code>voir_bas()</code> 426 pour regarder les cases autour de vous, 427 ces fonctions renvoient le type de la case : 428 <ul> 429 <li>0 pour un chemin</li> 430 <li>1 pour une arrivée</li> 431 <li>2 pour un mur</li> 432 <li>3 pour du vide</li> 433 </ul> 434 435 <p> 436 Les cases point d'interrogation ont un type caché qui est révélé 437 losqu'on les regarde. 438 </p> 439 440 <p> 441 Vous pouvez, si besoin, mettre un bloc if dans un bloc if ou else. 442 </p> 443 444 <!-- <p> 445 Si on a envie de mettre un nouveau if dans la partie else, 446 on peut utiliser le mot clé elif, exemple : 447 <pre><code># ce code 448 if voir_haut() == 0: 449 haut() 450 else: 451 if voir_droite() == 0: 452 droite() 453 454 # est équivalent à ce code : 455 if voir_haut() == 0: 456 haut() 457 elif voir_droite() == 0: 458 droite() 459 460 </code></pre> 461 </p>--> 462 463 464 <div id="edcontainer"> 465 <div class="edcolumn"> 466 Code python : 467 <pre id="code" class="breditor"></pre> 468 <div id="feedback"></div> 469 </div> 470 <div class="edcolumn"> 471 Plateau : 472 <div id="game"></div> 473 </div> 474 </div> 475 476 477 478 479 480 481 </body> 482 </html>