C++(15)--面向对象编程实践-欢乐斗地主(vector的花式输出)

面向对象编程实践-欢乐斗地主


《老九学堂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;

}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
用C++写的基于MFC界面的地主小游戏源码,内含详细注释,附带了简单的AI出牌规则,放出来供大家参考交流。vs2010编写,vs2015测试可用,理论上vs05及以上都可正常编译运行。 void Judge::MainFlow() { switch(DataCenter::Instance().GetPlayState()) { case EM_LandHolderBorn_PlayState: { //先检查是否已经问完了 //遍历玩家检查是否已经询问过了,如果已经都问过了,则设置叫分最高的为地主 BOOL bAllAsked = TRUE;//是否已经询问完了 vector & vecPlayer = DataCenter::Instance().GetPlayerList(); for (UINT i = 0; i m_nCurHighstScore) { m_nCurHighstScore = vecPlayer[i].GetLandOwerScore(); m_pToBeLandOwer = &vecPlayer;[i]; } if (vecPlayer[i].GetLandOwerScore() SetLandOwer(TRUE); } //然后根据情况执行询问流程 //如果地主已经产生,则跳入下一阶段 if (NULL != DataCenter::Instance().GetLandOwner()) { m_pCurPlayer = NULL; DataCenter::Instance().SetPlayState(EM_WaitPlayer_PlayState); MainFlow(); return; } //如果当前player为空,设置当前player为地主牌得主 if (m_pCurPlayer == NULL) { m_pCurPlayer = DataCenter::Instance().GetLandOwnerCardHolder(); } //对当前玩家执行地主问询 ASSERT(m_pCurPlayer); m_pCurPlayer->ExcuteCallLandOwer(); } break; case EM_WaitPlayer_PlayState: { //如果游戏已经结束,则执行结束逻辑 BOOL bLandOwerWin = FALSE; if (DataCenter::Instance().IsOver(bLandOwerWin)) { if (bLandOwerWin) { AfxMessageBox(_T("地主赢了!")); } else { AfxMessageBox(_T("佃户赢了!")); } DataCenter::Instance().SetPlayState(EM_WaitToStart_PlayState); //将所有玩家明牌 DataCenter::Instance().ShowAllPlayerCard(); RefreshView(); return; } //如果是出牌阶段而当前player为空,设置当前player为地主,并发予底牌 if (m_pCurPlayer == NULL) { m_pCurPlayer = DataCenter::Instance().GetLandOwner(); DataCenter::Instance().SendOutBottomCard(); RefreshView(); } ASSERT(m_pCurPlayer); m_pCurPlayer->ExcuteCallCardPlay(); } break; } } void Judge::CurPlayerCallScore(int nScore) { if (m_pCurPlayer == NULL) { ASSERT(FALSE); return; } //将玩家选择的分数设置给玩家 m_pCurPlayer->SetLandOwerScore(nScore); //如果当前玩家为空,直接返回 if(m_pCurPlayer == NULL) { return; } if (nScore == 3) { //如果玩家叫了三分,直接设为地主 m_pCurPlayer->SetLandOwer(TRUE); } else { //玩家叫的不是三分,则记下玩家叫的分数 m_pCurPlayer->SetLandOwerScore(nScore); } if (nScore == 0) { CString strWord; strWord.Format(_T("不叫")); m_pCurPlayer->Say(strWord); } else { CString strWord; strWord.Format(_T("%d分"), nScore); m_pCurPlayer->Say(strWord); } //玩家叫分后隐藏叫地主按钮 Judge::Instance().ShowCallLandOwerBtn(FALSE); //切换到下一个玩家,流程继续 SwitchToNextPlayer(); MainFlow(); }

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值