初学者遇到类和函数程序的问题 [英] Beginner having an issue with classes and functions program

查看:54
本文介绍了初学者遇到类和函数程序的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是一名初学程序员,致力于c ++ visual studio 2015中的一个程序,它接受一个名为rect的类的实例,并将其传递给rect中的一个函数,该函数设置一个随机大小的矩形,并在某个虚构的板上放置一个控制台窗口。在代码的底部有关于代码需要做什么的完整说明。我遇到的问题是当程序打印矩形时,矩形0不打印但矩形为1。矩形rect0通过引用传递,rect1通过指针传递。



I am a beginner programmer working on a program in c++ visual studio 2015 that takes an instance of a class titled rect and passes it to a function within rect that sets a rectangle of random size and position somewhere on a imaginary board in a console window. At the bottom of the code there are full instructions on what the code needs to do. The problem I am having is when the program prints the rectangles, the rectangle of "0's" is not printing but the rectangle of "1's" is. The rectangle rect0 is being passed by reference and the rect1 is being passed by pointer.

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



What I have tried:

I have tried adding a & to the rect0 in parenthesis

rect[0].setRandom(rect0);



但这只使代码使用指针函数而不是引用函数。


but this only made the code use the pointer function instead of the reference function.

推荐答案

首先,在指令中,表示使用指针的函数应该被称为 setRandomByPointer 。通过这样做,它可能会帮助您知道调用哪个函数。



但是如解决方案1中所述,可以使两个函数具有相同的名称和编译器可以找出要调用哪一个。



然后你好像没有正确地完成一些步骤或者没有按顺序执行它们...似乎也取决于以前的作业。有些东西似乎来自无处...



作为旁注,通常非静态成员函数可以在自己的矩形上运行。



顺便说一句,如果我们比较你的2个函数,我们可以看到第一个函数对参数进行操作( r ) :

First of all, in the instruction it is said that the function working with pointers should be called setRandomByPointer. By doing so, it might help you know which function is called.

But as mentioned in solution 1, it would be possible to have both functions having the same name and the compiler would be able to figure out which one to call.

Then it seems that you have not properly done some steps or not doing them in order... It also seems to depends on a previous homework. And some stuff seems to come from nowhere...

As a side note, normally a non static member function would operate on its own rectangle.

And by the way, if we compare your 2 functions, we can see that the first one operate on the argument (r):
r.min.x = pos_x - width;
...



而第二个操作对象本身( this ):


while the second one operate on the object itself (this) :

this->min.x = posX - widthPoint;
...





在你的作业中,你需要处理指令中指定的参数。在现实世界中,没有人会这样做,因为它是最令人困惑的方式(你在一个实例上调用函数但更新参数中传递的函数)。



In your homework, you need to work on the argument as specified in the instruction. In real world, no one would do that as it is the most confusing way to do that (you call the function on one instance but update the one passed in argument).


你必须学习c ++语言的两个重要概念:重载和类概念。



这意味着 this 始终是调用该方法的对象。这里有一些教程



如果你重载一个函数是什么意味着该函数具有相同名称但不同的调用参数编译器对其使用的参数有所了解。它使代码不清晰和棘手,所以有时候重命名一个函数会更好。一些教程是这里



我做重载只有不同的参数计数,例如:

You must learn two important concepts of the c++ language: overloading and class concept.

It means that this is always the object on which the method is called. Here is some tutorial.

If you overload an function what means that function have the same name but different call parameters the compiler desides on the parameter which it uses. It makes code unclear and tricky, so sometimes it is better to rename one function. Some tutorial is here.

I do overloading only with a different count of parameters like:
int DoStuff(char* p);
int DoStuff(char* p, int count);


这篇关于初学者遇到类和函数程序的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