Java-斗地主洗牌发牌

先给大家上效果图

这里写图片描述

项目思路

问题一 : 如何区分花色(黑,红,梅,方)?

按照常规逻辑,一副牌54张 如果按照从1-54用数字去代替是不好区分的(比较麻烦,各种if)
我这里就搞了一个数组去存储所有的牌,注意是所有的“牌”,然后搞另外一个数组去存这个数组
的下标,也就是说,我无论是洗牌,发牌,变的都是这个数据的下标,只要在显示的时候把数据
转换回来就可以了,如果还不是很懂,请往下看。

这里写图片描述

问题二:如何洗牌?

在我们常见的洗牌方法中有一种叫印度洗牌法,它的洗牌规则是这样的:从牌堆中间取出若干
然后放到牌堆顶部,如此循环,牌就洗乱了,那其实我们也可以仿照这样搞一个类似的洗牌方法:
/** 洗牌方法 */
    private void randomData() {
        // 初始化 牌堆下标 0-53
        for (int i = 0; i < ALL_CARD.length; i++) {
            mAllData[i] = i;
        }
        // 这个牌洗 54 次
        for (int i = 0; i < ALL_CARD.length; i++) {
            int r = mRandom.nextInt(53); // 从0-53 抽一个数
            exchange(r,0); // 抽出来的数和第0个交换  

            int k = i % 2;     // k 的取值 只可能是 0 或者 1 
            exchange(r,52+k);  // 去换一下 大小王 防止大小王不好洗开
        }
    }
/** 交换方法 */
    private void exchange(int p1, int p2){
        int temp = mAllData[p1];
        mAllData[p1] = mAllData[p2];
        mAllData[p2] = temp;
    }
这样 mAllData数组里面本来存放的是0-53的数据,就变得乱七八糟了,这要牌就洗好了

问题三 : 如何发牌?

发牌就比较简单了,现实生活中一般是1张1张的发,这里我们就直接一个人发17张(因为牌堆本身就是乱的,
洗了54次牌),然后剩下三张。
    /** 发牌方法 */
    private void allotData() {
        for (int i = 0; i < ALL_CARD.length; i++) {
            if (i < 17 ) { 
                mLeftData.add(mAllData[i]); // 第一个人的牌
            }else if(i > 16 && i < 34 ){
                mRightData.add(mAllData[i]); //第二个人的牌
            }else if(i > 33 && i < 51 ){
                mLocalData.add(mAllData[i]); //第三个人的牌
            }else{
                mThreeData.add(mAllData[i]); //剩下的牌
            }
        }
    }

问题四: 如何把数据变成“牌”?

到这一步之前我们上边所有的操作,都其实是ALL_CARD数组的下标,就相当我们拿到兑换券了,
直接去找ALL_CARD去把下标兑换成相应的“牌”就可以了;
/** 数据转换方法 */
    private void convertData(List<Integer> data) {      
        for (int i = 0; i < data.size(); i++) {
            int temp = data.get(i);

            data.set(i, ALL_CARD[temp]);
        }

    }

项目代码

主要逻辑代码

public class CardMatrix {

    public final int[] ALL_CARD = { // 所有的牌
            3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,  // 黑
            3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,  // 红
            3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,  // 梅
            3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,  // 方
            16, 17 };                                     // 大小王


    public int[] mAllData; //存卡牌下标

    public List<Integer> mLeftData;  // 左边玩家的牌
    public List<Integer> mRightData; // 右边玩家的牌
    public List<Integer> mLocalData; // 我自己的牌
    public List<Integer> mThreeData; // 剩下的牌


    private Random mRandom; // 随机函数


    public CardMatrix() {

        // 初始化数据
        initData();

        // 洗牌
        randomData();

        // 发牌
        allotData();

        // 转换
        convertData(mLeftData);
        convertData(mRightData);
        convertData(mLocalData);
        convertData(mThreeData);
    }

    private void initData() {
        mRandom = new Random();
        mAllData = new int[54];
        mLeftData  = new ArrayList<Integer>();
        mRightData = new ArrayList<Integer>();
        mLocalData = new ArrayList<Integer>();
        mThreeData = new ArrayList<Integer>();
    }

    /** 洗牌方法 */
    private void randomData() {
        // 初始化 牌堆下标
        for (int i = 0; i < ALL_CARD.length; i++) {
            mAllData[i] = i;
        }
        // 这个牌洗 54 次
        for (int i = 0; i < ALL_CARD.length; i++) {
            int r = mRandom.nextInt(53); // 从0-53 抽一个数
            exchange(r,0); // 抽出来的数和第0个交换

            int k = i % 2;
            exchange(r,52+k);  // 防止大小王 不好洗开
        }
    }

    /** 发牌方法 */
    private void allotData() {
        for (int i = 0; i < ALL_CARD.length; i++) {
            if (i < 17 ) { 
                mLeftData.add(mAllData[i]); // 第一个人的牌
            }else if(i > 16 && i < 34 ){
                mRightData.add(mAllData[i]); //第二个人的牌
            }else if(i > 33 && i < 51 ){
                mLocalData.add(mAllData[i]); //第三个人的牌
            }else{
                mThreeData.add(mAllData[i]); //剩下的牌
            }
        }
    }

    /** 交换数据 */
    private void exchange(int p1, int p2){
        int temp = mAllData[p1];
        mAllData[p1] = mAllData[p2];
        mAllData[p2] = temp;
    }

    /** 数据转换方法 */
    private void convertData(List<Integer> data) {

        for (int i = 0; i < data.size(); i++) {
            int temp = data.get(i);

            data.set(i, ALL_CARD[temp]);
        }

    }

    /** 获取方法 */
    public List<Integer> getLeftData() {
        Collections.sort(mLeftData); // 排序
        return mLeftData;
    }


    public List<Integer> getRightData() {
        Collections.sort(mRightData);
        return mRightData;
    }


    public List<Integer> getLocalData() {
        Collections.sort(mLocalData);
        return mLocalData;
    }


    public List<Integer> getThreeData() {
        return mThreeData;
    }


    /** 重新开始方法 */
    public void restart(){

        mLeftData.clear();
        mRightData.clear();
        mLocalData.clear();
        mThreeData.clear();

        // 洗牌
        randomData();

        // 发牌
        allotData();

        // 转换
        convertData(mLeftData);
        convertData(mRightData);
        convertData(mLocalData);
        convertData(mThreeData);
    }
}

测试方法

public static void main(String[] args) {
        CardMatrix m = new CardMatrix();

        System.out.println("左边玩家的牌: " + m.getLeftData().toString());
        System.out.println("右边玩家的牌: " + m.getRightData().toString());
        System.out.println("我自己  的牌: " + m.getLocalData().toString());
        System.out.println("最后剩下的牌: " + m.getThreeData().toString());


        while(true){
            Scanner scnn = new Scanner(System.in);
            String str = scnn.next();

            if ("0".equals(str)) {
                m.restart(); // 重新发牌
                System.out.println("左边玩家的牌: " + m.getLeftData().toString());
                System.out.println("右边玩家的牌: " + m.getRightData().toString());
                System.out.println("我自己  的牌: " + m.getLocalData().toString());
                System.out.println("最后剩下的牌: " + m.getThreeData().toString());
            }else{
                return ;
            }

        }
    }

运行项目

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值