123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 |
- class Boulier {
- static instance = null;
- static colors = {
- red: "Rouge",
- pink: "Rose",
- purple: "Violet",
- indigo: "Indigo",
- blue: "Bleu",
- cyan: "Cyan",
- green: "Vert",
- lime: "Lime",
- yellow: "Jaune",
- amber: "Ambre",
- orange: "Orange"
- };
- static setup(elt, nbLine, nbBoule) {
- Boulier.instance = new Boulier(elt, nbLine, nbBoule);
- return Boulier.instance;
- }
- static get(elt, nbLine, nbBoule) {
- if (Boulier.instance != null) {
- return Boulier.instance;
- } else if (elt != null && nbLine != null && nbBoule != null) {
- return Boulier.setup(elt, nbLine, nbBoule);
- } else {
- return false;
- }
- }
- static isSaved() {
- return localStorage.getItem('boulier-ball') != null;
- }
- static load(elt) {
- if (Boulier.instance == null) {
- Boulier.setup(elt, 1, 1);
- }
- const instance = Boulier.get();
- instance.load();
- return instance;
- }
- static clear() {
- localStorage.clear();
- }
- constructor(elt, nbLine, nbBall) {
- const emptySpace = Math.floor(nbBall / 2);
- this._elt = elt;
- this._callback = null;
- this._ball = nbBall;
- this.boulier = [];
- this.color = [];
- for (let i = 0; i < nbLine; i++) {
- const line = []
- for (let j = 0; j < nbBall + emptySpace; j++) {
- line.push(j < nbBall);
- }
- this.boulier.push(line);
- this.color.push(['red']);
- }
- }
- save() {
- localStorage.setItem('boulier-data', JSON.stringify(this.boulier));
- localStorage.setItem('boulier-color', JSON.stringify(this.color));
- localStorage.setItem('boulier-ball', this._ball);
- }
- load() {
- this.boulier = JSON.parse(localStorage.getItem('boulier-data'));
- this.color = JSON.parse(localStorage.getItem('boulier-color'));
- this._ball = parseInt(localStorage.getItem('boulier-ball'));
- }
- move(line, col) {
- // Vérifie les paramètres
- if (this.boulier.length <= line || this.boulier[line].length <= col || ! this.boulier[line][col]) {
- return false;
- }
- let data = this.boulier[line];
- // Détermine s'il faut bouger les boules vers la gauche ou la droite
- let right = true;
- for (let i = col; i < data.length; i++) {
- if (!data[i]) {
- right = false;
- break;
- }
- }
- // Si les mouvement est vers la droite, on inverse la ligne
- if (right) {
- data = data.reverse();
- col = data.length - col - 1;
- }
- // Compte le nombre de boule à deplacer et l'index de l'endroit où faire le déplacement
- let cpt = 0;
- let gap = false;
- let index = null;
- for (let i = col; i < data.length; i++) {
- if (!gap && data[i]) {
- cpt++;
- data[i] = false;
- } else if (gap && data[i]) {
- index = i - 1;
- break;
- } else {
- gap = true;
- }
- }
- if (index == null) {
- index = data.length - 1;
- }
- // Déplace les boules
- for (let i = 0; i < cpt; i++) {
- data[index - i] = true;
- }
- // Si le mouvement était vers la droite, on remet la ligne dans le bon sens
- if (right) {
- data = data.reverse();
- }
- // Callback
- if (this._callback != null && typeof this._callback === 'function') {
- this._callback(Boulier.instance);
- }
- }
- reset() {
- for(let i = 0; i < this.boulier.length; i++) {
- this.move(i, this.boulier[i].length - 1);
- }
- }
- render() {
- let html = '';
- for (let i = 0; i < this.boulier.length; i++) {
- html += '<div class="grid">';
- // Boule
- let cptBall = 0;
- let changeColor = Math.round(this._ball / this.color[i].length);
- for(let j = 0; j < this.boulier[i].length; j++) {
- const elt = this.boulier[i][j];
- html += '<div class="cell"><div class="line" data-line="' + i + '" data-col="' + j + '" ondragover="allowDrop(event)" ondrop="ballDrop(event, this)"></div>';
- if (elt) {
- let ballColor = this.color[i][Math.trunc(cptBall/changeColor)];
- if (ballColor == null) {
- ballColor = this.color[i][this.color[i].length - 1];
- }
- html += '<div class="ball ' + ballColor + '" data-line="' + i + '" data-col="' + j + '" draggable="true" ondragstart="ballDrag(event)" ondragover="allowDrop(event)" ondrop="ballDrop(event, this)" onclick="ballClick(this)"></div>';
- cptBall++;
- }
- html += '</div>';
- }
- html += '</div>';
- }
- this._elt.innerHTML = html;
- }
- onChange(callback) {
- this._callback = callback;
- }
- tostring() {
- let str = '';
- for (const line of this.boulier) {
- str += '-|';
- for (const boule of line) {
- if (boule) {
- str += 'o';
- } else {
- str += '-';
- }
- }
- str += '|-\n';
- }
- return str;
- }
- print() {
- console.log(this.tostring());
- }
- }
- function ballClick(elt) {
- const instance = Boulier.instance;
- if (instance == null) {
- return;
- }
- const line = parseInt(elt.getAttribute('data-line'));
- const col = parseInt(elt.getAttribute('data-col'));
- instance.move(line, col);
- instance.render();
- }
- function allowDrop(evt) {
- evt.preventDefault();
- }
- function ballDrag(evt) {
- const line = parseInt(evt.target.getAttribute('data-line'));
- const col = parseInt(evt.target.getAttribute('data-col'));
- evt.dataTransfer.setData("text", line + ";" + col);
- }
- function ballDrop(evt, elt) {
- evt.preventDefault();
- // Récupère l'instance
- const instance = Boulier.instance;
- if (instance == null) {
- return;
- }
- // Recupère les infos de la balle et de la destination
- const line = parseInt(elt.getAttribute('data-line'));
- const col = parseInt(elt.getAttribute('data-col'));
- const split = evt.dataTransfer.getData("text").split(';');
- const ballLine = parseInt(split[0]);
- const ballCol = parseInt([split[1]]);
- // Vérifie si le cas est valide
- if (line != ballLine || col == ballCol) {
- return;
- }
- let right = true;
- for (let i = ballCol; i < instance.boulier[line].length; i++) {
- if (!instance.boulier[line][i]) {
- right = false;
- break;
- }
- }
- if ((right && col > ballCol) || (!right && col < ballCol)) {
- return;
- }
- // Bouge
- instance.move(ballLine, ballCol);
- instance.render();
- }
|