C++编写的麻将可以用了,哈哈,控制台下操作

weixin_41703094 2018-12-30 05:16:43
#include "pch.h"
#include <iostream>
#include "mahjong.h"
#include "windows.h"

using namespace std;
int main()
{
using Fun = pair<string, bool> (Ma_desk::*)(const Player &)const;
Fun fun[] = { &Ma_desk::is_7double, &Ma_desk::is_ascol, &Ma_desk::is_pound,
&Ma_desk::is_gap, &Ma_desk::is_zfb, &Ma_desk::is_samecol,
&Ma_desk::is_catch5, &Ma_desk::is_dragon, &Ma_desk::is_bsfive,
&Ma_desk::is_no19, &Ma_desk::is_foursame, &Ma_desk::is_stuck,
&Ma_desk::is_high, &Ma_desk::is_side, &Ma_desk::is_drill,
&Ma_desk::is_doorclear, &Ma_desk::is_enough};

ifstream fin("mj.dat");
if (!fin)
{
MessageBox(NULL, TEXT("文件错误!"), TEXT("错误信息"), MB_DEFBUTTON1);
exit(EXIT_FAILURE);
}
Ma_desk m(fin);

string p[14] = { "A1-1","A1-2","A1-3", "A4-0","A4-1","A4-2","A6-0","A7-1","A7-2","A7-3","A8-0","A8-1","A9-2","A9-3" };

Player one(m, p);
m.del_this(one);

/*
for (auto s : one.getData())
cout << s.getName(s.getID()) << " ";
cout << endl;
cout << (m.is_win(one)?"成功":"失败")

Player one("玩家1");

for(int i=0;i<14;i++)
one.play_get(m.dispatch());
*/
LP:
try {
while(!m.is_win(one)&&!m.is_over())//没胜利,没流局
{
for (auto s : one.getData())
cout << s.getID() << " ";
cout << endl;
for (auto s : one.getData())
cout << s.getName(s.getID()) << " ";
string key;
cin >> key;
one.play_send(key);
one.play_get(m.dispatch());


}
cout << "胡了:";
for (auto s : one.getData())
cout << s.getName(s.getID()) << " ";
cout << endl;
for (int n = 0; n < 17; ++n)
if ((m.*fun[n])(one).second)
std::cout << (m.*fun[n])(one).first << endl;
}
catch (regex_error &r)
{
cout << r.what() << endl;
}
catch (exception &e)
{
cout << e.what() << endl;
goto LP;
}

}

...全文
507 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2019-01-02
  • 打赏
  • 举报
回复
#1代码后面有遗漏。
weixin_41703094 2018-12-30
  • 打赏
  • 举报
回复
weixin_41703094 2018-12-30
  • 打赏
  • 举报
回复
ooolinux 2018-12-30
  • 打赏
  • 举报
回复
不错不错,改成GUI的就更好了。
weixin_41703094 2018-12-30
  • 打赏
  • 举报
