I have posted here my working and accepted solution to the graphical editor programming challenge (detailed here) for your review.
The program recognizes the following image editing commands:
I M N: Creates a new table M × N (up to 250 × 250) with white (O) pixels.C: Clears the table to white.L X Y C: Colors the pixel with coordinates (X, Y) in colour C. (A "colour" is a single character.)V X Y1 Y2 C: Draws the vertical segment in the column X between the rows Y1 and Y2 inclusive in colour C.H X1 X2 Y C: Draws the horizontal segment in the row Y between the columns X1 and X2 inclusive in colour C.K X1 Y1 X2 Y2 C: Draws the filled rectangle in colour C. (X1, Y1) is the upper left corner, (X2, Y2) is the lower right corner of the rectangle.F X Y C: Fills the region with the colour C, starting with (X, Y) and including any neighbouring pixels with a common side and the same colour.S Name: Writes the picture in the file Name.X: Terminates the session.
// graphical_editor.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream> //provides access to cout and cin
#include <string> //Always import <string> if piping std input to a string in .net
#include <vector>
#include <fstream>
using std::cin;
using std::cout;
using std::string;
using std::vector;
using std::ofstream;
//This is where we store the pixels of the image
static vector<vector <string>> image_array;
//our definition of an X,Y coordinate pair.
typedef struct point {
int x_coordinate, y_coordinate;
};
void initialise_image();
void clear_image();
void save_image(string file_name);
int get_image_width();
int get_image_height();
void color_pixel(int x, int y, string color);
void color_point(point p, string color);
void color_vertical_line(int x, int y1, int y2, string color);
void color_horizontal_line(int x1, int x2, int y, string color);
void color_box(int x1, int x2, int y1, int y2, string color);
void flood_fill(point p, string color);
void add_matching_neighbours(point p, string original_color, string new_color, vector<point> &points_queue);
int main()
{
//myfile.open("example.txt");
char command; //first letter of a given line
while (cin >> command) {
//application terminates when command is X
if (command==('X')) {
return 0;
} else if (command==('I')) {
initialise_image();
}
else if (command=='S') {
string file_name;
cin >> file_name;
save_image(file_name);
}
else if (command=='L') {
string color;
point p;
cin >> p.x_coordinate >> p.y_coordinate >> color;
color_point(p, color);
}
else if (command=='V') {
string color;
int x, y1, y2;
cin >> x >> y1 >> y2 >> color;
color_vertical_line(x, y1, y2, color);
}
else if (command=='H') {
string color;
int x1, x2, y;
cin >> x1 >> x2 >> y >> color;
color_horizontal_line(x1, x2, y, color);
}
else if (command=='K') {
string color;
int x1, x2, y1, y2;
cin >> x1 >> y1 >> x2 >> y2 >> color;
color_box(x1, y1, x2, y2, color);
}
else if (command== 'F') {
string color;
point p;
cin >> p.x_coordinate >> p.y_coordinate >> color;
flood_fill(p, color);
}
else if (command == 'C') {
clear_image();
}
}
return 0;
}
/* This function creates a blank image size width by height
where width and height are read from standard input respectively.*/
void initialise_image()
{
/*read parameters height and width*/
int width, height;
cin >> width >> height;
/*first we create a vector of vectors (numRows+1)x(numColumns matrix+1). */
image_array.clear();
for (int i = 0; i < width+ 1; i++) {
image_array.push_back(vector<string>());
}
/*then we initialize each element of it one by one*/
for (int colNo = 0; colNo < width + 1; colNo++) {
for (int rowNo = 0; rowNo < height + 1; rowNo++) {
image_array[colNo].push_back("O");
}
}
}
/* resets all pixels of the image to color "O"*/
void clear_image() {
/*we initialize each element of it one by one*/
for (int y = 1; y < get_image_height()+1 ; y++) {
for (int x = 1; x < get_image_width()+1; x++) {
image_array[x][y] = "O";
}
}
}
/* saves the image in filename where filename is read from stdin*/
void save_image(string file_name) {
cout << file_name << "\n";
for (int y = 1; y < get_image_height()+1; y++) {
for (int x = 1; x < get_image_width()+1; x++) {
cout << image_array[x][y] ;
}
cout << "\n";
}
}
int get_image_width() {
return image_array.size()-1;
}
int get_image_height() {
return image_array[0].size()-1;
}
//colors the pixel at point p.x_coordinate, p.y_coordinate in color color.
void color_point(point p, string color) {
color_pixel(p.x_coordinate,p.y_coordinate, color);
}
void color_pixel(int x, int y, string color) {
image_array[x][y] = color;
}
void color_vertical_line(int x, int y1, int y2, string color) {
int y_adjustment;
if (y1 > y2) {
y_adjustment = -1;
}
else {
y_adjustment = 1;
}
int y = y1;
while (y != y2+y_adjustment) {
color_pixel(x, y, color);
y += y_adjustment;
}
}
void color_horizontal_line(int x1, int x2, int y, string color) {
int x_adjustment;
if (x1 > x2) {
x_adjustment = -1;
}
else {
x_adjustment = 1;
}
int x = x1;
while (x != x2 + x_adjustment) {
color_pixel(x, y, color);
x += x_adjustment;
}
}
//colors the box drawn between point x1, y1 and x2, y2.
void color_box(int x1, int y1, int x2, int y2, string color) {
int x_adjustment;
if (x1 > x2) {
x_adjustment = -1;
}
else {
x_adjustment = 1;
}
int y_adjustment;
if (y1 > y2) {
y_adjustment = -1;
}
else {
y_adjustment = 1;
}
int x = x1;
int y = y1;
while (x != x2 + x_adjustment) {
while (y != y2 + y_adjustment) {
color_pixel(x, y, color);
y += y_adjustment;
}
x += x_adjustment;
y = y1;
}
}
string get_point_color(point p) {
return image_array[p.x_coordinate][p.y_coordinate];
}
//fills all pixels that share a border and color with p the color color.
void flood_fill(point p, string color) {
//we will be using a queue to store points that have been colored but whose neighbours are yet to be.
vector <point> points_queue;
//first we add the point p to our queue
points_queue.push_back(p);
string original_color = get_point_color(p);
point current_point;
string final_color = "";
//if the original color of a point is the same as the new color then we return. Prevents infinite loop.
if (original_color.compare(color) == 0) {
return;
}
while (points_queue.size() > 0) {
//get element in front of queue for processing and remove it from queue.
current_point = points_queue[0];
points_queue.erase(points_queue.begin());
//if the point shares a color with the original point then color it in the new color.
if (get_point_color(current_point).compare(original_color) == 0) {
color_point(current_point, color);
}
// add it's neighbours to the queue who's color matches original_color.
add_matching_neighbours(current_point, original_color, color, points_queue);
}
}
//check if coordinates for point p lie in our image.
bool is_valid_point(point p) {
if (p.x_coordinate >= 1 && p.x_coordinate < get_image_width() + 1 && p.y_coordinate >= 1 && p.y_coordinate < get_image_height() + 1) {
return true;
}
else {
return false;
}
}
//checks all direct neighbours of p(north, south, east, west) and adds
//those whose color is the original color to points_queue after coloring them.
void add_matching_neighbours(point p, string original_color, string new_color, vector<point> &points_queue) {
point left_neighbour, right_neighbour, upper_neighbour, lower_neighbour;
left_neighbour.x_coordinate = p.x_coordinate - 1;
left_neighbour.y_coordinate = p.y_coordinate;
if (is_valid_point(left_neighbour) && get_point_color(left_neighbour).compare(original_color) == 0) {
points_queue.push_back(left_neighbour);
color_point(left_neighbour, new_color);
}
right_neighbour.x_coordinate = p.x_coordinate + 1;
right_neighbour.y_coordinate = p.y_coordinate;
if (is_valid_point(right_neighbour) && get_point_color(right_neighbour).compare(original_color) == 0) {
points_queue.push_back(right_neighbour);
color_point(right_neighbour, new_color);
}
upper_neighbour.x_coordinate = p.x_coordinate;
upper_neighbour.y_coordinate = p.y_coordinate + 1;
if (is_valid_point(upper_neighbour) && get_point_color(upper_neighbour).compare(original_color) == 0) {
points_queue.push_back(upper_neighbour);
color_point(upper_neighbour, new_color);
}
lower_neighbour.x_coordinate = p.x_coordinate;
lower_neighbour.y_coordinate = p.y_coordinate - 1;
if (is_valid_point(lower_neighbour) && get_point_color(lower_neighbour).compare(original_color) == 0) {
points_queue.push_back(lower_neighbour);
color_point(lower_neighbour, new_color);
}
}
stringeverywhere in your code? \$\endgroup\$