What if I make a prototype like that? a simple nonogram game without all that colors and cats, just black and white… It’s possible… –Hey hey hey slow down smart ass, what the hell is a nonogram?. You’re right I haven’t told anything about them, let’s start from there.
You know… I could try to explain what a Nonogram is without success, then you are going to think that I’m stupid and you’re going to open Wikipedia and search for it, so I’m gonna save you the trouble Here you have it.
Now that we’re masters of all Japanese puzzle we shall continue. To create a nonogram we need to visualize the end, for example we want to create this nonogram designed by my friend Chema (Great friend, better person).
This 5x5 nonogram may be easy to manually generate and create the desired game board right? but what if we want to make 50? 100? or 8x8 nonograms? The problem starts to complicate quickly, very quickly so why don’t we just design the final image of the nonogram and let a program generate the board for us? That would be great, we just have to open GIMP or Photoshop or any other image editor program and start painting. Oh yes, I like that.
The next step is to design the serialized file for each nonogram, would it be a XML? JSON? plain text? SQL? (Really? are you even evaluating SQL?). XML and JSON are just plain text with some improvements that would help in a bigger project or serialization. In this approach I decided to use plan text because it would be easier to serialize and deserialize, each file would start with the size of the nonogram and then a list for each row and column with the numbers that the board should show. This is the serialized text for the nonogram from above:
5x5Now that we’ve defined our serialized text we need to reverse from the final image to the text, here’s the thing!! We’re gonna analyze the image, pixel by pixel and generate the desired output. For my example I’ve asked Chema (Do you remember him? he’s my friend hahahaha) to use GIMP and create a 5x5 image, design his nonogram and export it as bitmap. We’re gonna open the image from a C# program and look if each pixel is black or white to generate the output.
row:2
row:4
row:1 1
row:1 2
row:2
col:2
col:1 2
col:2 1
col:2 1
col:2
First, we need some attributes and a constructor, I decided that each object will process just one image, so I open the image in the constructor. Like this:
private Bitmap image;
private int tileSize;
private string imageRoute;
public ImageProcessor(int tileSize, string imageRoute)
{
this.tileSize = tileSize;
image = (Bitmap) Bitmap.FromFile(imageRoute).Clone();
this.imageRoute= imageRoute;
}
Then we need a method that converts the rows and columns to a string[]. This could be the ugliest part of the code and if anyone has a better solution please let me know.
public string[] GenerateAxis(int mainAxisSize, int auxAxisSize, bool swapIndex)
{
string[] cols = new string[mainAxisSize / tileSize];
for (int i = 0; i < mainAxisSize / tileSize; i++)//Iterate over the main axis Col|row
{
int consecutiveNumbers = 0;//counter for consecutive black pixels
StringBuilder sb = new StringBuilder();
for (int j = 0; j < auxAxisSize / tileSize; j++)
{
//We store the index in a local copy because if we have to swap the index
//we could modify those values and generate an infinite loop
int a = i;
int b = j;
int aux = 0;
if (swapIndex)
{
aux = a;
a = b;
b = aux;
}
//Get the color of the pixel
Color pixel = image.Get Pixel(a,b);
//The image is in black and white so we look for one component to be almost black (It can be R|G|B)
if (pixel.R < 10)
consecutiveNumbers++;
else
{
if (consecutiveNumbers > 0)
{
sb.Append(consecutiveNumbers.ToString()).Append(" ");
consecutiveNumbers = 0;
}
}
}
if (consecutiveNumbers > 0)
sb.Append(consecutiveNumbers.ToString()).Append(" ");
//Trim the result to delete any whitespace, tab or extra line
cols[i] = sb.ToString().Trim();
}
return cols;
}
Now we have to call this method for the rows and columns, then format the output string and write it to a .txt file.
public void SerializeNonogram()
{
string[] cols = GenerateAxis(image.Width, image.Height, false);
string[] rows = GenerateAxis(image.Height, image.Width, true);
StringBuilder sb = new StringBuilder();
sb.AppendLine(rows.Length + "x" + cols.Length);
//If any row or column should be left blank then
//we print a "0"
foreach (string row in rows)
{
if (row == "")
sb.AppendLine("row:0");
else
sb.AppendLine("row:" + row);
}
foreach (string col in cols)
{
if (col == "")
sb.AppendLine("row:0");
else
sb.AppendLine("col:" + col);
}
File.WriteAllText("TextLevels\\"+imageRoute.Replace(".bmp", ".txt"), sb.ToString());
}
And that’s it!! It should generate a .txt with the same name as the input BitMap. I made a little bulk convert to generate all the levels of my game but that’s up to you :3