为了账号安全,请及时绑定邮箱和手机立即绑定

Java入门第三季7-1简易扑克牌游戏

标签:
Java

思路:
根据功能描述,分别创建4个类.
1,Card类,单张扑克牌类,因为后续的比较大小之类的,只能单张比较,而不能整副牌比较
2,Cards类,用于生成一副扑克牌,ArrayList是有序可重复的 可以存储一副牌
3,Player玩家类,具有id,name和手牌(两张牌)属性
4,CardsComparator类,用于自定义临时比较规则
5,PlayGame类 (主类)

Card类

package play.easy.cards;

//单张扑克牌类
public class Card {
    private String color;
    private String points;

    public Card(String newColor, String newpoints){
        this.color = newColor;
        this.points = newpoints;
    }
    public String getColor() {
        return color;
    }
    public String getPoints() {
        return points;
    }
    @Override  //将单张扑克牌属性转化成字符串输出
    public String toString() {
        return color + points;
    }
}

Cards类 难点在于怎样生成一副扑克牌,这里直接在构造器里生成一副扑克牌,实例化Cards类也就完成了一副扑克牌的创建

package play.easy.cards;

import java.util.ArrayList;
import java.util.List;

//扑克牌类
public class Cards {
    String[] color = {"黑桃","红桃","梅花","方片"};//花色大小顺序 从左到右依次减小
    String[] points = {"2","3","4","5","6","7","8","9","10","J","Q","K","A"};//点数
    //用cardsList存储一整副扑克牌
    List<Card> cardsList = new ArrayList<Card>();

    //扑克牌类构造器 初始化时 生成一副扑克牌
    public Cards(){
        for (String co : color) {
            for (String po : points) {
                cardsList.add(new Card(co, po));
            }
        }
    }
}

Player类 因为本次练习想同时练习ArrayList和HashMap的操作,所以玩家手牌属性,我这里使用HashMap来存储(结果带来的很多麻烦,详情见主类中注释)

package play.easy.cards;

import java.util.HashMap;
import java.util.Map;

//玩家类
public class Player {
    private int id;
    private String name;
    //使用Map集合来 存储手牌属性
    private Map<Integer, Card> handsCard = new HashMap<Integer ,Card>();

    //含参构造器
    public Player(int newId, String newName){
        this.id = newId;
        this.name = newName;
    }

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public Map<Integer, Card> getHandsCard() {
        return handsCard;
    }
}

CardsComparator类,用于自定义临时比较规则 两个要素:1,实现Comparator接口,2,重写compara()方法。难点在于怎么重写,具体参考注释吧,,,,我也是参考别人的(忧伤)

package play.easy.cards;

import java.util.Comparator;

//建立临时比较规则类   先比较大小,大小相同的话再比较花色 
public class CardsComparator implements Comparator<Card> {

    String color = "方片 梅花 黑桃 红桃";//花色大小顺序  注意这里去的是index 所以大小顺序是从左到右依次增大
    String points = "2 3 4 5 6 7 8 9 10 J Q K A";//点数
    @Override
    public int compare(Card o1, Card o2) {
        /**
         * 先比较点数 即比较各自点数所在 基准 points 中的位置大小 即可判断大小  
         * 因为按自然顺序 A < J < k < Q 与扑克牌大小顺序不符   这一点也是困扰了我很久,后来参照了一位幕友的方法
         * indexOf(String string)方法,返回字符串所在的索引位置
         */
        if ( points.indexOf(o1.getPoints()) == points.indexOf(o2.getPoints()) ) {
            //若相等,再进一步比较花色
            if ( color.indexOf(o1.getColor()) == color.indexOf(o2.getColor()) ) {
                    return 0;//这种情况不可能出现 但程序里必须要写
            }else {
                //不相等则返回差值
                return color.indexOf(o1.getColor()) - color.indexOf(o2.getColor());
            }

        }else {
            //不相等则返回差值
            return points.indexOf(o1.getPoints()) - points.indexOf(o2.getPoints());
        }
    }
}

PlayGame 主类 用于测试 处理顺序直观明了,注释个人认为不能再详细了,看不懂你打我

package play.easy.cards;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.Scanner;

//主类
public class PlayGame {

    Scanner input = new Scanner(System.in);
    //PlayGame 类实例对象 test
    static PlayGame test = new PlayGame();

