[小练习]生成54张扑克牌,洗牌。
题目要求:
生成54张扑克牌(13个数字*4种花色,再加大小王2张)
洗牌:将54张牌随机打乱
准备三个玩家,三人交替摸牌,最后三张底牌不能摸
查看三人各自手中的牌和底牌,要求按牌的大小顺序展示
提示:
需要几个集合,分别保存什么样的数据?
花色信息、点数信息、组合好的牌放在什么地方
如何比较每张牌的大小,相同数值的牌如何比较大小?
给牌添加对应的权重值
洗牌需要用什么方法才能将集合中的元素顺序打乱?
如何发牌,有什么注意事项?
代码:
https://gitee.com/fuqiqiqi/test/blob/master/U14/Test3.javahttps://gitee.com/fuqiqiqi/test/blob/master/U14/Test3.java
1.花色定义成数组常量,方便后续放入时可以用数组循环。
public static final String[] colors={"梅花","方块","黑桃","红桃"};
2.定义Cards类,将num定义成int是为了方便比较大小,将大王和小王也变成数字,封装在里面谁也不知道原本大王只是数字15,这样比较函数也简单。只是打印的时候比较麻烦,需要将数字转化成特定字符串。
public static class Cards implements Comparable<Cards>{int num ;String color;@Overridepublic String toString() {String a;if(num==1){a="3";}else if(num==2){a="4";}else if(num==3){a="5";}else if(num==4){a="6";}else if(num==5){a="7";}else if(num==6){a="8";}else if(num==7){a="9";}else if(num==8){a="10";}else if(num==9){a="J";}else if(num==10){a="Q";}else if(num==11){a="K";}else if(num==12){a="A";}else if(num==13){a="2";}else if(num==14){a="小王";}else if(num==15){a="大王";}else{a="0";System.out.println("出错了");}return " "+color+a;}@Overridepublic int compareTo(Cards o) { return num-o.num;}Cards(int a,String b){num=a;color=b;}}
3.将卡牌放进List,有了前面的铺垫就方便多了
List<Cards> a = new ArrayList<>();for (int i = 0; i < 4; i++) {for (int j = 1; j <= 13; j++) {a.add(new Cards(j, colors[i]));}}a.add(new Cards(14, ""));a.add(new Cards(15, ""));
4.将卡牌随机排序后依次发放到3个列表。后续打印出来就知道牌了。
Collections.shuffle(a);List<Cards> player1 = new ArrayList<>();List<Cards> player2 = new ArrayList<>();List<Cards> player3 = new ArrayList<>();List<Cards> dipai = new ArrayList<>();Cards c = null;for (int i = 0; i < a.size(); i++) {c = a.get(i);if (i >= a.size() - 3) {dipai.add(c);} else if (i % 3 == 0) {player1.add(c);} else if (i % 3 == 1) {player2.add(c);} else if (i % 3 == 2) {player3.add(c);}}Collections.sort(player1);Collections.sort(player2);Collections.sort(player3);Collections.sort(dipai);
代码改进:
-
num→牌面文字的映射太冗长
用数组或Map
一行就能搞定private static final String[] NUM_NAME = {"0","3","4","5","6","7","8","9","10","J","Q","K","A","2","小王","大王" };@Override public String toString() {if (num < 1 || num > 15) return "出错";return " " + color + NUM_NAME[num]; }
-
颜色/花色处理
大王小王其实没有花色,可以统一显示@Override public String toString() {if (num >= 14) return " " + NUM_NAME[num]; // 大小王return " " + color + NUM_NAME[num]; }
-
发牌逻辑可简化
使用List.subList
或IntStream
会更直观,例如for (int i = 0; i < 51; i += 3) {player1.add(a.get(i));player2.add(a.get(i + 1));player3.add(a.get(i + 2)); } dipai.addAll(a.subList(51, 54));
-
玩家直接用一个数组或列表
如果你以后想支持 4 人、5 人斗地主,直接List<List<Cards>> players = new ArrayList<>(3)
会更灵活。 -
其他小点
-
Cards
内部变量可以private final
,更安全。 -
main
方法里Cards c = null;
可以省掉,循环体里直接a.get(i)
即可。 -
打印时按固定顺序输出,避免
HashMap
的随机顺序String[] keys = {"player1","player2","player3","dipai"}; for (String k : keys) {System.out.println(k + ": " + map.get(k)); }
-
另一种思路:
U14/Test2.java · 伏琪/java基础语法练习 - 码云 - 开源中国https://gitee.com/fuqiqiqi/test/blob/master/U14/Test2.java
这个是在main()里写了比较器,还有定义了在类里定义了权重,又用Map将牌面与权重绑定。两种方法各有优缺点。
我是伏琪,关注订阅号伏琪了解更多。