一、思路分析
排序的过程中,最让人头疼的是:最小的数字 2
反而是最大的,因此我们不好找出它的规律。那怎么办呢?
![image-20240429113557682](https://img-blog.csdnimg.cn/img_convert/92a3ddadbd81ecb231b341137f097bbd.png)
牌没有规律,但是数字是有规律的。因此我们可以将牌按照指定的规则先进行手动的排列,然后再跟 1 / 2 / 3 ...
这样的数字一一对应。对应完后,我们就可以认为:数字越大,所对应的牌也就越大。
因此我们需要使用 Map集合
将这种对应关系存起来。
那么问题就来了:在 Map集合
集合中,是底下的需要作为 键
,还是上面的牌作为 键
呢?
其实谁作为键有一个规则,在下面的代码中,我们以谁为主导,谁就作为键。
在刚刚我们说了,我们需要将牌先跟序号对应起来,对应起来的目的:牌的规则我们不好把握,但是下面序号的规则就很好把握。
那么在下面的代码中,我们实际上操作的都是序号,因此我们需要将序号当做 键
。
与此同时,我们还会创建一个单列集合,用来单独存储牌的序号,这样准备牌的动作我们才算是准备好了。
接下来还有洗牌,所谓洗牌其实洗的就是序号。
发牌发的也是序号,前三个序号作为底牌,后面所有的序号再依次发给三个玩家。
发完后会发现,序号是没有顺序的,我们还需要将序号进行排序。
完事后,在看牌的时候,我们就可以拿着序号到一开始的 Map集合
中找对应的牌就行了。
此时牌就有序了。这种排序思想是利用了编程圈中的:对应思想 —— 如果原始数据的规律非常复杂,我们可以先手动排序让每一个数据
跟 唯一的序号
产生对应关系。
这里的序号就是数字,规律非常简单,后续的所有操作,我们以序号为准。
当真正需要操作原始数据的时候,再通过序号找到原始数据即可。
二、准备牌
基础代码
public class App {
public static void main(String[] args) {
//从程序的主入口开启斗地主游戏
new PokerGame();
}
}
public class PokerGame {
static {
String[] color = {"♦", "♣", "♥", "♠"};
String[] number = {"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"};
}
}
接下来的目的:将序号跟牌产生对应关系。
public class PokerGame {
//牌盒 Map
//此时我们只要把牌跟序号产生对应关系就可以了,不需要按照序号进行排序,所以只要HashMap就可以了
//由于在静态代码块中需要用到这个集合,因此集合前面需要加上static
static HashMap<Integer, String> hm = new HashMap<>();
static ArrayList<Integer> list = new ArrayList<>();
static {
String[] color = {"♦", "♣", "♥", "♠"};
String[] number = {"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"};
//序号
int serialNumber = 1;
for (String c : color) {
//依次表示每一个数字
for (String n : number) {
//依次表示每一个花色
hm.put(serialNumber, c + n);
list.add(serialNumber);
serialNumber++;
}
}
hm.put(serialNumber, "小王");
list.add(serialNumber);
serialNumber++;
hm.put(serialNumber, "大王");
list.add(serialNumber);
}
}
如果跟之前一样,外层循环是花色,内存循环是数字,那么打印结果如下。
思考一下这里面的规律,例如玩家1被分到的序号是:1 2 3 4 5 14
,通过这个序号,去查到对应的牌,真的就有序了吗?
{1=♦3, 2=♦4, 3=♦5, 4=♦6, 5=♦7, 6=♦8, 7=♦9, 8=♦10, 9=♦J, 10=♦Q, 11=♦K, 12=♦A, 13=♦2,
14=♣3, 15=♣4, 16=♣5, 17=♣6, 18=♣7, 19=♣8, 20=♣9, 21=♣10, 22=♣J, 23=♣Q, 24=♣K, 25=♣A, 26=♣2,
27=♥3, 28=♥4, 29=♥5, 30=♥6, 31=♥7, 32=♥8, 33=♥9, 34=♥10, 35=♥J, 36=♥Q, 37=♥K, 38=♥A, 39=♥2,
40=♠3, 41=♠4, 42=♠5, 43=♠6, 44=♠7, 45=♠8, 46=♠9, 47=♠10, 48=♠J, 49=♠Q, 50=♠K, 51=♠A, 52=♠2,
53=小王, 54=大王}
可以发现并不是,因此这种规则其实是不对的。
解决办法:只需要将循环的内外层对调一下就行了
//细节
for (String c : color) {
//依次表示每一个数字
for (String n : number) {
//依次表示每一个花色
hm.put(serialNumber, c + n);
System.out.println(c + n);
list.add(serialNumber);
serialNumber++;
}
}
三、洗牌
此时真正洗的应该是牌的序号
public PokerGame() {
//洗牌
Collections.shuffle(list);
}
四、发牌
发牌我们发的其实也是序号。
在之前我们使用的是 ArrayList
,但是这里可以使用 TreeSet
进行改进,因为 TreeSet
是支持排序的。
当我们将序号加入到 TreeSet
后,就会按照默认的方式进行排序,Integer
中默认的排序方式就是从小到大排列。
public PokerGame() {
//发牌
TreeSet<Integer> lord = new TreeSet<>();
TreeSet<Integer> player1 = new TreeSet<>();
TreeSet<Integer> player2 = new TreeSet<>();
TreeSet<Integer> player3 = new TreeSet<>();
for (int i = 0; i < list.size(); i++) {
//i :依次表示集合中的每一个索引
//list.get(i)元素:牌的序号
int serialNumber = list.get(i);
if(i <= 2){
lord.add(serialNumber);
continue;
}
if(i % 3 == 0){
player1.add(serialNumber);
}else if(i % 3 == 1){
player2.add(serialNumber);
}else{
player3.add(serialNumber);
}
}
}
五、看牌
//看牌
lookPoker("底牌",lord);
lookPoker("钢脑壳",player1);
lookPoker("大帅比",player2);
lookPoker("蛋筒",player3);
/*
* 参数一:玩家的名字
* 参数二:牌的序号
* */
public void lookPoker(String name, TreeSet<Integer> ts){
System.out.print(name + ": ");
//遍历TreeSet集合得到每一个序号,再拿着序号到Map集合中去找真正的牌
for (int serialNumber : ts) {
String poker = hm.get(serialNumber);
System.out.print(poker + " ");
}
System.out.println();
}
}
六、完整代码
package com.itheima.doudizhu2;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.TreeSet;
public class PokerGame {
//牌盒 Map
//此时我们只要把牌跟序号产生对应关系就可以了,不需要按照序号进行排序,所以只要HashMap就可以了
static HashMap<Integer, String> hm = new HashMap<>();
static ArrayList<Integer> list = new ArrayList<>();
static {
String[] color = {"♦", "♣", "♥", "♠"};
String[] number = {"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"};
//序号
int serialNumber = 1;
//细节
for (String c : color) {
//依次表示每一个数字
for (String n : number) {
//依次表示每一个花色
hm.put(serialNumber, c + n);
System.out.println(c + n);
list.add(serialNumber);
serialNumber++;
}
}
hm.put(serialNumber, "小王");
list.add(serialNumber);
serialNumber++;
hm.put(serialNumber, "大王");
list.add(serialNumber);
System.out.println(hm);
}
public PokerGame() {
//洗牌
Collections.shuffle(list);
//发牌
TreeSet<Integer> lord = new TreeSet<>();
TreeSet<Integer> player1 = new TreeSet<>();
TreeSet<Integer> player2 = new TreeSet<>();
TreeSet<Integer> player3 = new TreeSet<>();
for (int i = 0; i < list.size(); i++) {
//i :依次表示集合中的每一个索引
//list.get(i)元素:牌的序号
int serialNumber = list.get(i);
if(i <= 2){
lord.add(serialNumber);
continue;
}
if(i % 3 == 0){
player1.add(serialNumber);
}else if(i % 3 == 1){
player2.add(serialNumber);
}else{
player3.add(serialNumber);
}
}
//看牌
lookPoker("底牌",lord);
lookPoker("钢脑壳",player1);
lookPoker("大帅比",player2);
lookPoker("蛋筒",player3);
}
/*
* 参数一:玩家的名字
* 参数二:牌的序号
* */
public void lookPoker(String name, TreeSet<Integer> ts){
System.out.print(name + ": ");
//遍历TreeSet集合得到每一个序号,再拿着序号到Map集合中去找真正的牌
for (int serialNumber : ts) {
String poker = hm.get(serialNumber);
System.out.print(poker + " ");
}
System.out.println();
}
}