How do I check for adjacent tiles of the same type?
I am currently playing around with a project similar to the game Collapse.
This is my version of the grid that get created on startup.
My question is, how would I check for tiles that are adjacent to each other? For example, In the image above, there are 8 red tiles touching one another on the bottom left. If I were to click the red tile in the very corner, all 8 of those tiles should be cleared and new ones should fall down. I have researched and looked hard for a solution and have yet to find one so and help would be appreciated. I do know quite a bit of coding, Im just diving in to something new to widen my knowledge.
This is my Grid Script:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class Grid : MonoBehaviour {
public enum TileType
{
NORMAL,
COUNT,
};
[System.Serializable]
public struct TilePrefab
{
public TileType type;
public GameObject prefab;
};
public int xDim;
public int yDim;
public TilePrefab[] tilePrefabs;
public GameObject backgroundPrefab;
private Dictionary<TileType, GameObject> tilePrefabDict;
private Tile[,] tile;
void Start(){
tilePrefabDict = new Dictionary<TileType, GameObject>();
for (int i = 0; i < tilePrefabs.Length; i++) {
if(!tilePrefabDict.ContainsKey(tilePrefabs[i].type)){
tilePrefabDict.Add (tilePrefabs [i].type, tilePrefabs [i].prefab);
}
}
for (int x = 0; x < xDim; x++) {
for (int y = 0; y < yDim; y++) {
GameObject background = (GameObject)Instantiate (backgroundPrefab, GetWorldPosition(x, y, 0), Quaternion.identity);
background.transform.SetParent (transform);
}
}
tile = new Tile[xDim, yDim];
for (int x = 0; x < xDim; x++) {
for (int y = 0; y < yDim; y++) {
GameObject newTile = (GameObject)Instantiate (tilePrefabDict [TileType.NORMAL], GetWorldPosition(x,y, -1), Quaternion.identity);
newTile.name = "Piece(" + x + "," + y + ")";
newTile.transform.SetParent (transform);
tile [x, y] = newTile.GetComponent<Tile> ();
tile [x, y].Init (x, y, this, TileType.NORMAL);
if (tile [x, y].IsColored ()) {
tile [x, y].ColorComponent.SetColor ((TileColor.ColorType)Random.Range(0,tile[x,y].ColorComponent.NumColors));
}
}
}
}
Vector3 GetWorldPosition(int x, int y, int z){
return new Vector3 (transform.position.x - xDim / 2 + x,
transform.position.y + yDim / 2 - y, z);
}
}
And here is my Tile Script:
using UnityEngine;
using System.Collections;
public class Tile : MonoBehaviour {
private int x;
private int y;
public int X{
get{ return x;}
}
public int Y{
get{ return y;}
}
private Grid.TileType type;
public Grid.TileType Type{
get{ return type;}
}
private Grid grid;
public Grid GridRef{
get { return grid;}
}
private TileColor colorComponent;
public TileColor ColorComponent{
get{ return colorComponent;}
}
public void Init(int _x, int _y, Grid _grid, Grid.TileType _type){
x = _x;
y = _y;
grid = _grid;
type = _type;
}
void Awake(){
colorComponent = GetComponent<TileColor> ();
}
public bool IsColored(){
return colorComponent != null;
}
void OnMouseDown(){
Debug.Log ("Has been clicked!");
}
}
Again, any help would be appreciated and if you can explain the issue I am having with any example, that would be great. I am more of a visual learner with this kind of stuff.
Answer by Socapex · Dec 28, 2016 at 11:00 PM
Off the top of my head, aka a bad performing and untested solution.
Create a ContiguousPieces
set (C# HashSet) that will store the final contiguous pieces. Create a ToVisit
set that will store pieces that aren't visited yet. Add the clicked piece to ToVisit
. Iterate on the clicked block in a clockwise cross pattern (up, right, down, left). Anything that is the same color is added to the ToVisit
set. When done, move the piece from ToVisit
into ContiguousPieces
. Grab the next piece from ToVisit
if it isn't in ContiguousPieces
. Rince repeat until ToVisit
is empty.
Now since you are comfortable with writing code, lets talk a bit about discreet math. Your problem is a partition problem. To fix this "correctly", you can use disjoint set data structure. https://en.wikipedia.org/wiki/Disjoint-set_data_structure. Run a Union algorithm each time the board changes, and you will instantly have access to all the pieces in one set when a user clicks.
I wrote a maze creator thingy a while back using Kruskal https://en.wikipedia.org/wiki/Kruskal%27s_algorithm. It is based on the same type of theory. Some googling about disjoint sets, union and partitioning algorithms will give you all the info you need. The idea is to view your problem as a graph, once you have done that you can easily find an algorithm to solve it. Of course, only if you are interested ;)
Cheers
Can you explain a little more about what you mean? $$anonymous$$aybe with an example to understand. I haven't really worked on a project using a grid before so this portion of coding is sort of new to me...