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

news/2024/10/18 21:25:17/

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

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

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,累计读的页数和今天读的页数为0int Book::getTotalPages() {return this->totalPages;
}//返回书的总页数void Book::readPages(int pages) {this->pagesReadToday += pages;this->pagesReadTotal += pages;
}//将今天读的页数加上pages,累计读的页数也加上pagesint 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;  
}

http://www.ppmy.cn/news/63301.html

相关文章

【Win32绘图编程,GDI绘图对象】绘图基础,位图处理,绘图消息处理,画笔,画刷,文本绘制

这一篇文章分享本人学习win32绘图编程&#xff0c;其中包括GDI绘图对象&#xff0c;绘图基础&#xff0c;基本图形的绘制&#xff0c;画笔画刷的使用&#xff0c;文本绘制&#xff0c;以及文本字体的更改。 文章目录 一.绘图基础1.BeginPaint函数2.EndPaint函数3.颜色的使用 二…

前几天面了个32岁的测试员,年薪50w问题基本都能回答上,应该刷了不少八股文···

互联网行业竞争是一年比一年严峻&#xff0c;作为测试工程师的我们唯有不停地学习&#xff0c;不断的提升自己才能保证自己的核心竞争力从而拿到更好的薪水&#xff0c;进入心仪的企业&#xff08;阿里、字节、美团、腾讯等大厂.....&#xff09; 所以&#xff0c;大家就迎来了…

如何为自己的开源项目选择许可证

就结论而言&#xff0c;如果你很随意、不在乎&#xff0c;那就选择MIT协议&#xff0c;如果要为自己的权益提供尽可能的保障&#xff0c;那就GPL&#x1f6e1;️ 为自己的软件知识产权选择许可证的必要性在于&#xff0c;如果不去选择&#xff0c;则默认为放弃了自己的全部权利…

windows误删文件怎么恢复

在日常办公中&#xff0c;由于时间的不断积累&#xff0c;会有很多的文件。在清理文件时&#xff0c;稍有疏忽就会多删了一些的文件。如果是一些不需要的文件删了就删了&#xff0c;但如果这些文件是重要的&#xff0c;该怎么办?在windows误删文件怎么恢复呢?这里有小编整理的…

JVM运行时数据区

Java和C的区别&#xff0c;体现在自动内存分配和垃圾收集技术。 JVM在执行Java程序时&#xff0c;会将它管理的内存分为若干个不同的数据区域。 这些区域有各自的作用范围以及生命周期&#xff1a; 线程私有的区域&#xff0c;随着用户线程的启动和结束而建立和销毁。线程共…

CPU 架构(x86/ARM)简介

CPU 架构通过指令集的方式一般可分为 复杂指令集&#xff08;CISC&#xff09; 和 精简指令集&#xff08;RISC&#xff09; 两类&#xff0c;CISC 主要是 x86 架构&#xff0c;RISC 主要是 ARM 架构&#xff0c;还有 MIPS、RISC-V、PowerPC 等架构。 本文重点介绍 x86 和 ARM…

谷歌浏览器 | Chrome DevTools系统学习篇-概述

Chrome DevTools是一套直接内置到谷歌Chrome浏览器的web开发工具。DevTools可以帮助您即时编辑页面并快速诊断问题&#xff0c;最终帮助您更快地构建更好的网站。我们今天的概述主要讲述谷歌浏览器的日常使用和几大常见控制面板的介绍。 目录 1.打开谷歌浏览器 2.谷歌浏览器的…

Mysql 中left join时 on、and、where区别

1、准备两张表student与class表 student class 2、left join on左连接 select * from student s left join class c on s.classId c.id 左表数据全部显示&#xff0c;关联到的右表数据显示&#xff0c;没有显示null 3、left join on ... and对左表student进行条件筛选 …