Reputation: 35
This is a continuation of this question: Recursive Flood Fill algorithm in C using ASCII art and incrementing characters to fill the space
In the previous question, I asked about how to get the Flood Fill algorithm to properly. The algorithm works and fills the space properly but now I have a question regarding on the visuals and how letters are printed onto the room.
Below is a sample of the program with a more complicated room pattern.
#include <stdio.h>
#include <stdlib.h>
typedef struct room{
char **array;
int rows;
int cols;
} room;
void printRoom(room room);
int *findA(room room);
void floodFill(room room, int x, int y, char paint);
room buildRoom();
int main(int argc, char *argv[]){
// Make a new room
room newRoom = buildRoom();
printf("Before\n");
printRoom(newRoom);
// Find the A
int *a = findA(newRoom);
// Print the A
printf("A is at %d, %d\n", a[0], a[1]);
// Set current position to ' '
newRoom.array[a[0]][a[1]] = ' ';
// Flood fill the room
floodFill(newRoom, a[0], a[1], 'A');
// Print the room
printf("\nAfter\n");
printRoom(newRoom);
return 0;
}
int *findA(room room){
int *location = malloc(2 * sizeof(int));
for(int i = 0; i < room.rows; i++){
for(int j = 0; j < room.cols; j++){
if(room.array[i][j] == 'A'){
location[0] = i;
location[1] = j;
}
}
}
return location;
}
void floodFill(room room, int x, int y, char paint){
/* Base cases */
if(x < 0 || x >= room.rows || y < 0 || y >= room.cols) return;
if(room.array[x][y] != ' ') return;
// Paint the current position
room.array[x][y] = paint;
if(paint < 'Z') paint++;
/* Recursive calls */
floodFill(room, x, y - 1, paint);
floodFill(room, x, y + 1, paint);
floodFill(room, x - 1, y, paint);
floodFill(room, x + 1, y, paint);
}
void printRoom(room room){
for(int i = 0; i < room.rows; i++){
for(int j = 0; j < room.cols; j++){
printf("%c", room.array[i][j]);
}
printf("\n");
}
}
room buildRoom(){
room newRoom;
int row = 12;
int col = 14;
newRoom.rows = row;
newRoom.cols = col;
/* Allocate memory for the array */
newRoom.array = malloc(row * sizeof(char*));
for(int i = 0; i < row; i++){
newRoom.array[i] = malloc(col * sizeof(char));
}
char *row1 = "**************";
char *row2 = "* A *";
char *row3 = "* **** ***** *";
char *row4 = "* * * * *";
char *row5 = "* * **** *** *";
char *row6 = "* * * * * *";
char *row7 = "* * * ***";
char *row8 = "* **** * * * *";
char *row9 = "* * * * ***";
char *row10 = "*** ****** * *";
char *row11 = "* * * *";
char *row12 = "**************";
int i;
/* Make room.newArray[0][] = row1 */
for(i = 0; i < col; i++){
newRoom.array[0][i] = row1[i];
}
/* Make room.newArray[1][] = row2 */
for(i = 0; i < col; i++){
newRoom.array[1][i] = row2[i];
}
/* Make room.newArray[2][] = row3 */
for(i = 0; i < col; i++){
newRoom.array[2][i] = row3[i];
}
/* Make room.newArray[3][] = row4 */
for(i = 0; i < col; i++){
newRoom.array[3][i] = row4[i];
}
/* Make room.newArray[4][] = row5 */
for(i = 0; i < col; i++){
newRoom.array[4][i] = row5[i];
}
/* Make room.newArray[5][] = row6 */
for(i = 0; i < col; i++){
newRoom.array[5][i] = row6[i];
}
/* Make room.newArray[6][] = row7 */
for(i = 0; i < col; i++){
newRoom.array[6][i] = row7[i];
}
/* Make room.newArray[7][] = row8 */
for(i = 0; i < col; i++){
newRoom.array[7][i] = row8[i];
}
/* Make room.newArray[8][] = row9 */
for(i = 0; i < col; i++){
newRoom.array[8][i] = row9[i];
}
/* Make room.newArray[9][] = row10 */
for(i = 0; i < col; i++){
newRoom.array[9][i] = row10[i];
}
/* Make room.newArray[10][] = row11 */
for(i = 0; i < col; i++){
newRoom.array[10][i] = row11[i];
}
/* Make room.newArray[11][] = row12 */
for(i = 0; i < col; i++){
newRoom.array[11][i] = row12[i];
}
return newRoom;
}
Output
Before
**************
* A *
* **** ***** *
* * * * *
* * **** *** *
* * * * * *
* * * ***
* **** * * * *
* * * * ***
*** ****** * *
* * * *
**************
A is at 1, 3
After
**************
*CBAZZZZZZZZZ*
*D****Z*****Z*
*E*ZZZZ* *Z*
*F*Z**** ***Z*
*G*Z*ON* *ZZZ*
*HIJKLM* *Z***
*I****N* *Z* *
*J*RQPO* *Z***
***S******Z* *
* *TUVWXYZZ* *
**************
While the room is filled with no errors, I want the letters to print in a specific way. Below is an example of how I want it to print.
Preferred output
**************
*CBABCDEFGHIJ*
*D****E*****K*
*E*IHGF* *L*
*F*J**** ***M*
*G*K*MN* *PON*
*HIJKLM* *Q***
*I****N* *R* *
*J*RQPO* *S***
***S******T* *
* *TUVWXWVU* *
**************
In the preferred output above, it seems that the letters spread out from the 'A'. For example, the 'A' is surrounded by Bs, the Bs are surrounded by Cs and so on. In original output, the program goes simply goes in "one" direction where a 'Z' is next to the 'A'. The original program uses DSF but I have seen that a BSF approach can be possible with the Flood Fill algorithm and it seems that BSF is might create the pattern that I need but not sure how to implement it into the program. I could be totally wrong about it so any insight or help is greatly appreciated.
Upvotes: 1
Views: 373
Reputation: 16769
The most visually appealing way is to introduce a queue. Put the starting cell in the queue. Then follow the algorithm:
You have to change the state of the cell when you visit the cell. You can use the same matrix for this, or you can use new temporary matrix. If you use the same matrix then in the end you have to reset the visiting state of all the cells. If you use a temporary matrix then just discard it.
There are several different algorithms explained in Wikipedia article.
If you want to change visual appearance in a way that cells that are equally distant from the start are filled at the same time then your visiting flag must be more than a bool. It must be a distance from start. In that case you Change visual appearance when you run out of one generation of cells, and encouter in the queue a second generation. OR you have two queues. This could be simpler. When you pop from first queue you push to second queue. When first queue becomes empty change second queue to be the first.
Upvotes: 1