lvl4.html (10322B)
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 = "print(\"plus de x :(\")\nprint(y)"; 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 var target_x = 0; 110 var target_y = 0; 111 112 var movetime = 0; 113 var delayed_moves = []; 114 115 var config = { 116 type: Phaser.AUTO, 117 width: tilesize*10, 118 height: tilesize*10, 119 parent: "game", 120 scene: { 121 preload: preload, 122 create: create 123 } 124 }; 125 126 function preload() { 127 this.load.image("tilemap", "img/tilemap.png") 128 this.load.image("bot", "img/bot.png") 129 this.load.tilemapCSV('map', 'lvl/lvl4.csv'); 130 } 131 132 function create() { 133 map = this.make.tilemap({ key: 'map', tileWidth: 32, tileHeight: 32 }); 134 var tileset = map.addTilesetImage('tilemap'); 135 layer = map.createLayer(0, tileset, 0, 0); 136 137 bot = this.add.image(tilesize * 1.5, tilesize * 1.5, "bot"); 138 } 139 140 function gen_tiles() { 141 for (var i = 0 ; i < 10 ; i++) { 142 tiles[i] = []; 143 for (var j = 0 ; j < 10 ; j++) { 144 var id = map.getTileAt(i,j).index; 145 if (id == 4) 146 id = 0; 147 tiles[i][j] = id; 148 } 149 } 150 151 target_x = Math.floor(Math.random()*8); 152 target_y = Math.floor(Math.random()*7)+1; 153 154 var cnt = 0; 155 for (var i = 1 ; i < 8 ; i++) { 156 if (cnt < target_x && Math.random() < 0.5) { 157 cnt++; 158 tiles[i][0] = 1; 159 } else { 160 tiles[i][0] = 0; 161 } 162 } 163 tiles[8][0] = target_x - cnt; 164 tiles[target_x+1][target_y+1] = 1; 165 } 166 167 function get_tile_at(x,y) { 168 return tiles[x][y]; 169 } 170 171 function reset_board() { 172 movetime = 0; 173 bot.x = tilesize * 1.5; 174 bot.y = tilesize * 1.5; 175 bot.angle = 0; 176 177 for (move of delayed_moves){ 178 clearTimeout(move) 179 } 180 181 delayed_moves = [] 182 183 gen_tiles() 184 } 185 186 function move_left() { 187 delayed_moves.push( 188 setTimeout( 189 function() { 190 bot.x -= tilesize; 191 bot.angle = 180; 192 }, movetime) 193 ); 194 movetime += delay; 195 } 196 197 function move_right() { 198 delayed_moves.push( 199 setTimeout( 200 function() { 201 bot.x += tilesize; 202 bot.angle = 0; 203 }, movetime) 204 ); 205 movetime += delay; 206 } 207 208 function move_up() { 209 delayed_moves.push( 210 setTimeout( 211 function() { 212 bot.y -= tilesize; 213 bot.angle = -90; 214 }, movetime) 215 ); 216 movetime += delay; 217 } 218 219 function move_down() { 220 delayed_moves.push( 221 setTimeout( 222 function() { 223 bot.y += tilesize; 224 bot.angle = 90; 225 }, movetime) 226 ); 227 movetime += delay; 228 } 229 230 window.onload = function() { 231 loadSCO(); 232 document.getElementById("code").textContent = code; 233 234 game = new Phaser.Game(config); 235 236 brython(); 237 } 238 </script> 239 240 <script type="text/python"> 241 # Requires Brython and Ace editor 242 243 from browser import document, window, html 244 from sys import stderr, stdout, settrace 245 from traceback import print_exc, extract_stack, extract_tb 246 247 def make_max_line_tracer(maxlines): 248 lines = 0 249 def tracer(frame, event, arg): 250 nonlocal lines 251 if event == 'line': 252 lines += 1 253 if lines >= maxlines: 254 raise TimeoutError 255 return tracer 256 return tracer 257 258 def exec_code(editor, id): 259 global x, y 260 reset() 261 #x = window.target_x 262 y = window.target_y 263 264 feedback("Le drapeau n'est pas encore atteint") 265 266 code_lines = editor.session.getLength() 267 if code_lines > max_code_lines: 268 feedback("Trop de lignes utilisées ( " + str(code_lines) + "/" + str(max_code_lines) + ")") 269 return 270 271 console = document[id + "_console"] 272 console.clear() 273 stderr.write = lambda data : console_target(data, console, True) 274 stdout.write = lambda data : console_target(data, console) 275 276 code = editor.getValue() 277 try: 278 compiled = compile(code, "<" + id + ">", "exec") 279 except SyntaxError: 280 print_exc(limit=0) 281 return 282 283 settrace(make_max_line_tracer(10000)) # increase to allow longer execution 284 try: 285 exec(code) 286 except TimeoutError: 287 settrace(None) 288 print("L'exécution prend trop de temps, abandon.", file=stderr) 289 except Exception as e: 290 settrace(None) 291 tb_len = len(extract_tb(e.__traceback__)) - len(extract_stack()) 292 print_exc(limit=-tb_len) 293 finally: 294 settrace(None) 295 296 window.code = code 297 #window.score = check() 298 window.sendSCO() 299 300 def console_target(data, elt, err=False): 301 elt <= html.PRE(data, Class="stderr" if err else "stdout") 302 elt.scrollTop = elt.scrollHeight 303 304 breditors = document.select(".breditor") 305 306 max_code_lines = 15 307 308 for ed_elt in breditors: 309 editor = window.ace.edit(ed_elt.id) 310 editor.session.setMode("ace/mode/python") 311 #editor.setOption('fontSize', '14px') 312 editor.setOption('maxLines', max_code_lines) 313 editor.setOption('minLines', max_code_lines) 314 315 console = html.DIV(Class="console", id=ed_elt.id + "_console") 316 317 ed_elt.insertAdjacentElement('afterend', console) 318 319 exec_button = html.BUTTON("Exécuter →") 320 exec_button.bind("click", lambda ev : exec_code(editor, ed_elt.id)) 321 ed_elt.insertAdjacentElement('afterend', exec_button) 322 323 def feedback(msg): 324 document["feedback"].clear() 325 document["feedback"] <= msg 326 327 coords = [1,1] 328 329 def reset(): 330 global coords 331 window.reset_board() 332 coords = [1,1] 333 334 def gauche(): 335 if coords[0] >= 0: 336 move_to(coords[0]-1, coords[1], -1, 0, window.move_left) 337 338 def droite(): 339 if coords[0] < 10: 340 move_to(coords[0]+1, coords[1], 1, 0, window.move_right) 341 342 def haut(): 343 if coords[1] >= 0: 344 move_to(coords[0], coords[1]-1, 0, -1, window.move_up) 345 346 def bas(): 347 if coords[1] < 10: 348 move_to(coords[0], coords[1]+1, 0 , 1, window.move_down) 349 350 def move_to(x, y, dx, dy, move): 351 tile = window.get_tile_at(x, y) 352 if tile in (0,1,3): 353 move() 354 coords[0] += dx 355 coords[1] += dy 356 if tile == 1: 357 win() 358 elif tile == 3: 359 fall() 360 else: 361 feedback("Le robot n'est pas sur un drapeau") 362 window.score = 0 363 364 365 def voir_gauche(): 366 if coords[0] == 0: 367 return 3 368 else: 369 return voir(coords[0]-1, coords[1]) 370 371 def voir_droite(): 372 if coords[0] == 10: 373 return 3 374 else: 375 return voir(coords[0]+1, coords[1]) 376 377 def voir_haut(): 378 if coords[1] == 0: 379 return 3 380 else: 381 return voir(coords[0], coords[1]-1) 382 383 def voir_bas(): 384 if coords[1] == 10: 385 return 3 386 else: 387 return voir(coords[0], coords[1]+1) 388 389 def voir(x,y): 390 return window.get_tile_at(x,y) 391 392 def fall(): 393 feedback("Le robot est tombé dans le vide !") 394 raise Exception("Le robot est tombé dans le vide") 395 396 397 def win(): 398 window.score = 100 399 feedback("Bravo ! (exécutez plusieurs fois avant de continuer)") 400 document["feedback"] <= html.BUTTON("Passer à la suite", onclick="nextSCO();") 401 402 403 </script> 404 405 </head> 406 407 <body> 408 409 <h1>Niveau 4</h1> 410 411 <p> 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 </p> 419 420 <p> 421 Le drapeau est caché parmis ces points d'interrogation, 422 mais cette fois-ci vous n'avez plus la variable 423 <code>x</code> 424 (la variable 425 <code>y</code> 426 est encore là). 427 </p> 428 429 <p> 430 Les cases 431 <code><i>i</i></code> 432 contiennent un nombre qu'on peut voir en regardant leur contenu avec 433 les fonctions 434 <code>voir_droite()</code>, 435 <code>voir_gauche()</code>, 436 <code>voir_haut()</code>, ou 437 <code>voir_bas()</code>. 438 </p> 439 440 <p> 441 Cette fois-ci il faudra additionner le contenu de toutes les cases 442 <code><i>i</i></code> 443 du haut pour obtenir le déplacement x, 444 puis revenir au point de départ pour appliquer ce déplacement. 445 </p> 446 447 <p> 448 Exemples avec des variables : 449 <pre><code># on crée des variables 450 lol = 42 451 lul = "truc" 452 lel = lol + 2 453 454 # on modifie des variables 455 lol = 4 456 lel = lel - 2 457 458 # on utilise des variables 459 print(lul) 460 461 for i in range(lol): 462 print("salut") 463 464 if lel == 42: 465 print("ok") 466 </code></pre> 467 </p> 468 469 470 <div id="edcontainer"> 471 <div class="edcolumn"> 472 Code python : 473 <pre id="code" class="breditor"></pre> 474 <div id="feedback"></div> 475 </div> 476 <div class="edcolumn"> 477 Plateau : 478 <div id="game"></div> 479 </div> 480 </div> 481 482 </body> 483 </html>