This commit is contained in:
2026-02-06 13:50:53 +01:00
parent 186b3839f0
commit 8536d0b1bb
8 changed files with 271 additions and 0 deletions

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

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;
}

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>

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());
}
}

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()
);

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;
}
}

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}`;
}
}