    public static void main(String[] args) {

        System.out.println("------------创建扑克牌------------");
        //创建一副扑克牌
        Cards cards = new Cards();
        System.out.println("----------扑克牌创建成功!---------");
        //打印创建的扑克牌
        System.out.println("为:" + cards.cardsList.toString());
        System.out.println("------------开始洗牌------------");
        /**
         * 洗牌就是要把cardsList中的元素打乱  查找API发现了 swap方法
         * 调用Collections工具类 中的 swap(List<?> list, int i, int j) 把指定列表中i位置和j位置处元素交换
         * 具体方法可参考 API
         * 因为是洗牌,所以相互交换的两个位置应该是随机的,那么由此可以利用 Random类中的 nextInt()方法来获取两个随机位置
         * 即rd.nextInt(cards.cardsList.size()) 其中cardsList.size() 是List集合的长度
         */
        Random rd = new Random();
        //多次交换 共交换cards.cardsList.size()次
        for (int i = 0;i < cards.cardsList.size(); i++){
            Collections.swap(cards.cardsList, 
                rd.nextInt(cards.cardsList.size()), rd.nextInt(cards.cardsList.size()));
        }
        System.out.println("------------洗牌结束------------");
        //打印洗牌后的扑克牌
        //System.out.println("为:" + cards.cardsList.toString());

        System.out.println("------------创建玩家------------");
        System.out.println("请输入第1位玩家的ID和姓名:");
        //调用生成玩家方法
        Player player1 = test.generatePlayer();
        System.out.println("请输入第2位玩家的ID和姓名:");
        Player player2 = test.generatePlayer();

        System.out.println("-------欢迎玩家:"+player1.getName()
                        +"\n-------欢迎玩家:"+player2.getName());

        {//局部代码块  主要是想使用局部变量i 怕和其他地方冲突,所以在局部代码块里使用,用完就回收了,不会混乱
            System.out.println("------------开始发牌------------");
            //利用迭代器进行发牌    想练习使用迭代器   洗牌无序,发牌是有序的,这也符合实际发牌情况
            Iterator<Card> it = cards.cardsList.iterator();
            int i = 0;
            while(it.hasNext() && i<2){
                System.out.println("-------玩家:"+player1.getName()+"-拿牌");
                /**
                 * HashMap 的 put(k,v)方法  这里的 value 是一个 Card 实例
                 * 这里注意:执行了一次it.next()方法,那么指针会自动指向下一个元素
                 * 所以 虽然使用了两侧it.next() 但每次的值是不同的
                 */
                player1.getHandsCard().put(i, it.next());
                System.out.println("-------玩家:"+player2.getName()+"-拿牌");
                player2.getHandsCard().put(i, it.next());
                i++;
            }
            System.out.println("------------发牌结束------------");
            System.out.println("------------开始游戏------------");
        }

        /**
         * 想把每名玩家的手牌取出,即HashMap中的所有value值(Card类型)取出,然后使用Collections.sort()方法按照自定义的比较规则
         * 对player1手牌比较大小   因为我定义的玩家手牌是 Hashmap 所以这里尝试进行类型强转
         * 即(List<Card>)player1.getHandsCard().values() 虽然编译没报错,但实际执行还是抛出了
         * java.lang.ClassCastException: java.util.HashMap$Values cannot be cast to java.util.List的异常
         * 因为player1.getHandsCard().values()返回的是一个Collection 不能强转,因此 考虑怎样把Collection转成List
         * 后来经过百度,ArrayList有一个含参构造方法ArrayList(Collection<? extends E> c) 
         * 构造一个包含指定 collection 的元素的列表,这些元素是按照该 collection 的迭代器返回它们的顺序排列的,那么灵感来了,,, 
         * 如下 新建
         */
        //新建 List类型的玩家1手牌  将原来玩家1的手牌取出 并作为参数 构造新的ArrayList
        List<Card> player1HandsCard = new ArrayList<Card>(player1.getHandsCard().values());
        //排序  这样就可以调用Collections.sort()方法了  从而圆了我想使用自定义比较规则进行比较的梦想
        //排序后,元素都是按升序排列的,所以索引位置为1的就是最大的牌 所以用get(1)
        Collections.sort(player1HandsCard, new CardsComparator());
        System.out.println("玩家:"+player1.getName() + "最大的手牌为:" +
                            player1HandsCard.get(1).toString());

        //新建 List类型的玩家2手牌
        List<Card> player2HandsCard = new ArrayList<Card>(player2.getHandsCard().values());
        //排序
        Collections.sort(player2HandsCard, new CardsComparator());
        System.out.println("玩家:"+player2.getName() + "最大的手牌为:" +
                            player2HandsCard.get(1).toString()); 

        //存各自的最大手牌   再新建.......
        List<Card> winner = new ArrayList<Card>();
        winner.add(player1HandsCard.get(1));
        winner.add(player2HandsCard.get(1));
        //排序
        Collections.sort(winner, new CardsComparator());
        //判断最大的牌是谁的
        if (winner.get(1).equals(player1HandsCard.get(1))) {
            System.out.println("-------玩家:"+player1.getName()+" 获胜!");
        }else{
            System.out.println("-------玩家:"+player2.getName()+" 获胜!");
        }

        //显示玩家各自的手牌
        test.showHandsCard(player1, player2);
    }

    private void showHandsCard(Player player1, Player player2) {
        System.out.println("玩家各自的手牌为:");
        //HashMap 的 values()方法  返回的是一个value集合
        System.out.println(player1.getName()+":"+player1.getHandsCard().values().toString());
        System.out.println(player2.getName()+":"+player2.getHandsCard().values().toString());
    }

    //创建玩家的方法
    private Player generatePlayer() {
        try {
            System.out.println("输入ID:");
            int id = input.nextInt();
            System.out.println("输入姓名:");
            String name = input.next();
            Player player = new Player(id, name);
            //无异常则返回 玩家
            return player;
        } catch (Exception e) {
            /**
             * String s = input.nextLine();
             * 此句作用是清除缓存区中残留的空白符,不然会重复异常 因为缓存区还存在输入的非int型id
             * 不懂可参考:http://blog.csdn.net/wjy1090233191/article/details/42080029
             */
            String s = input.nextLine();
            System.out.println("请输入整数类型的ID!");
             return test.generatePlayer();//递归调用generatePlayer()方法
        }
    }
}

实测结果:
图1正常情况,图2 输入非int型 ID 情况
图片描述
图片描述

点击查看更多内容
15人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消