lvl10.html (10062B)
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)"; 69 70 score = 0; 71 72 API = window.API || window.parent.API; 73 74 function loadSCO() { 75 if (API) { 76 API.LMSInitialize(""); 77 78 suspend_data = API.LMSGetValue("cmi.suspend_data"); 79 80 if (suspend_data) { 81 code = suspend_data; 82 } 83 } 84 } 85 86 function sendSCO() { 87 if (API) { 88 API.LMSSetValue("cmi.core.score.raw", score); 89 API.LMSSetValue("cmi.suspend_data", code); 90 API.LMSSetValue("cmi.core.score.lesson_status", "completed"); 91 92 API.LMSCommit(""); 93 } 94 } 95 96 function nextSCO() { 97 if (API) { 98 API.LMSSetValue("nav.event","continue"); // Probably Moodle specific 99 API.LMSFinish(""); 100 } 101 } 102 103 // Phaser stuff 104 105 var tilesize = 32; 106 var delay = 250; 107 108 var tiles = []; 109 110 var movetime = 0; 111 var delayed_moves = []; 112 113 var config = { 114 type: Phaser.AUTO, 115 width: tilesize*10, 116 height: tilesize*10, 117 parent: "game", 118 scene: { 119 preload: preload, 120 create: create 121 } 122 }; 123 124 function preload() { 125 this.load.image("tilemap", "img/tilemap.png") 126 this.load.image("bot", "img/bot.png") 127 this.load.tilemapCSV('map', 'lvl/lvl10.csv'); 128 } 129 130 function create() { 131 map = this.make.tilemap({ key: 'map', tileWidth: 32, tileHeight: 32 }); 132 var tileset = map.addTilesetImage('tilemap'); 133 layer = map.createLayer(0, tileset, 0, 0); 134 135 bot = this.add.image(tilesize * 1.5, tilesize * 1.5, "bot"); 136 } 137 138 function gen_tiles() { 139 for (var i = 0 ; i < 10 ; i++) { 140 tiles[i] = []; 141 for (var j = 0 ; j < 10 ; j++) { 142 var id = map.getTileAt(i,j).index; 143 if (id == 4) 144 id = 3; 145 tiles[i][j] = id; 146 } 147 } 148 for (var x = 1 ; x < 9 ; x+=2) { 149 dy = Math.floor(Math.random()*8)+1; 150 tiles[x][0] = dy; 151 tiles[x+1][1+dy] = 0; 152 } 153 } 154 155 function get_tile_at(x,y) { 156 return tiles[x][y]; 157 } 158 159 function reset_board() { 160 movetime = 0; 161 bot.x = tilesize * 1.5; 162 bot.y = tilesize * 1.5; 163 bot.angle = 0; 164 165 for (move of delayed_moves){ 166 clearTimeout(move) 167 } 168 169 delayed_moves = [] 170 171 gen_tiles() 172 } 173 174 function move_left() { 175 delayed_moves.push( 176 setTimeout( 177 function() { 178 bot.x -= tilesize; 179 bot.angle = 180; 180 }, movetime) 181 ); 182 movetime += delay; 183 } 184 185 function move_right() { 186 delayed_moves.push( 187 setTimeout( 188 function() { 189 bot.x += tilesize; 190 bot.angle = 0; 191 }, movetime) 192 ); 193 movetime += delay; 194 } 195 196 function move_up() { 197 delayed_moves.push( 198 setTimeout( 199 function() { 200 bot.y -= tilesize; 201 bot.angle = -90; 202 }, movetime) 203 ); 204 movetime += delay; 205 } 206 207 function move_down() { 208 delayed_moves.push( 209 setTimeout( 210 function() { 211 bot.y += tilesize; 212 bot.angle = 90; 213 }, movetime) 214 ); 215 movetime += delay; 216 } 217 218 window.onload = function() { 219 loadSCO(); 220 document.getElementById("code").textContent = code; 221 222 game = new Phaser.Game(config); 223 224 brython(); 225 } 226 </script> 227 228 <script type="text/python"> 229 # Requires Brython and Ace editor 230 231 from browser import document, window, html 232 from sys import stderr, stdout, settrace 233 from traceback import print_exc, extract_stack, extract_tb 234 235 def make_max_line_tracer(maxlines): 236 lines = 0 237 def tracer(frame, event, arg): 238 nonlocal lines 239 if event == 'line': 240 lines += 1 241 if lines >= maxlines: 242 raise TimeoutError 243 return tracer 244 return tracer 245 246 def exec_code(editor, id): 247 reset() 248 249 feedback("Le drapeau n'est pas encore atteint") 250 251 code_lines = editor.session.getLength() 252 if code_lines > max_code_lines: 253 feedback("Trop de lignes utilisées ( " + str(code_lines) + "/" + str(max_code_lines) + ")") 254 return 255 256 console = document[id + "_console"] 257 console.clear() 258 stderr.write = lambda data : console_target(data, console, True) 259 stdout.write = lambda data : console_target(data, console) 260 261 code = editor.getValue() 262 try: 263 compiled = compile(code, "<" + id + ">", "exec") 264 except SyntaxError: 265 print_exc(limit=0) 266 return 267 268 settrace(make_max_line_tracer(10000)) # increase to allow longer execution 269 try: 270 exec(code) 271 except TimeoutError: 272 settrace(None) 273 print("L'exécution prend trop de temps, abandon.", file=stderr) 274 except Exception as e: 275 settrace(None) 276 tb_len = len(extract_tb(e.__traceback__)) - len(extract_stack()) 277 print_exc(limit=-tb_len) 278 finally: 279 settrace(None) 280 281 window.code = code 282 #window.score = check() 283 window.sendSCO() 284 285 def console_target(data, elt, err=False): 286 elt <= html.PRE(data, Class="stderr" if err else "stdout") 287 elt.scrollTop = elt.scrollHeight 288 289 breditors = document.select(".breditor") 290 291 max_code_lines = 15 292 293 for ed_elt in breditors: 294 editor = window.ace.edit(ed_elt.id) 295 editor.session.setMode("ace/mode/python") 296 #editor.setOption('fontSize', '14px') 297 editor.setOption('maxLines', max_code_lines) 298 editor.setOption('minLines', max_code_lines) 299 300 console = html.DIV(Class="console", id=ed_elt.id + "_console") 301 302 ed_elt.insertAdjacentElement('afterend', console) 303 304 exec_button = html.BUTTON("Exécuter →") 305 exec_button.bind("click", lambda ev : exec_code(editor, ed_elt.id)) 306 ed_elt.insertAdjacentElement('afterend', exec_button) 307 308 def feedback(msg): 309 document["feedback"].clear() 310 document["feedback"] <= msg 311 312 coords = [1,1] 313 314 def reset(): 315 global coords 316 window.reset_board() 317 coords = [1,1] 318 319 def gauche(): 320 if coords[0] >= 0: 321 move_to(coords[0]-1, coords[1], -1, 0, window.move_left) 322 323 def droite(): 324 if coords[0] < 10: 325 move_to(coords[0]+1, coords[1], 1, 0, window.move_right) 326 327 def haut(): 328 if coords[1] >= 0: 329 move_to(coords[0], coords[1]-1, 0, -1, window.move_up) 330 331 def bas(): 332 if coords[1] < 10: 333 move_to(coords[0], coords[1]+1, 0 , 1, window.move_down) 334 335 def move_to(x, y, dx, dy, move): 336 tile = window.get_tile_at(x, y) 337 if tile in (0,1,3): 338 move() 339 coords[0] += dx 340 coords[1] += dy 341 if tile == 1: 342 win() 343 elif tile == 3: 344 fall() 345 else: 346 feedback("Le robot n'est pas sur un drapeau") 347 window.score = 0 348 349 350 def voir_gauche(): 351 if coords[0] == 0: 352 return 3 353 else: 354 return voir(coords[0]-1, coords[1]) 355 356 def voir_droite(): 357 if coords[0] == 10: 358 return 3 359 else: 360 return voir(coords[0]+1, coords[1]) 361 362 def voir_haut(): 363 if coords[1] == 0: 364 return 3 365 else: 366 return voir(coords[0], coords[1]-1) 367 368 def voir_bas(): 369 if coords[1] == 10: 370 return 3 371 else: 372 return voir(coords[0], coords[1]+1) 373 374 def voir(x,y): 375 return window.get_tile_at(x,y) 376 377 def u(n): 378 for i in range(n): 379 bas() 380 droite() 381 droite() 382 for i in range(n): 383 haut() 384 385 def fall(): 386 feedback("Le robot est tombé dans le vide !") 387 raise Exception("Le robot est tombé dans le vide") 388 389 390 def win(): 391 window.score = 100 392 feedback("Bravo ! (exécutez plusieurs fois avant de continuer)") 393 #feedback("Bravo ! ") 394 document["feedback"] <= html.BUTTON("Passer à la suite", onclick="nextSCO();") 395 396 397 </script> 398 399 </head> 400 401 <body> 402 403 <h1>Niveau 10</h1> 404 405 <p> 406 Vous disposez des fonctions 407 <code>droite()</code>, 408 <code>gauche()</code>, 409 <code>haut()</code>, et 410 <code>bas()</code> 411 pour faire avancer le robot. 412 </p> 413 414 <p> 415 Il faut maintenant écrire vous-même la fonction 416 <code>u(<i>n</i>)</code> 417 qui va faire faire un virage vers le bas 418 de longueur <i>n</i> au robot. 419 </p> 420 421 <p> 422 Chaque barrière de <i>?</i> possède un point de passage. 423 Sa position est donnée par la case <i>i</i> correspondante. 424 Par exemple, si la case <i>i</i> au dessus du début vaut 2, 425 il faudra faire un U de 2 cases de profond pour passer. 426 </p> 427 428 <p> 429 Utilisez votre fonction <code>u(n)</code> et <code>voir_haut()</code> 430 pour passer chaque barrière. 431 </p> 432 433 <p> 434 Exemples de fonction avec paramètre : 435 <pre><code># on définis une fonction f qui prend 1 paramètre n 436 437 def f(n): 438 # à l'intérieur de la fonction, on utilise n comme une variable : 439 print(n) 440 for i in range(n): 441 print("lol") 442 443 # on appelle f : 444 445 f(42) # n vaudra 42 dans la fonction 446 </code></pre> 447 </p> 448 449 <div id="edcontainer"> 450 <div class="edcolumn"> 451 Code python : 452 <pre id="code" class="breditor"></pre> 453 <div id="feedback"></div> 454 </div> 455 <div class="edcolumn"> 456 Plateau : 457 <div id="game"></div> 458 </div> 459 </div> 460 461 </body> 462 </html>