/ INSTRUCTIONS // ------------ // Compile this code. You should see 3 rectangles
ID: 3837864 • Letter: #
Question
/ INSTRUCTIONS
// ------------
// Compile this code. You should see 3 rectangles, one of which you can move
// with the 'w', 'a', 's', and 'd' keys.
//
// Read through this code! Try to understand it before starting the assignment.
// Comment confusing lines with what you think code is doing, and experiment
// with existing code to test your understanding.
// Once you feel comfortable with this code, accomplish each of the following,
// and make sure your code compiles and runs after each step is completed.
//
// 1) Get and set functions
// a) In Rect, create a get and set methods for "min" and "max". Use the
// signature "void setMin(Vec2 const & min)" and
// "void setMax(Vec2 const & max)". Use the "this" pointer to disambiguate
// "min" and "max".
// 1) Refactor userRect to be dynamic
// a) Make userRect a dynamic object. That means it should be declared as
// "Rect * userRect" instead of "Rect userRect". Use new to dynamically
// allocate.
// b) the member operator '.' will need to be replaced with the
// pointer-to-member operator '->'
// c) Don't forget to delete userRect at the end of the program!
// 2) Operator Overloading
// a) Overload the += operator for Vec2, and have it do exactly what
// Vec2::add does.
// b) Replace uses of Vec2::add with the += operator. For example, instead of
// "min.add(delta);", use "min += delta;".
// 3) Random rectangles, by reference and by pointer
// a) create a method with the method signature "void setRandom(Rect & r)".
// This function will give the passed-in Rect object a random location.
// The random x should be between 0 and 50 x. The random y should be
// between 0 and 20. Limit the possible width and height to a minimum of 2
// and a maximum of 10.
// b) test "void setRandom(Rect & r)" on the local Rect object "rect0".
// c) create a method with the method signature
// "void setRandomByPointer(Rect * r)", which functions the same as
// "void setRandom(Rect & r)", except that the argument is
// passed-by-pointer.
// d) test "void setRandomByPointer(Rect * r)" on the local Rect object
// "rect1".
// 4) Test and show overlap
// a) Using the existing function "isOverlapping(Rect const &)", test to see
// if userRect collides with any other Rect objects. If userRect is
// overlapping, draw it with '+' instead '#'.
// b) Create a Rect * pointer that points to the address if the Rect object
// that userRect collides with. It should point at NULL if userRect is
// colliding with no other Rect objects.
// c) Print to the screen the width and height of a Rect object that userRect
// collides with. If no collision is happening, print "no collision"
// instead.
// 5) Array of objects
// a) Replace the Rect objects rect0 and rect1 with an array of 2 Rect
// objects, "rect[2]".
// b) Make sure you replace every remaining "rect0" with "rect[0]", and every
// "rect1" with "rect[1]".
// c) Increase the size of the "rect" array to 5. Make sure all 5 Rect
// objects are randomized, drawn to the screen, and tested for collision.
// d) If you have not already done so, replace
// duplicate-code-using-array-elements with a for-loop. For example:
// If you have:
// rect[0].draw('0');
// rect[1].draw('1');
// rect[2].draw('2');
// rect[3].draw('3');
// rect[4].draw('4');
// Replace it with:
// for(int i = 0; i < NUMBER_OF_RECTS; i++)
// {
// rect[i].draw('0'+i);
// }
// Do this where objects are randomized, drawn, and tested for collision
Code:
#define NOMINMAX // prevent Windows API from conflicting with "min" and "max"
#include <stdio.h> // C-style output. printf(char*,...), putchar(int)
#include <windows.h> // SetConsoleCursorPosition(HANDLE,COORD)
#include <conio.h> // _getch()
/**
* moves the console cursor to the given x/y coordinate
* 0, 0 is the upper-left hand coordinate. Standard consoles are 80x24.
* @param x
* @param y
*/
void moveCursor(int x, int y)
{
COORD c = {x,y};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c);
}
struct Vec2
{
short x, y;
Vec2() : x(0), y(0) { }
Vec2(int x, int y) : x(x), y(y) { }
void add(Vec2 v)
{
x += v.x;
y += v.y;
}
};
class Rect
{
Vec2 min, max;
public:
Rect(int minx, int miny, int maxx, int maxy)
:min(minx,miny),max(maxx,maxy)
{}
Rect(){}
void draw(const char letter) const
{
for(int row = min.y; row < max.y; row++)
{
for(int col = min.x; col < max.x; col++)
{
if(row >= 0 && col >= 0)
{
moveCursor(col, row);
putchar(letter);
}
}
}
}
bool isOverlapping(Rect const & r) const
{
return !( min.x >= r.max.x || max.x <= r.min.x
|| min.y >= r.max.y || max.y <= r.min.y);
}
void translate(Vec2 const & delta)
{
min.add(delta);
max.add(delta);
}
};
int main()
{
// initialization
Rect userRect(7, 5, 10, 9);
Rect rect0(10, 2, 14, 4);
Rect rect1(1, 6, 5, 15);
int userInput;
do
{
// draw
rect0.draw('0');
rect1.draw('1');
moveCursor(0, 0); // re-print instructions
printf("move with 'w', 'a', 's', and 'd'");
userRect.draw('#');
// user input
userInput = _getch();
// update
Vec2 move;
switch(userInput)
{
case 'w': move = Vec2( 0,-1); break;
case 'a': move = Vec2(-1, 0); break;
case 's': move = Vec2( 0,+1); break;
case 'd': move = Vec2(+1, 0); break;
}
userRect.draw(' '); // un-draw before moving
userRect.translate(move);
}while(userInput != 27); // escape key
return 0;
Explanation / Answer
main.cpp
#define NOMINMAX // prevent Windows API from conflicting with "min" and "max"
#include <stdio.h> // C-style output. printf(char*,...), putchar(int)
#include <conio.h> // _getch()
#include <stdlib.h>
#include <time.h>
#include "Rectangle.h"
#include "Vector2.h"
#include "moveCursor.h"
/**
* moves the console cursor to the given x/y coordinate
* 0, 0 is the upper-left hand coordinate. Standard consoles are 80x24.
* @param x
* @param y
*/
void setRandom(Rect & r) // Chris Randall helped me understand with this part.
{
// srand(time(NULL)); mistake
int x = rand() % 50;
int y = rand() % 20 + 3;
int x2 = rand() % 8+2;
int y2 = rand()% 8 + 2;
Vec2 min(x,y);
r.setMin(min);
Vec2 max(x+x2, y+y2);
r.setMax(max);
}
void checkCollision(Rect &userRect, Rect * rect, int rectNum)
{
for(int i = 0; i < rectNum; i++)
{
if(userRect.isOverlapping( rect[i] ) ) // checks if player overlaps with other rects
{
userRect.draw('+');
moveCursor(40, 0);
printf("Collision");
}
}
}
int main()
{
srand(time(NULL));
const int Number_of_Rects = 5;
// initialization
Rect userRect(7, 5, 10, 9); // Controlled Square Size
Rect * rect = new Rect[Number_of_Rects]; // creates an array of 5 rectangles.
// Rect * rect1 = new Rect; // (1, 6, 5, 15)
// rect1->setRandomByPointer(rect1);
int userInput;
for(int i = 0; i < Number_of_Rects; i++) // sets 5 rectanges to a random position
{
setRandom(rect[i]);
}
do
{
// draw
for(int i = 0; i < Number_of_Rects; i++) // draw 5 rectangles that are numbered from 0 - 4
{
rect[i].draw('0'+i);
}
//rect1->draw('1');
moveCursor(0, 0); // re-print instructions
printf("move with 'w', 'a', 's', and 'd'");
userRect.draw('#');
moveCursor(40, 0);
printf("No Collision");
checkCollision(userRect, rect, Number_of_Rects); // collision detection. Prints "+" if player collides with other Rects
/*for(int i = 0; i < Number_of_Rects; ++i) // old collision detector
{
if(userRect.isOverlapping( rect[i] ) )
{
userRect.draw('+');
moveCursor(40, 0);
printf("Collision");
}
else
{
moveCursor(40, 0);
printf("No Collision");
}
}*/
// user input
userInput = _getch();
// update
Vec2 move;
switch(userInput) // takes userInput to move controlled rectangle
{
case 'w': move = Vec2( 0,-1); break;
case 'a': move = Vec2(-1, 0); break;
case 's': move = Vec2( 0,+1); break;
case 'd': move = Vec2(+1, 0); break;
}
userRect.draw(' '); // un-draw before moving
userRect.translate(move); // Draws square at new location
}while(userInput != 27); // escape key
delete [] rect;
return 0;
}
Rectangle.h
#pragma once
#include "Vector2.h"
#include "moveCursor.h"
class Rect
{
Vec2 min, max;
public:
Rect(int minx, int miny, int maxx, int maxy)
:min(minx,miny),max(maxx,maxy){}
Vec2 getMin()
{
return min;
}
Vec2 getMax()
{
return max;
}
void setMin(Vec2 const & min)
{
this->min = min;
}
void setMax(Vec2 const & max)
{
this->max = max;
}
Rect(){}
void draw(const char letter) const
{
for(int row = min.y; row < max.y; row++)
{
for(int col = min.x; col < max.x; col++)
{
if(row >= 0 && col >= 0)
{
moveCursor(col, row);
putchar(letter);
}
}
}
}
bool isOverlapping(Rect const & r) const
{
return !( min.x >= r.max.x || max.x <= r.min.x
|| min.y >= r.max.y || max.y <= r.min.y);
}
void translate(Vec2 & delta)
{
min += delta;
max += delta;
}
};
Vector2.h
#pragma once
struct Vec2
{
short x, y;
void operator+=(Vec2 & v){x += v.x; y += v.y;}
void operator-=(Vec2 & v){x -= v.x; y -= v.y;}
Vec2() : x(0), y(0) { }
Vec2(int x, int y) : x(x), y(y) { }
};
moveCursor.h
#pragma once
#include <windows.h> // SetConsoleCursorPosition(HANDLE,COORD)
void moveCursor(int x, int y)
{
COORD c = {x,y};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c);
}
Related Questions
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.