截止现在,见实私域换量联盟已超1800家品牌,私域粉丝数超百万以上品牌100多家。累积私域池45亿粉丝。
换量联盟只限品牌,且为松散合作圈子,支持各大品牌互相置换合作,包括IP联名、联合市场推广、BD互推、渠道售卖等各种形态。及见实围绕“开学季”、“国庆”、“双11”大促等时间点和市场特点发起的市场联合运营活动等。
这些信息,会同步整理到每天发布在见实公号中。(点击查阅:换量联盟新人必读手册)
如您也想和更多品牌开展换量/异业合作,欢迎填写报名问卷(搜索“见实”公众号并发送“换量”即可)。提示,仅有此一个加入方式噢。
接下来,让我们一起看看最新的换量、招聘供需详情吧,如下,Enjoy:
换量异业合作品牌1
文和友
简介:文和友,2011年起步于长沙街头的全国知名文化餐饮品牌以做小龙虾和小吃起家。现拥有城市文和友 (原名“超级文和友”)、文和友龙虾馆、不超级文和友、文和友食品董顺桃臭豆腐等子品牌,形成了餐饮小吃、包装食品、文创礼品等主营产品。自建文和友望城荷花虾产业园,创办了小龙虾产业研究院,进行荷花虾生态屯养、小龙虾良种繁育研究,同时为当地养殖户提供养殖辅导服务。从2019年,占地面积2万m、共6层楼的长沙文和友开放起文和友因客流火爆几次登上热搜,门店年接待量超1000万人次。因为全新的用户体验,文和友成为食客和游客眼中的超级网红,媒体和业界津津乐道的“新物种”,依托于文和友还开展了电商消费品预制菜业务线的文和友食品。流量池:公众号200万私域池:12万+粉丝画像:一二线城市白领女性为主合作形式:购买、BD互换、IP联名其他需求:暂无联系方式:添加见实特助(微信ID:jianshisir)并回复【文和友】品牌2
童森教育
简介:童森教育|专家云课堂,面向幼儿园提供家长端的家庭教育领域专家在线课堂服务。流量池:10万+私域池:个微10万+粉丝画像:用户总量:10W+ (其中学龄前3-6岁儿童家长76W+,准小学一年级学生家长3 W+,小学二年级学生家长1W+) 用户增长:日均500+ (正常学期中工作日,面向B端幼儿园市场的拓展,固定带来C端用户资源) 用户分布:江苏、山东、福建、安徽、四川、重庆等(按用户规模排序);用户画像:二三四线城市、公办幼儿园、80%+女性家长 用户标签:省份、城市、幼儿园、儿童年龄、家长身份(爸爸、妈妈....)合作形式:购买、IP联名其他需求:暂无联系方式:添加见实特助(微信ID:jianshisir)并回复【童森教育】品牌3
喜枚
简介:喜枚,订阅制高端可生食蛋卡。顾客只需一次订购,一年月月配送。鲜蛋现发。顺丰包邮配送。流量池:10万+ 线下实体付费会员私域池:10万+ 线下实体付费会员粉丝画像:25+岁高净值人群,对生活有品质要求宝妈,健身瑜伽人群,有礼品需要人群。合作形式:联名、互换其他需求:暂无联系方式:添加见实特助(微信ID:jianshisir)并回复【喜枚】品牌4
罗拉密码
简介:中高端女性成衣原创设计流量池:抖音共计:860万私域池:正在筹备期粉丝画像:都市白领女强人合作形式:其他其他需求:希望有合作的机会联系方式:添加见实特助(微信ID:jianshisir)并回复【罗拉密码】品牌5
小拉出行
简介:小拉出行,致力于成为实惠,安全,便捷的互联网出行服务品牌。小拉出行服务司乘两端,主要定位于年轻,有高效出行需求的客户群体,提供优惠便利的用车服务,可以满足乘客多场景,随机性,定制化的出行需求。流量池:企业微信25万私域池:企业微信25万粉丝画像:学生以及35岁左右的公司职工 合作形式:CPS转化结算其他需求:暂无联系方式:添加见实特助(微信ID:jianshisir)并回复【小拉出行】品牌6
梅见
简介:1、梅见是中国人自产的青梅酒,更适合中国人的口味。梅见知名度高,长居中国青梅酒销售排名榜首,全网已销售1200万件,购买人数超578万人;2、梅见已连续在2021年、2022年、2023年蝉联荣获酒类权威奖项——世界品质评鉴大会国际蒙特奖金奖。流量池:16658029人私域池:企微 60000+粉丝画像:25-45 男45% 女55% 合作形式:购买 私域粉丝置换其他需求:暂无联系方式:添加见实特助(微信ID:jianshisir)并回复【梅见】↘换量品牌一览生鲜零售:
熊猫不走 钱大妈 FlowerPlus花加 爱买特 沈大成 好特卖 中原铺子 新希望(华西) 谊品生鲜 天圣福味 顺势通达(悦刻北京代理商) 虎头局 叮咚买菜 周黑鸭 广东嘉荣超市 哞哞小花牛 盒马 鲜丰水果 锅圈食汇 丘麦丘烘焙 年年有鱼 EGGLAB 天农食品 盈润农业 百果园果多美 二商肉食
餐厅美食:
廖记棒棒鸡 真功夫 同庆楼 香他她煲仔饭 豪客来牛排 熊大爷 管氏翅吧 胖哥俩 兰湘子湘菜小炒 贾国龙功夫菜 胖哥俩 卤校长火锅 重八牛府 壹宾犟人烧烤 鲜潭蒸汽石锅鱼 海盗虾饭 味满堂 陕西长安味道
食品零食:
鲁花 雀巢 五谷磨房 伊利集团 牛蒙蒙/蒙牛 新希望牛奶 君乐宝 阅农部落 榴芒一刻 良品铺子 百瑞源 统一企业 人类快乐 咚吃 圣上壹品五常大米 五芳斋 白象食品 大三湘茶油 匠心说 上海丙华实业 孕味食足 乌江榨菜 乐荷 李政昊粑粑糕 蒙牛niubay 野范鲜啤 坤生元 隔壁刘奶奶 黔西南古方红糖 明园蜂业 九只小梨/金豆芽/周十五 大希地 碗颂Bowlsong 饭扫光 四川龙帮食品 肴易购 胶囊茶语 三胖蛋 塞茵苏/圣牧低温乳品有限公司 每日黑巧 天味食品(旗下有好人家、大红袍等品牌) 杞里香 北大荒 厦门味正 珍田家 幸福西饼 麦子和麦 仟吉 泡小燕 王小卤 江西土哒哒农业发展有限公司 花蕉记 隆美栗园 热卤一叮 沈大成+邵万生 新希望华西乳业 36cake 好想你健康食品 六月鲜 百事桂格 超食元素 伊利 T137声亮亮陈皮燕窝固体饮料 福益德 自嗨锅 嘉顿 格力高 卫岗乳业 得益乳业 初巧 鲜炖燕窝 草本趣时
护肤美妆:
韩后 上美/韩束 佰草集 环亚集团(美肤宝、法兰琳卡、滋源、肌肤未来) 三草两木 girlcult 珂岸男士护肤 左颜右色 未兰 北京元知禾生物 乔本生医/守美佳 婷美 怡思丁防晒水 植美村 野兽青年YOUNGBEAST 云南白药采之汲 前海麦格美 丽人丽妆 汝新美肌 Refa美容仪 深圳珍妮肤 五柳泉甜梦饮/华熙生物 Refa 希野花园 kaleidos万花镜 广州酵道生物 爱茉莉太平洋 宁童童护肤 水羊潮妆 易美亚 欧泉琳 馨集萃 艾肌芙 Pinpoint 圣雪兰 广州qiuqiu 兰瑞 诗丽堂 德亿 普莉斯町 格莱蜜 蜥蜴会直供严选 三草两木 娇兰佳人 屈臣氏 资生堂 圣梦亲体美肤生活馆 蔻之初 Tripollar初普 悦诗风吟 肤见Cistto 太真化妆品 圣雪兰 青颜博士 圣雪兰 可可秀妍
珠宝首饰:
周大福珠宝 世纪缘珠宝 香港永福珠宝 i do珠宝 诗普琳珠宝 FANCI范琦 金雅福 欧阳琴珠宝 荟萃楼珠宝 千叶珠宝
酒/茶:
贡润祥茶膏 洋小慢 牛啤堂 CHALI茶里 南蝶贸易 锐澳酒业 酒号堡 贝叶集 宝酝集团 澜沧古茶 尚品荟萃酒业 晋善晋美酒业 走起清酿 今日酒价 成都中南糖酒 贵阳威尼托
服饰配饰:
九牧王 海澜之家 江南布衣集团 百丽国际 青蛙王子 阳光名店 伊维斯 芊艺 青婉 遐内衣 太平鸟男装 与狼共舞男装 MOONWK(月步) 艾莱依 特步 sussi古色兵码勇 bingdaily小冰定制 Missshine 漫画家(MANHOJIA) 影儿时尚集团 HUI/艺之卉时尚集团 海昌隐形眼镜 30.r 鼎骏服饰 壹廿运动 千百度集团 达芙妮 PlaySERIOUS 苏州依链科技 T.YES羽绒服 WARMTREES 古木夕羊 初棉 天创时尚 超视立 爆款商贸 LINC金羽杰 超视立 天创时尚 意大利零度 飞鸟和新酒 依文集团 包家服饰 CAT Dspace YOU+轻奢女装 泽字社 魔声严选 星选优品 艾安琪 边缝 Fmacm SIEGO西蔻 温州德赛集团 Eurkea 破天荒科技 海尔曼斯 依之舍 ZHONGWEIWEI 茜子 Gap神仙妈咪汇 小ck 紫色花语 雪中飞
母婴护理:
Deeyeo德佑 全棉时代 爱他美 帮宝适 孩子王 妙研生物 斯利安 玖小时文化 彩兔科技 凯儿得乐 贝肽斯母婴 好孩子 可优比 CICIIBEAR齐齐熊 Boiron法国宝弘 倍儿行 基诺浦 山东鼎鸿 多多家 elittle逸乐途 年衣 森林棠 伊维诗乐(evoceler)火火兔 Rookie 小雅象 Amila童装 广州润洁 bebebus 想象童装 贝贝粒母婴 鹿小吾 艾宝贝 基诺浦 逸乐途 美姿妈妈直营连锁 新启成集团 妈妈π
母婴食品:
贝因美 圣元优博 飞鹤电商平台 奶酪博士 蓓康僖 喜安智奶粉 禾泱泱 哈维生物 莱思纽卡 喵小侠 美卡熊
医药健康:
同仁堂健康 白云山药业 红日药业 阜大药号 扬子江药业 美中宜和医疗 swisse立健药店连锁 NBB 均瑶健康 健民医药 检逸医疗 小珂丽格 硬货先生 医小租/医贝诺 国家癌症中心 四川杏林医药 橄榄枝健康 轻通 泰恩康医药 怡脂 easysculpt 力克 博斯腾科技 白药生活+ 维卫康 暨大穗华口腔 概念180 童颜微美 美莱医疗 医鹿 蔓迪 健康中山、慧康中山、温州AI健康 浙江睿风 齿邦口腔连锁 美可普口腔 硅基动感 睿思尚品 宜生健康 999澳诺 深圳远东妇产医院 上膳良成 康老板 善生国际 杰士邦 同仁堂知嘛健康 快速问医生 彩虹医生 奇正藏药 澳维诺 温致科技 养世纪睡眠肽 就要你健康 炯小炯 新世纪医疗 德医皮肤 Schiff旭福 聚鹿康复 POSITIVE HOTEL 东方康圣健康 圣安米悦心理咨询 嗨CC 归领医疗 叮当快药 海俪恩 东南医药连锁 华熙生物-黑零 三诺生物 清风定 北京彩晔健康 汉康生物 有品科技picooc 欧几里德 何氏眼科 葵花药业 明眸皓齿(杭州口腔医院) 利薇德泰 奖门人食养 德伦口腔 胡庆余堂 条李 亿而悠 齿邦口腔连锁 观心实验室 亮健好药 山东哲成生物 雪活灵 壹念科技 张西峰微创脊柱中心
运动户外:
CAMEL骆驼 TOPSPORTS滔搏运动 乔丹&adidas经销商 hyperice筋膜枪 adidas/nike-锐力体育 探路者 堡狮龙bossini(李宁旗下) 鸿星尔克 Keep 单双号 Therabody 上海锐力健身装备有限公司 跑团邦
个人护理:
宝洁 参半 冷酸灵 舒客 BOP波普专研 生气斑马 韩愢 欧可林 丝域养发 DEVIL&DETAIL究式生活 美姿妈妈产后恢复中心 挪威Jordan 域发 博士园养发
潮流玩具:
TOP TOY 奥飞娱乐 锦鲤拿趣 ClicBot可立宝 主题派对 乐高活动中心 罗弗 小菜鸡潮玩 汇乐玩具 Hape 玩偶遇到爱
媒体/自媒体:
懂车帝 有车以后 军武次位面 全国广场舞大赛 么么直播 国潮广场舞 视频号端爷大气 武汉博之恒 蘩鸢直播 七朵丝绸 理想宝妈 十点配音 功道讲堂 彬彬有理 卓越智库 赫兹少女Her Zgirl 伴言平台 良心网 林粥粥 护研社 广州四阶里 好家长圈 福特宝 武汉诗意文化传媒 北坡BePole 社博 解郁丸 投稿派 金财互联 前程科教 焦点科技 微商公社 呼伦赞 卓越赣商 重庆趣象传媒 酷梦青年 上汽车享家 万孚健康(金秀儿) 野新派 小白秤 vivi探店 乐退族 时代海棠文化 上海源爱文化 元宇宙漂流局 懒懒
电商平台:
转转 旅购 豌豆公主 瞧瞧好货 海南离岛免税店 小鹅团 驿达食品 战壕网络 八八精选 深呼吸来咪 聚惠天下吃喝玩乐平台 哆邦惠 俏妃严选 蔚车 看购福利 南有佳品 国美电器 比利司全球好货 米妈 懂您烘焙 返利网 太平洋母婴 爆店 由物 小绿券 上海霁集贸易 持家有道 星速购 热饭电商 八百方 顺哥甄选 宜宾三江汇海科技 广东海外购 时宜志 呆萌价 芬香 云小派 广电广小店 云悦共享电商 悦店 积马
家居家装:
啄木鸟家庭维修 佛山照明 艾芬达 研选 全家微选 住小帮 绘睡 铭品装饰 花木美品家居 界面科技 涵普 明堂红木 深爱居 自然醒 科凡家居 艾美家 爱空间家装
数码家电:安克创新 长虹美菱中国区 联想来酷科技 凯伦诗 Zeiss卡尔蔡司 孩视宝 玻妞擦窗机器人 好视力 几光 QMDT 须眉科技 漫步者 荣事达 海信白电 OSIM傲胜 如影智能 美的 美国西屋 小熊电器 INXNI 以内 追觅
教育:
美术宝 好未来 凯叔讲故事 喜马拉雅儿童 猿辅导-南瓜科学 阿尔法蛋 新东方(重庆)网易有道 火花教育 欢乐童年 财鸟理财学堂 千聊 好来来彼芯 优路教育 习惯熊 班级小管家 家长知校 方直金太阳 上海典则文化 艺术宝 高途 小步早教 新东方 新精英生涯(古典古少侠) 每周微课 光明园迪 LingoAce 火把知识 海沛美学 小象学院 飞慕课 HD Education 渡影 尚德 深圳大白有品 顺势教育 统一AI 幸福双翼 博学宝 极客时间 民生在线教育 大陈唯舞 咚咚仔与咕咕喵 留归学堂 宝贝走天下 一招/一早 冰底学堂 浙江潮礼文化 喵喵机/作业帮 Momself 平行线教育 作业帮 夏骆学堂 升本猫 伴鱼 博商博文 学而思网校 小猪趣学 上海卡越教育 量子之歌 圆梦书店 广东易百分文化传媒
生活服务:
顺丰同城 58到家 集客生活文化传播 深港驾校 英皇电影城 车海洋 杰拉网咖(JULYI-CAFE) 章鱼电商 指望SPA 华扬联众 精武门 顺丰同城急送 湖南星富通 一起约茶 虎彩集团 名气家 香哈菜谱 中饮联 厦门悠生活 这位同学 酷某人干洗 成都杰兴华汽车服务
宠物:
新瑞鹏宠物医疗集团 玛氏食品 杭州E宠科技 再三/竺丰 小壳Cature 海洋之星宠物食品 宠兰科技 佳乐滋 喵湾科技 KNOWZA 宠帮帮 阿闻宠物 两小无猜 按食出动 小宠 畅享优品 宁波十方宠物类保险 金多乐 猫森林宠物用品
图书学习:
博库书城 广州新华集团购书中心 科大讯飞 福州亮阅文化 懒人听书 磨铁/轻果剧场/小浪滔滔 当当 潇湘书院 阳光宝贝 潇湘书院 中信出版集团 青豆书坊 中信书院 叫叫阅读 听力熊复读机 北京云亭文化 中信出版社 网易有道 樊登读书
茶饮咖啡:
7分甜 fnf精品速溶茶/八马茶业 小罐茶 沪上阿姨鲜果茶 TeaMajor鲜叶说 ITEAMO azi coffee 茉莉奶白
交通文旅:
嘀嗒出行 T3出行 同程旅行 新绎控股文旅板块 涵田度假村 复星文旅 京东汽车 开元酒店 百达星系 王小慧艺术馆 云上草原 宝盛集团 住友酒店集团 京东京车会 七十迈 帮邦行 吉利汽车 阳光出行网约车 大王岭漂流 侣行租车Lite 前小桔创意农场 呈心酒店
地产百货:
银泰百货 龙湖集团 K11购物艺术中心 天河城百货 重庆华宇集团 懂居文化 百利商业 万达广场 吾悦广场
商超便利:
物美 宜快宜慢便利连锁 锅圈食汇 中石化易捷
金融保险:
理财魔方 华泰证券 新奥保险经纪 水滴保 众安保险 富德生命人寿 呗嗒 汇丰金融 中财君道 招联金融 易博通eSender
通讯:
双V会员 长沙联通 中国联通北京市分公司
平台:
怡亚通 广州简知信息 福建山海盛世 富圈圈 微脉 海峡华艺 易企秀 安徽新虾网 美团 腾讯课堂 企鹅吉盒 逗豆星球 集藏家 大丰收 南京中益青年 当贝 北高峰 哈哈出行 一苗通 薄荷车选 IT金英会 快看漫画 喵回收 酷狗概念版 奇思妙想 慧用工 云闪付 欧菲斯集团 有趣计划 学长派 律谷云法律共享平台 集藏家 正和岛 花瓣网 高灯科技 赛尔汇 名龙堂造 腾讯
培训招聘:
青团社 前程无忧 青云网聘 人瑞人才 微服优选 去狮城科技 肯耐珂萨/肯家 博罗派 58同城招聘 安心电话录音 去狮城科技
其他:
立白 蓝月亮 中顺洁柔 PODO漫画 广博文具 南国书香 艺康、餐智选 极物严选 华膳信息 米粒盲盒小程序 绿葆 袋拉拉 giffarine/芝芙莲 恒安/心相印/七度空间 餐智选 TAIC太可 隐舍瑜伽 伊顿国际幼儿园 麦淘亲子 神州鹰 艺康集团(Ecolab) 盛趣游戏 富贵竹 洛苑文化 青鸟消防 仝友知工程 丸兔科技 源密码 Seke 童心同乐 聚惠扫扫 爱丽思IRIS 言启演示 名龙堂造 曼联俱乐部/梦剧场 布咚音乐 GERM 极能充 微光app 蔓莎蒂 一莎斗金 油画家维克多/油画家Michael 凡创文化 银湖妈妈帮 寐觉晚安睡眠香膏 招联消金 顺势通达科技 野兽青年YOUNGBEAST 小倍养基
哦,对了:
您想获取的私域资料和、私域服务、私域换量、游学等活动,请在见实公号菜单栏领取;或添加见实小boss微信(微信号:jskj44)报名加入会员。↘私域服务对接1.私域讲师团 2.私域换量联盟 3.私域服务商黄页 4.超全787篇私域案例大汇总!最近在网上看到一个有意思的开源项目,快手团队开发的开源AI斗地主——DouZero。今天我们就一起来学习制作一个基于DouZero的欢乐斗地主出牌器,看看AI是如何来帮助我们斗地主,赢欢乐豆,实现财富自由的吧!
首先一起来看看AI斗地主出牌器的效果:
私信小编01即可获取大量python学习资源
下面,我们开始介绍这个AI出牌器的制作过程。
一、核心功能设计首先我们这款出牌器是基于DouZero开发的,核心是需要利用训练好的AI模型来帮助我们,给出最优出牌方案。
其次关于出牌器,先要需要确认一个AI出牌角色,代表我们玩家自己。我们只要给这个AI输入玩家手牌和三张底牌。确认好地主和农民的各个角色,告诉它三个人对应的关系,这样就可以确定队友和对手。我们还要将每一轮其他两人的出牌输入,这样出牌器就可以根据出牌数据,及时提供给我们最优出牌决策,带领我们取得胜利!
那么如何获取三者之间的关系呢?谁是地主?谁是农民?是自己一人作战还是农民合作?自己玩家的手牌是什么?三张底牌是什么?这些也都需要在开局后确认好。
拆解需求,大致可以整理出核心功能如下:
UI设计排版布局
显示三张底牌显示AI角色出牌数据区域,上家出牌数据区域,下家出牌数据区域,本局胜率区域AI玩家手牌区域AI出牌器开始停止手牌和出牌数据识别
游戏刚开始根据屏幕位置,截图识别AI玩家手牌及三张底牌确认三者之间的关系,识别地主和农民角色,确认队友及对手关系识别每轮三位玩家依次出了什么牌,刷新显示对应区域AI出牌方案输出
加载训练好的AI模型,初始化游戏环境每轮出牌判断,根据上家出牌数据给出最优出牌决策自动刷新玩家剩余手牌和本局胜率预测二、实现步骤1. UI设计排版布局根据上述功能,我们首先考虑进行简单的UI布局设计,这里我们使用的是pyqt5。核心设计代码如下:
def setupUi(self, Form): Form.setObjectName("Form") Form.resize(440, 395) font = QtGui.QFont() font.setFamily("Arial") font.setPointSize(9) font.setBold(True) font.setItalic(False) font.setWeight(75) Form.setFont(font) self.WinRate = QtWidgets.QLabel(Form) self.WinRate.setGeometry(QtCore.QRect(240, 180, 171, 61)) font = QtGui.QFont() font.setPointSize(14) self.WinRate.setFont(font) self.WinRate.setAlignment(QtCore.Qt.AlignCenter) self.WinRate.setObjectName("WinRate") self.InitCard = QtWidgets.QPushButton(Form) self.InitCard.setGeometry(QtCore.QRect(60, 330, 121, 41)) font = QtGui.QFont() font.setFamily("Arial") font.setPointSize(14) font.setBold(True) font.setWeight(75) self.InitCard.setFont(font) self.InitCard.setStyleSheet("") self.InitCard.setObjectName("InitCard") self.UserHandCards = QtWidgets.QLabel(Form) self.UserHandCards.setGeometry(QtCore.QRect(10, 260, 421, 41)) font = QtGui.QFont() font.setPointSize(14) self.UserHandCards.setFont(font) self.UserHandCards.setAlignment(QtCore.Qt.AlignCenter) self.UserHandCards.setObjectName("UserHandCards") self.LPlayer = QtWidgets.QFrame(Form) self.LPlayer.setGeometry(QtCore.QRect(10, 80, 201, 61)) self.LPlayer.setFrameShape(QtWidgets.QFrame.StyledPanel) self.LPlayer.setFrameShadow(QtWidgets.QFrame.Raised) self.LPlayer.setObjectName("LPlayer") self.LPlayedCard = QtWidgets.QLabel(self.LPlayer) self.LPlayedCard.setGeometry(QtCore.QRect(0, 0, 201, 61)) font = QtGui.QFont() font.setPointSize(14) self.LPlayedCard.setFont(font) self.LPlayedCard.setAlignment(QtCore.Qt.AlignCenter) self.LPlayedCard.setObjectName("LPlayedCard") self.RPlayer = QtWidgets.QFrame(Form) self.RPlayer.setGeometry(QtCore.QRect(230, 80, 201, 61)) font = QtGui.QFont() font.setPointSize(16) self.RPlayer.setFont(font) self.RPlayer.setFrameShape(QtWidgets.QFrame.StyledPanel) self.RPlayer.setFrameShadow(QtWidgets.QFrame.Raised) self.RPlayer.setObjectName("RPlayer") self.RPlayedCard = QtWidgets.QLabel(self.RPlayer) self.RPlayedCard.setGeometry(QtCore.QRect(0, 0, 201, 61)) font = QtGui.QFont() font.setPointSize(14) self.RPlayedCard.setFont(font) self.RPlayedCard.setAlignment(QtCore.Qt.AlignCenter) self.RPlayedCard.setObjectName("RPlayedCard") self.Player = QtWidgets.QFrame(Form) self.Player.setGeometry(QtCore.QRect(40, 180, 171, 61)) self.Player.setFrameShape(QtWidgets.QFrame.StyledPanel) self.Player.setFrameShadow(QtWidgets.QFrame.Raised) self.Player.setObjectName("Player") self.PredictedCard = QtWidgets.QLabel(self.Player) self.PredictedCard.setGeometry(QtCore.QRect(0, 0, 171, 61)) font = QtGui.QFont() font.setPointSize(14) self.PredictedCard.setFont(font) self.PredictedCard.setAlignment(QtCore.Qt.AlignCenter) self.PredictedCard.setObjectName("PredictedCard") self.ThreeLandlordCards = QtWidgets.QLabel(Form) self.ThreeLandlordCards.setGeometry(QtCore.QRect(140, 10, 161, 41)) font = QtGui.QFont() font.setPointSize(16) self.ThreeLandlordCards.setFont(font) self.ThreeLandlordCards.setAlignment(QtCore.Qt.AlignCenter) self.ThreeLandlordCards.setObjectName("ThreeLandlordCards") self.Stop = QtWidgets.QPushButton(Form) self.Stop.setGeometry(QtCore.QRect(260, 330, 111, 41)) font = QtGui.QFont() font.setFamily("Arial") font.setPointSize(14) font.setBold(True) font.setWeight(75) self.Stop.setFont(font) self.Stop.setStyleSheet("") self.Stop.setObjectName("Stop") self.retranslateUi(Form) self.InitCardednnect(Formit_cards) self.Stopednnect(Form.stop) QtCore.QMetaObjectnnectSlotsByName(Form)def retranslateUi(self, Form): _translate = QtCore.QCoreApplication.translate Form.setWindowTitle(_translate("Form", "AI欢乐斗地主--Dragon少年")) self.WinRate.setText(_translate("Form", "胜率:--%")) self.InitCard.setText(_translate("Form", "开始")) self.UserHandCards.setText(_translate("Form", "手牌")) self.LPlayedCard.setText(_translate("Form", "上家出牌区域")) self.RPlayedCard.setText(_translate("Form", "下家出牌区域")) self.PredictedCard.setText(_translate("Form", "AI出牌区域")) self.ThreeLandlordCards.setText(_translate("Form", "三张底牌")) self.Stop.setText(_translate("Form", "停止"))
实现效果如下:
2. 手牌和出牌数据识别下面我们需要所有扑克牌的模板图片与游戏屏幕特定区域的截图进行对比,这样才能获取AI玩家手牌、底牌、每一轮出牌、三者关系(地主、地主上家、地主下家)。
识别AI玩家手牌及三张底牌:
我们可以截取游戏屏幕,根据固定位置来识别当前AI玩家的手牌和三张底牌。核心代码如下:
# 牌检测结果滤波def cards_filter(self, location, distance): if len(location) == 0: return 0 locList = [location[0][0]] count = 1 for e in location: flag = 1 # “是新的”标志 for have in locList: if abs(e[0] - have) <= distance: flag = 0 break if flag: count += 1 locListend(e[0]) return count# 获取玩家AI手牌def find_my_cards(self, pos): user_hand_cards_real = "" img = pyautoguireenshot(region=pos) for card in AllCards: result = pyautogui.locateAll(needleImage='pics/m' + card + '.png', haystackImage=img, confidence=self.MyConfidence) user_hand_cards_real += card[1] * selfds_filter(list(result), self.MyFilter) return user_hand_cards_real# 获取地主三张底牌def find_three_landlord_cards(self, pos): three_landlord_cards_real = "" img = pyautoguireenshot(region=pos) img = img.resize((349, 168)) for card in AllCards: result = pyautogui.locateAll(needleImage='pics/o' + card + '.png', haystackImage=img, confidence=self.ThreeLandlordCardsConfidence) three_landlord_cards_real += card[1] * selfds_filter(list(result), self.OtherFilter) return three_landlord_cards_real
效果如下所示:
地主、地主上家、地主下家:
同理我们可以根据游戏屏幕截图,识别地主的图标,确认地主角色。核心代码如下:
# 查找地主角色def find_landlord(self, landlord_flag_pos): for pos in landlord_flag_pos: result = pyautogui.locateOnScreen('pics/landlord_words.png', region=pos, confidence=self.LandlordFlagConfidence) if result is not None: return landlord_flag_posdex(pos) return None
这样我们就可以得到玩家AI手牌,其他玩家手牌(预测),地主三张底牌,三者角色关系,出牌顺序。核心代码如下:
# 坐标self.MyHandCardsPos = (414, 804, 1041, 59) # AI玩家截图区域self.LPlayedCardsPos = (530, 470, 380, 160) # 左侧玩家截图区域self.RPlayedCardsPos = (1010, 470, 380, 160) # 右侧玩家截图区域self.LandlordFlagPos = [(1320, 300, 110, 140), (320, 720, 110, 140), (500, 300, 110, 140)] # 地主标志截图区域(右-我-左)self.ThreeLandlordCardsPos = (817, 36, 287, 136) # 地主底牌截图区域,resize成349x168def init_cards(self): # 玩家手牌 selfer_hand_cards_real = "" selfer_hand_cards_env = [] # 其他玩家出牌 self.other_played_cards_real = "" self.other_played_cards_env = [] # 其他玩家手牌(整副牌减去玩家手牌,后续再减掉历史出牌) self.other_hand_cards = [] # 三张底牌 self.three_landlord_cards_real = "" self.three_landlord_cards_env = [] # 玩家角色代码:0-地主上家, 1-地主, 2-地主下家 selfer_position_code = None selfer_position = "" # 开局时三个玩家的手牌 selfd_play_data_list = {} # 出牌顺序:0-玩家出牌, 1-玩家下家出牌, 2-玩家上家出牌 self.play_order = 0 self.env = None # 识别玩家手牌 selfer_hand_cards_real = self.find_my_cards(self.MyHandCardsPos) self.UserHandCards.setText(selfer_hand_cards_real) selfer_hand_cards_env = [RealCard2EnvCard[c] for c in list(selfer_hand_cards_real)] # 识别三张底牌 self.three_landlord_cards_real = self.find_three_landlord_cards(self.ThreeLandlordCardsPos) self.ThreeLandlordCards.setText("底牌:" + self.three_landlord_cards_real) self.three_landlord_cards_env = [RealCard2EnvCard[c] for c in list(self.three_landlord_cards_real)] # 识别玩家的角色 selfer_position_code = self.find_landlord(self.LandlordFlagPos) if selfer_position_code is None: items = ("地主上家", "地主", "地主下家") item, okPressed = QInputDialog.getItem(self, "选择角色", "未识别到地主,请手动选择角色:", items, 0, False) if okPressed and item: selfer_position_code = itemsdex(item) else: return selfer_position = ['landlord_up', 'landlord', 'landlord_down'][selfer_position_code] for player in self.Players: player.setStyleSheet('background-color: rgba(255, 0, 0, 0);') self.Players[selfer_position_code].setStyleSheet('background-color: rgba(255, 0, 0, 0.1);') # 整副牌减去玩家手上的牌,就是其他人的手牌,再分配给另外两个角色(如何分配对AI判断没有影响) for i in set(AllEnvCard): self.other_hand_cards.extend([i] * (AllEnvCardunt(i) - selfer_hand_cards_envunt(i))) selfd_play_data_list.update({ 'three_landlord_cards': self.three_landlord_cards_env, ['landlord_up', 'landlord', 'landlord_down'][(selfer_position_code + 0) % 3]: selfer_hand_cards_env, ['landlord_up', 'landlord', 'landlord_down'][(selfer_position_code + 1) % 3]: self.other_hand_cards[0:17] if (selfer_position_code + 1) % 3 != 1 else self.other_hand_cards[17:], ['landlord_up', 'landlord', 'landlord_down'][(selfer_position_code + 2) % 3]: self.other_hand_cards[0:17] if (selfer_position_code + 1) % 3 == 1 else self.other_hand_cards[17:] }) print(selfd_play_data_list) # 生成手牌结束,校验手牌数量 if len(selfd_play_data_list["three_landlord_cards"]) != 3: QMessageBox.critical(self, "底牌识别出错", "底牌必须是3张!", QMessageBox.Yes, QMessageBox.Yes) selfit_display() return if len(selfd_play_data_list["landlord_up"]) != 17 or \ len(selfd_play_data_list["landlord_down"]) != 17 or \ len(selfd_play_data_list["landlord"]) != 20: QMessageBox.critical(self, "手牌识别出错", "初始手牌数目有误", QMessageBox.Yes, QMessageBox.Yes) selfit_display() return # 得到出牌顺序 self.play_order = 0 if selfer_position == "landlord" else 1 if selfer_position == "landlord_up" else 2
效果如下:
3. AI出牌方案输出下面我们就需要用到DouZero开源的AI斗地主了。DouZero项目地址:https://github/kwai/DouZero。我们需要将该开源项目下载并导入项目中。
创建一个AI玩家角色,初始化游戏环境,加载模型,进行每轮的出牌判断,控制一局游戏流程的进行和结束。核心代码如下:
# 创建一个代表玩家的AIai_players = [0, 0]ai_players[0] = selfer_positionai_players[1] = DeepAgent(selfer_position, selfd_play_model_path_dict[selfer_position])# 初始化游戏环境self.env = GameEnv(ai_players)# 游戏开始self.start()def start(self): self.envd_play_init(selfd_play_data_list) print("开始出牌\n") while not self.env_over: # 玩家出牌时就通过智能体获取action,否则通过识别获取其他玩家出牌 if self.play_order == 0: self.PredictedCard.setText("...") action_message = self.env.step(selfer_position) # 更新界面 self.UserHandCards.setText("手牌:" + str(''.join( [EnvCard2RealCard[c] for c in self.env_sets[selfer_position].player_hand_cards]))[::-1]) self.PredictedCard.setText(action_message["action"] if action_message["action"] else "不出") self.WinRate.setText("胜率:" + action_message["win_rate"]) print("\n手牌:", str(''.join( [EnvCard2RealCard[c] for c in self.env_sets[selfer_position].player_hand_cards]))) print("出牌:", action_message["action"] if action_message["action"] else "不出", ", 胜率:", action_message["win_rate"]) while self.have_white(self.RPlayedCardsPos) == 1 or \ pyautogui.locateOnScreen('pics/pass.png', region=self.RPlayedCardsPos, confidence=self.LandlordFlagConfidence): print("等待玩家出牌") selfunter.restart() while selfunter.elapsed() < 100: QtWidgets.QApplicationcessEvents(QEventLoop.AllEvents, 50) self.play_order = 1 elif self.play_order == 1: self.RPlayedCard.setText("...") pass_flag = None while self.have_white(self.RPlayedCardsPos) == 0 and \ not pyautogui.locateOnScreen('pics/pass.png', region=self.RPlayedCardsPos, confidence=self.LandlordFlagConfidence): print("等待下家出牌") selfunter.restart() while selfunter.elapsed() < 500: QtWidgets.QApplicationcessEvents(QEventLoop.AllEvents, 50) selfunter.restart() while selfunter.elapsed() < 500: QtWidgets.QApplicationcessEvents(QEventLoop.AllEvents, 50) # 不出 pass_flag = pyautogui.locateOnScreen('pics/pass.png', region=self.RPlayedCardsPos, confidence=self.LandlordFlagConfidence) # 未找到"不出" if pass_flag is None: # 识别下家出牌 self.other_played_cards_real = self.find_other_cards(self.RPlayedCardsPos) # 找到"不出" else: self.other_played_cards_real = "" print("\n下家出牌:", self.other_played_cards_real) self.other_played_cards_env = [RealCard2EnvCard[c] for c in list(self.other_played_cards_real)] self.env.step(selfer_position, self.other_played_cards_env) # 更新界面 self.RPlayedCard.setText(self.other_played_cards_real if self.other_played_cards_real else "不出") self.play_order = 2 elif self.play_order == 2: self.LPlayedCard.setText("...") while self.have_white(self.LPlayedCardsPos) == 0 and \ not pyautogui.locateOnScreen('pics/pass.png', region=self.LPlayedCardsPos, confidence=self.LandlordFlagConfidence): print("等待上家出牌") selfunter.restart() while selfunter.elapsed() < 500: QtWidgets.QApplicationcessEvents(QEventLoop.AllEvents, 50) selfunter.restart() while selfunter.elapsed() < 500: QtWidgets.QApplicationcessEvents(QEventLoop.AllEvents, 50) # 不出 pass_flag = pyautogui.locateOnScreen('pics/pass.png', region=self.LPlayedCardsPos, confidence=self.LandlordFlagConfidence) # 未找到"不出" if pass_flag is None: # 识别上家出牌 self.other_played_cards_real = self.find_other_cards(self.LPlayedCardsPos) # 找到"不出" else: self.other_played_cards_real = "" print("\n上家出牌:", self.other_played_cards_real) self.other_played_cards_env = [RealCard2EnvCard[c] for c in list(self.other_played_cards_real)] self.env.step(selfer_position, self.other_played_cards_env) self.play_order = 0 # 更新界面 self.LPlayedCard.setText(self.other_played_cards_real if self.other_played_cards_real else "不出") else: pass selfunter.restart() while selfunter.elapsed() < 100: QtWidgets.QApplicationcessEvents(QEventLoop.AllEvents, 50) print("{}胜,本局结束!\n".format("农民" if self.envner == "farmer" else "地主")) QMessageBoxrmation(self, "本局结束", "{}胜!".format("农民" if self.envner == "farmer" else "地主"), QMessageBox.Yes, QMessageBox.Yes) self.env.reset() selfit_display()
到这里,整个AI斗地主出牌流程基本已经完成了。
三、出牌器用法按照上述过程,这款AI出牌器已经制作完成了。后面应该如何使用呢?如果不想研究源码,只想使用这款AI斗地主出牌器,验证下效果,该怎么配置环境运行这个AI出牌器呢?下面就开始介绍。
1. 环境配置首先我们需要安装这些第三方库,配置相关环境,如下所示:
torch==1.9.0GitPython==3.0.5gitdb2==2.0.6PyAutoGUI==0.9.50PyQt5==5.13.0PyQt5-sip==12.8.1Pillow>=5.2.0opencv-pythonrlcard2. 坐标调整确认
我们可以打开欢乐斗地主游戏界面,将游戏窗口模式下最大化运行,把AI出牌器程序窗口需要移至右下角,不能遮挡手牌、地主标志、底牌、历史出牌这些关键位置。
其次我们要确认屏幕截图获取的各个区域是否正确。如果有问题需要进行区域位置坐标调整。
# 坐标self.MyHandCardsPos = (414, 804, 1041, 59) # 我的截图区域self.LPlayedCardsPos = (530, 470, 380, 160) # 左边截图区域self.RPlayedCardsPos = (1010, 470, 380, 160) # 右边截图区域self.LandlordFlagPos = [(1320, 300, 110, 140), (320, 720, 110, 140), (500, 300, 110, 140)] # 地主标志截图区域(右-我-左)self.ThreeLandlordCardsPos = (817, 36, 287, 136) # 地主底牌截图区域,resize成349x168
3. 运行测试当所有环境配置完成,各区域坐标位置确认无误之后,下面我们就可以直接运行程序,测试效果啦~
首先我们运行AI出牌器程序,打开欢乐斗地主游戏界面,进入游戏。当玩家就位,手牌分发完毕,地主身份确认之后,我们就可以点击画面中开始按钮,让AI来帮助我们斗地主了。
下面可以一起来看看这款AI出牌器的实验效果喔,看看AI是如何带领农民打倒地主,取得胜利的!
若本篇内容对您有所帮助,请三连点赞,再看,转发支持一下。