Member 12833480 Ответов: 2

Новичок, имеющий проблемы с классами и функциями программы


Я начинающий программист, работающий над программой на c++ visual studio 2015, которая берет экземпляр класса под названием rect и передает его функции внутри rect, которая устанавливает прямоугольник случайного размера и положения где-то на воображаемой доске в окне консоли. В нижней части кода есть полные инструкции о том, что код должен делать. Проблема, с которой я сталкиваюсь, заключается в том, что когда программа печатает прямоугольники, прямоугольник "0" не печатается, а прямоугольник "1" печатается. Прямоугольник rect0 передается по ссылке, а rect1-по указателю.

/*
iLab2: rectangles
*/

#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()
#include <time.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 moveCursor(int x, int y)
{
	COORD c = { x,y };
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c);
}

struct Vec2
{
	short x, y;		// variables x and y for storing rectangle coordinates
	Vec2() : x(0), y(0) { }		// default constructor for vect2 if no parameters are specified
	Vec2(int x, int y) : x(x), y(y) { } // default constructor for vect2 if parameters are given
	void operator+=(Vec2 v)		// function for adding or subtracting (if v is negative) to move the rectangle
	{
		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);
				}
			}
		}
	}

	void setMax(int maxx, int maxy)
	{
		this->max.x = maxx;
		this->max.y = maxy;
	}

	void setMin(int minx, int miny)
	{
		this->min.x = minx;
		this->min.y = miny;
	}
	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+=(delta);
		max+=(delta);
	}
	void setRandom(Rect & r);
	void setRandom(Rect* r);
};


void Rect::setRandom(Rect & r)
{
	srand(time(NULL));		// added to make the random placement and size of the rect different each time program runs
	int pos_x, pos_y, height, width;
	pos_x = rand() % 51;
	pos_y = rand() % 21;

	height = 2 + rand() % 11;
	width = 2 + rand() % 11;

	height = height / 2;
	width = width / 2;

	r.min.x = pos_x - width;
	r.min.y = pos_y - height;
	r.max.x = pos_x + width;
	r.max.y = pos_y + height;
}
void Rect::setRandom(Rect * r)
{
	srand(time(NULL));		// added to make the random placement and size of the rect different each time program runs
	int posX, posY, heightPoint, widthPoint;
	posX = rand() % 51;
	posY = rand() % 21;

	heightPoint = 2 + rand() % 11;
	widthPoint = 2 + rand() % 11;

	heightPoint = heightPoint / 2;
	widthPoint = widthPoint / 2;

	this->min.x = posX - widthPoint;
	this->min.y = posY - heightPoint;
	this->max.x = posX + widthPoint;
	this->max.y = posY + heightPoint;
}

int main()
{
	// initialization
	//Rect userRect(7, 5, 10, 9);		// (x-min, y-min, x-max, y-max) x-min how far left the rectange can be
	//Rect rect0(10, 2, 14, 4);		// (x-min, y-min, x-max, y-max)
	//Rect rect1(1, 6, 5, 15);		// (x-min, y-min, x-max, y-max)
	//Rect userRect;
	Rect * userRect;
	Rect rect0;
	Rect rect1;
	const int rectSize = 5;
	Rect rect[rectSize];


	userRect = new Rect();
	// set
	rect[0].setRandom(rect0);
	rect[1].setRandom(& rect1);
	userRect->setMin(7, 5);
	userRect->setMax(10, 9);
	//rect0.setMin(10, 2);
	//rect0.setMax(14, 4);
	//rect1.setMin(1, 6);
	//rect1.setMax(5, 15);
	int userInput;

	do
	{
		// draw
		rect[0].draw('0');	
		//rect[1].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;		// Moves the user Rectangle -y or up on the screen
		case 'a':	move = Vec2(-1, 0);	break;		// Moves the user Rectangle -x or left on the screen
		case 's':	move = Vec2(0, +1);	break;		// Moves the user Rectangle +y or down on the screen
		case 'd':	move = Vec2(+1, 0);	break;		// Moves the user Rectangle +x or right on the screen
		}
		userRect->draw(' ');	// un-draw before moving
		userRect->translate(move);		// moves the user rectangle to the new location
	} while (userInput != 27); // escape key
	delete userRect;	// delete dynamic object to release memory
	return 0;
}

// INSTRUCTIONS
// ------------
// 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


Что я уже пробовал:

Я попытался добавить & к rect0 в скобках
rect[0].setRandom(rect0);

но это только заставило код использовать функцию указателя вместо функции ссылки.

Richard MacCutchan

Вы должны указать нам на фактический код, который терпит неудачу, и объяснить, что должно произойти.

2 Ответов

Рейтинг:
4

KarstenK

Вы должны изучить два важных понятия языка c++: перегрузка и понятие класса.

Это означает, что этот всегда является объектом, на котором вызывается метод. Вот некоторые из них руководство.

Если вы перегружаете функцию, что означает, что эта функция имеет одно и то же имя, но разные параметры вызова компилятор выбирает параметр, который он использует. Это делает код неясным и сложным, поэтому иногда лучше переименовать одну функцию. Какой-то учебник есть здесь.

Я делаю перегрузку только с другим количеством параметров, таких как:

int DoStuff(char* p);
int DoStuff(char* p, int count);


Philippe Mori

В соответствии с назначением ожидается вызов функции, работающей с указателем setRandomByPointer Таким образом, хотя вы правы в том, что понимание перегрузки важно, оно не обязательно для этого проекта.

Рейтинг:
19

Philippe Mori

Прежде всего, в инструкции сказано, что должна быть вызвана функция, работающая с указателями setRandomByPointer Таким образом, это может помочь вам узнать, какая функция вызывается.

Но, как уже упоминалось в решении 1, можно было бы иметь обе функции с одинаковым именем, и компилятор смог бы выяснить, какую из них вызвать.

Тогда кажется, что вы неправильно сделали какие-то шаги или делаете их не по порядку... Это также, по-видимому, зависит от предыдущего домашнего задания. И некоторые вещи, кажется, приходят из ниоткуда...

Кроме того, обычно нестатическая функция-член будет работать на своем собственном прямоугольнике.

И кстати, если мы сравним ваши 2 функции, то увидим, что первая работает на аргументе (r):

r.min.x = pos_x - width;
...

в то время как второй работает на самом объекте (this) :
this->min.x = posX - widthPoint;
...


В вашем домашнем задании вам нужно работать над аргументом, как указано в инструкции. В реальном мире никто бы этого не сделал, так как это самый запутанный способ сделать это (вы вызываете функцию в одном экземпляре, но обновляете тот, который передан в аргументе).