- Home /
Optimizing code for color generation of chess board
Hey, another optimazation problem with my chess game. My code works but yeah its just a bunch of repeating if statements that can be shorten down and optimized.
int indexCount = tiles.Count - 1;
if (indexCount % 9 == 0)
{
piece.GetComponent<Renderer>().material.color = Color.black;
}
if (indexCount % 9 == 2 && indexCount <= 9 * 6)
{
piece.GetComponent<Renderer>().material.color = Color.black;
}
if (indexCount % 9 == 3 && indexCount >= 9 * 5)
{
piece.GetComponent<Renderer>().material.color = Color.black;
}
if (indexCount % 9 == 4 && indexCount <= 9 * 4)
{
piece.GetComponent<Renderer>().material.color = Color.black;
}
if (indexCount % 9 == 5 && indexCount >= 9 * 3)
{
piece.GetComponent<Renderer>().material.color = Color.black;
}
if (indexCount % 9 == 6 && indexCount <= 9 * 2)
{
piece.GetComponent<Renderer>().material.color = Color.black;
}
if (indexCount % 9 == 7 && indexCount >= 9)
{
piece.GetComponent<Renderer>().material.color = Color.black;
}
indexCount allows me to count each tile as it was an index (so i dont count a grid from 1 to 64, but 0 to 63). The way the code works is that it checks each index and accesses the indexes that belong in the multiplication table of 9 and fills them. Then it repeats but checks for the remainder of 9. The extra stuff in the if-statements are so that it only handles a diagonal row at a time and doesnt alter any indexes outside of this row.
How can i optimize this code? Make sure to note the operators change when handling even and uneven numbers outside of the diagonal row.
Thanks
Answer by DiegoSLTS · May 25, 2016 at 02:50 AM
That 9 there looks so wierd. You only need the row and column of a tile to set it's color. In your code I guess this should work to get the row and column of a tile:
int row = (tiles.Count - 1) / 8; //integer division, so for the first 8 tiles you'll be in row 0, for the next 8 tiles you'll be in row 1 and so on until row 7 (the 8th row)
int column = (tiles.Count - 1) % 8; //no matter what row you're filling, the column will always go from 0 to 7
Once you have the row and column, do this (it's what I'm doing in my game):
piece.GetComponent<Renderer>().material.color = row % 2 == column % 2 ? Color.black : Color.white;
EDIT: If all your tiles are already white and want to set the black ones to black, get the row and column like before and then:
if (row % 2 == column % 2)
piece.GetComponent<Renderer>().material.color = Color.black;
Thanks again! :) can you explain the:
piece.GetComponent<Renderer>().material.color = row % 2 == column % 2 ? Color.black : Color.white;
like the ? out of nowhere and the :, i never seen it before :o
Yes, I'll explain. First, the "condition ? value_for_true : value_for_false" is the ternary operator: https://en.wikipedia.org/wiki/%3F:
It's a way to write if/else statements when you need to asign a different value depending on the condition. This 2 things are equivalent:
Color c = condition ? Color.black : Color.white;
// and
Color c;
if (condition)
c = Color.black;
else
c = Color.white;
For the condition, I'm checking if row and column are even or odd rows. If you look at the board, every black tile is in a position where row and column are both even, or row and column ar both odd. For white tiles you'll see that either row is even and column is odd, or row is odd and column is even.
Now, "row % 2" (and "column % 2") returns 0 when row (column) is even, and 1 when row (column) is odd. I don't really care if they're odd or even, I just want to know if they're different or not, so ins$$anonymous$$d of checking if:
(row % 2 == 0 && column % 2 == 0) || (row % 2 == 1 && column % 2 == 1)
I just check if:
row % 2 == column % 2
holy damn thanks a lot that was a really good explanation :) thanks i learned a lot!
Answer by Jessespike · May 24, 2016 at 08:25 PM
Less code does not mean optimized. You can replace the 7 short if-statements for 1 longer one, less code, but I wouldn't call it optimized, since it's doing the same thing:
int indexCount = tiles.Count - 1;
if (indexCount % 9 == 0 ||
indexCount % 9 == 2 && indexCount <= 9 * 6 ||
indexCount % 9 == 3 && indexCount >= 9 * 5 ||
indexCount % 9 == 4 && indexCount <= 9 * 4 ||
indexCount % 9 == 5 && indexCount >= 9 * 3 ||
indexCount % 9 == 6 && indexCount <= 9 * 2 ||
indexCount % 9 == 7 && indexCount >= 9)
{
piece.GetComponent<Renderer>().material.color = Color.black;
}
Instead of using GetComponent to fetch the Renderer's material, you can store the material and access it directly, this could be considered an optimized, a micro one perhaps, probably won't even be noticeable though.
The logic is a bit funky, not sure how you are generating the board, but you could probably replace the magic numbers for something easier to read, again I wouldn't consider this an optimization.
// Tiles are children to the ChessBoard (An empty GameObject here)
Renderer[] tiles = GetComponentsInChildren<Renderer>();
for (int i = 0; i < tiles.Length; i++)
{
tiles[i].material.color = (i % 2 == 0) ? Color.black : Color.white;
}
If you want to optimize, then the best thing is probably to import the Chessboard as a model, you won't need to generate the tiles and colors on start every time.
Yeah i might have formulated it a bit bad, i just want to shorten down my code so i dont have 10+ if statements when they all do nearly the same thing. If you wondered how i generated the board its made with two for-loops and the object used for all tiles is called piece. While tiles is the list where i store all tiles in the grid
Shorter code in this case is also an optimization, but it's a microoptimization that probably won't make a significant difference. Anyway, it's good to know that the original code, with all the ifs, will check all the conditions after and before the if that evaluated to true. In the or-ed code once a condition is true (always checked from left to right) the rest are not checked since one "true" is enough with "ors". In a similar way, and-ed conditions are not checked after one being false, since for an and to be true all conditions must be true.
It's not just an optimization tip, some times it's the source of obscure bugs since people assume all the conditions are checked, and some times those conditions are the result of some function. If that function does something else than returning false or true then you have a function that "should" be called in certain places, but since the previous condition was enough to evaluate the whole if the function it's never called.
I don't think your second piece of code works, it looks like it'll paint all odd tiles in a row to black, and all even tiles in a row to white, unless the board is created one row from left to right, the next from right to left and so on (which would be a weird way to create a board).
well the code works haha, the result of the code is what you see in the image. By the second code do you mean the "&& indexCount @Jessespike ?
Yes, I was talking about the second solution Jessespike wrote:
// Tiles are children to the ChessBoard (An empty GameObject here)
Renderer[] tiles = GetComponentsInChildren<Renderer>();
for (int i = 0; i < tiles.Length; i++)
{
tiles[i].material.color = (i % 2 == 0) ? Color.black : Color.white;
}
That wll make the first tile of each row black, the second white, and so on unless you're filling the rows first from left to right, then from right to left, etc, etc.
Answer by DiGiaCom-Tech · May 25, 2016 at 07:05 PM
@vittu1994 ... The best optimization I can think of here is to simply set the gameObject material colors in the editor. Those settings will persist and you don't have to mess with them ever again. In short, this is a 'NO CODE' solution ... a no code solution is going to be better/faster than any optimized code anyone can come up with.
However, if you want to allow the player to set their own colors -or- you want an Inspector Editor feature where you can quickly set & update the colors yourself then @DiegoSLTS answer is the way to go.
Answer by noorudheen · May 24, 2016 at 08:42 PM
try this:(not tested)
private GameObject[] grid;
public Gameobject block;
public float blockSize;
void Start(){
grid = new grid[2,2];
}
void Update(){
for(int i = 0; i <grid.length; i++){
for(int j = 0; j <grid.height; j++){
temp = (GameObject) instantiate(Block, new vector3(i * blockSize, j * blockSize,0),quternion.identity);
grid[i,j] = temp;
}
}
}
Troll somewhere else. If you don't have anything constructive to say, then don't.
@jessespike : $$anonymous$$Y CODE LOO$$anonymous$$S LI$$anonymous$$E A TROLL FOR YOU!... OOOOOOOPZZZZ!
I think he was replying to: "Try the optimize class, its simple and easy" ;)
Your answer
Follow this Question
Related Questions
Help optimizing my code for chess game 1 Answer
A node in a childnode? 1 Answer
Optimization on list handling 2 Answers
Grid obstacle detection 1 Answer
Can someone help me to find what I am doing wrong?(code attached) 1 Answer