2022级吉林大学面向对象第二次上机测试

【注:解答全部为本人所写,仅供同学们学习时参考使用,请勿照搬抄袭!】

类的抽象、类的数据表示、类的实现、对象的使用

1、使用伪随机数加密的算法,按要求实现:
伪随机数加密的算法:根据一个给定的伪随机数种子,就可以得到无穷多个伪随机数。
伪随机数种子固定,得到的这个伪随机数数列就是固定的。

设有一个要加密的数列,X0,X1,X2,X3,…,也称明文,
一个给定的伪随机数种子 Seed.

加密:
根据种子Seed,可得到伪随机数数列 Y0,Y1,Y2,Y3,…,
通过计算可得到另一个数列,Z0,Z1, Z2, Z3,…,
其中Zi=Xi XOR Yi,(Xi 异或 Yi)
这样Zi数列就是一个对原始数列X0,X1,X2,X3,…的加密,
Z0,Z1, Z2, Z3,…,也称密文,seed就是密钥。

解密:
根据种子Seed,仍可得到伪随机数数列 Y0,Y1,Y2,Y3,…,
同上通过计算可得到另一个数列,X0,X1, X2, X3,…,
其中Xi=Yi XOR Zi,(Yi 异或 Zi),
这样Xi数列就是一个对加密数列Z0,Z1,Z2,Z3,…的解密,
Xi就是加密前的明文。
下面的TRandom类是用线性调和算法,实现的一个伪随机数发生器,仔细阅读代码,理解其含义。
线性调和算法的基本原理是:对于给定的N、M和K,任给一个X,
不断用X=((N*X+M) mod K )进行迭代计算,那么得到的无穷多个x值,
近似于在(0,K)上的均匀分布.其中N,M,K为较大的数(N最好是素数).

#include <limits.h> //声明INT_MAX和ULONG_MAX常量
#include <windows.h> //声明GetTickCount()函数,其返回从开机到现在经过的毫秒数
//#include <stdlib.h> //声明rand和srand函数
//#include <time.h> //声明time函数
class TRandom
{
public:
//缺省使用系统时间(开机后经过的毫秒数)为种子
TRandom (long seed=0) { mSeed=(seed?seed: GetTickCount()); }

//也可以定义自己的种子
void Seed(long seed=0)	{ mSeed=(seed?seed: GetTickCount( )); }     

//取得一个随机的整数
int  Integer()  			  { return Next();}        

//取得一个在指定范围内的随机整数
int  Integer(int min,int max) { return min+Next()%(max-min+1);} 

	//取得一个随机的(0到1之间的)小数
double Real() 				{return double(Next())/double(INT_MAX);}

private:
//使用调和算法
void Change() {mSeed=(314159265*mSeed+13579)%ULONG_MAX;}

	//取得伪随机数发生器的随机数序列中的下一个随机整数
int  Next() { 
            int loops=mSeed%3;	
            for (int i=0;i<=loops;i++)  
                Change ();
	return int(mSeed/2); 
        }
unsigned long  mSeed;   //随机数发生器的种子

};

1)利用上面提到的TRandom类,实现指定全局函数,以便完成字节数组的加密和解密。
void Coder(unsigned char data[],int len, unsinged long key);

void Coder(unsigned char data[], int len, unsigned long key) {
TRandom rand(key);
    for (int i = 0; i < len; i++) {
        data[i] ^= rand.Integer() % 256;  
    }

2)利用上面提到的TRandom类,实现指定全局函数,以便完成字节数组的加密和解密。
void Coder(unsigned char data[],int len, TRandom& rand, unsinged long key);

void Coder(unsigned char data[], int len, TRandom& rand, unsigned long key) {
    rand.Seed(key);
    for (int i = 0; i < len; i++) {
        data[i] ^= rand.Integer() % 256;
    }
}


 void Decoder(unsigned char data[], int len, TRandom& rand, unsigned long key) {
    rand.Seed(key);
    for (int i = 0; i < len; i++) {
        data[i] ^= rand.Integer() % 256;
    }
}

3)将第二问中的TRandom& rand,改成TRandom rand,结果改变了吗?为什么?

 结果不变。因为在函数中对rand修改时,实际上修改的是原对象而非传递的副本。

4)将第二问中的TRandom& rand,改成const TRandom& rand,行吗?为什么?

不可行,每生成一次随机数mSeed都会改变

5)如何定义一个加密/解密器类(Crypter),来实现同样功能呢?

