diff --git a/R4.01_R4.A.10/td_tp/tp3/README.md b/R4.01_R4.A.10/td_tp/tp3/README.md new file mode 100644 index 0000000..c1ac127 --- /dev/null +++ b/R4.01_R4.A.10/td_tp/tp3/README.md @@ -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 d’algorithmes, 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. + +
+ +
+ +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. + diff --git a/R4.01_R4.A.10/td_tp/tp3/img/chifoumi.png b/R4.01_R4.A.10/td_tp/tp3/img/chifoumi.png new file mode 100644 index 0000000..1cc9d1f Binary files /dev/null and b/R4.01_R4.A.10/td_tp/tp3/img/chifoumi.png differ diff --git a/R4.01_R4.A.10/td_tp/tp3/src/css/style.css b/R4.01_R4.A.10/td_tp/tp3/src/css/style.css new file mode 100644 index 0000000..16ae716 --- /dev/null +++ b/R4.01_R4.A.10/td_tp/tp3/src/css/style.css @@ -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; +} + + + diff --git a/R4.01_R4.A.10/td_tp/tp3/src/index.html b/R4.01_R4.A.10/td_tp/tp3/src/index.html new file mode 100644 index 0000000..d05cf97 --- /dev/null +++ b/R4.01_R4.A.10/td_tp/tp3/src/index.html @@ -0,0 +1,40 @@ + + + + + Pierre Feuille Ciseaux + + + + + + + + +
+

+ Pierre - Feuille - Ciseaux +

+
+ + + + + + + + + +
+
+

+

+
+
+ + + + diff --git a/R4.01_R4.A.10/td_tp/tp3/src/js/controller.js b/R4.01_R4.A.10/td_tp/tp3/src/js/controller.js new file mode 100644 index 0000000..3fdd070 --- /dev/null +++ b/R4.01_R4.A.10/td_tp/tp3/src/js/controller.js @@ -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()); + } +} + diff --git a/R4.01_R4.A.10/td_tp/tp3/src/js/main.js b/R4.01_R4.A.10/td_tp/tp3/src/js/main.js new file mode 100644 index 0000000..41c419f --- /dev/null +++ b/R4.01_R4.A.10/td_tp/tp3/src/js/main.js @@ -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() +); + diff --git a/R4.01_R4.A.10/td_tp/tp3/src/js/model.js b/R4.01_R4.A.10/td_tp/tp3/src/js/model.js new file mode 100644 index 0000000..053e363 --- /dev/null +++ b/R4.01_R4.A.10/td_tp/tp3/src/js/model.js @@ -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; + } +} diff --git a/R4.01_R4.A.10/td_tp/tp3/src/js/view.js b/R4.01_R4.A.10/td_tp/tp3/src/js/view.js new file mode 100644 index 0000000..98c77eb --- /dev/null +++ b/R4.01_R4.A.10/td_tp/tp3/src/js/view.js @@ -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 , ordinateur → ${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}`; + } +} +