/*
* This file is part of MazeSolver.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright (c) 2014 MazeSolver
* Sergio M. Afonso Fumero <theSkatrak@gmail.com>
* Kevin I. Robayna Hernández <kevinirobaynahdez@gmail.com>
*/
/**
* @file AldousBroder.java
* @date 10 Nov 2014
*/
package es.ull.mazesolver.maze.algorithm;
import java.awt.Point;
import java.util.ArrayList;
import es.ull.mazesolver.maze.MazeCreationAlgorithm;
import es.ull.mazesolver.util.Direction;
/**
* Implementación del algoritmo Aldous-Broder para la generación aleatoria de
* laberintos perfectos.
*/
public class AldousBroder extends MazeCreationAlgorithm {
private short cellVisitedCount = 0;
private ArrayList <ArrayList <Boolean>> m_included_cells;
/**
* Constructor. Crea una nueva instancia de la clase.
*
* @param rows
* Número de filas del laberinto.
* @param columns
* Número de columnas del laberinto.
*/
public AldousBroder (int rows, int columns) {
super(rows, columns);
// Creamos una matriz de visitados para saber en cada momento cuáles son
// las celdas que no se han visitado todavía.
m_included_cells = new ArrayList <ArrayList <Boolean>>(rows);
for (int y = 0; y < rows; y++) {
m_included_cells.add(new ArrayList <Boolean>(columns));
for (int x = 0; x < columns; x++)
m_included_cells.get(y).add(false);
}
}
/*
* (non-Javadoc)
*
* @see maze.MazeCreationAlgorithm#runCreationAlgorithm()
*/
@Override
public void runCreationAlgorithm () {
int x = (int) (Math.random() * m_columns);
int y = (int) (Math.random() * m_rows);
Point p = new Point(x, y);
while (cellVisitedCount < (m_columns * m_rows)) {
Direction dir = getRandomDirection(p.y, p.x);
p = dir.movePoint(p);
if (!m_included_cells.get(p.y).get(p.x)) {
openPassage(p.y, p.x, dir.getOpposite());
m_included_cells.get(p.y).set(p.x, true);
cellVisitedCount++;
}
}
}
/**
* Obtiene una dirección aleatoria a partir de la posición indicada que no
* se sale del tamaño del laberinto.
*
* @param y
* Posición en el eje Y desde la que se quiere partir.
* @param x
* Posición en el eje X desde la que se quiere partir.
* @return Dirección aleatoria dentro del rango.
*/
private Direction getRandomDirection (int y, int x) {
Point p = new Point(x, y);
Point next_pos;
Direction dir;
do {
dir = Direction.random();
next_pos = dir.movePoint(p);
}
while (next_pos.y < 0 || next_pos.y >= m_rows || next_pos.x < 0 || next_pos.x >= m_columns);
return dir;
}
}