lvl11.html (10307B)
1 <head> 2 3 <meta charset="utf-8"/> 4 5 <style> 6 h1,h2 { 7 font-family: Sans; 8 } 9 10 .stderr { 11 background-color: #fee; 12 color: #900; 13 } 14 15 .stderr, .stdout { 16 /* display: contents; */ /* uncomment to make print( end='') work */ 17 margin: 0px; 18 padding: 0px 0.3em; 19 } 20 21 .console { 22 max-height: 20em; 23 overflow: auto; 24 border: medium solid black; 25 } 26 27 .console:empty { 28 display: none; 29 } 30 31 #feedback { 32 border: solid #aaa; 33 background-color: #eee; 34 } 35 36 #feedback:empty { 37 display: none; 38 } 39 40 #edcontainer { 41 display: flex; 42 } 43 .edcolumn { 44 flex: 50%; 45 } 46 #breditor { 47 width: 100%; 48 } 49 50 51 </style> 52 53 <script src="https://cdn.jsdelivr.net/npm/phaser@3.55.0/dist/phaser.min.js"></script> 54 <script src="https://unpkg.com/brython@3.9.3/brython.js"></script> 55 <script src="https://unpkg.com/brython@3.9.3/brython_stdlib.js"></script> 56 <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ace.min.js"></script> 57 <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/mode-python.min.js"></script> 58 <!-- 59 <script src="lib/phaser/phaser.min.js"></script> 60 <script src="lib/brython/brython.js"></script> 61 <script src="lib/brython/brython_stdlib.js"></script> 62 <script src="lib/ace/ace.js"></script> 63 <script src="lib/ace/mode-python.js"></script> 64 --> 65 66 <script type="text/javascript"> 67 68 code = "# il faut définir la fonction u(n)\n" + 69 "# et utiliser une variable pour se souvenir de combien descendre"; 70 71 score = 0; 72 73 API = window.API || window.parent.API; 74 75 function loadSCO() { 76 if (API) { 77 API.LMSInitialize(""); 78 79 suspend_data = API.LMSGetValue("cmi.suspend_data"); 80 81 if (suspend_data) { 82 code = suspend_data; 83 } 84 } 85 } 86 87 function sendSCO() { 88 if (API) { 89 API.LMSSetValue("cmi.core.score.raw", score); 90 API.LMSSetValue("cmi.suspend_data", code); 91 API.LMSSetValue("cmi.core.score.lesson_status", "completed"); 92 93 API.LMSCommit(""); 94 } 95 } 96 97 function nextSCO() { 98 if (API) { 99 API.LMSSetValue("nav.event","continue"); // Probably Moodle specific 100 API.LMSFinish(""); 101 } 102 } 103 104 // Phaser stuff 105 106 var tilesize = 32; 107 var delay = 250; 108 109 var tiles = []; 110 111 var movetime = 0; 112 var delayed_moves = []; 113 114 var config = { 115 type: Phaser.AUTO, 116 width: tilesize*10, 117 height: tilesize*10, 118 parent: "game", 119 scene: { 120 preload: preload, 121 create: create 122 } 123 }; 124 125 function preload() { 126 this.load.image("tilemap", "img/tilemap.png") 127 this.load.image("bot", "img/bot.png") 128 this.load.tilemapCSV('map', 'lvl/lvl11.csv'); 129 } 130 131 function create() { 132 map = this.make.tilemap({ key: 'map', tileWidth: 32, tileHeight: 32 }); 133 var tileset = map.addTilesetImage('tilemap'); 134 layer = map.createLayer(0, tileset, 0, 0); 135 136 bot = this.add.image(tilesize * 1.5, tilesize * 1.5, "bot"); 137 } 138 139 function gen_tiles() { 140 for (var i = 0 ; i < 10 ; i++) { 141 tiles[i] = []; 142 for (var j = 0 ; j < 10 ; j++) { 143 var id = map.getTileAt(i,j).index; 144 if (id == 4) 145 id = 3; 146 tiles[i][j] = id; 147 } 148 } 149 var dy = 0; 150 for (var x = 1 ; x < 9 ; x+=2) { 151 var ddy = Math.floor(Math.random()*3); 152 if(x==1) 153 ddy++; 154 tiles[x][0] = ddy; 155 dy += ddy; 156 tiles[x+1][1+dy] = 0; 157 } 158 } 159 160 function get_tile_at(x,y) { 161 return tiles[x][y]; 162 } 163 164 function reset_board() { 165 movetime = 0; 166 bot.x = tilesize * 1.5; 167 bot.y = tilesize * 1.5; 168 bot.angle = 0; 169 170 for (move of delayed_moves){ 171 clearTimeout(move) 172 } 173 174 delayed_moves = [] 175 176 gen_tiles() 177 } 178 179 function move_left() { 180 delayed_moves.push( 181 setTimeout( 182 function() { 183 bot.x -= tilesize; 184 bot.angle = 180; 185 }, movetime) 186 ); 187 movetime += delay; 188 } 189 190 function move_right() { 191 delayed_moves.push( 192 setTimeout( 193 function() { 194 bot.x += tilesize; 195 bot.angle = 0; 196 }, movetime) 197 ); 198 movetime += delay; 199 } 200 201 function move_up() { 202 delayed_moves.push( 203 setTimeout( 204 function() { 205 bot.y -= tilesize; 206 bot.angle = -90; 207 }, movetime) 208 ); 209 movetime += delay; 210 } 211 212 function move_down() { 213 delayed_moves.push( 214 setTimeout( 215 function() { 216 bot.y += tilesize; 217 bot.angle = 90; 218 }, movetime) 219 ); 220 movetime += delay; 221 } 222 223 window.onload = function() { 224 loadSCO(); 225 document.getElementById("code").textContent = code; 226 227 game = new Phaser.Game(config); 228 229 brython(); 230 } 231 </script> 232 233 <script type="text/python"> 234 # Requires Brython and Ace editor 235 236 from browser import document, window, html 237 from sys import stderr, stdout, settrace 238 from traceback import print_exc, extract_stack, extract_tb 239 240 def make_max_line_tracer(maxlines): 241 lines = 0 242 def tracer(frame, event, arg): 243 nonlocal lines 244 if event == 'line': 245 lines += 1 246 if lines >= maxlines: 247 raise TimeoutError 248 return tracer 249 return tracer 250 251 def exec_code(editor, id): 252 reset() 253 254 feedback("Le drapeau n'est pas encore atteint") 255 256 code_lines = editor.session.getLength() 257 if code_lines > max_code_lines: 258 feedback("Trop de lignes utilisées ( " + str(code_lines) + "/" + str(max_code_lines) + ")") 259 return 260 261 console = document[id + "_console"] 262 console.clear() 263 stderr.write = lambda data : console_target(data, console, True) 264 stdout.write = lambda data : console_target(data, console) 265 266 code = editor.getValue() 267 try: 268 compiled = compile(code, "<" + id + ">", "exec") 269 except SyntaxError: 270 print_exc(limit=0) 271 return 272 273 settrace(make_max_line_tracer(10000)) # increase to allow longer execution 274 try: 275 exec(code) 276 except TimeoutError: 277 settrace(None) 278 print("L'exécution prend trop de temps, abandon.", file=stderr) 279 except Exception as e: 280 settrace(None) 281 tb_len = len(extract_tb(e.__traceback__)) - len(extract_stack()) 282 print_exc(limit=-tb_len) 283 finally: 284 settrace(None) 285 286 window.code = code 287 #window.score = check() 288 window.sendSCO() 289 290 def console_target(data, elt, err=False): 291 elt <= html.PRE(data, Class="stderr" if err else "stdout") 292 elt.scrollTop = elt.scrollHeight 293 294 breditors = document.select(".breditor") 295 296 max_code_lines = 15 297 298 for ed_elt in breditors: 299 editor = window.ace.edit(ed_elt.id) 300 editor.session.setMode("ace/mode/python") 301 #editor.setOption('fontSize', '14px') 302 editor.setOption('maxLines', max_code_lines) 303 editor.setOption('minLines', max_code_lines) 304 305 console = html.DIV(Class="console", id=ed_elt.id + "_console") 306 307 ed_elt.insertAdjacentElement('afterend', console) 308 309 exec_button = html.BUTTON("Exécuter →") 310 exec_button.bind("click", lambda ev : exec_code(editor, ed_elt.id)) 311 ed_elt.insertAdjacentElement('afterend', exec_button) 312 313 def feedback(msg): 314 document["feedback"].clear() 315 document["feedback"] <= msg 316 317 coords = [1,1] 318 319 def reset(): 320 global coords 321 window.reset_board() 322 coords = [1,1] 323 324 def gauche(): 325 if coords[0] >= 0: 326 move_to(coords[0]-1, coords[1], -1, 0, window.move_left) 327 328 def droite(): 329 if coords[0] < 10: 330 move_to(coords[0]+1, coords[1], 1, 0, window.move_right) 331 332 def haut(): 333 if coords[1] >= 0: 334 move_to(coords[0], coords[1]-1, 0, -1, window.move_up) 335 336 def bas(): 337 if coords[1] < 10: 338 move_to(coords[0], coords[1]+1, 0 , 1, window.move_down) 339 340 def move_to(x, y, dx, dy, move): 341 tile = window.get_tile_at(x, y) 342 if tile in (0,1,3): 343 move() 344 coords[0] += dx 345 coords[1] += dy 346 if tile == 1: 347 win() 348 elif tile == 3: 349 fall() 350 else: 351 feedback("Le robot n'est pas sur un drapeau") 352 window.score = 0 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 u(n): 383 for i in range(n): 384 bas() 385 droite() 386 droite() 387 for i in range(n): 388 haut() 389 390 def fall(): 391 feedback("Le robot est tombé dans le vide !") 392 raise Exception("Le robot est tombé dans le vide") 393 394 395 def win(): 396 window.score = 100 397 feedback("Bravo ! (exécutez plusieurs fois avant de continuer)") 398 #feedback("Bravo ! ") 399 document["feedback"] <= html.BUTTON("Passer à la suite", onclick="nextSCO();") 400 401 402 </script> 403 404 </head> 405 406 <body> 407 408 <h1>Niveau 11</h1> 409 410 <p> 411 Vous disposez des fonctions 412 <code>droite()</code>, 413 <code>gauche()</code>, 414 <code>haut()</code>, et 415 <code>bas()</code> 416 pour faire avancer le robot. 417 </p> 418 419 <p> 420 Il faut maintenant écrire vous-même la fonction 421 <code>u(<i>n</i>)</code> 422 qui va faire faire un virage vers le bas 423 de longueur <i>n</i> au robot. 424 </p> 425 426 <p> 427 Chaque barrière de <i>?</i> possède un point de passage. 428 </p> 429 <p> 430 Cette fois-ci, sa position est la 431 <b>somme des cases <i>i</i> précédentes</b>. 432 Par exemple, si la case <i>i</i> au dessus du début vaut 2 433 et la case <i>i</i> suivante vaut 1, 434 alors pour le 2ème virage 435 il faudra faire un U de 3 cases de profond pour passer. 436 </p> 437 438 <p> 439 Utilisez votre fonction <code>u(n)</code> et <code>voir_haut()</code> 440 pour passer chaque barrière. 441 </p> 442 443 <p> 444 Exemples de fonction avec paramètre : 445 <pre><code># on définis une fonction f qui prend 1 paramètre n 446 447 def f(n): 448 # à l'intérieur de la fonction, on utilise n comme une variable : 449 print(n) 450 for i in range(n): 451 print("lol") 452 453 # on appelle f : 454 455 f(42) # n vaudra 42 dans la fonction 456 </code></pre> 457 </p> 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 </body> 472 </html>