随机漫步程序——矢量类及其实现

矢量类声明`

#ifndef VECTOR_H_
#define VECTOR_H_

#include<iostream>
namespace VECTOR
{
	class Vector
	{
	public:
		enum  Mode {RECT , POL};
		//枚举变量Mode, 默认RECT = 0, POL = 1
		//RECT标识直角坐标系 , POL标识极坐标系
	private:
		double x;
		double y;
		double mag;
		double ang;
		Mode mode;  //状态成员 ,控制构造函数、reset()方法、运算符重载函数使用那种形式
		            //这种成员是描述对象所处的状态
	 //一些供类内部使用的私有的方法
		void set_mag();
		void set_ang();
		void set_x();
		void set_y();
	public:
		Vector();
		Vector(double n1, double n2, Mode form = RECT);
		void reset(double n1, double n2, Mode form = RECT);
		//这里提供的方法可以直接修改对象的属性
		//显式的使用有参的构造函数也可以实现同样的目标
		//Vector shove = Vector(100, 300); 但是使用构造函数修改属性,这里创建了一个临时对象,然后将其赋给shove
		~Vector() {}

		//以下是几个 内联的 常函数
		double xval() const { return x; }
		double yval() const { return y; }
		double magval() const { return mag; }
		double angval() const { return ang; }

		//设置直角坐标/极坐标模式
		void polar_mode() { mode = POL; }
		void rect_mode() { mode = RECT; }

		//运算符重载
		//使用可以构造函数实现可以同时完成对矢量两种表达方式的修改
		Vector operator+(const Vector& b) const; //形参的const确保对象b不被修改,常函数的const确保调用该函数的对象的属性不被修改。这样就去确保了调用者和传入对象都不会被修改
		Vector operator-(const Vector& b) const;
		Vector operator-() const;  // - 运算符进行两次重载
		Vector operator*(double n) const;

		//非成员的友元函数
		friend Vector operator*(double n, const Vector& a); //这里用来调整乘法的顺序,与上面成员函数相反的相乘顺序也能运行
		friend std::ostream& operator<<(std::ostream& os, const Vector& v); //返回引用,链式编程
	};
}
#endif // !VECTOR_H_

矢量类方法实现

#include "Vector.h"
#include<cmath>
using std::sqrt;
using std::sin;
using std::cos;
using std::atan;   // (x)
using std::atan2;  // (y/x)  返回值都是弧度
using std::cout;

namespace VECTOR
{
	const double Rad_to_Deg = 45.0 / atan(1.0);
	// should be about 57.2957795130823


	//以下是四个私有方法,用来设置属性
	void Vector::set_mag()
	{
		mag = sqrt(x * x + y * y);
	}

	void Vector::set_ang()
	{
		if (x == 0.0 && y == 0.0)
		{
			ang = 0.0;
		}
		else
		{
			ang = atan2(y, x);
		}
	}

	void Vector::set_x()
	{
		x = mag * cos(ang);
	}

	void Vector::set_y()
	{
		y = mag * sin(ang);
	}

	//公有方法

	//默认构造
	Vector::Vector()
	{
		x = y = mag = ang = 0.0;
		mode = RECT;
	}

	//用于初始化
	Vector::Vector(double n1, double n2, Mode form )
	{
		mode = form;  //设置模式
		if (mode == RECT)
		{
			x = n1;
			y = n2;
			set_mag();
			set_ang();
		}
		else if (mode == POL)
		{
			mag = n1;
			ang = n2;
			set_x();
			set_y();
		}
		else
		{
			cout << "第三个参数错误,将向量置0";
			x = y = mag = ang = 0.0;
			mode = RECT;
		}

	}

	//用于修改对象
	void Vector::reset(double n1, double n2, Mode form )
	{
		mode = form;  //设置模式
		if (mode == RECT)
		{
			x = n1;
			y = n2;
			set_mag();
			set_ang();
		}
		else if (mode == POL)
		{
			mag = n1;
			ang = n2;
			set_x();
			set_y();
		}
		else
		{
			cout << "第三个参数错误,将向量置0";
			x = y = mag = ang = 0.0;
			mode = RECT;
		}
	}


	//运算符重载
	Vector Vector::operator+(const Vector& b) const
	{
		//这里描述的是两个矢量相加,使用构造函数来完成最简单、最可靠
		//注意:这里使用的是默认直角模式,可以同时修改x,y和幅值极角
		//这里仅仅是为了修改属性的值,所以用哪种模式无所谓
		return Vector(this->x + b.x, this->y + b.y);
		//这里使用有参构造函数创建了一个无名的新对象,并返回了该对象的副本
		//这确保了新对象是根据构造函数制定的标准创建的。
	}
	/*********************************************************
	如果某方法通过计算得到了一个新的类对象,则应考虑该方法是否能通过
	调整传入参数来使用构造函数来实现,这样实现最简洁、可靠、正确。
	**********************************************************/

	//用下面这种方法完成也是一样的,但是比较麻烦
	/**********************************************
	Vector Vector::operator+(const Vector& b) const
	{
		Vector sum;
		sum.x = this->x + b.x;
		sum.y = this->y + b.y;
		sum.set_mag();
		sum.set_ang();
		return sum;   //值传递方式返回一个新对象
	}
	***********************************************/

	//-运算符可以进行量操作数相减和单操作数取反两种操作,所以这里进行两种重载

	//向量相减
	Vector Vector::operator-(const Vector& b) const
	{
		return Vector(this->x - b.x, this->y - b.y);
	}
	//向量取反
	Vector Vector::operator-() const
	{
		return Vector(-this->x , -this->y );
	}

	//相乘顺序为 a * n; 并返回一个无名新对象的拷贝 
	Vector Vector::operator*(double n) const
	{
		return Vector(this->x * n, this->y * n);
	}

	//使用一个非成员友函数来 允许不同的相乘顺序 ,n * a
	Vector operator*(double n, const Vector& a)
	{
		return  a * n;  //调用成员函数实现的运算符重载,这种写法最简洁
	}

	//返回对象本身,(os << v) == os , (os << v2) == os , ...  链式编程
	std::ostream& operator<<(std::ostream& os, const Vector& v)
	{
		if (v.mode == Vector::RECT)
			os << "(x,y) = (" << v.x << ", " << v.y << ")";
		else if (v.mode == Vector::POL)
		{
			os << "(m,a) = (" << v.mag << ", "
				<< v.ang * Rad_to_Deg << ")";
		}
		else
			os << "Vector object mode is invalid";
		return os;
	}

}

醉鬼漫步程序

#include<iostream>
#include<cstdlib>    //rand() , srand(), prototype
#include<ctime>     //time() prototype
#include<fstream>
#include"Vector.h"
int main()
{
	using namespace std;
	using VECTOR::Vector;  //使用using声明使名称空间中的类可用

	srand(time(0));  //随机数种子
	double direction;
	Vector step;                //记录每一步的情况(矢量表示)
	Vector resualt(0.0, 0.0);  //使用resualt矢量记录前进情况
	unsigned long steps = 0;   //记录行走的步数
	double dstep;              //用户输入的步长
	double target;

	ofstream fout;
	fout.open("thewalk.txt");

	cout << "Enter target distance (q to quit): ";   
	while (cin >> target)    //这里其实没有做q退出的功能,不是数字就退出
	{
		cout << "Enter the step length: ";
		if (!(cin >> dstep))  //输入dstep ,并对可能发生的进行错误处理   
		{
			break;      
		}

		while (resualt.magval() < target)
		{
			direction = rand() % 360;   //获取0-359的角度值
			step.reset(dstep, direction, Vector::POL);
			resualt = resualt + step;  //使用resualt矢量记录前进情况,这里将矢量设置为直角坐标模式
			steps++;
		}
		cout << "After " << steps << " steps, the subject has the following location:\n";
		cout << resualt << endl;
		resualt.polar_mode();
		cout << "or\n" << resualt << endl;
		cout << "Average outwards distance per step = " << resualt.magval() / steps << endl;

		fout << resualt << endl;  //写入到文件中,其实是调用友元函数operator<<(fout,result)

		steps = 0;
		resualt.reset(0.0, 0.0);
		cout << "Enter target distance (q to quit): ";
	}
	cout << "Bye!\n";
	cin.clear();
	while (cin.get() != '\n')   //等待回车键
		continue;
	return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值