回复
#pragma once #include "string" #include "fstream" #include "sstream" #include "map" #include "memory" #include "random" #include "iostream" #include "iomanip" #include "set" #include "vector" #include "regex" #include "ctime" #include "exception" #include "functional" #include "utility" #include "tuple" class Ma_card; //记录牌的位置和数量 template<typename Iter> std::map<std::string, std::pair<std::size_t, std::size_t>> record_place_count(Iter b, Iter e); //给出指定牌型(如对、三张、杠)的数量 template<typename Iter> std::size_t accu_type_count(Iter start, Iter over, int format); //*************************麻将牌********************************** class Ma_card { private: std::shared_ptr<std::map<std::string, std::string>>ma_data; std::string CardId;//牌ID public: Ma_card() :ma_data(new std::map<std::string, std::string>()), CardId("") {} Ma_card(std::shared_ptr<std::map<std::string, std::string>>m, std::string s) :ma_data(m), CardId(s) {} std::string getID()const { return CardId; } std::string getName(std::string ID)const { auto ret = ma_data->find(ID); return ret->second; } const std::shared_ptr<std::map<std::string, std::string>>& getdata()const { return ma_data; } operator bool()const //判断牌是否有效 { if (CardId == "") return false; else return true; } bool is_wan()const { return CardId.substr(0, 1) == "A"; } bool is_bing()const { return CardId.substr(0, 1) == "B"; } bool is_tiao()const { return CardId.substr(0, 1) == "C"; } bool is_feng()const { return CardId.substr(0, 1) > "C"; } bool is_incr(const Ma_card &lhs)const//判断两张牌是否是递增关系 { if (CardId.substr(0, 1) == lhs.CardId.substr(0, 1)) return std::stoul(lhs.CardId.substr(1, 1)) - std::stoul(CardId.substr(1, 1)) == 1; return false; } friend bool operator==(const Ma_card&lhs, const Ma_card &rhs) //判断两张牌是否相同 { return lhs.CardId.substr(0, 2) == rhs.CardId.substr(0, 2); } friend bool operator!=(const Ma_card&lhs, const Ma_card &rhs)//判断两张牌是否不同 { return !(lhs.CardId.substr(0, 2) == rhs.CardId.substr(0, 2)); } friend std::ostream &operator<<(std::ostream &os, const Ma_card&m) { auto ret = m.ma_data->find(m.CardId); os << ret->second; return os; } friend bool operator<(const Ma_card&lhs, const Ma_card&rhs) //关联容器的排序,目的为将风牌放到最后,其它按牌型、大小放置 { return lhs.CardId < rhs.CardId; } }; class Ma_desk; //*********************************************玩家************************** class Player { private: friend class Ma_desk; std::set<Ma_card>data;//玩家手中的牌 Ma_card last;//玩家手中最近一次拿到的牌,便于处理胡牌规则 std::string name;//玩家名字 bool flag = true;//是玩家还是电脑 long long asset = 0;//玩家财富 std::size_t multiple = 1;//下注倍数 long long base = 100;//下注的基数 std::size_t sideflag = 0;//边牌计数 std::size_t drillflag = 0;//钻牌计数 bool myself = false; //自摸标志 bool doorclear = true; //门清标志 public: Player() = default; Player(const std::string &n, bool f = true, long long a = 0, std::size_t m = 1, std::size_t b = 100) :name(n), flag(f), asset(a), multiple(m), base(b) {} Player(const Ma_desk &md, std::string(&p)[14]); void play_get(Ma_card m);//玩家取牌 void play_send(std::string);//玩家发牌 long long computer(bool);//计算胡牌或输牌后所得 void set_multiple(std::size_t m);//设置下注倍数 void set_base(std::size_t b);//设置下注基数 std::size_t calc_appoint_vol(const std::string ID)const //计算某一张牌的数量 { std::size_t num = 0; for (auto it : data) if (it.getID().substr(0,2) == ID) num++; return num; } std::size_t calc_wan_count()const //计算万牌的张数 { std::size_t n = 0; for (auto it : data) if (it.is_wan()) n++; return n; } std::size_t calc_bing_count()const //计算饼牌的张数 { std::size_t n = 0; for (auto it : data) if (it.is_bing()) n++; return n; } std::size_t calc_tiao_count()const //计算条牌的张数 { std::size_t n = 0; for (auto it : data) if (it.is_tiao()) n++; return n; } std::size_t calc_feng_count()const //计算风牌的张数 { std::size_t n = 0; for (auto it : data) if (it.is_feng()) n++; return n; } std::set<Ma_card>& getData() { return data; } /* friend std::ostream &operator<<(std::ostream &os, const Player &p) { std::cout << "玩家名字:" << p.name << std::endl; std::cout << "拥有的牌: "; for (auto it = p.data.begin(); it != p.data.end(); ++it) std::cout << *it << " "; return os; } */ }; void Player::play_get(Ma_card m) { auto ret = data.insert(m); last = m; if (!ret.second) throw std::invalid_argument(m.getName(m.getID())+"这张牌错误!"); } void Player::play_send(std::string id) { auto it = data.begin(); bool flag = true; for (; it != data.end(); ) if (it->getID() == id) { it = data.erase(it); flag = false; break; } else ++it; if (it == data.end() && flag) throw std::out_of_range("玩家手中没有这张牌!"); } void Player::set_multiple(std::size_t m) { multiple = m; } void Player::set_base(std::size_t b) { base = b; } long long Player::computer(bool flag) { long long result = 0; if (flag) { result = base * multiple; } else { result = -base * multiple; } return result; } //***************************************麻将桌面管理**************************** class Ma_desk { private: using Mybase = std::map<std::string, std::string>; static std::regex win[]; std::shared_ptr<Mybase>mahjong; //载入麻将牌信息,牌名及ID std::vector<std::string>manage;//桌面麻将牌管理信息 std::size_t count;//胡牌时的总张数 public: Ma_desk(std::ifstream &); Ma_card dispatch(); std::shared_ptr<Mybase> getDeskinfo()const//调试用的 { return mahjong; } void del_this(Player &p)//调试用的 { for (auto it = p.data.begin(); it != p.data.end(); ++it) { for (auto pi = manage.begin(); pi != manage.end();) if (*pi == it->getID() && !manage.empty()) { pi = manage.erase(pi); --count; } else ++pi; } } bool is_over()const { if (manage.size() < 10)//流局剩余牌数量 return true; return false; } bool is_win(const Player&)const;//*********玩家是否胡牌,核心程序之一**************** bool judge(const Player &)const; std::tuple<Ma_card, Ma_card,std::size_t> judge_two(const Player &)const; std::pair<std::string,bool> is_convention(const Player&p)const //判断是不是尿胡 { } std::pair<std::string, bool> is_enough(const Player&p)const //判断是不是够扇 { std::size_t w(0), b(0), t(0); for (auto it = p.data.begin(); it != p.data.end(); ++it) { if ((*it).is_wan()) ++w; if ((*it).is_bing()) ++b; if ((*it).is_tiao()) ++t; } if (w >= 8 || b >= 8 || t >= 8) return std::make_pair("够扇", true); return std::make_pair("够扇", false); } std::pair<std::string, bool> is_zfb(const Player &p)const //判断是不是中发白 { std::size_t red = p.calc_appoint_vol("H0"); std::size_t fa = p.calc_appoint_vol("H1"); std::size_t white = p.calc_appoint_vol("H2"); if (red != 0 && red == fa && red == white) return std::make_pair("中发白", true); return std::make_pair("中发白", false); } std::pair<std::string,bool> is_samecol(const Player&p)const //判断是不是清一色 { std::size_t vol = p.data.size(); if (p.calc_bing_count() == vol || p.calc_tiao_count() == vol || p.calc_feng_count() == vol || p.calc_wan_count() == vol) return std::make_pair("清一色", true); return std::make_pair("清一色", false); } std::pair<std::string,bool> is_ascol(const Player&p)const //判断是不是混一色 { std::size_t vol = p.calc_feng_count(); std::size_t total = p.data.size(); if (vol != 0) if (p.calc_bing_count() + vol == total || p.calc_tiao_count() + vol == total || p.calc_wan_count() + vol == total) return std::make_pair("混一色", true); return std::make_pair("混一色", false); } std::pair<std::string,bool> is_drill(const Player&p)const //判断是不是钻胡 { if (p.drillflag == 3) return std::make_pair("三钻", true); if (p.drillflag == 4) return std::make_pair("四钻", true); return std::make_pair("没有钻牌", false); } std::pair<std::string, bool> is_side(const Player&p)const //判断是不是边 { if (p.sideflag == 3) return std::make_pair("三边", true); if (p.sideflag == 4) return std::make_pair("四边", true); return std::make_pair("没有边牌", false); } std::pair<std::string,bool> is_doorclear(const Player&p)const //判断是不是门清 { return std::make_pair("门清", p.doorclear); } std::pair<std::string,bool> is_gap(const Player &p)const //判断是不是缺门 { std::size_t num[3]{ p.calc_bing_count(), p.calc_tiao_count(), p.calc_wan_count() }, total = 0; for (int n = 0; n < 3; ++n) if (num[n] == 0) ++total; if (total == 1) return std::make_pair("缺门", true); if (total == 2) return std::make_pair("缺两门", true); return std::make_pair("缺门", false); } std::pair<std::string, bool> is_258(const Player &p)const //判断是不是258将 { } std::pair<std::string, bool> is_foursame(const Player &p)const //判断是不是四归一 { auto result = accu_type_count(p.data.begin(), p.data.end(), 4); return std::make_pair("四归一", result > 0); } std::pair<std::string, bool> is_no19(const Player &p)const //判断是不是断19 { for (auto it = p.data.begin(); it != p.data.end(); ++it) { if (it->is_feng()) return std::make_pair("断幺九", false); if(stoul(it->getID().substr(1, 1))==1|| stoul(it->getID().substr(1, 1))==9) return std::make_pair("断幺九", false); } return std::make_pair("断幺九", true); } std::pair<std::string, bool> is_pound(const Player&p)const //判断是不是砸 { auto result = judge_two(p); auto pound = std::get<2>(result); //std::cout << std::get<0>(result) << " " << pound << " " << std::get<1>(result) << std::endl; if (pound == 3) return std::make_pair("三砸", true); if (pound == 4) return std::make_pair("四砸", true); return std::make_pair("没有砸", false); } std::pair<std::string, bool> is_high(const Player&p)const //判断是不是一边高 { bool is_no[3]{ true,true,true };//共有三种方案 std::size_t flag(0); //方案一 p.last前面一张后面一张 auto pt = p; for (auto it = pt.data.begin(); it != pt.data.end(); ) { if (*it == pt.last) { ++flag; it = pt.data.erase(it); } else ++it; if (flag == 2) break; } if (flag != 2)//没有其余牌与最后一张牌相同 return std::make_pair("一边高", false); flag = 0;

33,311

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 新手乐园
社区管理员
  • 新手乐园社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