初学者对类和函数有问题
Beginner having an issue with classes and functions
我是一个初学者程序员,在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(rect[0]);
rect[1].setRandom(& rect[1]);
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'); // drawing the 0 rectangle with an x width of 4 and a y height of 2
rect[1].draw('1'); // drawing the 1 rectangle with a x width of 4 and a y height of 9
moveCursor(0, 0); // re-print instructions
printf("move with 'w', 'a', 's', and 'd'");
userRect->draw('#'); // drawing the user rectangle in its starting location with a x width of 3 and a y height of 4
// 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
你有两个不同的setRandom()
方法,有三个问题。
-
每次
setRandom()
被调用时,srand()
也被调用。srand()
应该只被调用一次,当程序启动时——仔细阅读这个问题的第一个答案。 -
代码重复。两个
setRandom()
中的代码几乎相同。代码重复是不好的。重复的代码意味着,如果需要以某种方式更改算法,您将不得不记住在两个地方进行修改。或者三个地方。或者四个位置。或者代码中存在多少重复的代码块。你必须记住它们,然后找到它们。 -
与#2相同的问题,但对于"几乎相同"的部分。不同之处在于:
setRandom()
的第一个版本接受对另一个对象的引用,并修改通过引用传递的另一个对象。第二个版本的setRandom()
接受指向另一个对象的指针,而不是引用,但完全忽略它,并初始化this
,而不是指向的对象。
并且,由于这些错误,我们得到了您所看到的结果。
rect[0].setRandom(rect0);
这将初始化rect0
。rect[0]
被完全忽略,根本不初始化。
rect[1].setRandom(& rect1);
这将初始化rect[1]
。rect1
被完全忽略,根本不初始化。
这就是为什么代码的其余部分无法绘制rect[0]
。它根本不初始化。
显示的代码完全令人困惑,因为它有四个而不是两个对象。rect0、rect1和包含另外两个对象的rect[]
数组。在声明rect0和rect1之后,它们将被完全忽略,除了初始化失败之外,它们显然没有任何用途。
这里也没有任何真正的理由让setRandom()
接受指针或对其他对象的引用。setRandom()
的明显目的是随机初始化对象的尺寸。
所以它应该简单地随机初始化this
的维度。通过指针或引用传递其他对象根本没有意义。
然后,在去掉rect0
和rect1
之后,简单地调用单个setRandom()
方法…
rect[0].setRandom();
rect[1].setRandom();
…剩下的代码将继续并正确地绘制两个随机初始化的对象。
代码Rect rect[ rectSize ]
将创建5个矩形到数组rect,所有这些矩形都是min(0,0) max(0,0)(初始状态)。当你调用rect[ 0 ].setRandom( rect0 )
时,它将更新rect0(你通过引用传递它),而对rect[0]不做任何事情。当你调用rect[ 1 ].setRandom( &rect1 )
时,你更新rect[1](通过this->min)。x = posX -某个值)。所以你得到了rect[0]和rect[1]的差值
- 这个返回元素位置的基于循环的函数有什么问题?
- 我关于函数"Assert"的C++代码有问题
- 标准对此指向成员函数类型模板参数有何说明?是我的代码有误,还是 MSVS 16.6 有问题?
- C++类中的友元函数有问题?
- 在MySql中使用字符串操作函数有什么问题
- 我的重载函数有什么问题?
- std::函数有性能问题,如何避免?
- 这个子字符串函数有什么问题
- 虚拟 CTOR 的克隆函数实现是否有问题
- 我的基于可变模板的包装器函数有什么问题?
- 这个 c++ 模板函数有什么问题
- C++序列计算器x_{n+1} = f(x_n),数学函数有问题
- 通过初始化列表调用另一个类的构造函数.有问题
- 我的哈希函数有问题吗?
- 我无法创建公共继承的构造函数有问题C++
- 调用函数有问题
- 初学者对类和函数有问题
- c++的析构函数有问题
- 调用带指针的类函数有问题
- 在循环中使用cin函数有问题