Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

/ 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);
}