用Java实现简易的洗牌和发牌功能

简介: 在日常生活中,想必大家都玩过或者听过斗地主吧,斗地主大致分为三个过程:洗牌,发牌,玩家按照规则将手中的牌给打完,谁最先打完,谁就获胜。这听起来挺简单的,但是影响你胜利的因素有很多:洗牌,玩家的水平。在赌场中很多人就是在洗牌跟发牌的过程中作弊的,那么我们可不可以用代码来实现洗牌跟发牌的功能来实现相对公平呢?

在日常生活中,想必大家都玩过或者听过斗地主吧,斗地主大致分为三个过程:洗牌,发牌,玩家按照规则将手中的牌给打完,谁最先打完,谁就获胜。这听起来挺简单的,但是影响你胜利的因素有很多:洗牌,玩家的水平。在赌场中很多人就是在洗牌跟发牌的过程中作弊的,那么我们可不可以用代码来实现洗牌跟发牌的功能来实现相对公平呢?


代码思路

要想发牌跟洗牌我们首先需要有扑克牌,每张不同的牌对应不同的花色跟数字,这里就需要我们抽象出一副扑克牌对象,然后进行洗牌,洗牌我们就随机打乱扑克牌的顺序,然后就是发牌,每个人平均分发相同数量的扑克牌。


代码实现

我们在这里创建一个Poker的包用来包装我们跟扑克牌相关的类。在Poker包中创建三个Java文件:Poker文件用来产生扑克牌,包含花色跟点数;Game文件用来实现创建一套扑克牌、洗牌和发牌的功能;而Test文件则是我们用来测试的。


Poker的Java文件抽象出一张扑克牌

package poker;
public class Poker {
//扑克牌的点数
    private int rank;
//扑克牌的花色
    private String suit;
//创建构造方法
    public Poker(int rank, String suit) {
        this.rank = rank;
        this.suit = suit;
    }
//以下这些方法我们今天暂时用不上
    public int getRank() {
        return rank;
    }
    public void setRank(int rank) {
        this.rank = rank;
    }
    public String getSuit() {
        return suit;
    }
//重写toString方法
    @Override
    public String toString() {
        return "{ "+rank+" "+suit+"}";
    }
}

Game的Java文件实现洗牌跟发牌功能


创建存放花色的字符串数组的成员变量


这些花色不能被更改,并且仅在当前类中可以使用,所以我们直接用

private static final修饰保证安全性。

private static final String[] suit = {"♥","♣","♦","♠"};

创建一副扑克牌

扑克牌我们用数组来存放

public List<Poker> buyPoker() {
        List<Poker> pokers = new ArrayList<>();
        for (int i = 0; i < 4; i++) {
            for (int j = 1; j <=13 ; j++) {
                Poker poker = new Poker(j,suit[i]);
                pokers.add(poker);
            }
        }
        return pokers;
    }

用Test来看是否创建成功,我们在写代码的时候要养成边写边测试的习惯,这样能及时发现错误。

public class Test {
    public static void main(String[] args) {
        Game game = new Game();
        List<Poker> poker = game.buyPoker();
    }
}

image.png


洗牌

洗牌的操作原理是随机两两扑克牌互换,既然是随机的,我们就需要用到Random来产生随机数,我们从数组的后面开始与前面随机位置对应的数互换,因为这样我们容易产生随机数。

  public void shuffle(List<Poker> poker) {
        for (int i = poker.size()-1; i > 0 ; i--) {
            Random random = new Random();
            int index = random.nextInt(i);
            swap(poker,i,index);
        }
    }
//创建私有方法来实现交换
  private void swap(List<Poker> pokers,int i,int j) {
        Poker tmp = pokers.get(i);
        pokers.set(i,pokers.get(j));
        pokers.set(j,tmp);
    }

同样,我们进行一下测试。

image.png

我们可以看到:我们的洗牌功能已经实现了,每次生成的扑克牌的顺序都是不一样的。


发牌

这里我们创建一个二维数组,分别存放三个玩家所分得的手牌。

public List<List<Poker>> game(List<Poker> pokers) {
        List<List<Poker>> hand = new ArrayList<>();
        List<Poker> hand1 = new ArrayList<>();
        List<Poker> hand2 = new ArrayList<>();
        List<Poker> hand3 = new ArrayList<>();
        hand.add(hand1);
        hand.add(hand2);
        hand.add(hand3);
        for (int i = 0; i < 3; i++) {
        //我们这里测试每人分发五张
            for (int j = 0; j < 5; j++) {
//我们默认每次从下标为0的位置分发,并且分发一次就移除这个下表为0的扑克牌,
//移除之后,它后面的数字也会自动补齐到0位置
                Poker tmp = pokers.remove(0);
                hand.get(i).add(tmp);
            }
        }
        return hand;
    }

整体功能实现


Poker.java

public class Poker {
    private int rank;
    private String suit;
    public Poker(int rank, String suit) {
        this.rank = rank;
        this.suit = suit;
    }
    public int getRank() {
        return rank;
    }
    public void setRank(int rank) {
        this.rank = rank;
    }
    public String getSuit() {
        return suit;
    }
    @Override
    public String toString() {
        return "{ "+rank+" "+suit+"}";
    }
}

