[c#] Minesweeper, get neighbours is not easy.

hello, i’m having some troubles getting neighbours in a minesweeper game.

FIRST: if you have suggestion and other ideas for getting the neighbours please tell me. all the methods i can think of are pretty expensive performance-wise.

my idea is to get the neighbours with the function Physics.OverlapSphere

here’s the code, i link an image because i think it’s more readable:

IMAGE

CODE:

using UnityEngine;
using System.Collections;

public class MainScript : MonoBehaviour {
	static int mineNum = 99;
	public static bool firstClick = true;

	public static void SetMines(){
		GameObject[] gameObjects; //array of gameobjects
		for(int i=0;i < mineNum;i++){ //this cycle selects random cells and convert the to mines
			gameObjects = GameObject.FindGameObjectsWithTag("Cell"); //store in the array all the gameobjects with tag "cell"
			GameObject mineObj = gameObjects[Random.Range(0, gameObjects.Length)]; //pick a random gameobject from the previous array...
			mineObj.tag = "Mine"; //...and put the new tag "mine" in that object...
		}
		for(int j=0;j < mineNum;j++){
			GameObject[] mineObj = GameObject.FindGameObjectsWithTag("Mine"); //find all the mines
			Vector3 pos = mineObj[j].GetComponent<Transform>().position; //get the position of the mines...
			Collider[] insideSphere = Physics.OverlapSphere(pos,0.9f); //...and use that position to "spawn" an OverlapSphere that will return an array of colliders inside that sphere.
			for(int k=0;k < 9;k++){ //now we have an array of the colliders that sorrounded the mine. now i want to change a variable... 
				CellScript script;
				script = insideSphere[k].gameObject.GetComponent<CellScript>(); //ERROR IS HERE: i want to get the script attached to all the neighbours...
				script.minesAround += 1; //...and increase by 1 the counter "minesAround" so at the end all the cells will have variable with the number of sorrounding mines.
			}
		}
	}
}

the error i get is Array index is out of range at line 21 but i don’t understand why…the Overlap sphere should return 9 colliders and my for cycle counts from 0 to 8 (=9 times).

i hope you understand what i’m trying to achieve and maybe help me :slight_smile: thanks!

It would be a lot simpler if you just use a 2D array to represent the game state, and use GameObjects for display only.

–Eric

you mean something like Array[x Coordinate][y Coordinate]?
i thought about that but i didn’t figured out how to set up a relationship Array[×][y]<---->gameObject
say if i have Array[3][5] how do i get the script attached to the object at position 3;5? do i even need to do that?! confused

sorry i may be overlooking something really simple…
thanks for the help :slight_smile:

You don’t need to get scripts or anything. Just one array, so to get, say, the neighbor to the right of [3,2] just look at [4,2].

–Eric

ok let’s see if my idea is taking form…
i create a new array that contains all my cells.
at the beginning, when i spawn the map, i store the cells in that array for future reference.
something like this: (it’s a concept code, it probably doesn’t work)

public Transform cell;
public int width = 16, height = 16; 

void Awake () {
	BoardGenerator();
}

void BoardGenerator () {
	for(int i = 0;i < height;i++){
		for(int j = 0;j < width;j++){
			transform.position = new Vector3(j,i,0);
			Transform cellPrefab = Instantiate(cell,transform.position,transform.rotation) as Transform;
			GameObject[width][height] cellsArray; //declare array
			cellsArray[j][i] = cellPrefab.gameObject; //fill it with all the cells
		}
	}
}

then, when i need to check around a cell, i pass the coords of the clicked cell to the CheckAround function.
the CheckAround should look something like this

void CheckAround (int xCor,int yCor) { 
//xCor and yCor are the coordinates of the cell being clicked
		if(cellsArray[xCor+1][yCor+1].tag == "Mine"){
			minesAround += 1; //this var will probably be in a different script (attached to all the cells) that contains info like "isFlagged" or "isOpen" etc.
		}
		...
		...
		...
		/*check all the cells around and increment minesAround at each mine found
			 * xCor+1,yCor+1
			 * xCor,yCor+1
			 * xCor-1,yCor+1
			 * xCor-1,yCor
			 * xCor-1,yCor-1
			 * xCor,yCor-1
			 * xCor+1,yCor-1
			 * xCor+1,yCor
			 * */
	}

so, it’s ok to make a GameObject array and store all the cells?
then i’ll pass the coords and get from there the tag of the surrounding cells.

I think you are trying too hard to link more than necessary two elements that should be distinct : a logical part, the array, and the graphical part, the game objects. I would advise you to solve two small problems instead of a big one.

How do you generate a logical grid ? By creating a two dimensionnal array (of string, for example), and filling it randomly with the letter X, as a bomb. Then fill the other cases with either an empty string, or an integer (the number of bombs around the case).

How do you generate a visual grid ? Instantiate multiple game objects, and store the associated case by any way you want : a naming convention (game object name would be Case_X:5_Y:6), a monobehaviour with two integers (X and Y), both (a monobehaviour with a formatted string ; not recommanded though, too complicated).
Or make a dictionary that map a duo of integers to the game object. You don’t lack choices, to be honest.

thanks for the reply, maybe i’m understanding a little bit better where the logical part ends and where the visual begins, basically all the info i need can be stored in an array (maybe i’ll try an int array) and the process of checking neighbours will also be done within that array, only after this process i can transport all the data i need to the actual objects in the scene.
i’ll try something in the next days. thank you!
if someone has any other hints i really appreciate them! :slight_smile:

array of data… use an array of data

your world view is just a projection of that data