UNPKG

tresenraya

Version:

Módulo para facilitar la creación del popular juego llamado tres en raya en tus proyectos

254 lines (171 loc) 10.1 kB
const EventEmitter = require('events'); const mejorPos = require('./funciones/mejorPos.js'); module.exports.partidas = []; module.exports.partida = class Partida extends EventEmitter { constructor(opciones = { fichas: [ '❌', '⭕' ], jugadores: [ 'Jugador 1', 'Jugador 2' ], tablero: [ '1️⃣', '2️⃣', '3️⃣', '4️⃣', '5️⃣', '6️⃣', '7️⃣', '8️⃣', '9️⃣' ] }) { super(); try { if(!this['_comprobaciones'](opciones)) return; } catch(e) { throw new Error(e.message); } } elegir(pos) { if(this.finalizado) return false;//throw new Error('¡La partida ya ha finalizado!'); if(!pos) throw new Error('Debes especificar la posición en la que quieres que se añada la ficha (del 1 al 9)'); if(isNaN(pos) || (Number(pos) < 1 || Number(pos) > 9)) throw new TypeError(pos + ' no es un número válido (debes introducir un número del 1 al 9)'); if(this.opciones.fichas.includes(this.tablero.array[pos-1])) throw new Error('Ya hay una ficha posicionada en la posición ' + pos + ' del tablero. Recuerda usar el método llamado "disponible" para comprobar si ya hay una ficha posicionada en esa posición del tablero.'); this.turno.paso++; this.tablero.array[pos-1] = this.opciones.fichas[this.opciones.jugadores.indexOf(this.turno.jugador)]; this.tablero.string = this.tablero.array.slice(0, 3).join(' ') + '\n' + this.tablero.array.slice(3, 6).join(' ') + '\n' + this.tablero.array.slice(6, 9).join(' '); const selecciones = require('./jsons/selecciones.json').ganadoras; if(selecciones.some(x => !x.some(p => this.opciones.fichas[this.opciones.jugadores.indexOf(this.turno.jugador)] != (this.tablero.array[p])))) { this.perdedor = this.opciones.jugadores.find(x => x != this.turno.jugador); this.emit('ganador', this.turno.jugador, this.tablero, this.turno.paso); this.finalizado = true; return; } let n = 0; this.tablero.array.forEach(p => { if(this.opciones.fichas.includes(p)) { n++; } }); if(n >= 9) { this.emit('empate', this.opciones.jugadores, this.tablero, this.turno.paso); this.finalizado = true; return; } this.turno.jugador = this.opciones.jugadores.find(x => x != this.turno.jugador); this.turno.ficha = this.opciones.fichas[this.opciones.jugadores.indexOf(this.turno.jugador)]; const sels = require('./jsons/selecciones.json').mejorPos.slice(0, -4);/*[ { ya: [0, 6], seleccion: 4 }, { ya: [0, 2], seleccion: 2 }, { ya: [0, 1], seleccion: 3 }, { ya: [3, 4], seleccion: 6 }, { ya: [6, 7], seleccion: 9 }, { ya: [3, 6], seleccion: 1 }, { ya: [4, 7], seleccion: 2 }, { ya: [5, 8], seleccion: 3 }, { ya: [0, 3], seleccion: 7 }, { ya: [1, 4], seleccion: 8 }, { ya: [2, 5], seleccion: 9 }, { ya: [1, 2], seleccion: 1 }, { ya: [4, 5], seleccion: 4 }, { ya: [7, 8], seleccion: 7 }, { ya: [3, 5], seleccion: 5 }, { ya: [6, 8], seleccion: 8 }, { ya: [1, 7], seleccion: 5 }, { ya: [2, 8], seleccion: 6 }, { ya: [0, 4], seleccion: 9 }, { ya: [2, 4], seleccion: 7 }, { ya: [0, 8], seleccion: 5 }, { ya: [2, 6], seleccion: 5 }, { ya: [4, 8], seleccion: 1 }, { ya: [6, 4], seleccion: 3 }, { ya: [0, 4], seleccion: 9 } ];*/ this.opciones.jugadores.slice(0, 2).forEach(j => { let nums = []; let n = 0; const p = this.opciones.fichas[this.opciones.jugadores.indexOf(j)]; sels.filter(x => !x.ya.some(f => this.tablero.array[f] != p) && !this.opciones.fichas.includes(this.tablero.array[x.seleccion-1])) .forEach((y) => { if(!nums.includes((y.ya).reduce((a, b) => a.toString() + b.toString()))) { nums.push((y.ya).reduce((a, b) => a.toString() + b.toString())); n++; } }); //p = Math.floor((((/*this.opciones.tablero.filter(x => x === p).length*/n) + ((n) / 1.15)) * 100) / 9); if(j == this.turno.jugador) { this.turno.posibilidades = n; } const k = j.split(/ +/g).join('_').toLowerCase(); /*this.posibilidades[k] = { porcentaje: p, numero: n }*/ this.posibilidades[k] = n; }); } disponible(pos) { if(!pos) throw new Error('Debes especificar la posición en la que quieres verificar si está disponible para posicionar una ficha (número del 1 al 9)'); if(isNaN(pos) || (Number(pos) < 1 || Number(pos) > 9)) throw new TypeError(pos + ' no es un número válido (debes introducir un número del 1 al 9)'); return !(this.opciones.fichas.includes(this.tablero.array[pos-1])); } pasar() { if(this.finalizado) throw new Error('La partida ha finalizado, no se puede pasar a otro turno.');//throw new Error('¡La partida ya ha finalizado!'); this.turno.paso++; this.turno.jugador = this.opciones.jugadores.find(x => x != this.turno.jugador); this.turno.ficha = this.opciones.fichas[this.opciones.jugadores.indexOf(this.turno.jugador)]; return true; } finalizar(razon = '') { if(this.finalizado) return false; this.finalizado = true; this.emit('finalizado', this.opciones.jugadores, this.tablero, this.turno, (razon || '')); return true; } mejorPos(favor) { return mejorPos(this.tablero.array, this.opciones.fichas, (favor || 'x')); } _comprobaciones(opciones) { if(!opciones.fichas) opciones.fichas = [ '❌', '⭕' ]; if(!opciones.jugadores) opciones.jugadores = [ 'Jugador 1', 'Jugador 2' ]; if(!opciones.tablero) opciones.tablero = [ '1️⃣', '2️⃣', '3️⃣', '4️⃣', '5️⃣', '6️⃣', '7️⃣', '8️⃣', '9️⃣' ]; if(Object.entries(opciones).filter(x => ['fichas', 'jugadores', 'tablero'].includes(x[0])).some(x => !(x[1] instanceof Array))) { const opcion = Object.entries(opciones).filter(x => ['fichas', 'jugadores', 'tablero'].includes(x[0])).find(x => !(x[1] instanceof Array))[0]; throw new TypeError('No has introducido un Array en \'opciones.' + opcion + '\''); return false; } if(!opciones.fichas[1]) throw new TypeError('Debes introducir dos valores en el array de fichas.'); if(opciones.fichas.slice(0, 2).some(x => typeof(x) !== 'string')) throw new TypeError('Algún valor de algún elemento del Array de fichas no es un String.'); if(opciones.fichas[0].toLowerCase() == opciones.fichas[1].toLowerCase()) { const arrayString = (JSON.stringify(opciones.fichas)).split(',').join(', '); throw new TypeError('Los valores de los elementos del array de fichas (' + arrayString + ') son iguales, deben ser diferentes.'); return false; } if(opciones.fichas.slice(0, 2).some(f => opciones.tablero.some(t => t.toLowerCase() == f.toLowerCase()))) { throw new TypeError('Algún elemento del array opciones.tablero es igual a algún elemento del array opciones.fichas'); return false; } if(!opciones.jugadores[1]) throw new TypeError('Debes introducir dos valores en el array de jugadores.'); if(opciones.jugadores.slice(0, 2).some(x => typeof(x) !== 'string')) throw new TypeError('Algún valor de algún elemento del Array de jugadores no es un String.'); if(opciones.jugadores[0].toLowerCase() == opciones.jugadores[1].toLowerCase()) { const arrayString = (JSON.stringify(opciones.jugadores)).split(',').join(', '); throw new TypeError('Los valores de los elementos del array de jugadores (' + arrayString + ') son iguales, deben ser diferentes.'); return false; } if(!opciones.tablero[8]) throw new TypeError('Debes introducir nueve valores en el array tablero.'); if(opciones.tablero.slice(0, 9).some(x => typeof(x) !== 'string')) throw new TypeError('Algún valor de algún elemento del Array tablero no es un String.'); if(opciones.id) { if(typeof(opciones.id) != 'string') throw new TypeError("Debes introducir un String en 'opciones.id'"); if(module.exports.partidas.includes(opciones.id)) throw new RangeError('Ya hay una partida iniciada con esa ID.'); module.exports.partidas.push(opciones.id); } opciones.fichas = opciones.fichas.slice(0, 2); opciones.jugadores = opciones.jugadores.slice(0, 2); opciones.tablero = opciones.tablero.slice(0, 9); this.opciones = opciones; this.tablero = { array: opciones.tablero, string: (opciones.tablero.slice(0, 3).join(' ') + '\n' + opciones.tablero.slice(3, 6).join(' ') + '\n' + opciones.tablero.slice(6, 9).join(' ')) }; this.turno = { jugador: (opciones.jugadores[Math.floor(Math.random() * 2)]), paso: 0, posibilidades: 0 }; this.turno.ficha = this.opciones.fichas[this.opciones.jugadores.indexOf(this.turno.jugador)]; this.perdedor = null; this.finalizado = false; this.posibilidades = {}; opciones.jugadores.slice(0, 2).forEach(j => { const k = j.split(/ +/g).join('_').toLowerCase(); /*this.posibilidades[k] = { porcentaje: 0, numero: 0 };*/ this.posibilidades[k] = 0; }); ['ganador', 'empate', 'finalizado'].map(e => { this.on(e, () => { module.exports.partidas = module.exports.partidas.filter(id => id != opciones.id); }); }); return true; } }