class Crypter {
public:
    Crypter(unsigned long key) : rand(key) {}

    void encode(unsigned char data[], int len) {
        for (int i = 0; i < len; i++) {
            data[i] ^= rand.Integer() % 256;
        }
    }

    void decode(unsigned char data[], int len) {
        for (int i = 0; i < len; i++) {
            data[i] ^= rand.Integer() % 256;
        }
    }

private:
    TRandom rand;
};


使用示例:
Crypter crypter(12345); // 初始化加密/解密器,指定密钥为12345
unsigned char data[] = "Hello World!"; // 待加密/解密的数据
int len = sizeof(data) - 1; // 数据长度

crypter.encode(data, len); // 加密
printf("%s", data);

crypter.decode(data, len); // 解密
printf("%s", data);

2.练习根据给定的描述,抽象出类,给出适当的数据成员和成员函数,并给出具体的类定义和实现。

书的主要功能有:取得总页数;今天读了指定页数;取得累计读了多少页;取得剩余多少也未读;

类定义:
class Book {
private:
  int totalPages;
  int pagesReadToday;
  int pagesReadTotal;
public:
  Book(int totalPages);
  int getTotalPages();
  void readPages(int pages);
  int getPagesReadToday();
  int getPagesReadTotal();
  int getPagesLeft();
};

类实现:
Book::Book(int totalPages) {
  this->totalPages = totalPages;
  this->pagesReadToday = 0;
  this->pagesReadTotal = 0;
} //构造函数,初始化书的总页数为totalPages,累计读的页数和今天读的页数为0

int Book::getTotalPages() {
  return this->totalPages;
}//返回书的总页数

void Book::readPages(int pages) {
  this->pagesReadToday += pages;
  this->pagesReadTotal += pages;
}//将今天读的页数加上pages,累计读的页数也加上pages


int Book::getPagesReadToday() {
  return this->pagesReadToday;
}//返回今天读的页数


int Book::getPagesReadTotal() {
  return this->pagesReadTotal;
}//返回累计读的页数


int Book::getPagesLeft() {
  return this->totalPages - this->pagesReadTotal;
}//返回剩余未读的页数

3、请给出Card类的定义和实现:
只用一副无大小王的扑克,扑克的花色(suit)分为 Spade、Heart、Diamond和Club,
每门花色的牌共13张,面值(rank)分别为 2、3、4、5、6、7、8、9、10、Jack、
Queen、King和Ace,每张扑克牌应包含 如下信息:唯一的ID号(0-51)、花色、面值、
背面图案的编号、扑克牌的宽度、扑克牌的高度、扑克牌的左顶点坐标等。
扑克牌的操作有:存取背面图案,判断与另一张扑克牌是相同花色吗? 判断与另一张扑克牌是相同面值吗?判断扑克牌是给指定的花色吗?
判断扑克牌是给指定的面值吗?设置扑克牌坐标,取得扑克牌的右下角坐标等.

1)请写出扑克牌类Card类的定义和实现,要求选取适当形式的数据成员
描述每张扑克牌的信息,同时以成员函数的形式实现指定的操作。

enum Suit { Spade, Heart, Diamond, Club };
enum Rank { Two = 2, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King, Ace };
//枚举类型,Two初始值定为2,后面的值依次递增

class Card {
private:
    int id;
    Suit suit;
    Rank rank;
    int back_id;
    int width;
    int height;
    int x;
    int y;
public:
    Card(int _id, Suit _suit, Rank _rank, int _back_id, int _width, int _height, int _x, int _y)
        : id(_id), suit(_suit), rank(_rank), back_id(_back_id), width(_width), height(_height), x(_x), y(_y) {}
    Suit get_suit() const { return suit; }
    Rank get_rank() const { return rank; }
    bool is_same_suit(const Card& other) const { return suit == other.suit; }
    bool is_same_rank(const Card& other) const { return rank == other.rank; }
    bool is_given_suit(Suit given_suit) const { return suit == given_suit; }
    bool is_given_rank(Rank given_rank) const { return rank == given_rank; }
    void set_coordinates(int new_x, int new_y) { x = new_x; y = new_y; }
    int get_right_bottom_x() const { return x + width; }
    int get_right_bottom_y() const { return y + height; }
};

2)给Card类添加一个显式的拷贝构造函数并实现它。

