Mini ASCII Art Studio
Napraviti mini editor za ASCII art na malom platnu. Platno je pravougaona mreža znakova (boja). Treba omogućiti osnovne operacije crtanja i transformacija.
Zadatak rešiti u više fajlova: main.c, canvas.h, canvas.c.
Boja se predstavlja jednim ASCII karakterom char, koji je moguće ispisati (npr. A, B, #, .).
Platno Canvas treba da podržava sledeće funkcionalnosti:
-
Canvasstruktura (širina, visina i matrica piksela) -
Canvas canvas_new(int w, int h, char fill)– pravi novo platno i popunjava bojomfill; -
void canvas_print(Canvas c)– ispisuje platno; -
Canvas canvas_set(Canvas c, int x, int y, char col)– postavlja piksel(x,y)nacol; -
Canvas canvas_hline(Canvas c, int y, int x1, int x2, char col)– horizontalna linija; -
Canvas canvas_vline(Canvas c, int x, int y1, int y2, char col)– vertikalna linija; -
Canvas canvas_fill_rect(Canvas c, int x, int y, int w, int h, char col)– puni pravougaonik; -
Canvas canvas_mirror(Canvas c, char axis)–axis='H'za horizontalno preslikavanje,axis='V'za vertikalno preslikavanje; -
Canvas canvas_rotate90(Canvas c)– rotira platno$90^{\circ}$ udesno (dimenzije se preračunavaju u kopiji koju vraća); i -
int canvas_distinct_colors(Canvas c)– vraća broj različitih boja na platnu.
Ulaz
Sa standardnog ulaza se učitava broj upita
-
c <w> <h> <c>– kreira novo platno dimenzije<w>x<h>ispunjeno bojom<c>; -
s <x> <y> <c>– postavlja piksel(<x>,<y>)na<c>; -
h <y> <x1> <x2> <c>– iscrtava horizontalnu linija boje<c>u redu<y>od<x1>do<x2>; -
v <x> <y1> <y2> <c>– iscrtava vertikalnu linija boje<c> u koloni<x>od<y1>do<y2>; -
r <x> <y> <w> <h> <c>– iscrtava pravougaonik boje<c>sa početkom u(<x>,<y>)dimenzije<w>x<h>; -
m <axis>– preslikava horizontalno<axis>=Hili vertikalno<axis>=V; -
t– rotira platno za$90^{\circ}$ udesno; -
p– ispisuje platno; i -
n– ispisuje broj različitih boja na platnu.
Svi indeksi su nula-bazirani. Pretpostaviti da su dimenzije i koordinate su u granicama platna i da neće biti nevalidnih upita. Platno neće biti rezolucije veće od
Izlaz
Na standardni izlaz ispisati platno pri obradi upita p, ili vrednosti pri obradi upita n.
Primer
Ulaz
10
c 5 4 .
h 1 0 4 A
v 0 0 3 B
s 4 3 C
p
n
m H
p
t
p
Izlaz
B....
BAAAA
B....
B...C
4
....B
AAAAB
....B
C...B
C.A.
..A.
..A.
..A.
BBBB
Rešenje
canvas.h
#ifndef CANVAS_H
#define CANVAS_H
#define MAX_W 32
#define MAX_H 32
typedef struct Canvas {
int w;
int h;
char pix[MAX_H][MAX_W];
} Canvas;
// Better to use pointers for passing and returning large structs (see later lectures)
Canvas canvas_new(int w, int h, char fill);
Canvas canvas_set(Canvas c, int x, int y, char col);
Canvas canvas_hline(Canvas c, int y, int x1, int x2, char col);
Canvas canvas_vline(Canvas c, int x, int y1, int y2, char col);
Canvas canvas_fill_rect(Canvas c, int x, int y, int w, int h, char col);
Canvas canvas_mirror(Canvas c, char axis);
Canvas canvas_rotate90(Canvas c);
int canvas_distinct_colors(Canvas c);
void canvas_print(Canvas c);
#endif // CANVAS_H
canvas.c
#include "canvas.h"
#include <stdio.h>
#include <ctype.h>
Canvas canvas_new(int w, int h, char fill)
{
Canvas c;
c.w = w; c.h = h;
for (int y = 0; y < c.h; y++) {
for (int x = 0; x < c.w; x++) {
c.pix[y][x] = fill;
}
}
return c;
}
Canvas canvas_set(Canvas c, int x, int y, char col)
{
c.pix[y][x] = col;
return c;
}
Canvas canvas_hline(Canvas c, int y, int x1, int x2, char col)
{
for (int x = x1; x <= x2; x++) {
c.pix[y][x] = col;
}
return c;
}
Canvas canvas_vline(Canvas c, int x, int y1, int y2, char col)
{
for (int y = y1; y <= y2; y++) {
c.pix[y][x] = col;
}
return c;
}
Canvas canvas_fill_rect(Canvas c, int x, int y, int w, int h, char col)
{
int x2 = x + w - 1;
int y2 = y + h - 1;
for (int yy = y; yy <= y2; yy++) {
for (int xx = x; xx <= x2; xx++) {
c.pix[yy][xx] = col;
}
}
return c;
}
Canvas canvas_mirror(Canvas c, char axis)
{
if (axis == 'H') {
for (int y = 0; y < c.h; y++) {
for (int x = 0; x < c.w / 2; x++) {
// new(x,y) = old(w-1-x,y)
char tmp = c.pix[y][x];
c.pix[y][x] = c.pix[y][c.w - 1 - x];
c.pix[y][c.w - 1 - x] = tmp;
}
}
} else if (axis == 'V') {
for (int y = 0; y < c.h / 2; y++) {
for (int x = 0; x < c.w; x++) {
// new(x,y) = old(x,h-1-y)
char tmp = c.pix[y][x];
c.pix[y][x] = c.pix[c.h - 1 - y][x];
c.pix[c.h - 1 - y][x] = tmp;
}
}
}
return c;
}
Canvas canvas_rotate90(Canvas c)
{
Canvas out = c; // copy to initialize
out.w = c.h;
out.h = c.w;
for (int y = 0; y < out.h; y++) {
for (int x = 0; x < out.w; x++) {
// new(x,y) = old(y, old_h-1-x)
int ox = y;
int oy = c.h - 1 - x;
if (ox >= 0 && ox < c.w && oy >= 0 && oy < c.h) {
out.pix[y][x] = c.pix[oy][ox];
}
}
}
return out;
}
int canvas_distinct_colors(Canvas c)
{
int used[256] = { 0 };
for (int y = 0; y < c.h; y++) {
for (int x = 0; x < c.w; x++) {
if (isprint(c.pix[y][x])) {
used[(int) c.pix[y][x]] = 1;
}
}
}
int count = 0;
for (int i = 0; i < 256; i++) {
count += used[i];
}
return count;
}
void canvas_print(Canvas c)
{
for (int y = 0; y < c.h; y++) {
for (int x = 0; x < c.w; x++) {
putchar(c.pix[y][x]);
}
putchar('\n');
}
}main.c
#include <stdio.h>
#include "canvas.h"
int main(void)
{
int q;
scanf("%d", &q);
Canvas cv;
while (q--) {
char op;
scanf(" %c", &op);
if (op == 'c') {
int w, h; char b;
scanf("%d %d %c", &w, &h, &b);
cv = canvas_new(w, h, b);
} else if (op == 's') {
int x, y; char b;
scanf("%d %d %c", &x, &y, &b);
cv = canvas_set(cv, x, y, b);
} else if (op == 'h') {
int y, x1, x2; char b;
scanf("%d %d %d %c", &y, &x1, &x2, &b);
cv = canvas_hline(cv, y, x1, x2, b);
} else if (op == 'v') {
int x, y1, y2; char b;
scanf("%d %d %d %c", &x, &y1, &y2, &b);
cv = canvas_vline(cv, x, y1, y2, b);
} else if (op == 'r') {
int x, y, w, h; char b;
scanf("%d %d %d %d %c", &x, &y, &w, &h, &b);
cv = canvas_fill_rect(cv, x, y, w, h, b);
} else if (op == 'm') {
char axis;
scanf(" %c", &axis);
cv = canvas_mirror(cv, axis);
} else if (op == 't') {
cv = canvas_rotate90(cv);
} else if (op == 'p') {
canvas_print(cv);
} else if (op == 'n') {
printf("%d\n", canvas_distinct_colors(cv));
}
}
return 0;
}
Makefile
CC = gcc
CFLAGS = -Wall -Wextra -pedantic
.PHONY: all clean
all: main
main: main.o canvas.o
$(CC) $(CFLAGS) -o main main.o canvas.o
main.o: main.c canvas.h
$(CC) $(CFLAGS) -c main.c -o main.o
canvas.o: canvas.c canvas.h
$(CC) $(CFLAGS) -c canvas.c -o canvas.o
clean:
rm -f main.o canvas.o color.o main