lvl7.html (9873B)
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 = "# 3 portiques à passer ..."; 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/lvl7.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 if (Math.random() < 0.5) 150 tiles[0][2] = 3; 151 else 152 tiles[2][2] = 3; 153 if (Math.random() < 0.5) 154 tiles[0][6] = 3; 155 else 156 tiles[2][6] = 3; 157 if (Math.random() < 0.5) 158 tiles[6][4] = 3; 159 else 160 tiles[8][4] = 3; 161 } 162 163 function get_tile_at(x,y) { 164 return tiles[x][y]; 165 } 166 167 function reset_board() { 168 movetime = 0; 169 bot.x = tilesize * 1.5; 170 bot.y = tilesize * 1.5; 171 bot.angle = 0; 172 173 for (move of delayed_moves){ 174 clearTimeout(move) 175 } 176 177 delayed_moves = [] 178 179 gen_tiles() 180 } 181 182 function move_left() { 183 delayed_moves.push( 184 setTimeout( 185 function() { 186 bot.x -= tilesize; 187 bot.angle = 180; 188 }, movetime) 189 ); 190 movetime += delay; 191 } 192 193 function move_right() { 194 delayed_moves.push( 195 setTimeout( 196 function() { 197 bot.x += tilesize; 198 bot.angle = 0; 199 }, movetime) 200 ); 201 movetime += delay; 202 } 203 204 function move_up() { 205 delayed_moves.push( 206 setTimeout( 207 function() { 208 bot.y -= tilesize; 209 bot.angle = -90; 210 }, movetime) 211 ); 212 movetime += delay; 213 } 214 215 function move_down() { 216 delayed_moves.push( 217 setTimeout( 218 function() { 219 bot.y += tilesize; 220 bot.angle = 90; 221 }, movetime) 222 ); 223 movetime += delay; 224 } 225 226 window.onload = function() { 227 loadSCO(); 228 document.getElementById("code").textContent = code; 229 230 game = new Phaser.Game(config); 231 232 brython(); 233 } 234 </script> 235 236 <script type="text/python"> 237 # Requires Brython and Ace editor 238 239 from browser import document, window, html 240 from sys import stderr, stdout, settrace 241 from traceback import print_exc, extract_stack, extract_tb 242 243 def make_max_line_tracer(maxlines): 244 lines = 0 245 def tracer(frame, event, arg): 246 nonlocal lines 247 if event == 'line': 248 lines += 1 249 if lines >= maxlines: 250 raise TimeoutError 251 return tracer 252 return tracer 253 254 def exec_code(editor, id): 255 reset() 256 257 feedback("Le drapeau n'est pas encore atteint") 258 259 code_lines = editor.session.getLength() 260 if code_lines > max_code_lines: 261 feedback("Trop de lignes utilisées ( " + str(code_lines) + "/" + str(max_code_lines) + ")") 262 return 263 264 console = document[id + "_console"] 265 console.clear() 266 stderr.write = lambda data : console_target(data, console, True) 267 stdout.write = lambda data : console_target(data, console) 268 269 code = editor.getValue() 270 try: 271 compiled = compile(code, "<" + id + ">", "exec") 272 except SyntaxError: 273 print_exc(limit=0) 274 return 275 276 settrace(make_max_line_tracer(10000)) # increase to allow longer execution 277 try: 278 exec(code) 279 except TimeoutError: 280 settrace(None) 281 print("L'exécution prend trop de temps, abandon.", file=stderr) 282 except Exception as e: 283 settrace(None) 284 tb_len = len(extract_tb(e.__traceback__)) - len(extract_stack()) 285 print_exc(limit=-tb_len) 286 finally: 287 settrace(None) 288 289 window.code = code 290 #window.score = check() 291 window.sendSCO() 292 293 def console_target(data, elt, err=False): 294 elt <= html.PRE(data, Class="stderr" if err else "stdout") 295 elt.scrollTop = elt.scrollHeight 296 297 breditors = document.select(".breditor") 298 299 max_code_lines = 25 300 301 for ed_elt in breditors: 302 editor = window.ace.edit(ed_elt.id) 303 editor.session.setMode("ace/mode/python") 304 #editor.setOption('fontSize', '14px') 305 editor.setOption('maxLines', max_code_lines) 306 editor.setOption('minLines', max_code_lines) 307 308 console = html.DIV(Class="console", id=ed_elt.id + "_console") 309 310 ed_elt.insertAdjacentElement('afterend', console) 311 312 exec_button = html.BUTTON("Exécuter →") 313 exec_button.bind("click", lambda ev : exec_code(editor, ed_elt.id)) 314 ed_elt.insertAdjacentElement('afterend', exec_button) 315 316 def feedback(msg): 317 document["feedback"].clear() 318 document["feedback"] <= msg 319 320 coords = [1,1] 321 322 def reset(): 323 global coords 324 window.reset_board() 325 coords = [1,1] 326 327 def gauche(): 328 if coords[0] >= 0: 329 move_to(coords[0]-1, coords[1], -1, 0, window.move_left) 330 331 def droite(): 332 if coords[0] < 10: 333 move_to(coords[0]+1, coords[1], 1, 0, window.move_right) 334 335 def haut(): 336 if coords[1] >= 0: 337 move_to(coords[0], coords[1]-1, 0, -1, window.move_up) 338 339 def bas(): 340 if coords[1] < 10: 341 move_to(coords[0], coords[1]+1, 0 , 1, window.move_down) 342 343 def move_to(x, y, dx, dy, move): 344 tile = window.get_tile_at(x, y) 345 if tile in (0,1,3): 346 move() 347 coords[0] += dx 348 coords[1] += dy 349 if tile == 1: 350 win() 351 elif tile == 3: 352 fall() 353 else: 354 feedback("Le robot n'est pas sur un drapeau") 355 window.score = 0 356 357 358 def voir_gauche(): 359 if coords[0] == 0: 360 return 3 361 else: 362 return voir(coords[0]-1, coords[1]) 363 364 def voir_droite(): 365 if coords[0] == 10: 366 return 3 367 else: 368 return voir(coords[0]+1, coords[1]) 369 370 def voir_haut(): 371 if coords[1] == 0: 372 return 3 373 else: 374 return voir(coords[0], coords[1]-1) 375 376 def voir_bas(): 377 if coords[1] == 10: 378 return 3 379 else: 380 return voir(coords[0], coords[1]+1) 381 382 def voir(x,y): 383 return window.get_tile_at(x,y) 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 7</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 Vous disposez des fonctions 416 <code>voir_droite()</code>, 417 <code>voir_gauche()</code>, 418 <code>voir_haut()</code>, et 419 <code>voir_bas()</code> 420 pour déterminer le type des cases, 421 qui donneront un des nombres suivants : 422 <ul> 423 <li>0 pour un chemin</li> 424 <li>1 pour un drapeau</li> 425 <li>3 pour du vide</li> 426 </ul> 427 </p> 428 429 <p> 430 Écrivez une fonction pour passer un carrefour, 431 puis utiliser là pour faire le parcours en entier. 432 </p> 433 434 <p> 435 Exemple de définition et d'appel de fonction : 436 <pre><code># on définis la fonction f : 437 def f(): 438 # elle contient le code suivant : 439 print("Bonjour !") 440 441 # on appelle la fonction f : 442 f() 443 </code></pre> 444 </p> 445 446 447 <div id="edcontainer"> 448 <div class="edcolumn"> 449 Code python : 450 <pre id="code" class="breditor"></pre> 451 <div id="feedback"></div> 452 </div> 453 <div class="edcolumn"> 454 Plateau : 455 <div id="game"></div> 456 </div> 457 </div> 458 459 </body> 460 </html>