Game.java

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class Game {
    private static final String[] suit = {"♥","♣","♦","♠"};
    public List<Poker> buyPoker() {
        List<Poker> pokers = new ArrayList<>();
        for (int i = 0; i < 4; i++) {
            for (int j = 1; j <=13 ; j++) {
                Poker poker = new Poker(j,suit[i]);
                pokers.add(poker);
            }
        }
        return pokers;
    }
    //洗牌
    public void shuffle(List<Poker> poker) {
        for (int i = poker.size()-1; i > 0 ; i--) {
            Random random = new Random();
            int index = random.nextInt(i);
            swap(poker,i,index);
        }
    }
    private void swap(List<Poker> pokers,int i,int j) {
        Poker tmp = pokers.get(i);
        pokers.set(i,pokers.get(j));
        pokers.set(j,tmp);
    }
    public List<List<Poker>> game(List<Poker> pokers) {
        List<List<Poker>> hand = new ArrayList<>();
        List<Poker> hand1 = new ArrayList<>();
        List<Poker> hand2 = new ArrayList<>();
        List<Poker> hand3 = new ArrayList<>();
        hand.add(hand1);
        hand.add(hand2);
        hand.add(hand3);
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 5; j++) {
                Poker tmp = pokers.remove(0);
                hand.get(i).add(tmp);
            }
        }
        return hand;
    }
}

Test.java

public class Test {
    public static void main(String[] args) {
        Game game = new Game();
        List<Poker> poker = game.buyPoker();
        System.out.println(poker);
        game.shuffle(poker);
        System.out.println(poker);
        List<List<Poker>> hand = game.game(poker);
        for (int i = 0; i < hand.size(); i++) {
            System.out.println("第"+(i+1)+"个人的牌"+hand.get(i));
        }
        System.out.println("剩下的牌");
        System.out.println(poker);
    }
}

40.png

相关文章
|
6天前
|
Java 开发者
Java多线程教程:使用ReentrantLock实现高级锁功能
【4月更文挑战第6天】`ReentrantLock`是Java并发编程中一个强大的同步工具,比`synchronized`提供更丰富功能。它支持可响应性、可中断性、公平性选择及条件变量。通过示例展示了创建、公平性设置、可中断锁定、尝试锁定及条件变量的使用。`ReentrantLock`使线程同步更灵活,适用于高性能应用,但使用需谨慎,理解其原理并恰当使用。
|
6天前
|
运维 监控 JavaScript
JAVA村卫生室、诊所云HIS系统源码 支持医保功能
运维运营分系统 1、系统运维:环境管理、应用管理、菜单管理、接口管理、任务管理、配置管理 2、综合监管:统计监管的医疗机构的综合信息,包括医疗业务量、人员配备量、支付分类占比等。 3、系统运营:机构管理、药品目录管理、用户管理、角色管理、字典管理、模板管理、消息管理、运营配置、售后服务、外部系统。
32 0
|
6天前
|
Java
【Java每日一题】— —第二十一题:编程把现实生活的手机事物映射成一个标准类Phone,并定义一个测试类PhoneDemo测试Phone类的功能
【Java每日一题】— —第二十一题:编程把现实生活的手机事物映射成一个标准类Phone,并定义一个测试类PhoneDemo测试Phone类的功能
44 0
|
6天前
|
安全 Java 数据库连接
【Java每日一题】——第四十四题:综合案例:编程模拟智能手机和普通手机功能。
【Java每日一题】——第四十四题:综合案例:编程模拟智能手机和普通手机功能。
87 0
|
6天前
|
存储 前端开发 搜索推荐
13:Session机制实现用户登录与注销功能-Java Web
13:Session机制实现用户登录与注销功能-Java Web
33 3
|
6天前
|
安全 前端开发 Java
10:基于Servlet模拟用户登录功能的实现与解析-Java Web
10:基于Servlet模拟用户登录功能的实现与解析-Java Web
26 3
|
6天前
|
存储 监控 Java
如何在Java中实现等待文件修改后再读取数据的功能?
如何在Java中实现等待文件修改后再读取数据的功能?
19 0
|
6天前
|
Java API 数据安全/隐私保护
【亮剑】如何在Java项目中结合Spring框架实现邮件发送功能
【4月更文挑战第30天】本文介绍了如何在Java项目中结合Spring框架实现邮件发送功能。首先,需在`pom.xml`添加Spring和JavaMail依赖。然后,在`applicationContext.xml`配置邮件发送器,包括SMTP服务器信息。接着,创建一个使用依赖注入的`EmailService`类,通过`JavaMailSender`发送邮件。最后,调用`EmailService`的`sendSimpleEmail`方法即可发送邮件。最佳实践包括:使用配置管理敏感信息,利用`MimeMessage`构造复杂邮件,异常处理和日志记录,以及在大量发送时考虑使用邮件队列。
|
6天前
|
分布式计算 DataWorks 监控
DataWorks操作报错合集之DataWorks在调用java sdk的createFile功能时报错com.aliyuncs.exceptions.ClientException: 1201111000 如何解决
DataWorks是阿里云提供的一站式大数据开发与治理平台,支持数据集成、数据开发、数据服务、数据质量管理、数据安全管理等全流程数据处理。在使用DataWorks过程中,可能会遇到各种操作报错。以下是一些常见的报错情况及其可能的原因和解决方法。
13 1
|
6天前
|
缓存 Java 测试技术
Java多线程实战-实现多线程文件下载,支持断点续传、日志记录等功能
Java多线程实战-实现多线程文件下载,支持断点续传、日志记录等功能