Projeto: gerenciador de tela polimórfico usando a hierarquia Forma. Desenvolva um pacote gráfico básico. Use a hierarquia Forma implementada no Exercício 21.13. Limite-se a formas bidimensionais, como quadrados, retângulos, triângulos e círculos. Interaja com o usuário. Permita que o usuário especifique a posição, o tamanho, a forma e os caracteres de preenchimento a serem usados no desenho de cada forma. O usuário pode especificar mais de uma da mesma forma. Ao criar cada forma, coloque um ponteiro Forma * para cada novo objeto Forma em um array. Cada classe Forma agora deverá ter sua própria função-membro desenhar. Escreva um gerenciador de tela polimórfico que atravesse o array, enviando mensagens desenhar a cada objeto no array para formar uma imagem na tela. Redesenhe a imagem da tela toda vez que o usuário especificar uma forma adicional.
Passo 1
Vamos criar um aplicativo orientado a menus que permite ao usuário desenhar uma das quatro formas em uma matriz.
Vamos começar definindo as classes de forma.
Classe base de forma
A classe é uma classe abstrata pura que contém uma função usada para desenhar uma certa forma em uma matriz de um tamanho específico.
#ifndef H_SHAPE_H
#define H_SHAPE_H
#include
#include
using namespace std;
class Shape {
public:
virtual void draw(char**, int, int) const = 0;
};
#endif
Forma bidimensional
Essa classe conterá as propriedades de caractere de posição e preenchimento.
Declaração de classe:
#ifndef H_TWODIMENSIONALSHAPE_H
#define H_TWODIMENSIONALSHAPE_H
#include "Shape.h"
class TwoDimensionalShape : public Shape {
public:
TwoDimensionalShape(int xPos, int yPos,
char fillCharacter);
int getXPos() const;
void setXPos(int xPos);
int getYPos() const;
void setYPos(int yPos);
char getFillCharacter() const;
void setFillCharacter(char fillCharacter);
protected:
int xPos;
int yPos;
char fillCharacter;
};
#endif
Implementação da classe:
#include "TwoDimensionalShape.h"
TwoDimensionalShape::TwoDimensionalShape(
int xPos, int yPos, char fillCharacter)
: xPos(xPos), yPos(yPos),
fillCharacter(fillCharacter) {}
int TwoDimensionalShape::getXPos() const {
return xPos;
}
void TwoDimensionalShape::setXPos(int xPos) {
TwoDimensionalShape::xPos = xPos;
}
int TwoDimensionalShape::getYPos() const {
return yPos;
}
void TwoDimensionalShape::setYPos(int yPos) {
TwoDimensionalShape::yPos = yPos;
}
char TwoDimensionalShape::getFillCharacter() const {
return fillCharacter;
}
void TwoDimensionalShape::setFillCharacter(
char fillCharacter) {
TwoDimensionalShape::fillCharacter = fillCharacter;
}
Passo 2
Círculo
Esta classe contém o comprimento do raio do círculo, bem como sua própria implementação da função draw().
#ifndef H_CIRCLE_H
#define H_CIRCLE_H
#include "TwoDimensionalShape.h"
class Circle : public TwoDimensionalShape {
public:
explicit Circle(int xPos, int yPos, char fill,
double radius);
void draw(char** arr, int row, int col) const;
private:
double radius;
};
#endif
Usamos a fórmula do círculo para desenhar o círculo. Iremos percorrer as coordenadas da matriz, verificando se uma coordenada está dentro ou na borda do círculo.
Fórmula do círculo:
#include "Circle.h"
Circle::Circle(int xPos, int yPos,
char fill, double radius)
: TwoDimensionalShape(xPos, yPos, fill),
radius(radius) {}
void Circle::draw(char** arr, int row, int col) const {
for (int i = 0; i
for (int j = 0; j
if (pow(i - yPos, 2.0) + pow(j - xPos, 2.0)
arr[i][j] = fillCharacter;
}
Retângulo
Declaração de classe:
#ifndef H_RECTANGLE_H
#define H_RECTANGLE_H
#include "TwoDimensionalShape.h"
class Rectangle : public TwoDimensionalShape {
public:
Rectangle(int xPos, int yPos, char fill,
double a, double b);
void draw(char** arr, int row, int col) const;
protected:
double a;
double b;
};
#endif
Para desenhar retângulos, vamos iterar o comprimento e a largura do retângulo, definindo as coordenadas para o caractere de preenchimento (observe que estamos definindo o canto superior esquerdo do retângulo como nosso ponto de partida):
Implementação da classe:
#include "Rectangle.h"
Rectangle::Rectangle(int xPos, int yPos,
char fill, double a, double b)
: TwoDimensionalShape(xPos, yPos, fill), a(a), b(b) {}
void Rectangle::draw(char **arr, int row, int col) const {
for (int i = 0; i
for (int j = 0; j
if (yPos + i
arr[yPos + i][xPos + j] = fillCharacter;
else
{
cout
exit(1);
}
}
Passo 3
Praça
Essa classe herdará todos os comportamentos e propriedades necessários da classe Rectangle.
Declaração de classe:
#ifndef H_SQUARE_H
#define H_SQUARE_H
#include "Rectangle.h"
class Square : public Rectangle {
public:
explicit Square(int xPos, int yPos, char fill,
double a);
};
#endif
#include "Square.h"
Square::Square(int xPos, int yPos,
char fill, double a)
: Rectangle(xPos, yPos, fill, a, a) {}
Triângulo
Declaração de classe:
#ifndef H_TRIANGLE_H
#define H_TRIANGLE_H
#include "TwoDimensionalShape.h"
class Triangle : public TwoDimensionalShape {
public:
Triangle(int xPos, int yPos, char fill,
double a);
void draw(char** arr, int row, int col) const;
protected:
double a;
};
#endif
Para desenhar triângulos, vamos iterar pelas linhas para o comprimento do lado, incrementando o comprimento do tamanho da coluna a cada iteração.
Implementação da classe:
#include "Triangle.h"
Triangle::Triangle(int xPos, int yPos,
char fill, double a)
: TwoDimensionalShape(xPos, yPos, fill),
a(a) {}
void Triangle::draw(char **arr, int row, int col) const {
for (int i = 0; i
for (int j = 0; j
if (yPos + i
arr[yPos + i][xPos + j] = fillCharacter;
else
{
cout
exit(1);
}
}
Passo 4
Gerenciador de tela
Esta classe é uma interface para o usuário, também usada como classe de driver.
Funcionalidades:
clear() aloca nova memória para a matriz arr (desaloca antes, se necessário)
draw() desenha formas atuais dentro do vetor de formas na matriz arr
display() gera a matriz (os "gráficos")
função de driver run()
Declaração de classe:
#ifndef H_SCREENMANAGER_H
#define H_SCREENMANAGER_H
#include
#include "Shape.h"
class ScreenManager {
public:
ScreenManager();
void clear();
void draw();
void display();
bool run();
private:
char** arr;
vector
const int ROW = 30;
const int COL = 30;
};
#endif
Agora, vamos implementar a classe.
Em primeiro lugar, o cabeçalho do arquivo junto com a implementação do construtor:
#include
#include "ScreenManager.h"
#include "Circle.h"
#include "Triangle.h"
#include "Square.h"
using namespace std;
ScreenManager::ScreenManager() {
clear();
}
...
A implementação da função clear():
void ScreenManager::clear() {
if (arr != nullptr)
{
for (int i = 0; i
delete[] arr[i];
delete[] arr;
}
arr = new char*[ROW];
for (int i = 0; i
arr[i] = new char[COL]();
}
Para exibir a matriz:
Limpe a matriz (caso já haja algo escrito nela)
Escreva formas atuais
Saída
void ScreenManager::display() {
clear();
for (Shape* shape : shapes)
shape->draw(arr, ROW, COL);
for (int i = 0; i
{
for (int j = 0; j
cout
cout
}
}
A implementação da função draw().
Em primeiro lugar, solicite ao usuário informações básicas:
void ScreenManager::draw() {
cout
> ";
int shape, xPos, yPos;
char fill;
cin >> shape;
cout > ";
cin >> xPos >> yPos;
cout > ";
cin >> fill;
cin.ignore();
...
}
Com base na forma inserida, solicite informações adicionais ao usuário e, por fim, insira uma forma correspondente no vetor:
void ScreenManager::draw() {
...
if (shape == 1)
{
double radius;
cout > ";
cin >> radius;
shapes.push_back(
new Circle(xPos, yPos, fill, radius)
);
}
else if (shape == 2)
{
double a, b;
cout > ";
cin >> a >> b;
shapes.push_back(
new Rectangle(xPos, yPos, fill, a, b)
);
}
else if (shape == 3 || shape == 4)
{
double a;
cout > ";
cin >> a;
if (shape == 3)
shapes.push_back(
new Square(xPos, yPos, fill, a)
);
else
shapes.push_back(
new Triangle(xPos, yPos, fill, a)
);
}
else
cout
}
Por fim, a função do driver que exibe as opções básicas do menu e solicita que o usuário insira uma opção:
bool ScreenManager::run() {
cout
> ";
int choice;
cin >> choice;
if (choice == 1)
draw();
else if (choice == 2)
display();
else if (choice == 3)
shapes.clear();
else if (choice == 0)
return false;
else
cout
return true;
}
Observação: o valor de retorno é usado para determinar se o aplicativo deve terminar.
O main:
#include "ScreenManager.h"
using namespace std;
int main()
{
ScreenManager screenManager;
while(screenManager.run());
}
Resposta
Ver todo o desenvolvimento.