一、斗地主规则介绍

1.1 基本规则

参加人数:3人

总牌数:54张,从2到A,四种花色("梅花", "红桃", "黑桃", "方形"),共52张,加黑白色的小王,彩色的大王。

分牌数:每人先分17张,最后确定地主拿3张

胜利规则:三人中有一人出完牌

1.2 出牌规则

单张:任意一张牌

对子:两张一样的牌

顺子:大于四张,连续的牌

三带一:三张一样的牌带任意一张

炸弹:四张一样,或双王

1.3 大小规则

单张:从3到10,J,Q,K,A,2,小王,大王依次增大

对子:同单张规则

三带一:三张牌满足单张规则

顺子:最小牌满足单张规则

炸弹:具有通吃属性,王炸无敌,四炸满足单张规则

二、代码实现规则

2.1 定义扑克牌

每张扑克牌应该具有自己的花色与值

 /*** 定义扑克牌*/class Card implements Comparable<Card> {/*** 花色(黑桃、红桃、梅花、方块)*/private String color;/*** 大小(2-10,J,Q,K,A,大王,小王)*/private String value;public Card() {}public Card(String color, String value) {this.color = color;this.value = value;}public String getColor() {return color;}public void setColor(String color) {this.color = color;}public String getValue() {return value;}public void setValue(String value) {this.value = value;}@Overridepublic boolean equals(Object obj) {if (obj instanceof Card) {Card card = (Card) obj;if (card.value.equalsIgnoreCase(this.value) && card.color.equalsIgnoreCase(this.color)) {return true;}}return false;}@Overridepublic int hashCode() {return color.hashCode() + value.hashCode();}//定义大小规则@Overridepublic int compareTo(Card card) {return findIndex(this) - findIndex(card);}@Overridepublic String toString() {final StringBuilder sb = new StringBuilder("Card{");sb.append("color='").append(color).append('\'');sb.append(", value='").append(value).append('\'');sb.append('}');return sb.toString();}}

2.2 定义玩家

每个玩家具有自己的游戏名,在游戏中具有自己的上家与下家,持有牌与预出牌,并记录当前是否具有出牌资格

   /*** 定义玩家*/static class Player {/*** 用户名*/private String username;/*** 是否为第一个出牌*/private boolean first;/*** 持有牌*/LinkedList<Card> cards = new LinkedList<>();/*** 当前选择出牌*/LinkedList<Card> putCards = new LinkedList<>();/*** 上一位出牌人*/private Player before;/*** 下一位出牌人*/private Player next;public Player() {}public Player(String username) {this.username = username;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public void setCards(LinkedList<Card> cards) {this.cards = cards;}public boolean isFirst() {return first;}public void setFirst(boolean first) {this.first = first;}public LinkedList<Card> getCards() {return cards;}public LinkedList<Card> getPutCards() {return putCards;}public void setPutCards(LinkedList<Card> putCards) {this.putCards = putCards;}public Player getBefore() {return before;}public void setBefore(Player before) {this.before = before;}public Player getNext() {return next;}public void setNext(Player next) {this.next = next;}@Overridepublic String toString() {final StringBuilder sb = new StringBuilder("Player{");sb.append("username='").append(username).append('\'');sb.append(", cards=").append(cards);sb.append(", putCards=").append(putCards);sb.append('}');return sb.toString();}}

2.3 定义游戏规则

一场完整的斗地主,需要洗牌,分牌,确定地主,判断出牌是否大于上两家

/*** 玩扑克牌** @author sunyiran* @date 2018-10-19*/
public class PlayCards {/*** 扑克牌的值*/private static final String[] cardVlues = {"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2", "小王","大王"};/*** 扑克牌的花色*/private static final String[] cardColors = {"梅花", "红桃", "黑桃", "方形"};/*** 一副扑克牌*/private ArrayList<Card> cardList = new ArrayList<>(54);/*** 参加玩家*/private Player[] players;public PlayCards() {}public PlayCards(Player[] players) {getCardArr();this.players = players;}/*** 获取一副扑克牌的算法*/private void getCardArr() {//前52张牌具有花色for (int i = 0; i < 52; i++) {Card card = new Card();card.setColor(cardColors[i % 4]);card.setValue(cardVlues[i % 13]);cardList.add(card);}cardList.add(new Card("黑白", "小王"));cardList.add(new Card("彩色", "大王"));}/*** 获取扑克牌大小位置** @param card* @return*/private int findIndex(Card card) {for (int i = 0; i < cardVlues.length; i++) {if (card.value.equalsIgnoreCase(cardVlues[i])) {return i;}}return -1;}/*** 洗牌** @param player 上轮赢家*/private List<Card> shuffle(Player player) {//清除玩家手里的牌Arrays.stream(players).forEach(x -> {LinkedList<Card> cards = x.cards;cards.clear();});//赢家取消优先级if (player != null)player.setFirst(false);//采用随机策略洗牌Random random = new Random();for (int i = 0; i < cardList.size(); i++) {Card temp = cardList.get(i);//要交换的索引int changeIndex = random.nextInt(54);cardList.set(i, cardList.get(changeIndex));cardList.set(changeIndex, temp);}return cardList;}/*** 分牌*/private void distributional() {//留下三张给地主for (int i = 0; i < 51; i++) {if (i < 17) {players[0].getCards().add(cardList.get(i));}if (i >= 17 && i < 34) {players[1].getCards().add(cardList.get(i));}if (i >= 34) {players[2].getCards().add(cardList.get(i));}}//随机确定地主players[new Random().nextInt(3)].setFirst(true);//地主拿三张Arrays.stream(players).filter(Player::isFirst).forEach(x -> {LinkedList<Card> cards = x.getCards();cards.add(cardList.get(51));cards.add(cardList.get(52));cards.add(cardList.get(53));System.out.println("当前地主: " + x.getUsername());});//按顺序排序players[0].getCards().sort(Card::compareTo);players[1].getCards().sort(Card::compareTo);players[2].getCards().sort(Card::compareTo);}/*** 判断出牌是否合法(根据出牌规则)** @param player* @return 个位代表出牌个数,个位相同时,值高低也代表大小级别(可以用Map优化)*/private int compliance(Player player) {LinkedList<Card> cards = player.getPutCards();LinkedList<Card> hasCards = player.getCards();//可以不出牌if (cards.size() == 0) {return 0;}//每张牌必须是自己手里的牌long count = cards.stream().filter(x -> !hasCards.contains(x)).count();if (count > 0) {return -1;}//如果是单张牌,只要在牌中即可if (cards.size() == 1) {return 1 + (findIndex(cards.get(0)) + 1) * 10;}//如果是两张,则为对子或王炸if (cards.size() == 2 && cards.contains(new Card("彩色", "大王")) && cards.contains(new Card("黑白", "小王"))) {return 20000002;}if (cards.size() == 2 && cards.get(0).value.equals(cards.get(1).value)) {return 2 + (findIndex(cards.get(0)) + 1) * 100;}//如果是四张,则为三带一,或者炸弹//判断是否为炸弹boolean bomb = cards.get(0).value.equals(cards.get(1).value) && cards.get(1).value.equals(cards.get(2).value) && cards.get(2).value.equals(cards.get(3).value);if (cards.size() == 4) {if (bomb) {return 4 + (findIndex(cards.get(0)) + 1) * 100000;} else {//偷懒,第一张牌不允许为单张return 4 + (findIndex(cards.get(0)) + 1) * 1000;}}//大于四张,则为连子if (cards.size() > 4) {for (int i = 1; i < cards.size(); i++) {if (findIndex(cards.get(i)) != findIndex(cards.get(i - 1)) + 1) {return -1;}}return cards.size() + (findIndex(cards.get(0)) + 1) * 1000;}return -1;}/*** 判断出牌是否合法(根据大小规则)** @param player* @return*/private boolean compareSize(Player player) {//出牌一定比上两家大//自己int self = compliance(player);String v1 = String.valueOf(self);//上方第一家int before1 = compliance(player.before);String v2 = String.valueOf(self);//上方第二家int before2 = compliance(player.before.before);String v3 = String.valueOf(self);if (before1 == 0 && before2 == 0 && self > 0) {return true;}if (self == 0) {return true;}int amout1 = Integer.parseInt(v1.substring(v1.length() - 2));int amout2 = Integer.parseInt(v2.substring(v2.length() - 2));int amout3 = Integer.parseInt(v3.substring(v3.length() - 2));if (self == 20000002) {return true;}if (before1 > 0 && (amout1 == amout2 || self > 100003) && self > before1) {return true;}if (before1 == 0 && before2 > 0 && (amout1 == amout3 || self > 100003) && self > before2) {return true;}System.out.println("您的出牌没能大于上家");return false;}
}

2.4 定义游戏流程

玩家在控制台输入想要打出的牌,一行一张牌,输入end结束。每次会显示上两家出牌记录,以及自身当前持有牌组

    /*** 比赛流程* @param players 参加的玩家*/public static void start(Player[] players) {
//        //定义玩家
//        Player p1 = new Player("一号");
//        Player p2 = new Player("二号");
//        Player p3 = new Player("三号");
//
//        p1.setNext(p2);
//        p1.setBefore(p3);
//        p2.setNext(p3);
//        p2.setBefore(p1);
//        p3.setNext(p1);
//        p3.setBefore(p2);//开局PlayCards play = new PlayCards(players);//洗牌play.shuffle(null);//分牌play.distributional();Scanner sc = new Scanner(System.in);boolean exit = play.players[0].getCards().size() > 0 && play.players[1].getCards().size() > 0 && play.players[2].getCards().size() > 0;while (exit) {Player player = Arrays.stream(play.players).filter(Player::isFirst).findFirst().get();//显示上两家出牌System.out.println("上两家出牌为");System.out.println(player.before.getPutCards());System.out.println(player.before.before.getPutCards());//当前玩家输出的一组牌LinkedList<Card> putCards = player.getPutCards();//从手里清除打出的牌player.getCards().removeAll(putCards);//清除上次出牌记录putCards.clear();System.out.println(player.getUsername() + "玩家请出牌");System.out.println("您当前持有的卡牌:" + player.getCards());//控制台输入输出的每张牌String line;while (!(line = sc.nextLine()).equalsIgnoreCase("end")) {String[] split = line.split("[:|:]");if (split.length != 2) {System.out.println("请按规则输入");continue;}Card card = play.new Card(split[0], split[1]);putCards.add(card);}//如果当前玩家出牌符合规定,则下一位玩家出牌,否则重新出牌if (play.compliance(player) > -1 && play.compareSize(player)) {player.setFirst(false);player.getNext().setFirst(true);} else {putCards.clear();System.out.println("请选择正确的牌组重新出牌");}}}

三、体验斗地主

更多规则测试,请下载源码,在本地运行

四、扩展方向

相对于完整的网络斗地主:

1、图形界面:可以采用Swing做简单开发,也可以基于安卓或IOS做App开发,当然Web界面也是不错的

2、网络图形:可以用socket通信实现多人在线游戏

单机斗地主之完整功能初版相关推荐

  1. android 单机斗地主,单机斗地主

    单机斗地主是一款画面精美.特效绚丽.操作爽快的斗地主棋牌竞技游戏,拥有精美的界面,动感的音乐,简单的操作,为斗地主玩家提供了流畅而有节奏的游戏感觉.并且还拥有强大的AI以及智能的提示功能.电脑具有很高 ...

  2. 单机斗地主单机_单击浏览器中的URL会发生什么

    单机斗地主单机 In this article, I want my readers to get a picture of a very basic concept of the web world ...

  3. 基于JavaGUI实现的单机斗地主游戏

    源代码下载地址 介绍 基于JavaGUI实现的单机斗地主游戏 开发工具及环境等 支持Eclipse.IDEA 功能 实现出牌.取消出牌.跳过不要.抢地主.输赢判断.发牌动画等(具体看演示图片) 展示

  4. 单机斗地主的一些内容(一)

    来新公司两周了,写了一个简单的单机斗地主,下面写一些简单的逻辑给大家分享一下. 1.首先要对斗地主的流程了解: 洗牌--发牌--抢地主--出牌--AI出牌--结算.大致流程就是这样,至于细节下面慢慢的 ...

  5. 插件完整_紫天学习星球教学:布料模拟插件完整功能使用详解01(中文)

    视频作者:TutorialsUp 视频来源:https://youtu.be/da7WY3uFQCc 中文讲解:紫天肖万涛 这是针对ClothWorks布料模拟插件的完整功能讲解,我们会分几部陆续放出 ...

  6. 将文件复制到ftp发生错误 请检查是否有权限_SE文件管理器2.8.6解锁完整功能版...

    飞鱼资源部落 [特别声明]所有软件皆来源于网上收集整理,仅供学习与交流技术,不得用作其它用途,如有侵犯你的权益,请联系我们,我们将于24小时内进行删除,谢谢你的配合! 1 SE文件管理器是一款专业的手 ...

  7. 0606-工厂模式、单例模式、DBDA的单例和完整功能

    工厂模式:只要指定类名,就可以据此获取一个该类的对象. 单例模式:某个类,只允许其"创建"出一个对象. 单例的方法:三私一公(一个私有化对象,一个私有化构造方法,一个私有化克隆方法 ...

  8. 从前端到后台,开发一个完整功能的小程序

    原址 <微信小程序开发入门>专栏前面的文章主要介绍了小程序前端的开发,对于一个较复杂和完整功能的小程序都是需要后台的支撑的,比如数据的获取和存储.逻辑的处理等.  后台的开发,可以选择PH ...

  9. android单机斗地主,单机斗地主最新安卓版

    单机斗地主最新安卓版是一款操作流畅的经典单机斗地主类游戏,妈妈再也不用担心我因为金币不够不能玩斗地主了,本作为大家提供了无限金币,让你畅玩一整天都不用担心.游戏中有各种的赛事哦,随时可参与,根据你的状 ...

最新文章

  1. 原 EOS智能合约开发入门
  2. python中文教程-中谷python中文视频教程(全38集)
  3. [Python人工智能] 二.theano实现回归神经网络分析
  4. axios异步请求数据的简单使用
  5. 《Python Cookbook 3rd》笔记(1.19):转换并同时计算数据
  6. 基于java SSM框架的旅游网站设计开发(含源文件)
  7. 紫色大气Bootstrap网站模板
  8. 删除以x为根节点的子树并释放☆
  9. 2021江苏南通名师高考成绩查询,2021南通市地区高考成绩排名查询,南通市高考各高中成绩喜报榜单...
  10. 支付宝花呗接口接入php,支付宝小程序开通花呗接口,这是正式向微信小程序正式宣战?...
  11. plsql查询数据显示为乱码解决方案
  12. 那些精贵的3D视觉系统学习资源总结(附书籍、网址与视频教程)
  13. uniapp启动页面
  14. java 向量存储_关于java:使用AES-256和初始化向量进行加密
  15. OpenCPU入门基础
  16. vue使用CKEditor4编辑器
  17. html怎么转换成ftl模板,FreeMarker入门+模板静态化+模板字符串静态化
  18. 大型IT系统性能测试入门经典-系统性能测试基础
  19. 秋天来了,穿衣搭配。简单几件穿出独特气质
  20. 今天ifttt很火呀

热门文章

  1. WIN10 开启SFTP FTP FTPS配置
  2. 使用EasyExcel添加Excel数据
  3. 软件设计模式——单例模式
  4. Pytorch入门实战 | 第P2周:彩色图片识别
  5. Android N Android O 默认MTP模式 实时文件扫描
  6. 互联网企业盈利模式全分析
  7. Django视图学习——处理Http404异常
  8. ZYNQ开发系列——hw_platform包和BSP包中的一些理解
  9. FPGA和CPLD的区别
  10. 美容美发美甲店做活动效果提升30%的营销方案18个套路