面向对象编程实践-欢乐斗地主
《老九学堂C++课程》《C++ primer》学习笔记。《老九学堂C++课程》详情请到B站搜索《老九零基础学编程C++入门》
-------------简单的事情重复做,重复的事情用心做,用心的事情坚持做(老九君)---------------
要求:实现录入及打印地主的信息功能
实现地主的摸牌,及查看牌面的功能。
// main 文件
#include <iostream>
#include "LandOwner.h"
using namespace std;
int main(){
LandOwner *ptr_landowner1 = new LandOwner();
LandOwner *ptr_landowner2 = new LandOwner("专业斗地主");
LandOwner *ptr_landowner3 = new LandOwner("周扒皮");
ptr_landowner1 -> ShowInfo();
ptr_landowner2 -> ShowInfo();
ptr_landowner3 -> ShowInfo();
ptr_landowner2 -> TouchCard(3);
// 向量容器vector, 动态数组可以在运行阶段设置长度
// 具有数组的快速索引方式
// 可以插入和删除元素
// 定义和初始化 vector<double> vec1; vector<string> vec2(5); vector<int> vec3(20, 998)
// 54 个元素的数组来表示扑克牌,除13得到花色,模13得到牌面
delete ptr_landowner1;
delete ptr_landowner2;
delete ptr_landowner3;
}
// .h 文件
// 地主类
// Created by 陈莹莹 on 2021/2/5.
//
#ifndef HELLOWORLD_LANDOWNER_H
#define HELLOWORLD_LANDOWNER_H
#include <iostream>
#include <vector>
using namespace std;
class LandOwner {
private:
string m_NickName;
string m_Sex;
int m_Gold;
long m_Exp;
vector<int> currCards; // 当前玩家的手牌数组
vector<int> packCards; // 默认的一副牌,从1-54
vector<int> surplCards; // 摸牌后剩余的牌
bool isContains(int); // 剩余牌中是否包含cardNum这个牌面
void deleteCards(vector<int> &, int); // 删除剩余牌数组数
string getColor(int); // 获得牌的花色
string getValue(int); // 获得牌面
public:
LandOwner();
LandOwner(string);
LandOwner(string, string, int, long);
~LandOwner();
void ShowInfo();
string GetNickName(){return m_NickName;}
void SetNickName(string val){m_NickName = val;}
string GetSex(){return m_Sex;}
void SetSex(string val){m_Sex=val;}
int GetGold(){return m_Gold;}
void SetGold(int val){m_Gold=val;}
long GetExp(){return m_Exp;}
void SetExp(long val){m_Exp=val;}
void TouchCard(int cardCount);
void InitCards();
void ShowCards(vector<int> &);
};
#endif //HELLOWORLD_LANDOWNER_H
vector显示输出:传统for循环输出、迭代器输出、简化迭代器:auto、auto区间遍历、copy算法输出
// .cpp文件
//
// Created by 陈莹莹 on 2021/2/5.
//
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
#include <cstdlib>
#include <ctime>
#include "LandOwner.h"
using namespace std;
LandOwner::LandOwner(){
SetNickName("默认地主");
SetSex("保密");
SetExp(0);
SetGold(1000);
cout << "LandOwner()" << endl;
InitCards();
}
LandOwner::LandOwner(string nickName):m_NickName(nickName){
SetSex("保密");
SetExp(0);
SetGold(1000);
cout << "LandOwner(string nickName)" << endl;
InitCards();
// ShowCards(packCards);
// ShowCards(currCards);
// ShowCards(surplCards);
// cout << "测试" << isContains(13);
}
LandOwner::LandOwner(string nickName, string sex, int gold, long exp):m_NickName(nickName),m_Sex(sex),m_Gold(gold), m_Exp(exp)
{
cout << "LandOwner(stirng nickName, string sex, int gold, long exp)" << endl;
InitCards();
}
void LandOwner::ShowInfo(){
cout << "昵称:" << GetNickName() << endl;
cout << "性别:" << GetSex() << endl;
cout << "金币:" << GetGold() << endl;
cout << "经验:" << GetExp() << endl;
}
void LandOwner::InitCards(){
// 初始化packCards, surplusCards, currCards
// 生成默认的一副扑克牌
for(int i = 0; i < 54; i++){
packCards.push_back(i + 1);
surplCards.push_back(i + 1);
}
currCards.clear();
}
void LandOwner::ShowCards(vector<int> &cards) {
// 显示牌面信息
// C 语言的习惯: 传统for 循环
/*
* for(int i = 0; i < cards.size(); i++){
cout << cards[i] << "\t";
}
cout << "\n" << endl;*/
// C++语言习惯,迭代器的写法
/*
* for(vector<int>::const_iterator iter = cards.begin(); iter != cards.end(); iter++){
cout << *iter << ", ";
}
cout << endl; */
// C++11 之后:迭代器的简写版本,类型推断
/*for(auto iter = cards.begin(); iter != cards.end(); iter++){
cout << *iter << "。 ";
}
cout << endl;*/
// for 区间遍历
for(auto card : cards){
cout << card << ":" << getColor(card) << "-" << getValue(card) << "\t";
}
cout << endl;
// 使用算法的方式,将容器的内容复制到cout 绑定的迭代器中
// #include <iterator>
// copy(cards.cbegin(), cards.cend(), ostream_iterator<int>(cout, "- "));
// cout << endl;
}
void LandOwner::TouchCard(int cardCount) {
// 摸牌, 随机生成一张剩余牌中有的牌,更新连个牌面数组currCards, suplusCards
srand(time(NULL));
for(int i = 0; i < cardCount; i++){
int randIdex = rand() % 54 ; // 0-53 之间的随机数字
// 判断:随机生成的这张牌是否在余牌数组中,私有方法
if(isContains(packCards[randIdex])){
currCards.push_back(packCards[randIdex]);
// 在剩余牌数组中删除这张牌
deleteCards(surplCards, packCards[randIdex]);
}
else{
i--; // 换一张牌
}
}
cout << "<地主摸牌>-当前手牌如下" << endl;
ShowCards(currCards);
cout << "<地主摸牌>-剩余牌" << endl;
ShowCards(surplCards);
}
bool LandOwner::isContains(int cardNum) {
// 普通青年的做法
// for(int i = 0; i < surplCards.size(); i++){
// if(surplCards[i] == packCards[cardIndex]){
// return true
// }
// }
// return false
// 使用算法来查找-find
vector<int>::iterator iter = find(surplCards.begin(), surplCards.end(), cardNum);
// if(iter == surplCards.end()){
// return false;
// }
// return true;
return iter != surplCards.end();
}
void LandOwner::deleteCards(vector<int> &cardVec, int card){
// 普通青年的做法
// for(auto iter = cardVec.begin(); iter != cardVec.end();){
// if(*iter == card){
// //iter = cardVec.erase(iter); // 返回值指向已删除元素的下一个元素
// }
// else{
// iter++;
// }
//
// }
// 使用算法删除
auto iter = find(cardVec.begin(), cardVec.end(), card);
if(iter != cardVec.end()){
cardVec.erase(iter); //方法调用不好
}
}
string LandOwner::getColor(int card) { // card 给的牌面
if(card == 53) return "小王";
if(card == 54) return "大王";
string colors[] = {"黑桃", "红心", "方块", "梅花"};
return colors[(card - 1) / 13];
}
string LandOwner::getValue(int card) {
if(card == 53) return "Balck Joker";
if(card == 54) return "Red Jocker";
string values[] = {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
return values[(card - 1) % 13];
}
LandOwner::~LandOwner(){
cout << GetNickName() << "被释放" << endl;
}