宠物小屋 - 需求
-
动物:猫 (CCat)、狗(CDog)、蛇(CSnake)
- 包含名字(m_strName)、颜色(m_strColor)、年龄(m_nAge)。
-
笼子类(CCage):负责装动物,每个笼子的编号不能相同,一个笼子只装一个动物。
-
房子类(CHouse):负责存放装动物的笼子。
-
人(CPeople):负责花钱买动物,造笼子,将动物放在笼子中,存放到房子里,杀死某个笼子动物,销毁某个笼子(如果有动物一并销毁),查看某个或所有笼子动物,和某个动物玩耍。
getline
控制台程序,通过输入命含,可以进行简单的人机交互。
提示:获取输入字符可以用
string:getline(cin,cmd); //获取输入的命令(阻塞等待)。
#include<string>
basic istream<_Elem,_Traits>& getline(
basic_istream<_Elem,_Traits>& _Istr,
basic_string<_Elem,_Traits,_Alloc>& _Str,
const _Elem _Delim)
_Istr : 表示一个输入流,譬如cin.
_Str : 将输入流读取的字符串放到_Str中。
_Delim : 遇到这个学符就停正读取,不设置默认为'\n'
值传递vs指针or引用
//尽量不用值传递,用引用or指针
//原因:值传递时并不是直接把变量a=1传过去,而是在函数里面重新创建了一个跟a的类型一样的变量b,让b=1,因此涉及到变量创建和变量赋值的过程,如果该变量类型是一个很大的类,那么会创建很久赋值很久 ,性能损耗比较大。而指针的话就是创建一个指针和赋值一个地址,性能损耗相对来说小很多,引用则是创建一个指向变量a的符号b~
类图
头文件
#pragma once
#include <string>
using namespace std;
class CAnimal
{
public:
CAnimal(void);
virtual ~CAnimal(void);
public:
int m_nAge;
string m_strName;
string m_strColor;
public:
virtual void PlayAnimal() = 0; //纯虚函数,抽象类,不可以定义对象
void InitAnimal(string& name, string& color, int age);
void ShowAnimal();
};
#pragma once
#include "Animal.h"
class CCage
{
public:
CCage(void);
~CCage(void);
public:
CAnimal* m_pAni;
int m_nId;
public:
void InitCage(int id);
};
#pragma once
#include "Animal.h"
class CCat :
public CAnimal
{
public:
CCat(void);
~CCat(void);
public:
virtual void PlayAnimal();
};
#pragma once
#define ANIMAL_KIDN_CAT 1
#define ANIMAL_KIDN_DOG 2
#define ANIMAL_KIDN_SNAKE 3
#define ANIMAL_COST_CAT 400
#define ANIMAL_COST_DOG 600
#define ANIMAL_COST_SNAKE 1000
#define PEOPLE_MONEY 2000
#define CMD_BUY_ANIMAL_DOG "buy dog"
#define CMD_BUY_ANIMAL_CAT "buy cat"
#define CMD_BUY_ANIMAL_SNAKE "buy snake"
#define CMD_PROGRAM_QUIT "quit"
#define CMD_LOOK_ANIMAL "look"
#define CMD_KILL_ANIMAL "kill"
#define CMD_DESTORY_CAGE "destory"
#define CMD_PLAYWITH_ANIMAL "play"
#define CMD_SHOW_PEOPLE "show"
#define CMD_HELP "help"
#pragma once
#include "Animal.h"
class CDog :
public CAnimal
{
public:
CDog(void);
~CDog(void);
public:
virtual void PlayAnimal();
};
#pragma once
#include <list>
using namespace std;
#include "Cage.h"
class CHouse
{
public:
CHouse(void);
~CHouse(void);
public:
list<CCage*> m_lstCage;
};
#pragma once
#include <string>
using namespace std;
#include "Animal.h"
#include "Cage.h"
#include "House.h"
class CPeople
{
public:
CPeople(void);
~CPeople(void);
public:
int m_nMoney;
string m_nstrName;
public:
void InitPeople(string& name, int money);
//尽量不用值传递,用引用or指针
//原因:值传递时并不是直接把变量a=1传过去,而是在函数里面重新创建了一个跟a的类型一样的变量b,让b=1,因此涉及到变量创建和变量赋值的过程,如果该变量类型是一个很大的类,那么会创建很久赋值很久 ,性能损耗比较大。而指针的话就是创建一个指针和赋值一个地址,性能损耗相对来说小很多,引用则是创建一个指向变量a的符号b~
void ShowPeople();
bool BuyAnimal(CAnimal* pAni, int AnimalKind);
CCage* CreateCage();
void PushAnimal(CCage* pCage, CAnimal* pAnimal);
void PushCage(CHouse* pHouse, CCage* pCage);
void LookAnimal(CHouse* pHouse, int Id);
void PlayWithAniamal(CHouse* pHouse, int Id);
void KillAnimal(CHouse* pHouse, int Id);
void DestoryCage(CHouse* pHouse, int Id);
};
#pragma once
#include "Animal.h"
class CSnake :
public CAnimal
{
public:
CSnake(void);
~CSnake(void);
public:
virtual void PlayAnimal();
};
源文件
#include "Animal.h"
#include <iostream>
using namespace std;
CAnimal::CAnimal(void) {
m_strColor = " ";
m_strName = " ";
m_nAge = 0;
}
CAnimal::~CAnimal(void) {
m_strColor = " ";
m_strName = " ";
m_nAge = 0;
}
void CAnimal::InitAnimal(string& name, string& color, int age) {
m_strName = name;
m_strColor = color;
m_nAge = age;
}
void CAnimal::ShowAnimal() {
cout << "Animal info:name=" << m_strName << ",color=" << m_strColor << ",age=" << m_nAge << endl;
}
#include "Cage.h"
#include <iostream>
using namespace std;
CCage::CCage(void) {
m_pAni = NULL;
m_nId = 0;
}
CCage::~CCage(void) {
}
void CCage::InitCage(int id) {
m_nId = id;
}
#include "Cat.h"
#include <iostream>
using namespace std;
CCat::CCat(void) {
}
CCat::~CCat(void) {
}
void CCat::PlayAnimal() {
cout << "猫猫喵喵叫~" << endl;
}
#include "Dog.h"
#include <iostream>
using namespace std;
CDog::CDog(void) {
}
CDog::~CDog(void) {
}
void CDog::PlayAnimal() {
cout << "狗狗汪汪叫~" << endl;
}
#include "House.h"
#include <iostream>
using namespace std;
CHouse::CHouse(void) {
m_lstCage.clear();
}
CHouse::~CHouse(void) {
list<CCage*>::iterator ite = m_lstCage.begin();
while (ite != m_lstCage.end())
{
//先删除动物,再删除笼子,最后回收清空链表
if ((*ite)->m_pAni) //判断有没有动物
{
delete (*ite)->m_pAni;
(*ite)->m_pAni = NULL;
}
delete(*ite);
(*ite) = NULL;
//ite++;//方式1
ite = m_lstCage.erase(ite); //方式2
//擦除,返回删除的下一个节点,其功能等同于ite++
}
m_lstCage.clear();
}
#include "People.h"
#include "Def_config.h"
#include <iostream>
using namespace std;
CPeople::CPeople(void) {
m_nMoney = 0;
m_nstrName = " ";
}
CPeople::~CPeople(void) {
m_nMoney = 0;
m_nstrName = " ";
}
void CPeople::InitPeople(string& name, int money) {
m_nMoney = money;
m_nstrName = name;
}
void CPeople::ShowPeople() {
cout << "people info:name" << m_nstrName << ",money=" << m_nMoney << endl;
}
#define BUY_ANIMAL(ANIMAL_COST,TIPS)\
if (m_nMoney - ANIMAL_COST < 0){\
cout << TIPS << endl;\
return false;\
}\
else\
{\
cout << "购买成功" << endl;\
}\
m_nMoney -= ANIMAL_COST;
bool CPeople::BuyAnimal(CAnimal* pAni, int AnimalKind) {
if (pAni == NULL)
{
cout << "没有动物啦,不用买了" << endl;
return false;
}
switch (AnimalKind)
{
case ANIMAL_KIDN_CAT:
{
//if (m_nMoney - ANIMAL_COST_CAT < 0) {
// cout << "买猫咪钱不够噢~攒攒钱再来吧~" << endl;
// return false;
//}
//m_nMoney -= ANIMAL_COST_CAT;
BUY_ANIMAL(ANIMAL_COST_CAT, "买猫咪钱不够噢~攒攒钱再来吧~")
}
break;
case ANIMAL_KIDN_DOG:
{
BUY_ANIMAL(ANIMAL_COST_DOG, "买狗狗钱不够噢~攒攒钱再来吧~")
}
break;
case ANIMAL_KIDN_SNAKE:
{
BUY_ANIMAL(ANIMAL_COST_SNAKE, "买小蛇钱不够噢~攒攒钱再来吧~")
}
break;
}
return true;
}
CCage* CPeople::CreateCage() {
CCage* pCage = new CCage;
int Id = 0;
do
{
cout << "请输入笼子编号(编号应>0):" << endl;
cin >> Id;
} while (Id <= 0);
pCage->InitCage(Id);
return pCage;
}
void CPeople::PushAnimal(CCage* pCage, CAnimal* pAnimal) {
if (pCage == NULL)
{
cout << "没有笼子,不能装动物啊" << endl;
return;
}
if (pAnimal == NULL)
{
cout << "没有动物,不用装笼子啊" << endl;
return;
}
pCage->m_pAni = pAnimal;
cout << "动物成功装进笼子啦" << endl;
}
void CPeople::PushCage(CHouse* pHouse, CCage* pCage) {
if (pHouse == NULL)
{
cout << "没有房子啊" << endl;
return;
}
if (pCage == NULL)
{
cout << "没有笼子啦" << endl;
}
pHouse->m_lstCage.push_back(pCage);
cout << "笼子成功放到房子里去啦" << endl;
}
void CPeople::LookAnimal(CHouse* pHouse, int Id) {
if (pHouse == NULL)
{
cout << "没有房子啊,当然也没有笼子和动物,你想看空气吗?" << endl;
return;
}
//查看笼子,id==0的话,是查看所有笼子,id=1就查看1号笼子以此类推~
if (Id == 0)//代表查看所有笼子里的动物
{
list<CCage*>::iterator ite = pHouse->m_lstCage.begin();
while (ite != pHouse->m_lstCage.end())
{
if (*ite)//先判断有没有笼子
{
cout << "笼子编号:ID=" << (*ite)->m_nId << " ";
if ((*ite)->m_pAni) //判断笼子里有没有动物
{
(*ite)->m_pAni->ShowAnimal();
}
else {
cout << "没有动物呀~" << endl;
}
}
ite++;
}
}
else {//遍历匹配某号笼子里的动物
list<CCage*>::iterator ite = pHouse->m_lstCage.begin();
while (ite != pHouse->m_lstCage.end())
{
if (*ite)
{
if ((*ite)->m_nId == Id) //匹配成功
{
cout << "笼子编号:ID=" << (*ite)->m_nId << " ";
if ((*ite)->m_pAni) //判断笼子里有没有动物
{
(*ite)->m_pAni->ShowAnimal();
}
else {
cout << "没有动物呀~" << endl;
}
return;
}
}
ite++;
}
}
}
void CPeople::PlayWithAniamal(CHouse* pHouse, int Id) {
if (pHouse == NULL)
{
cout << "没有房子啊,当然也没有笼子和动物,你是个孤儿,自己玩儿吧" << endl;
return;
}
list<CCage*>::iterator ite = pHouse->m_lstCage.begin();
while (ite != pHouse->m_lstCage.end())//遍历
{
if ((*ite) && (*ite)->m_nId == Id) //匹配到笼子
{
if ((*ite)->m_pAni)
{
cout << "name = " << m_nstrName << "正在玩儿~" << " ";
(*ite)->m_pAni->PlayAnimal();
}
return;
}
ite++;
}
cout << "没有找到笼子和动物一块儿玩儿~" << endl;
}
void CPeople::KillAnimal(CHouse* pHouse, int Id) {
if (pHouse == NULL)
{
cout << "没有房子啊,当然也没有笼子和动物,不需要杀死or抛弃动物了,你已经是孤儿了~" << endl;
return;
}
list<CCage*>::iterator ite = pHouse->m_lstCage.begin();
while (ite != pHouse->m_lstCage.end())//遍历
{
if ((*ite) && (*ite)->m_nId == Id) //匹配到笼子
{
if ((*ite)->m_pAni)
{
delete (*ite)->m_pAni;
(*ite)->m_pAni = NULL;
}
cout << "成功杀死动物" << endl;
return;
}
ite++;
}
cout << "没有匹配到笼子,杀死动物失败" << endl;
}
void CPeople::DestoryCage(CHouse* pHouse, int Id) {
if (pHouse == NULL)
{
cout << "没有房子啊,当然也没有笼子,没办法销毁笼子嗷~" << endl;
return;
}
list<CCage*>::iterator ite = pHouse->m_lstCage.begin();
while (ite != pHouse->m_lstCage.end())//遍历
{
if ((*ite) && (*ite)->m_nId == Id) //匹配到笼子
{
//先判断有无动物,有的话删除动物
if ((*ite)->m_pAni)
{
delete (*ite)->m_pAni;
(*ite)->m_pAni = NULL;
}
//销毁笼子
delete (*ite);
(*ite) = NULL;
//删除链表节点
pHouse->m_lstCage.erase(ite);
cout << "成功销毁笼子" << endl;
return;
}
ite++;
}
cout << "没有找到需要销毁的笼子" << endl;
}
#include "Snake.h"
#include <iostream>
using namespace std;
CSnake::CSnake(void) {
}
CSnake::~CSnake(void) {
}
void CSnake::PlayAnimal() {
cout << "蛇嘶嘶吐舌~" << endl;
}
主函数
#include "People.h"
#include "House.h"
#include "Def_config.h"
#include "Dog.h"
#include "Cat.h"
#include "Snake.h"
#include <sstream>
#include <iostream>
using namespace std;
#define DEF_BUY_ANIMAL_PART(ANI_CLASS,ANI_KIND)\
pAni = new ANI_CLASS;\
GetAnimalAttr(Animalname, color, age);\
pAni->InitAnimal(Animalname, color, age);\
pPeople->BuyAnimal(pAni, ANI_KIND);
void GetAnimalAttr(string& Animalname, string& color, int &age) {
cout << "请输入动物信息:1.名字 2.颜色 3.年龄(例:小娃 白 5)" << endl;
string AnimalAttr;
getline(cin, AnimalAttr);
stringstream ss(AnimalAttr);
string s;
int i = 0;
while (ss >> s)
{
switch (i)
{
case 0: {
Animalname = s;
}
break;
case 1: {
color = s;
}
break;
case 2: {
age = atoi(s.c_str());//字符串转int类型
}
break;
}
i++;
}//以空格为标记点 遍历三次 依次把名字 颜色 年龄获取到
}
void showHelp() {
cout << CMD_BUY_ANIMAL_DOG << ":买狗" << endl;
cout << CMD_BUY_ANIMAL_CAT << ":买猫" << endl;
cout << CMD_BUY_ANIMAL_SNAKE << ":买蛇" << endl;
cout << CMD_PROGRAM_QUIT << ":退出程序" << endl;
cout << CMD_LOOK_ANIMAL << ":查看动物信息" << endl;
cout << CMD_KILL_ANIMAL << ":杀死动物" << endl;
cout << CMD_DESTORY_CAGE << ":销毁笼子及笼内动物" << endl;
cout << CMD_PLAYWITH_ANIMAL << ":和动物玩耍" << endl;
cout << CMD_SHOW_PEOPLE << ":展示人物信息" << endl;
cout << CMD_HELP << ":帮助文档" << endl;
}
int main(){
CPeople* pPeople = new CPeople;
CHouse* pHouse = new CHouse;
string name = "小红";
pPeople->InitPeople(name, PEOPLE_MONEY);
string cmd;
showHelp();
while (1)
{
//cin >> cmd; // cmd只会读取到buy,空格后的内容没有读取到,可以尝试用getline解决该问题
//getline(cin, cmd); //第三个参数不给的话默认'\n'结束
//问题:第二次循环到getline的时候,由于缓冲区有第一次cin没获取的\n,所以第二次getline时程序无法cin,直接获取缓冲区的\n,因此后面不会进入任何一个if,直接空循环一次再回到getline(此时为第三次,缓冲区为空,cin……,也就是说该代码在循环偶数次情况下均无法正常cin)
//解决方式:利用cin.sync();//清除缓冲区
cin.sync();
getline(cin, cmd);
//———————————————————————————— 退出————————————————————————————
if (CMD_PROGRAM_QUIT == cmd)
{
break;
}
//——————————————————————————————————————————————————————————————
//———————————————————————————— 帮助—————————————————————————————
if (CMD_HELP == cmd)
{
showHelp();
}
//——————————————————————————————————————————————————————————————
//—————————————————————人机交互 买动物 安置动物—————————————————————
{
CAnimal* pAni = NULL;
string Animalname;
string color;
int age;
if (CMD_BUY_ANIMAL_CAT == cmd)
{
cout << "买猫咪~" << endl;
DEF_BUY_ANIMAL_PART(CCat, ANIMAL_KIDN_CAT);
}
else if (CMD_BUY_ANIMAL_DOG == cmd)
{
cout << "买狗狗~" << endl;
DEF_BUY_ANIMAL_PART(CDog, ANIMAL_KIDN_DOG);
}
else if (CMD_BUY_ANIMAL_SNAKE == cmd)
{
cout << "买小蛇~" << endl;
DEF_BUY_ANIMAL_PART(CSnake, ANIMAL_KIDN_SNAKE);
}
//安置动物
if (pAni)//判断有没有动物,是否购买成功了
{
//建笼子
CCage* pCage = pPeople->CreateCage();
//装笼子
pPeople->PushAnimal(pCage, pAni);
//笼子放到房子里
pPeople->PushCage(pHouse, pCage);
}
}
//——————————————————————————————————————————————————————————————
//——————————————————————————查看动物——————————————————————————————
if (CMD_LOOK_ANIMAL == cmd)
{
int id = 0;
cout << "请输入查看笼子的ID(id==0:代表查看所有动物)" << endl;
cin >> id;
pPeople->LookAnimal(pHouse, id);
}
//——————————————————————————————————————————————————————————————
int id = 0;
//——————————————————————————杀死动物——————————————————————————————
if (CMD_KILL_ANIMAL == cmd)
{
cout << "请输入需要杀死动物的所属笼子ID" << endl;
cin >> id;
pPeople->KillAnimal(pHouse, id);
}
//——————————————————————————————————————————————————————————————
//——————————————————————————销毁笼子————————————————————————————sshow
if (CMD_DESTORY_CAGE == cmd)
{
cout << "请输入需要销毁的笼子ID" << endl;
cin >> id;
pPeople->DestoryCage(pHouse, id);
}
//——————————————————————————————————————————————————————————————
//——————————————————————————和动物玩——————————————————————————————
if (CMD_PLAYWITH_ANIMAL == cmd)
{
cout << "请输入想一起玩耍的动物所属笼子ID" << endl;
cin >> id;
pPeople->PlayWithAniamal(pHouse, id);
}
//——————————————————————————————————————————————————————————————
//——————————————————————————人物信息——————————————————————————————
if (CMD_SHOW_PEOPLE == cmd)
{
pPeople->ShowPeople();
}
//——————————————————————————————————————————————————————————————
}
//回收人、屋子的空间~(笼子和动物已经在屋子的析构里写了,所有不用再删啦)
delete pPeople;
pPeople = NULL;
delete pHouse;
pHouse = NULL;
return 0;
}