Java 高级程序设计:实验十 实现一个红五的发牌程序

代码地址:Github

实验目的和要求

  1. 理解多线程技术;

  2. 了解红五游戏的规则。

  3. 了解敏捷开发过程

实验内容

实现一个红五的发牌程序,给四位玩家排序时候采用多线程的方式进行,排序结束再统一输出每一位玩家排好序的结果。

  • 游戏由两副牌构成
  • 4个玩家
  • 系统能随机洗牌后模拟真实情况分别向4个玩家发牌,并剩下8张底牌
  • 程序能符合人性的方式输出四个玩家手上的牌和底牌(按照人类合理的理牌顺序输出)*合理的理牌顺序是分花色,分大小归类排序,每次都按照打2,并且黑心是主牌进行整理主牌大小顺序:
    • 黑色:红心5,大王,小王,黑桃3,梅花3,黑桃2,梅花2,红色2,方色2, A,K,Q,J,10,9,8,7,6, 5,4
    • 红色副牌:A,K,Q,J,10,9,8,7,6, 4,3
    • 梅花色副牌:A,K,Q,J,10,9,8,7,6,5,4
    • 方色副牌:A,K,Q,J,10,9,8,7,6,5, 4,3

实验结果

Poker.java

package com.owem;

import java.util.Objects;

/**
 * @author Owem
 * @date 2022/11/22 17:08
 * @description TODO
 **/
public class Poker {
    public int color;  // 花色 1~4 代表 黑桃、红桃、梅花、方块
    public int point;  // 点数 2~16 代表 2、3、4、5、6、7、8、9、10、J、Q、K、A、小王、大王

    public Poker() {
    }

    public Poker(int color, int point) {
        this.color = color;
        this.point = point;
    }

    @Override
    public String toString() {
        String colorResult = switch (color) {
            case 1 -> "黑桃";
            case 2 -> "红桃";
            case 3 -> "梅花";
            case 4 -> "方块";
            default -> throw new IllegalStateException("Unexpected value: " + color);
        };
        String pointResult = switch (point) {
            case 11 -> "J";
            case 12 -> "Q";
            case 13 -> "K";
            case 14 -> "A";
            case 15 -> "小王";
            case 16 -> "大王";
            default -> String.valueOf(point);
        };

        if (Objects.equals(pointResult, "小王") || Objects.equals(pointResult, "大王")) {
            return pointResult;
        }
        return colorResult + " " + pointResult;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Poker poker = (Poker) o;

        if (color != poker.color) return false;
        return point == poker.point;
    }

    @Override
    public int hashCode() {
        int result = color;
        result = 31 * result + point;
        return result;
    }
}

Dealer.java

package com.owem;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @author Owem
 * @date 2022/11/22 16:51
 * @description TODO
 **/
public class Dealer {
    private static final ArrayList<Poker> library = new ArrayList<>();  // 牌库
    private static final HashMap<Integer, ArrayList<Poker>> gamerCard = new HashMap<>();  // 玩家手牌
    private static final ArrayList<Poker> bottomCard = new ArrayList<>();  // 底牌
    private static final ArrayList<Poker> standardBarrel = new ArrayList<>();  // 标准桶
    private static final AtomicBoolean isLock = new AtomicBoolean(false);  // 锁初始化变量

    private static void fillContainer() {
        // 在牌库里填充两幅标准套牌
        for (int time = 0; time < 2; time++) {
            for (int color = 1; color <= 4; color++) {
                for (int point = 2; point <= 14; point++) {
                    library.add(new Poker(color, point));
                }
            }
            library.add(new Poker(1, 16));  // 大王
            library.add(new Poker(1, 15));  // 小王
        }
        // 洗牌
        Collections.shuffle(library);
        // 初始化标准桶
        standardBarrel.add(new Poker(2, 5));  // 红桃 5
        standardBarrel.add(new Poker(1, 16));  // 大王
        standardBarrel.add(new Poker(1, 15));  // 小王
        standardBarrel.add(new Poker(1, 3));  // 黑桃 3
        standardBarrel.add(new Poker(3, 3));  // 梅花 3
        standardBarrel.add(new Poker(1, 2));  // 黑桃 2
        standardBarrel.add(new Poker(3, 2));  // 梅花 2
        standardBarrel.add(new Poker(2, 2));  // 红桃 2
        standardBarrel.add(new Poker(4, 2));  // 方块 2
        for (int color = 1; color <= 4; color++) {
            for (int point = 14; point > 2; point--) {
                if (color == 2 && point == 5) continue;
                if ((color == 1 || color == 3) && point == 3) continue;
                standardBarrel.add(new Poker(color, point));
            }
        }
    }

    // 发牌
    private static void deal() {
        for (int time = 0; time < 25; time++) {
            for (int gamerId = 0; gamerId < 4; gamerId++) {
                gamerCard.get(gamerId).add(library.get(4 * time + gamerId));
            }
        }
        for (int i = 100; i < library.size(); i++) {
            bottomCard.add(library.get(i));
        }
    }

    public static boolean lock(){    //加锁
        return isLock.compareAndSet(false, true);
    }

    public static void unlock() {   //解锁
        isLock.set(false);
    }

    // 桶排序
    private static void cardSort(ArrayList<Poker> pokerList) {
        while (!lock()) {}  //加锁失败,自旋
        System.out.println("----当前线程: " + Thread.currentThread().getName() + ", 手牌数: " + pokerList.size() + "----");
        for (Poker p1 : standardBarrel) {
            for (Poker p2 : pokerList) {
                if (p1.equals(p2)) System.out.println(p1);
            }
        }

        unlock();
    }

    private static void init() {
        fillContainer();
        // 创建玩家
        for (int gamerId = 0; gamerId < 4; gamerId++) {
            gamerCard.put(gamerId, new ArrayList<>());
        }
        deal();
    }

    public static void main(String[] args) {
        init();
        System.out.println("-----------------底牌数: " + bottomCard.size() + "-----------------");
        for (Poker p : bottomCard) {
            System.out.println(p);
        }
        ExecutorService service = Executors.newFixedThreadPool(4);   //线程池
        service.submit(() -> cardSort(gamerCard.get(0)));
        service.submit(() -> cardSort(gamerCard.get(1)));
        service.submit(() -> cardSort(gamerCard.get(2)));
        service.submit(() -> cardSort(gamerCard.get(3)));
    }
}

结果截图:

image-20221122194025470