思路:
根据功能描述,分别创建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人点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