Package com.barrybecker4.puzzle.tantrix.model.verfication

Source Code of com.barrybecker4.puzzle.tantrix.model.verfication.InnerSpaceDetector

// Copyright by Barry G. Becker, 2012. Licensed under MIT License: http://www.opensource.org/licenses/MIT
package com.barrybecker4.puzzle.tantrix.model.verfication;

import com.barrybecker4.common.geometry.Box;
import com.barrybecker4.common.geometry.ByteLocation;
import com.barrybecker4.common.geometry.Location;
import com.barrybecker4.puzzle.tantrix.model.HexUtil;
import com.barrybecker4.puzzle.tantrix.model.Tantrix;

import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Set;

import static com.barrybecker4.puzzle.tantrix.model.HexTile.NUM_SIDES;

/**
* Used to determine if a candidate solution has empty spaces within the tantrix.
* A val;id solution cannot have such spaces.
*
@author Barry Becker
*/
public class InnerSpaceDetector {

    Tantrix tantrix;

    /**
     * Constructor.
     * @param tantrix the tantrix state to test for solution.
     */
    public InnerSpaceDetector(Tantrix tantrix) {
        this.tantrix = tantrix;
    }

    /**
     * Start with an empty position on the border of the bbox.
     * Do a seed fill to visit all the spaces connected to that.
     * Finally, if there are any empty spaces inside the bbox that are not visited,
     * then there are inner spaces and it is not a valid solution.
     * @return true if there are no inner empty spaces.
     */
    public boolean hasInnerSpaces() {

        Set<Location> seedEmpties = findEmptyBorderPositions();
        Set<Location> visited = findConnectedEmpties(seedEmpties);
        return !allEmptiesVisited(visited);
    }

    /**
     * @return all the empty positions on the border
     */
    private Set<Location> findEmptyBorderPositions() {

        Box bbox = tantrix.getBoundingBox();
        Set<Location> empties = new HashSet<Location>();

        for (int i = bbox.getMinCol(); i <= bbox.getMaxCol(); i++) {
            Location loc = new ByteLocation(bbox.getMinRow(), i);
            if (tantrix.get(loc) == null)  {
                empties.add(loc);
            }
            loc = new ByteLocation(bbox.getMaxRow(), i);
            if (tantrix.get(loc) == null)  {
                empties.add(loc);
            }
        }

        for (int i = bbox.getMinRow() + 1; i < bbox.getMaxRow(); i++) {
            Location loc = new ByteLocation(i, bbox.getMinCol());
            if (tantrix.get(loc) == null)  {
                empties.add(loc);
            }
            loc = new ByteLocation(i, bbox.getMaxCol());
            if (tantrix.get(loc) == null)  {
                empties.add(loc);
            }
        }

        int totalLocs = (bbox.getHeight() + 1) * (bbox.getWidth() + 1);
        assert (totalLocs == tantrix.size() || empties.size() > 0):
                "We should have found at least one empty position on the border. Num Tiles ="
                + tantrix.size() + " bbox area = " + bbox.getArea();
        return empties;
    }

    private Set<Location> findConnectedEmpties(Set<Location> seedEmpties) {
        Set<Location> visited = new HashSet<Location>();

        Queue<Location> searchQueue = new LinkedList<Location>();
        searchQueue.addAll(seedEmpties);
        visited.addAll(seedEmpties);

        while (!searchQueue.isEmpty()) {
            Location loc = searchQueue.remove();
            List<Location> nbrEmpties = findEmptyNeighborLocations(loc);
            for (Location empty : nbrEmpties) {
                if (!visited.contains(empty)) {
                    visited.add(empty);
                    searchQueue.add(empty);
                }
            }
        }

        return visited;
    }

    /**
     * @return all the empty neighbor positions next to the current one.
     */
    private List<Location> findEmptyNeighborLocations(Location loc) {
        List<Location> emptyNbrLocations = new LinkedList<Location>();
        Box bbox = tantrix.getBoundingBox();

        for (byte i=0; i< NUM_SIDES; i++) {

            Location nbrLoc = HexUtil.getNeighborLocation(loc, i);
            if (tantrix.get(nbrLoc) == null && bbox.contains(nbrLoc)) {
                emptyNbrLocations.add(nbrLoc);
            }
        }
        return emptyNbrLocations;
    }

    /**
     * @param visited set of visited empties.
     * @return true if any empties in the tantrix bbox are not visited
     */
    private boolean allEmptiesVisited(Set<Location> visited) {
        Box bbox = tantrix.getBoundingBox();
        for (int i = bbox.getMinRow(); i < bbox.getMaxRow(); i++) {
            for (int j = bbox.getMinCol(); j <= bbox.getMaxCol(); j++)  {
                Location loc = new ByteLocation(i, j);
                if (tantrix.get(loc) == null && !visited.contains(loc))  {
                    return false;
                }
            }
        }
        return true;
    }

}
TOP

Related Classes of com.barrybecker4.puzzle.tantrix.model.verfication.InnerSpaceDetector

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.