Domanda molto interessante. +1 :) Ecco la mia opinione su questo.
Controllare il mio violino http://jsfiddle.net/BuddhiP/J9bLC/ per la soluzione completa. Proverò a spiegare i punti principali qui.
Inizio con una scheda come questa. Ho usato 0 invece di -1 perché è più facile.
var a = 'a', b = 'b';
var board = [
[a, 0, a],
[b, b, b],
[a, 0, a]
];
La mia strategia è semplice.
- Verificare se una delle righe ha lo stesso giocatore (aob), in tal caso abbiamo un vincitore.
- Else, Controllare se una delle colonne ha lo stesso giocatore
- Else, Controllare se diagonali ha un giocatore
Questi sono i tre casi vincenti.
Per prima cosa ho creato una funzione che può richiedere un set di righe (Es: [a, 0, b]) e controllare se l'intera riga contiene lo stesso valore e se tale valore non è zero (o -1 nel Astuccio).
checkForWinner = function() {
lines = Array.prototype.slice.call(arguments);
// Find compact all rows to unique values.
var x = _.map(lines, function (l) {
return _.uniq(l);
});
// Find the rows where all threee fields contained the same value.
var y = _.filter(x, function (cl) {
return (cl.length == 1 && cl[0] !== 0);
});
var w = (y.length > 0) ? y[0] : null;
return w;
};
Qui prendo valori unici di fila, e se riesco a trovare un solo valore unico che non è uguale a zero, il che è il vincitore.
Se non c'è nessun vincitore nelle righe, quindi controllo le colonne. Per riutilizzare il mio codice, utilizzo il metodo _.zip() per trasformare colonne in righe e quindi utilizzare la stessa funzione sopra per verificare se abbiamo un vincitore.
var board2 = _.zip.apply(this, board);
winner = checkForWinner.apply(this, board2);
Se ancora non trovo un vincitore, il tempo di controllare le diagonali. Ho scritto questa funzione per estrarre due diagonali dal tabellone come due file, e utilizzare la stessa funzione checkForWinner per vedere se le diagonali sono dominate da uno qualsiasi dei giocatori.
extractDiagonals = function (b) {
var d1 = _.map(b, function (line, index) {
return line[index];
});
var d2 = _.map(b, function (line, index) {
return line[line.length - index - 1];
});
return [d1, d2];
};
Infine questo è dove ho effettivamente controllare la scheda per un vincitore:
// Check rows
winner = checkForWinner.apply(this, board);
if (!winner) {
var board2 = _.zip.apply(this, board);
// Check columns, now in rows
winner = checkForWinner.apply(this, board2);
if (!winner) {
var diags = extractDiagonals(board);
// Check for the diagonals now in two rows.
winner = checkForWinner.apply(this, diags);
}
}
Se qualcuno di voi si chiedono perché io uso applicare() il metodo invece di chiamare direttamente la funzione, la ragione è applicabile () consente di passare elementi di un array come elenco di argomenti a una funzione.
Credo che questo dovrebbe funzionare anche per le matrici 4x4 o superiori, anche se non li ho testati.
Ho avuto pochissimo tempo per testare la soluzione, quindi per favore fatemi sapere se trovate errori.
Presumo, per un tic-tac-toe, nei modelli 'solution' non si vogliono confrontare gli zeri ma le celle vuote. – akuhn
potresti provare a convertire gli array a 1 livello in profondità per semplificare il confronto. Ma io non conosco alcun array più lento snippet ... :( – ajax333221