Card(const Card& other): id(other.id), suit(other.suit), rank(other.rank), back_id(other.back_id), width(other.width), height(other.height), x(other.x), y(other.y) {}

4、练习根据给定的描述,抽象出类,给出适当的数据成员和成员函数,并给出具体的类定义。
游戏中的英雄有各自的魅力值、声望值、攻击力、防御力、法力等,每个英雄可以最多带5个宝物, 每种宝物有特有提升英雄某种能力的效果。游戏中假设共有6种宝物(暂时用1,2,3,…6代表,1提升魅力2点,2提升声望3点,3提升攻击力1点,…),英雄这个类需要有功能:取得当前状态下的各种能力值,在指定位置中携带指定宝物,丢弃指定位置中的宝物等。

class Hero {
public:
	int getcharm() {
		return this->charm;
	}
	int getprestige() {
		return this->prestige;
	}
	int getattack() {
		return this->attack;
	}
	int getdefense() {
		return this->defense;
	}
	int getmagic() {
		return this->magic;
	}
	int* getTreasure() {
		return this->treasure;
	}
	void CarryTreasure(int position, int Treasure) {
		if (position < 0 || position > 5) return;
		else if (treasure[position] == 0) treasure[position] = Treasure;
		else {
			cout << "此位置已经有宝物,请更换空间存储"; 
			return;
		}
	}
	void DropTreasure(int position) {
		if (position >= 0 && position <= 5) {
			treasure[position] = 0;
		}
		else return;
	}
private:
	int charm;
	int prestige;
	int attack;
	int defense;
	int magic;
	int treasure[5] = {0};
}; 

5.已知类Demo的类定义如下,请改写Demo类,使得无论如何,用户至多只能创建并访问Demo类的唯一一个实例。 ————注:使用单例模式!

class Demo {
    public:
     	   Demo(  ) { mNum = 0; }
       void  AddValue(int value) { mNum+=value;}
       void  ShowValue( ) const  { cout<<"Value="<<value<<endl;} 
  private:
       int   mNum;
};
class Demo{
public:
	static Demo& GetExam () {
		static Demo temp;
		return temp;
}
	void AddValue(int value) { mNum += value; }
	void ShowValue() const { cout << “value=<< value << endl; }
private:
	Demo() {mNum = 0};
	Demo(const Demo&)= delete;
	Demo& operator=(const Demo&) = delete;
	int mNum;
};

6.一个游戏中有很多怪物(Monster),怪物之间可能要发生战斗(fight),
每场战斗都是一个怪物与另一怪物之间的一对一战斗。每个怪物都有自己
的速度(Speed)、生命值(hitpoint)、攻击力值(damage)和防御力值(defense);
战斗时,两个怪物依次攻击对方,即怪物a首先攻击怪物b, 然后轮到怪物b
攻击怪物a,之后,怪物a再次攻击怪物b,…,直到一方生命值为0;
战斗时,由速度快的一方首先发起攻击;若速度一样,比较生命值,由高者首先攻击;
若生命值也相等,比较攻击力,由高者首先攻击;若攻击力还相等,比较防御力,由
高者首先攻击;若四项都相等,则选择任一方首先攻击;
怪物A攻击怪物B时,会给怪物B造成伤害,使得怪物B的生命值降低,降低值为:
2*A的攻击力-B的防御力,最小为1。

请根据你对上述描述的理解,定义并实现怪物类Monster,成员的设计可以任意,
但要求该类至少有一个成员函数fight,用来描述与另外一个怪物进行战斗的过程。
不必考虑怪物的生命值减少至0后如何处理。

类的定义:
Class Monster{
public:
	Monster(int sp, int hit, int dam, int def) : speed(sp), hitpoint(hit), damage(dam), defense(def) {} 
	void fight(Monster& other); 
private: 
	int speed;
	int hitpoint;
	int damage;
	int defense; 
};
  
 
Fight函数外联实现:
void Monster::fight(Monster& other) {
	
Monster& attacker = (speed > other.speed) ? (*this) : ((speed < other.speed) ? other : 
                         (hitpoint > other.hitpoint) ? (*this) : ((hitpoint < other.hitpoint) ? other : (damage > other.damage) ? (*this) : ((damage < other.damage) ? other : (defense > other.defense) ? (*this) : other)));

Monster& defender = (&attacker == (*this)) ? other : (*this);
int hurt = max{ 2 * attacker.damage – defender.defense, 1};
defender.hitpoint -= hurt;  
}
  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值