Published
Edited
Mar 30, 2020
1 fork
Importers
1 star
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
html`<div class="table" id="memory-game"></div>`
Insert cell
Insert cell
{
riprova,
memory({
containerID: 'memory-game', // stringa
coupleAmount: difficulty, // intero
images: deck, // array di stringhe(url)
cardBack: 'https://i.imgur.com/pov6rz2.png', // stringa
onTurn: () => {
audio.tap.play();
},
onVictory: () => {
audio.victory.play();
mutable running = false;
},
onStart: () => {
mutable milliseconds = 0;
mutable running = true;
}
});
}
Insert cell
Insert cell
html`<style>
.table {
display: flex;
flex-wrap: wrap;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
background-image: url(https://i.imgur.com/fw6LJQw.jpg);
padding: 30px;
align-items: center;
justify-content: center;
min-height: 200px;
}

.card {
margin: .5em;
height: 150px;
width: 107px;
border-radius: 7px;
background-color: white;
-webkit-box-shadow: 2px 2px 7px 1px rgba(0,0,0,0.42);
-moz-box-shadow: 2px 2px 7px 1px rgba(0,0,0,0.42);
box-shadow: 2px 2px 7px 1px rgba(0,0,0,0.42);
box-sizing: border-box;
background-position: center;
background-size: 90%;
background-repeat: no-repeat;
background-color: white;
}

.cover {
background-size: cover;
padding: 30px;
}
</style>`
Insert cell
Insert cell
Insert cell
function memory({
containerID,
coupleAmount,
cardBack,
images,
onVictory,
onStart,
onTurn
}) {
const state = { turned: [], locked: false, started: false }; // stato iniziale del gioco
const deck = images.slice(); // creo una copia del mazzo
const board = document.getElementById(containerID); // seleziono il contenitore della partita

function handleClick({ target }, index) {
if (state.turned.includes(index) || state.locked) return; // se è già girata non fare nulla
if (onTurn) onTurn(); // se esiste una funzione onTurn la chiamo
if (!state.started && onStart) {
// quando inizia la partita, chiama onStart
state.started = true;
onStart();
}
state.turned.push(index); // salvo quale carta ho girato
target.classList.toggle('cover'); // giro la carta
target.setAttribute('style', `background-image: url(${couples[index]})`);
const { turned } = state;
const check = {
first: turned[turned.length - 2],
second: turned[turned.length - 1]
};
if (turned.length % 2 === 0) {
// se ho girato un numero pari di carte
if (couples[check.first] === couples[check.second]) {
// se ho girato due carte uguali
if (turned.length === couples.length && onVictory) onVictory(); // se non ci sono altre carte da girare, finisce.
} else {
// se ho sbagliato
state.locked = true; // impedisci di girare altre carte
const timer = setTimeout(() => {
// aspetta un secondo, poi
const cards = board.getElementsByClassName('card');
const first = cards[check.first];
first.classList.toggle('cover');
first.setAttribute('style', `background-image: url(${cardBack}})`);
const second = cards[check.second];
second.classList.toggle('cover');
second.setAttribute('style', `background-image: url(${cardBack}})`);
// togli le due carte dall'elenco di carte girate
turned.pop();
turned.pop();
state.locked = false; // consenti di girare altre carte
}, 500);
}
}
}

// togli tutte le carte in gioco
while (board.hasChildNodes()) {
board.removeChild(board.lastChild);
}

// togli una carta a caso dal mazzo finché non ho il numero giusto di carte
while (deck.length > coupleAmount) {
const randomCard = Math.floor(Math.random() * deck.length);
deck.splice(randomCard, 1);
}
// duplica le carte e mischia il mazzo
const couples = shuffle([].concat(deck, deck));

// assegna ad ogni carta il suo evento click, e posizionala sul tavolo
for (let i = 0; i < coupleAmount * 2; i++) {
const card = document.createElement('div');
card.setAttribute('class', 'card cover');
card.setAttribute('style', `background-image: url(${cardBack})`);
card.addEventListener('click', e => handleClick(e, i));
board.appendChild(card);
}
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
{
const prefetch = document.createElement('div');
// commentando la riga seguente si vedranno tutte le immagini caricate grandi 1 pixel
prefetch.setAttribute('style', 'display: none'); // 👈🏻
deck.forEach(d => {
const img = document.createElement('img');
img.setAttribute('src', d);
img.setAttribute('alt', '');
img.setAttribute('height', 1);
img.setAttribute('width', 1);
prefetch.appendChild(img);
});
return prefetch;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
audio = new Object({
victory: new Audio(
await FileAttachment('hero_simple-celebration-03.wav').url()
),
tap: new Audio(await FileAttachment('ui_tap-variant-01.wav').url())
})
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more