ajout tp2mvc, tp3 et update des tp 1 et 2
This commit is contained in:
@@ -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>
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -48,15 +48,14 @@ class Ant {
|
|||||||
}
|
}
|
||||||
|
|
||||||
computeNextState() {
|
computeNextState() {
|
||||||
if(this.tiles[this.x][this.y] === 1) { //On vérifie si la prochaine case est noire
|
if(this.tiles[this.x][this.y] === 1) {
|
||||||
//On fait en sorte à ce qu'elle soit repeinte en blanc et tourne de 90° à gauche.
|
|
||||||
this.tiles[this.x][this.y] = 0;
|
this.tiles[this.x][this.y] = 0;
|
||||||
this.rotateLeft();
|
this.rotateLeft();
|
||||||
} else { //Dans ce cas si la prochaine case est blanche
|
} else {
|
||||||
// On fait en sorte à ce qu'elle soit repeinte en noir et tourne de 90° à droite.
|
this.tiles[this.x][this.y] = 1;
|
||||||
this.tiles[this.x][this.y] = 1;
|
this.rotateRight();
|
||||||
this.rotateRight();
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default Ant;
|
export default Ant;
|
||||||
@@ -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);
|
||||||
@@ -26,13 +26,16 @@ function peep() {
|
|||||||
const time = randomTime(1000, 1500);
|
const time = randomTime(1000, 1500);
|
||||||
const hole = randomHole(holes);
|
const hole = randomHole(holes);
|
||||||
|
|
||||||
// TODO
|
const mole = hole.querySelector('.mole');
|
||||||
|
mole.classList.add('up');
|
||||||
|
mole.classList.remove('whacked');
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
mole.classList.remove('up');
|
||||||
// TODO
|
if(!timeUp) {
|
||||||
//
|
peep();
|
||||||
}}, time);
|
}
|
||||||
|
}, time);
|
||||||
}
|
}
|
||||||
|
|
||||||
function startGame() {
|
function startGame() {
|
||||||
@@ -40,13 +43,31 @@ function startGame() {
|
|||||||
score = 0;
|
score = 0;
|
||||||
timeUp = false;
|
timeUp = false;
|
||||||
|
|
||||||
// TODO
|
moles.forEach(mole => {
|
||||||
|
mole.classList.remove('up');
|
||||||
|
mole.classList.remove('whacked');
|
||||||
|
});
|
||||||
|
|
||||||
|
peep();
|
||||||
|
setTimeout(()=>{
|
||||||
|
timeUp = true;
|
||||||
|
}, duration * 1000)
|
||||||
}
|
}
|
||||||
|
|
||||||
function bonk(e) {
|
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));
|
moles.forEach(mole => mole.addEventListener('click', bonk));
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ body {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
background-color: #f0f0f0;
|
background-color: #f0f0f0;
|
||||||
/* font-family: Arial, sans-serif;*/
|
font-family: Arial, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
.game {
|
.game {
|
||||||
@@ -24,7 +24,7 @@ body {
|
|||||||
background : radial-gradient(rgb(150,250,150), #00ee00);
|
background : radial-gradient(rgb(150,250,150), #00ee00);
|
||||||
|
|
||||||
/* background-color: red;/*#8b4513;*/
|
/* background-color: red;/*#8b4513;*/
|
||||||
/* background-image : url('img/mole2.png');*/
|
/*background-image : url('img/mole2.png');*/
|
||||||
position: relative;
|
position: relative;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
margin: 10px;
|
margin: 10px;
|
||||||
@@ -43,9 +43,9 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.mole.up img{
|
.mole.up img{
|
||||||
/* background-image : url('img/mole2.png');
|
background-image : url('img/mole2.png');
|
||||||
background-size:contain;
|
background-size:contain;
|
||||||
background-repeat: no-repeat;*/
|
background-repeat: no-repeat;
|
||||||
width:90px;
|
width:90px;
|
||||||
height:90px;
|
height:90px;
|
||||||
|
|
||||||
@@ -54,9 +54,9 @@ body {
|
|||||||
|
|
||||||
.mole.whacked img {
|
.mole.whacked img {
|
||||||
content: url('img/mole-whacked.png');
|
content: url('img/mole-whacked.png');
|
||||||
/* background-image : url('img/mole-whacked.png');
|
background-image : url('img/mole-whacked.png');
|
||||||
background-size:contain;
|
background-size:contain;
|
||||||
background-repeat: no-repeat;*/
|
background-repeat: no-repeat;
|
||||||
width:90px;
|
width:90px;
|
||||||
height:90px;
|
height:90px;
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|
||||||
|
<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 |
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -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>
|
||||||
|
|
||||||
@@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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()
|
||||||
|
);
|
||||||
|
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user