ajout tp2mvc, tp3 et update des tp 1 et 2

This commit is contained in:
EmmanuelTiamzon
2026-04-14 12:28:43 +02:00
parent d1e3f215aa
commit dbc0fbd946
14 changed files with 404 additions and 85 deletions
@@ -1,40 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.classless.min.css"
>
<script src="eratosthene.js"></script>
</head>
<body>
<main>
<form role="search">
<input name="limit" type="text">
<input type="submit" value="compute">
</form>
<article>
<p>time : <span id="time1"></span></p>
<p>time : <span id="time2"></span></p>
<p id="primes"></p>
</article>
</main>
<script>
document.querySelector("form").addEventListener("submit",ev => {
ev.preventDefault();
let start,end;
start = performance.now();
primes = eratosthene1(ev.target.limit.value);
end = performance.now();
document.getElementById("time1").textContent = end - start;
document.getElementById("primes").textContent = primes;
})
</script>
</body>
</html>
-23
View File
@@ -1,23 +0,0 @@
function eratosthene(n)
{
let primes = [];
let filterArray = [];
for(let i = 2; i <=n; i++){
// TODO
}
return primes;
}
function eratosthene1(n)
{
let numbers = Array.from({length : n - 2}, (v,k) => k + 2);
let p ,primes = [];
while(numbers.length){
[p,...numbers] = numbers;
numbers = numbers.filter( x => x%p != 0);
primes = [...primes,p];
}
return primes;
}
+3 -4
View File
@@ -48,15 +48,14 @@ class Ant {
}
computeNextState() {
if(this.tiles[this.x][this.y] === 1) { //On vérifie si la prochaine case est noire
//On fait en sorte à ce qu'elle soit repeinte en blanc et tourne de 90° à gauche.
if(this.tiles[this.x][this.y] === 1) {
this.tiles[this.x][this.y] = 0;
this.rotateLeft();
} else { //Dans ce cas si la prochaine case est blanche
// On fait en sorte à ce qu'elle soit repeinte en noir et tourne de 90° à droite.
} else {
this.tiles[this.x][this.y] = 1;
this.rotateRight();
}
}
}
export default Ant;
+91
View File
@@ -0,0 +1,91 @@
let customers = [
{
'id': 1,
'f_name': 'Abby',
'l_name': 'Thomas',
'gender': 'M',
'married': true,
'age': 32,
'expense': 500,
'purchased': ['Shampoo', 'Toys', 'Book']
},
{
'id': 2,
'f_name': 'Jerry',
'l_name': 'Tom',
'gender': 'M',
'married': true,
'age': 64,
'expense': 100,
'purchased': ['Stick', 'Blade']
},
{
'id': 3,
'f_name': 'Dianna',
'l_name': 'Cherry',
'gender': 'F',
'married': true,
'age': 22,
'expense': 1500,
'purchased': ['Lipstik', 'Nail Polish', 'Bag', 'Book']
},
{
'id': 4,
'f_name': 'Dev',
'l_name': 'Currian',
'gender': 'M',
'married': true,
'age': 82,
'expense': 90,
'purchased': ['Book']
},
{
'id': 5,
'f_name': 'Maria',
'l_name': 'Gomes',
'gender': 'F',
'married': false,
'age': 7,
'expense': 300,
'purchased': ['Toys']
},
{
'id': 6,
'f_name': 'Homer',
'l_name': 'Simpson',
'gender': 'M',
'married': true,
'age': 39,
'expense': 500,
'purchased': ['Book']
}
];
// Question 1 :
function filterOldPeople(customers) {
customers.filter(returnOldPeople);
}
function returnOldPeople(customer) {
return customer.age > 60;
}
let oldCustomers = filterOldPeople(customers);
//console.log(oldCustomers);
// Question 2 :
function fullName(customer) {
customer.full_name = customer.f_name +" "+ customer.l_name;
}
customers.forEach(fullName);
//console.log(customers);
//Question 3 :
function isUnderTen(customer) {
return customer.age < 10;
}
customers.some(isUnderTen);
+28 -7
View File
@@ -26,13 +26,16 @@ function peep() {
const time = randomTime(1000, 1500);
const hole = randomHole(holes);
// TODO
const mole = hole.querySelector('.mole');
mole.classList.add('up');
mole.classList.remove('whacked');
setTimeout(() => {
// TODO
//
}}, time);
mole.classList.remove('up');
if(!timeUp) {
peep();
}
}, time);
}
function startGame() {
@@ -40,13 +43,31 @@ function startGame() {
score = 0;
timeUp = false;
// TODO
moles.forEach(mole => {
mole.classList.remove('up');
mole.classList.remove('whacked');
});
peep();
setTimeout(()=>{
timeUp = true;
}, duration * 1000)
}
function bonk(e) {
if(!this.classList.contains('up')) {
return;
}
// TODO
score ++;
scoreBoard.textContent = score;
this.classList.remove('up');
this.classList.add('whacked');
setTimeout(()=>{
this.classList.remove('whacked');
}, 800);
}
moles.forEach(mole => mole.addEventListener('click', bonk));
+5 -5
View File
@@ -4,7 +4,7 @@ body {
align-items: center;
height: 100vh;
background-color: #f0f0f0;
/* font-family: Arial, sans-serif;*/
font-family: Arial, sans-serif;
}
.game {
@@ -43,9 +43,9 @@ body {
}
.mole.up img{
/* background-image : url('img/mole2.png');
background-image : url('img/mole2.png');
background-size:contain;
background-repeat: no-repeat;*/
background-repeat: no-repeat;
width:90px;
height:90px;
@@ -54,9 +54,9 @@ body {
.mole.whacked img {
content: url('img/mole-whacked.png');
/* background-image : url('img/mole-whacked.png');
background-image : url('img/mole-whacked.png');
background-size:contain;
background-repeat: no-repeat;*/
background-repeat: no-repeat;
width:90px;
height:90px;
+84
View File
@@ -0,0 +1,84 @@
#### Ex1 : modele MVC et pattern strategy
> Stratégie est un patron de conception comportemental qui permet de définir une
> famille dalgorithmes, de les mettre dans des classes séparées et de rendre
> leurs objets interchangeables. (source wikipédia)
Le but est de réaliser ce pattern de conception dans le jeu très simple du chifoumi.
<div align="center">
<img src="./img/chifoumi.png">
</div>
Pour l'instant, le jeu utilise le pattern MVC. Le modèle, qui calcule le coup de l'ordinateur utilise
un tirage aléatoire. On veut pouvoir utilisé d'autres méthodes, qui utilisent l'historique des coups
joués par le joueur.
1. Modifiez le modèle et la vue pour que le jeu affiche le pourcentage de victoires, matchs nuls et défaites du joueur depuis le début
de la partie.
On veut maintenant séparer la façon dont l'ordinateur choisit son coup de la logique du jeu. Le modèle utilisera
une stratégie donnée.
2. Créez un sous-répétoires `stratégies` dans lequel on stokera les différentes stratégies disponibles.
Les différentes stratégies réaliseront l'interface
```js
getChoice(playerHistory)
```
qui calcule le coup de l'ordinateur, en fonction de l'historique des différents coups du joueur.
3. Ecrivez 3 stratégies simples `RandomStrategy.js` (stratégie initiale), `CopyPlayerStrategy.js`
(joue le même coup que le joueur) `CounterMostUsedStrategy.js` (joue le coup le plus joué par le joueur) :
Chaque fichier implémente la stratégie correspondante sous la forme :
```js
export default class RandomStrategy {
getChoice(playerHistory) {
....
}
}
```
4. Mettez à jour le modèle pour qu'il puisse utiliser une stratégie donnée.
5. testez dans le main.
#### Ajout d'une stratégie
On va ajouter une stratégie markovienne d'ordre 1. On fait
l'hyptohése que le coup du joueur dépend de son coup précedent (ordre 1).
On met à jour au fur et à mesure la matrice de transitions entre
les coups joué par le joueur. Par exemple,
```js
{
rock: { rock: 2, paper: 5, scissors: 1 },
paper: { rock: 1, paper: 3, scissors: 4 },
scissors: { rock: 6, paper: 1, scissors: 2 }
}
```
signifie qu'après paper, le joueur a joué 1 fois rock, 3 fois paper, et 4 fois scissors.
On se sert de la matrice pour contrer la prédiction.
5. Écrivezz cette stratégie, et testez la.
#### Stratégie mixte
Le but est d'implanter une stratégie mixte. On se donne une probabilité `p`.
- la stratégie markovienne est jouée avec la probabilité `p`.
- la stratégie aléatoire est jouée avec la probabilité `1-p`
Écrivez la stratégie mixte, et testez.
#### Stratégie adaptative
La probabilité `p` dépend du score. On l'adapte au fur et à mesure. Si on gagne beaucoup (trop),
on joue au hasard, sinon avec Markov.
Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

+41
View File
@@ -0,0 +1,41 @@
.game {
}
.choices{
display : flex;
align-items:stretch;
height:8em;
}
.choices > span:nth-child(2) {
margin-left:3em;
}
.choices span i{
font-size: 2em;
cursor: pointer;
border: none;
margin-right:0.25em;
transition: transform 0.2s, color 0.2s;
}
#player,#computer{
font-size: 3em;
border: none;
margin-right:0.25em;
}
.choices span i:hover {
color:#398712
}
#player {
color:#398712
}
#computer {
color:#D93526;
}
+40
View File
@@ -0,0 +1,40 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Pierre Feuille Ciseaux</title>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.classless.min.css"
>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.15.4/css/all.css">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<main>
<h1>
Pierre - Feuille - Ciseaux
</h1>
<div class="choices">
<span>
<i data-choice="rock" class="far fa-hand-rock"></i>
<i data-choice="paper" class="far fa-hand-paper"></i>
<i data-choice="scissors" class="far fa-hand-scissors"></i>
</span>
<span>
<span id="player"></span>
<span id="computer"></span>
</span>
</div>
<div class="game">
<p id="score"></p>
<p id="result"></p>
</div>
</main>
<script type="module" src="js/main.js"></script>
</body>
</html>
+18
View File
@@ -0,0 +1,18 @@
export default class GameController {
constructor(model, view) {
this.model = model;
this.view = view;
this.view.bindPlay(this.handlePlay);
this.view.displayScore(this.model.getScore());
}
handlePlay = (playerChoice) => {
const computerChoice = this.model.getComputerChoice();
const result = this.model.getResult(playerChoice, computerChoice);
this.view.displayResult(playerChoice, computerChoice, result);
this.view.displayScore(this.model.getScore());
}
}
+9
View File
@@ -0,0 +1,9 @@
import GameModel from "./model.js";
import GameView from "./view.js";
import GameController from "./controller.js";
const app = new GameController(
new GameModel(),
new GameView()
);
+29
View File
@@ -0,0 +1,29 @@
export default class GameModel {
constructor() {
this.choices = ["rock", "paper", "scissors"];
this.score = { player: 0, computer: 0};
}
getComputerChoice() {
const index = Math.floor(Math.random() * this.choices.length);
return this.choices[index];
}
getResult(player, computer) {
if (player === computer) return "égalité";
if (
(player === "rock" && computer === "scissors") ||
(player === "paper" && computer === "rock") ||
(player === "scissors" && computer === "paper")
) {
this.score.player++;
return "gagné";
}
this.score.computer++;
return "perdu";
}
getScore() {
return this.score;
}
}
+50
View File
@@ -0,0 +1,50 @@
export default class GameView {
#icons = {
"rock" : "far fa-hand-rock",
"paper" : "far fa-hand-paper",
"scissors" : "far fa-hand-scissors"
}
constructor() {
this.resultEl = document.getElementById("result");
this.scoreEl = document.getElementById("score");
this.buttons = document.querySelectorAll(".choices span i");
this.player = document.getElementById("player");
this.computer = document.getElementById("computer");
}
bindPlay(handler) {
this.buttons.forEach(button => {
button.addEventListener("click", () => {
handler(button.dataset.choice);
});
});
}
displayResult(player, computer, result) {
let i = document.createElement("i");
i.classList.add(...this.#icons[player].split(' '))
this.player.replaceChildren(i)
i = document.createElement("i");
i.classList.add(...this.#icons[computer].split(' '))
this.computer.replaceChildren(i)
this.resultEl.innerHTML =
`Joueur <i class="${this.#icons[player]}"></i>, ordinateur <i class="${this.#icons[computer]}"></i> → ${result}`;
}
displayScore(score) {
let winRate = ((score.player * 100 / score.count) || 0).toFixed(2)
let lossRate = ((score.computer * 100 / score.count) ||0).toFixed(2)
let drawRate = (100 - winRate - lossRate).toFixed(2)
this.scoreEl.textContent =
`Score — Joueur: ${score.player} | Ordinateur: ${score.computer}`;
}
}