Approach for filling 6x6 matrix with shapes
Hello, guys. I'm trying to develop a Tetris-like blocks game. I've got 6x6 unit "module" that filled with shapes like this;
I thought that i should create an 6x6 matrix and fill it with my blocks. Thus far I've developed an approach like this,
matrix =
[0,0,0,0,0,0]
[0,0,0,0,0,0]
[0,0,0,0,0,0]
[0,0,0,0,0,0]
[0,0,0,0,0,0]
[0,0,0,0,0,0]
shapes //For example L
L =
[1,0]
[1,0]
[1,1]
Also I'll need a filling algorithm that places shapes and fills empty spaces. I don't know if there's an example for this. Everything will be appreciated.
4th Grade Senior Math, please be gentle :)
how do you want to fill it? without missing a spot? with predefined shapes?
Yes exactly like this. I've got 24 shapes to fill with and i want to fill randomly.
ok, then I'm out. I have no idea how to code that all of those blocks fit leaving no space at all. I used to have a real puzzle toy challenging you with exactly this kind of task and I never found the underlying system.
but I found this:
Answer by toddisarockstar · Mar 22, 2017 at 06:28 AM
public int[][] grid;
public Vector2[][] pieces;
int i;
int i2;
public Texture2D dis;
public Color[] col;
int numberplaced;
int squaresplaced;
int attempts;
int maxattempts;
int gridsize;
void Start () {
maxattempts = 10000;//this is max number of times the script will try to fill every square!!!
//we need colors for our pieces
col = new Color[5];
col [0] = Color.red;
col [1] = Color.green;
col [2] = Color.blue;
col [3] = Color.yellow;
col [4] = Color.cyan;
int bx;
int by;
int i;
//an make an array of arrays to represent our pieces
pieces = new Vector2[5][];
//inside the array of pieces i make an array to stick coordinates for the shape of the peices
//each piece is going to need local coordinates of its own blocks to represent its shape;
//make a red dot
pieces [0] = new Vector2[1];
pieces [0] [0] = new Vector2 (0, 0);
//make a green square
pieces [1] = new Vector2[4];
pieces [1] [0] = new Vector2 (0, 0);
pieces [1] [1] = new Vector2 (0, 1);
pieces [1] [2] = new Vector2 (1, 0);
pieces [1] [3] = new Vector2 (1, 1);
//make a blue line
pieces [2] = new Vector2[4];
pieces [2] [0] = new Vector2 (0, 0);
pieces [2] [1] = new Vector2 (0, 1);
pieces [2] [2] = new Vector2 (0, 2);
pieces [2] [3] = new Vector2 (0, 3);
//make a yellow L
pieces [3] = new Vector2[5];
pieces [3] [0] = new Vector2 (0,0);
pieces [3] [1] = new Vector2 (0,1);
pieces [3] [2] = new Vector2 (0,2);
pieces [3] [3] = new Vector2 (1,0);
pieces [3] [4] = new Vector2 (2,0);
//make a small light blue line
pieces [4] = new Vector2[2];
pieces [4] [0] = new Vector2 (0, 0);
pieces [4] [1] = new Vector2 (1, 0);
//pieces [4] [2] = new Vector2 (2, 0);
gridsize = 6;
//we will keep looping random attempts to fill all squares !!!!
while(squaresplaced<gridsize*gridsize){
squaresplaced=0;
attempts++;
if(attempts>maxattempts){squaresplaced=gridsize*gridsize;}
//now to create the grid i
//create an array of arrays; (array of 6 each containg 6 arrays;
//so that we have values that can be checked with 2 coordinates;
grid = new int[gridsize][];
i = grid.Length;
while (i>0) {i--;
grid [i] = new int[gridsize];
}
// now here is where things get a bit crazy
// first of all i need to loop through all our pieces right?
numberplaced = pieces.Length;
while(numberplaced==pieces.Length){
numberplaced=0;
int p = pieces.Length;
while (p>0) {p--;
int xpad=0;
int ypad=0;
//find the size of our piece to make sure we dont try to
//place it where it hangs off the grid
i=pieces[p].Length;
while(i>0){i--;
if(xpad<pieces[p][i].x){xpad=Mathf.FloorToInt(pieces[p][i].x);}
if(ypad<pieces[p][i].y){ypad=Mathf.FloorToInt(pieces[p][i].y);}
}
//lets choose a random coordinate to start with
int gridy=Random.Range(0,grid.Length-ypad);
int gridx=Random.Range(0,grid[0].Length-xpad);
//another number that stops the loop after checking all the squares
int count = grid.Length*grid[0].Length;
//print ("count="+count);
//now i need a loop inside a loop
//to page through every sqaure in my grid
//starting with our random start position
while(count>0){
while(gridx>-1){
count--;
//here we check through all our piece coordinates against the grid to see if they fit
if(gridx+xpad<grid[0].Length){
if(gridy+ypad<grid.Length){
bool placed=true;
int b=pieces[p].Length;
while(b>0){b--;
bx = Mathf.FloorToInt(pieces[p][b].x);
by = Mathf.FloorToInt(pieces[p][b].y);
//if(gridx+bx>=grid[0].Length){placed=false;}
//if(gridy+by>=grid.Length){placed=false;}
if(placed==true){
if(grid[gridx+bx][gridy+by]!=0){placed=false;}}
}
//if successfull we will mark it on the grid
if(placed==true){
numberplaced++;
b=pieces[p].Length;
while(b>0){b--;
bx = Mathf.RoundToInt(pieces[p][b].x);
by = Mathf.RoundToInt(pieces[p][b].y);
squaresplaced++;
grid[gridx+bx][gridy+by]=p+1;
}
count=0;
gridx=-1;
}
}}
gridx--;
}
gridx=grid[0].Length-1;
if(gridy<1){gridy=grid.Length;}
gridy--;
}
}
}
//print ("squares placed:" + squaresplaced);
}
i = gridsize * gridsize;
if (squaresplaced < i + 1) {
print ("i filled " + squaresplaced + "out of " + i + "squares with your peices without overlap");}
print ("i used " + attempts + "random attempts to get this!!!!");
if (squaresplaced != i) {print ("if you increase my Max attempts i will fill them all!!!");}
//I added this at the bottome just to display what is going on!!!!
dis = new Texture2D (grid.Length, grid [0].Length);
i =dis.width;
while (i>0) {i--;
i2 = dis.height;
while(i2>0){i2--;
if(grid[i][i2]>0){dis.SetPixel(i,i2,col[grid[i][i2]-1]);}
else{dis.SetPixel(i,i2,Color.clear);}
}}
dis.Apply ();
dis.filterMode = FilterMode.Point;
}
void OnGUI(){
GUI.DrawTexture (new Rect(0, 0, 300, 300), dis);
}
first all you need a grid which is a two dimentional array, or an array inside an array. so we have 36 variables that can be accessed with coordinates.
then we need the coordinates to represet the shape of the pieces for checking purposes since each piece has multiple coordinates and we have multiple pieces we use another array of arrays for the pieces!
the script i wrote starts with a peice and trys to randomly place it. if it doesen't fit it continues to try every other place on the grid. If successful, it trys the same process with the next piece untill it cant find a proper placement.
if all the squares in the grid are full it stops. if all the squares are not full. it erases and trys again till it gives you what you want.
the script allways uses the same amounts of peices so depending on size / shape of your peices there is a chance that is either impossible to fit them or there could be very few possible outcomes.
the little grid is simple to figure out for the PC. if you where using a bigger grid you would pry need to implement a little AI such as checking ahead of itself before placing the blocks or starting with big peices and using small ones last.
Anyways, this code produces your random outcome just fine on a little 6*6 grid !
you can take the time to change the number and shape of the peices as you need i just gave it a few basics for example
if i was in your situation i would just run this code for a good amount of time and store all the possiblitys. then use the outputs in your game assets instead of the user running this!
Answer by Alp-Giray-Savrum · Mar 22, 2017 at 05:58 PM
Thanks a lot, I'll try to implement this code to my game !