Skip to content

Instantly share code, notes, and snippets.

Created Apr 16, 2015
Embed
What would you like to do?
#include "console.h"
void Console::clear()
{
// Description: Clears the screen
COORD coordScreen = { 0, 0 };
DWORD cCharsWritten;
CONSOLE_SCREEN_BUFFER_INFO csbi;
DWORD dwConSize;
GetConsoleScreenBufferInfo(hConsole, &csbi);
dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
FillConsoleOutputCharacter(hConsole, TEXT(' '), dwConSize, coordScreen, &cCharsWritten);
GetConsoleScreenBufferInfo(hConsole, &csbi);
FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten);
SetConsoleCursorPosition(hConsole, coordScreen);
};
void Console::gotoXY(int x, int y)
{
// Precondition: two non-negative integer parameters for the x and y are provided
// Description: Moves the cursor to x, y in console window, i.e. x=left\right y=top\bottom
// Example: gotoXY(10, 10) moves the cursor to those coordinates
// gotoXY(0, 10) moves the cursor to those coordinates
// gotoXY(-1, 0), gotoXY(0, -1) and gotoXY(-1, -1) throws an exception
if(x<0||y<0)
{
std::cout << "Coordinates cannot be less than zero." << std::endl;
exit(1);
}
else
{
COORD point;
point.X = x;
point.Y = y;
SetConsoleCursorPosition(hConsole, point);
}
};
void Console::setColour(COLOUR foreground, COLOUR background)
{
int colour = background * 16 + foreground;
SetConsoleTextAttribute(hConsole, colour);
};
HANDLE Console::hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
#pragma once
#include <iostream>
#include <string>
#include <windows.h>
class Console
{
private:
static HANDLE hConsole;
public:
static enum COLOUR {BLACK, BLUE, GREEN, AQUA, RED, PURPLE, YELLOW, DEFAULT, GRAY, LIGHT_BLUE,
LIGHT_GREEN, LIGHT_AQUA, LIGHT_RED, LIGHT_PURPLE, LIGHT_YELLOW, WHITE };
static void clear();
// Description: Clears the screen
static void gotoXY(int x, int y);
// Precondition: two non-negative integer parameters for the x and y are provided
// Description: Moves the cursor to x, y in console window, i.e. x=left\right y=top\bottom
// Example: gotoXY(10, 10) moves the cursor to those coordinates
// gotoXY(0, 10) moves the cursor to those coordinates
// gotoXY(-1, 0), gotoXY(0, -1) and gotoXY(-1, -1) throw an exception
static void setColour(COLOUR foreground, COLOUR background);
// Precondition: an enumerated COLOUR foreground and background type for colour is required from
// BLACK, BLUE, GREEN, AQUA, RED, PURPLE, YELLOW, DEFAULT, GRAY, LIGHT_BLUE,
// LIGHT_GREEN, LIGHT_AQUA, LIGHT_RED, LIGHT_PURPLE, LIGHT_YELLOW, WHITE
// Postcondition: text foreground and background colour is changed to one of these 256 possibilities
// Description: changes the foreground and background text colour within the console window
// Example: setColour(BLACK, WHITE) changes the foreground text colour to black and the background to white.
};
#pragma once
#include "vertex.h"
#include "shape.h"
//#include "rhombus.h"
//#include "pentagon.h"
#include "console.h"
//#include "square.h"
#include "triangle.h"
#include <iostream>
#include <list>
#include <cmath>
using namespace std;
Console c;
void displayGrid();
int main()
{
list<Shape*> shapes;
// Uncomment code that adds shapes as you provide the required functionality.
// Complete the functionality for each 20 mark component before moving on to the next.
// You can add the scaling and rotation functionality at any time, but it has to be
// applied to at least one shape to earn their associated marks.
// Output a shape's area (5 marks) and perimeter (5 marks) next to its centroid.
// Examples of marking:
// - adding complete code for the Rhombus and Pentagon will receive 40 marks;
// - adding complete code for a Rhombus, rotation and scaling will also receive 40 marks;
// - adding complete code for a Rhombus, Pentagon and rotation will receive 50 marks;
// - adding the Rhombus without perimeter will receive 15 marks;
// - adding a complete Rhombus and the Pentagon without area will receive 35 marks.
// 20 marks
// add a rhombus and associated functionality
// shapes.push_back(new Rhombus(Vertex(20, 20), 8));
// adds a rhombus at centroid (x, y) of radius r
// 20 marks
// add a pentagon, its header, source files and associated functionality
// shapes.push_back(new Pentagon(Vertex(60,20),8));
// adds a pentagon at centroid (x, y) of radius r
// 20 marks
// add a octagon, its header, source files and associated functionality
// shapes.push_back(new Octagon(Vertex(20,60),8,6));
// adds a octagon at centroid (x, y) of radius r
// 20 marks
// add a circle, its header, source files and associated functionality
// shapes.push_back(new Circle(Vertex(60,60),8,6));
// adds a circle at centroid (x, y) of radius r
list<Shape*>::iterator itr = shapes.begin();
while(itr!=shapes.end())
{
(*itr)->drawShape();
shapes.push_back(new Triangle(Vertex(20, 20), 8));
// output shape statistics
// scale shape (double it)
// draw shape
// rotate shape by 20 degrees
// draw shape
itr++;
}
// marks for the following can only be earned if applied to at least one shape
// +10 marks
// add the scaling functionality to Shape
// scale each shape by a factor of 2 output them all
// +10 marks
// add the rotation functionality to Shape
// rotate each shape by a 20 degrees and output them all
system("pause");
return true;
}
void displayGrid()
{
c.clear();
c.gotoXY(0, 0);
c.setColour(c.WHITE, c.BLACK);
for (int y = 0; y < 20; y++)
{
for (int x = 0; x < 50; x++)
{
cout << ".";
}
cout << endl;
}
}
#include "shape.h"
Shape::Shape(Vertex point) : centroid(point)
{
// constructs a shape
}
void Shape::drawShape()
{
// plots each vertex and draws a line between them using Bresenham's algorithm
// you can adjust your console font and dimensions if you want to increase the resolution of your shapes
list<Vertex>::iterator current = vertices.begin();
list<Vertex>::iterator previous = vertices.begin();
while(current!=vertices.end())
{
Console::gotoXY((*current).getX(),(*current).getY());
cout << "*";
if(current!=vertices.begin())
drawLine((*current).getX(),(*current).getY(), (*previous).getX(),(*previous).getY());
previous = current;
current++;
}
previous = vertices.begin();
drawLine(vertices.back().getX(), vertices.back().getY(), vertices.front().getX(), vertices.front().getY());
}
void Shape::drawLine(int x1, int y1, int x2, int y2)
{
// Bresenham's line algorithm
// draws an approximation of a straight line between two points (x1, y1) and (x2, y2) of a grid
bool steep = (abs(y2 - y1) > abs(x2 - x1));
if(steep)
{
swap(x1, y1);
swap(x2, y2);
}
if(x1 > x2)
{
swap(x1, x2);
swap(y1, y2);
}
int dx = x2 - x1;
int dy = abs(y2 - y1);
float error = dx / 2.0f;
int ystep = (y1 < y2) ? 1 : -1;
int y = y1;
int maxX = x2;
for(int x=x1; x<maxX; x++)
{
if(steep)
{
Console::gotoXY(y,x);
cout << "*";
}
else
{
Console::gotoXY(x,y);
cout << "*";
}
error -= dy;
if(error < 0)
{
y += ystep;
error += dx;
}
}
}
void Shape::rotate(double degrees)
{
// rotates the vertices of a shape by a specified angle in degrees
//
// a simple method for rotating a point around 0,0 is
// x' = x * cos(degrees in radians) - y * sin(degrees in radians)
// y' = y * cos(degrees in radians) + x * sin(degrees in radians)
// first translate the object to the origin of the graph (0,0)
// then apply the rotation formula to each vertex of the shape
// finally, translate the object back to its original centroid
// remember that 0,0 is at the top left, not the bottom left, corner of the console
// this means that your shapes may appear upside down
// place your code here and add comments that describe your understanding of what is happening
}
void Shape::scale(double factor)
{
// scales the shape by a given factor
// requires a scaling factor as an input
// do not scale if the scaling factor would result in a shape that is outside of the boundaries of the grid
// place your code here and add comments that describe your understanding of what is happening
}
double Shape::round(double x)
{
// a method for rounding floating point numbers to the nearest integral
// use this if you want a better approximation for x and y in integer space
// use if the available version of C++ does not provide a round() function
if (ceil(x+0.5) == floor(x+0.5))
{
int a = (int) ceil(x);
if (a%2 == 0)
return ceil(x);
else
return floor(x);
}
else
return floor(x+0.5);
}
void Shape::outputStatistics()
{
// place your code here and add comments that describe your understanding of what is happening
}
#pragma once
#include "console.h"
#include "vertex.h"
#include <iostream>
#include <list>
#include <cstdlib>
#include <cmath>
using namespace std;
#define PI 3.14159265358979323846
class Shape
{
list<Vertex>::iterator itr;
protected:
list<Vertex> vertices;
Vertex centroid;
void drawLine(int x1, int y1, int x2, int y2);
Shape(Vertex point);
double round(double x);
public:
void drawShape();
virtual int area() = 0;
virtual int perimeter() = 0;
virtual void outputStatistics();
void rotate(double degrees);
void scale(double factor);
};
#include "triangle.h"
Triangle::Triangle(Vertex point, int radius) : Shape(point)
{
// constructs an equilateral triangle of radius around a point in 2D space
if((radius>centroid.getX()/2) || (radius>centroid.getX()/2))
{
cout << "Object must fit on screen." << endl;
system("pause");
exit(0);
}
this->radius = radius;
plotVertices();
}
int Triangle::area()
{
// returns the area of an equilateral triangle
return 0.433 * radius * radius;
}
int Triangle::perimeter()
{
// returns the perimeter of an equilateral triangle
return radius * 3;
}
void Triangle::plotVertices()
{
// a formula for rotating a point around 0,0 is
// x' = x * cos(degrees in radians) - y * sin(degrees in radians)
// y' = y * cos(degrees in radians) + x * sin(degrees in radians)
// the coordinates for point A are the same as the centroid adjusted for the radius
// the coordinates for point B are determined by rotating point A by 120 degrees
// the coordinates for point C are determined by rotating point A by 240 degrees
// remember that 0,0 is at the top left, not the bottom left, corner of the console
int x, y, _x, _y;
double radians;
x = centroid.getX();
y = centroid.getY()+radius;
vertices.push_back(Vertex(x,y));
x = vertices.back().getX() - centroid.getX();
y = vertices.back().getY() - centroid.getY();
radians = 120*PI/180;
_x = round(x * cos(radians) - y * sin(radians));
_y = round(y * cos(radians) + x * sin(radians));
_x = _x + centroid.getX();
_y = _y + centroid.getY();
vertices.push_back(Vertex(_x,_y));
radians = 240*PI/180;
_x = round(x * cos(radians) - y * sin(radians));
_y = round(y * cos(radians) + x * sin(radians));
_x = _x + centroid.getX();
_y = _y + centroid.getY();
vertices.push_back(Vertex(_x,_y));
}
#include "shape.h"
class Triangle : public Shape
{
int radius;
void plotVertices();
public:
Triangle(Vertex point, int radius = 10);
int area();
int perimeter();
};
#include "vertex.h"
Vertex::Vertex(int x, int y)
{
this->x = x;
this->y = y;
}
int Vertex::getX()
{
return x;
}
int Vertex::getY()
{
return y;
}
void Vertex::setX(int x)
{
this->x = x;
}
void Vertex::setY(int y)
{
this->y = y;
}
#pragma once
class Vertex
{
int x;
int y;
public:
Vertex(int x = 25, int y = 25);
int getX();
int getY();
void setX(int x);
void setY(int y);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment