Mi juego jugable, con W regulable, H y numPlayers, es aquí: http://pconstrictor.github.io/cellsurround/
(El código fuente está allí también todavía tiene que ser reprogramado para utilizar la sintaxis módulo ES6, y es de esperar volver a escribir utilizando FP Así que.. si hay un diseño de modelo más simple, me gustaría saberlo).
Para el modelo de datos, utilicé una sola matriz 2D de tamaño w por h. Cada celda tiene una lista de lados (cuatro en el caso de esta cuadrícula) y se 'llena' cuando todos los lados están 'llenos'. Tenga en cuenta que el usuario obtiene un turno extra. Además, a veces una sola acción da como resultado que dos celdas se llenen simultáneamente.
// MODEL
exports.SquareGrid = function(width, height, players) {
// reset (also serves as init)
this.reset = function(w, h, players) {
this.players = players;
this.player = players.firstPlayer();
var m = [];
this.matrix = m; // will be a 2D array (well, array of arrays)
this.height = h;
this.width = w;
// fill matrix
var toLeft = null, above = null; // these will be used for cells
// sharing sides
for (var row = 0; row < h; row++) {
m[row] = [];
for (var col = 0; col < w; col++) {
toLeft = col ? m[row][col - 1] : null;
above = row ? m[row - 1][col] : null;
m[row][col] = exports.createSquareCell(above, toLeft);
}
}
}
...
}
Para realmente presentan la interfaz de usuario, que utiliza una sola matriz 2D (de tamaño 2w + 1 por 2h + 1) como el modelo de vista, en el que puntos, bordes y células son todos simplemente representados como ya sea lleno o vacío. (Los puntos comienzan llenos y siempre permanecen así). Esto se traduce muy bien en, por ejemplo, una tabla HTML que se puede representar fácilmente con dos bucles y sin lógica adicional. Aquí está la matriz de 7 por 9 que corresponde a un modelo de 3x4. Tenga en cuenta que estas pseudo columnas y filas idealmente deberían mostrarse en tamaños alternos, solo por razones visuales.
(w = 3, h = 4) so (ww = 7, hh = 9)
. ___ . ___ . ___ .
| | | |
| | p1 | p1 |
. . ___ . ___ .
| | | |
| | p1 | p2 |
. . ___ . ___ .
| | |
| | |
. . ___ . .
| |
| |
. ___ . ___ . ___ .
Aquí está el modelo de vista real.
// VIEW MODEL
exports.SquareGridView = function(gameModel, appId, resetFuncString) {
// prepare to render the latest of whatever is in the model
this.refresh = function() {
var h = this.gridModel.height;
var w = this.gridModel.width;
// Initialize the UI table, whose dimensions are bigger than the
// model's.
var viewPm = [];
var hh = viewCoord(h);
var ww = viewCoord(w);
for (var i = 0; i < hh; i++) {
viewPm[i] = [];
}
// But loop over the model when actually filling it in. (Shared
// cells cause double writes to viewPm, but oh well.)
for (var row = 0; row < h; row++) {
for (var col = 0; col < w; col++) {
var cell = this.gridModel.matrix[row][col];
var i = viewCoord(row), j = viewCoord(col);
viewPm[i][j] = cell.owner;
viewPm[i - 1][j] = cell.sides['top'];
viewPm[i + 1][j] = cell.sides['bottom'];
viewPm[i][j - 1] = cell.sides['left'];
viewPm[i][j + 1] = cell.sides['right'];
// Note: vertices can be either filled or left undefined here (and hard-coded as filled in the HTML).
}
}
...
Y aquí está el paso de hacer-como-html real: se omite
var t = []; // the html text
// TODO: split the HTML bits out into a template file? Use React or Elm?
...
t.push('<table class="squaregrid">\n');
var tdClass, tdId; // 'vertex', '0.0';
for (var i = 0; i < hh; i++) {
t.push(" <tr> \n");
for (var j = 0; j < ww; j++) {
t.push(this.tdHtml(viewPm, i, j));
}
t.push(" </tr>\n");
}
t.push("</table>\n");
...
La función tdHtml()
- se genera un TD con correcta identificación y clases.
Esto funciona, pero probablemente no sea suficiente para el espacio de juego real, porque necesita realizar un seguimiento de * quién * capturó una celda determinada. Entonces, mi solución (y la de Steve y nybbler) es usar una matriz 2D de objetos de celda en su lugar. –
Por supuesto, sería fácil agregar una tercera matriz 2D para representar qué celdas pertenecen a qué jugador (o a nadie). Esto hace que los sistemas de coordenadas sean mucho más fáciles de traducir que en mi solución, ya que para una celda dada 'top' es 'i', left es' j', 'right' es 'j + 1', bottom es' i + 1' , como el tuyo arriba. Sin embargo, me gustaría pensar dos veces antes de cruzar un modelo en tres matrices y hacer que toda la base de código sea específica para las celdas cuadradas (SquareGrid). –