lvl9.html (9641B)
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/lvl9.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 = 0; 145 tiles[i][j] = id; 146 } 147 } 148 } 149 150 function get_tile_at(x,y) { 151 return tiles[x][y]; 152 } 153 154 function reset_board() { 155 movetime = 0; 156 bot.x = tilesize * 1.5; 157 bot.y = tilesize * 1.5; 158 bot.angle = 0; 159 160 for (move of delayed_moves){ 161 clearTimeout(move) 162 } 163 164 delayed_moves = [] 165 166 gen_tiles() 167 } 168 169 function move_left() { 170 delayed_moves.push( 171 setTimeout( 172 function() { 173 bot.x -= tilesize; 174 bot.angle = 180; 175 }, movetime) 176 ); 177 movetime += delay; 178 } 179 180 function move_right() { 181 delayed_moves.push( 182 setTimeout( 183 function() { 184 bot.x += tilesize; 185 bot.angle = 0; 186 }, movetime) 187 ); 188 movetime += delay; 189 } 190 191 function move_up() { 192 delayed_moves.push( 193 setTimeout( 194 function() { 195 bot.y -= tilesize; 196 bot.angle = -90; 197 }, movetime) 198 ); 199 movetime += delay; 200 } 201 202 function move_down() { 203 delayed_moves.push( 204 setTimeout( 205 function() { 206 bot.y += tilesize; 207 bot.angle = 90; 208 }, movetime) 209 ); 210 movetime += delay; 211 } 212 213 window.onload = function() { 214 loadSCO(); 215 document.getElementById("code").textContent = code; 216 217 game = new Phaser.Game(config); 218 219 brython(); 220 } 221 </script> 222 223 <script type="text/python"> 224 # Requires Brython and Ace editor 225 226 from browser import document, window, html 227 from sys import stderr, stdout, settrace 228 from traceback import print_exc, extract_stack, extract_tb 229 230 def make_max_line_tracer(maxlines): 231 lines = 0 232 def tracer(frame, event, arg): 233 nonlocal lines 234 if event == 'line': 235 lines += 1 236 if lines >= maxlines: 237 raise TimeoutError 238 return tracer 239 return tracer 240 241 def exec_code(editor, id): 242 reset() 243 244 feedback("Le drapeau n'est pas encore atteint") 245 246 code_lines = editor.session.getLength() 247 if code_lines > max_code_lines: 248 feedback("Trop de lignes utilisées ( " + str(code_lines) + "/" + str(max_code_lines) + ")") 249 return 250 251 console = document[id + "_console"] 252 console.clear() 253 stderr.write = lambda data : console_target(data, console, True) 254 stdout.write = lambda data : console_target(data, console) 255 256 code = editor.getValue() 257 try: 258 compiled = compile(code, "<" + id + ">", "exec") 259 except SyntaxError: 260 print_exc(limit=0) 261 return 262 263 settrace(make_max_line_tracer(10000)) # increase to allow longer execution 264 try: 265 exec(code) 266 except TimeoutError: 267 settrace(None) 268 print("L'exécution prend trop de temps, abandon.", file=stderr) 269 except Exception as e: 270 settrace(None) 271 tb_len = len(extract_tb(e.__traceback__)) - len(extract_stack()) 272 print_exc(limit=-tb_len) 273 finally: 274 settrace(None) 275 276 window.code = code 277 #window.score = check() 278 window.sendSCO() 279 280 def console_target(data, elt, err=False): 281 elt <= html.PRE(data, Class="stderr" if err else "stdout") 282 elt.scrollTop = elt.scrollHeight 283 284 breditors = document.select(".breditor") 285 286 max_code_lines = 15 287 288 for ed_elt in breditors: 289 editor = window.ace.edit(ed_elt.id) 290 editor.session.setMode("ace/mode/python") 291 #editor.setOption('fontSize', '14px') 292 editor.setOption('maxLines', max_code_lines) 293 editor.setOption('minLines', max_code_lines) 294 295 console = html.DIV(Class="console", id=ed_elt.id + "_console") 296 297 ed_elt.insertAdjacentElement('afterend', console) 298 299 exec_button = html.BUTTON("Exécuter →") 300 exec_button.bind("click", lambda ev : exec_code(editor, ed_elt.id)) 301 ed_elt.insertAdjacentElement('afterend', exec_button) 302 303 def feedback(msg): 304 document["feedback"].clear() 305 document["feedback"] <= msg 306 307 coords = [1,1] 308 309 def reset(): 310 global coords 311 window.reset_board() 312 coords = [1,1] 313 314 def gauche(): 315 if coords[0] >= 0: 316 move_to(coords[0]-1, coords[1], -1, 0, window.move_left) 317 318 def droite(): 319 if coords[0] < 10: 320 move_to(coords[0]+1, coords[1], 1, 0, window.move_right) 321 322 def haut(): 323 if coords[1] >= 0: 324 move_to(coords[0], coords[1]-1, 0, -1, window.move_up) 325 326 def bas(): 327 if coords[1] < 10: 328 move_to(coords[0], coords[1]+1, 0 , 1, window.move_down) 329 330 def move_to(x, y, dx, dy, move): 331 tile = window.get_tile_at(x, y) 332 if tile in (0,1,3): 333 move() 334 coords[0] += dx 335 coords[1] += dy 336 if tile == 1: 337 win() 338 elif tile == 3: 339 fall() 340 else: 341 feedback("Le robot n'est pas sur un drapeau") 342 window.score = 0 343 344 345 def voir_gauche(): 346 if coords[0] == 0: 347 return 3 348 else: 349 return voir(coords[0]-1, coords[1]) 350 351 def voir_droite(): 352 if coords[0] == 10: 353 return 3 354 else: 355 return voir(coords[0]+1, coords[1]) 356 357 def voir_haut(): 358 if coords[1] == 0: 359 return 3 360 else: 361 return voir(coords[0], coords[1]-1) 362 363 def voir_bas(): 364 if coords[1] == 10: 365 return 3 366 else: 367 return voir(coords[0], coords[1]+1) 368 369 def voir(x,y): 370 return window.get_tile_at(x,y) 371 372 def pas_u(n): 373 for i in range(n): 374 bas() 375 droite() 376 droite() 377 for i in range(n): 378 haut() 379 380 def fall(): 381 feedback("Le robot est tombé dans le vide !") 382 raise Exception("Le robot est tombé dans le vide") 383 384 385 def win(): 386 window.score = 100 387 # feedback("Bravo ! (exécutez plusieurs fois avant de continuer)") 388 feedback("Bravo ! ") 389 document["feedback"] <= html.BUTTON("Passer à la suite", onclick="nextSCO();") 390 391 392 </script> 393 394 </head> 395 396 <body> 397 398 <h1>Niveau 9</h1> 399 400 <p> 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 </p> 408 409 <p> 410 Il faut maintenant écrire vous-même la fonction 411 <code>u(<i>n</i>)</code> 412 qui va faire faire un virage vers le bas 413 de longueur <i>n</i> au robot. 414 </p> 415 416 <p> 417 Exemples de fonction avec paramètre : 418 <pre><code># on définis une fonction f qui prend 1 paramètre n 419 420 def f(n): 421 # à l'intérieur de la fonction, on utilise n comme une variable : 422 print(n) 423 for i in range(n): 424 print("lol") 425 426 # on appelle f : 427 428 f(42) # n vaudra 42 dans la fonction 429 430 lol = 4 431 f(lol) # n vaudra 4 dans la fonction 432 433 for i in range(3): 434 f(i) 435 </code></pre> 436 </p> 437 438 439 <div id="edcontainer"> 440 <div class="edcolumn"> 441 Code python : 442 <pre id="code" class="breditor"></pre> 443 <div id="feedback"></div> 444 </div> 445 <div class="edcolumn"> 446 Plateau : 447 <div id="game"></div> 448 </div> 449 </div> 450 451 </body> 452 </html>