斗地主综合案例练习
1. 准备牌:54张牌,存储到一个【集合】中
特殊牌:大王、小王
其他52张牌:
定义一个【数组/集合】,存储4种花色:♠、♥、♣、♦
定义一个【数组/集合】,存储13个序号:2,A,K...3
循环嵌套遍历两个【数组/集合】,组装52张牌
♠2,♠A,♠K...♠3 ♥2,♥A,♥K...♥3
....
2. 洗牌
使用集合工具类Collections的方法
static void shuffle(List<?> list) 使用指定的随机源对指定列表进行置换。
会随机的打乱集合中元素的顺序
3. 发牌
要求:1人17张牌,剩余3张作为底牌,一人一张轮流发牌:集合的索引(0-53)%3
定义4个集合,存储3个玩家的牌和底牌
索引%2,有两个值(0,1) %2=0 1%2=1 2%2=0
索引%3,有三个值(0,1,2) 0%3=0 1%3=1 2%3=2 3%3=0
索引>=51 给底牌发牌
4. 看牌
直接打印集合,遍历存储玩家和底牌的集合
牌:
大王、小王
♠2,♠A,♠K...♠3 ♥2,♥A,♥K...♥3
....
集合1:
存储玩家的17张牌 i%3==0
集合2:
存储玩家的17张牌 i%3==1
集合3:
存储玩家的17张牌 i%3==2
集合4:
存储3张底牌 i>=51
public static void main(String[] args) {
// 1. 准备牌
// 定义一个存储54张牌的ArrayList集合,泛型使用String
ArrayList<String> poker = new ArrayList<>();
// 定义两个数组,一个数组存储牌的花色,一个数组存储牌的序号
String[] colors = {"♠", "♥", "♣", "♦"};
String[] numbers = {"2", "A", "K", "Q", "J", "10", "9", "8", "7", "6", "5", "4", "3"};
// 先把大王和小王存储到poker集合中
poker.add("大王");
poker.add("小王");
// 循环嵌套遍历两个数组,组装52张牌
for (String number : numbers) {
for (String color : colors) {
// System.out.println(color + number);
//把组装好的牌存储到poker集合中
poker.add(color + number);
}
}
// System.out.println(poker);
// 2. 洗牌 使用集合的工具类Collections中的方法
// static void shuffle(List<?> list) 使用默认随机源对指定列表进行置换。
Collections.shuffle(poker);
// System.out.println(poker);
// 3. 发牌
// 定义4个集合,存储玩家的牌和底牌
ArrayList<String> player01 = new ArrayList<>();
ArrayList<String> player02 = new ArrayList<>();
ArrayList<String> player03 = new ArrayList<>();
ArrayList<String> dipai = new ArrayList<>();
// 遍历poker集合,获取每一张牌
// 使用poker集合的索引%3给3个玩家轮流发牌,剩余3张牌给底牌
// 注意:先判断底牌(i>=51),否则牌就发没了
for (int i = 0; i < poker.size(); i++) {
//获取每一张牌
String p = poker.get(i);
//轮流发牌
if (i >= 51) {
//给底牌发牌
dipai.add(p);
} else if (i % 3 == 0) {
//给玩家1发牌
player01.add(p);
} else if (i % 3 == 1) {
//给玩家2发牌
player02.add(p);
} else if (i % 3 == 2) {
//给玩家3发牌
player03.add(p);
}
}
// 4. 看牌
System.out.println("player01:" + player01);
System.out.println("player02:" + player02);
System.out.println("player03:" + player03);
System.out.println("dipai:" + dipai);
}
数据结构
先进后出
入口和出口在同一侧
存储元素到集合 入、压栈
取出集合中元素 出、弹栈
2号元素要出来,3号元素必须先出来
入栈:123 出栈:321 类似子弹弹夹
先进先出
入口和出口在集合的两侧
存储:123 取出:123 类似排队安检
查询快:数组的地址是连续的,通过数组的首地址可以找到数组,通过数组的索引可以快速查找某一个元素
增删慢:数组的长度是固定的,想要增加/删除一个元素,必须创建一个新数组,把原数组的数据复制过来
int[] arr = new int[] {1,2,3,4};
首地址:0x11 new int[] {1,2,3,4}; 销毁
要把数组中索引是3的元素删除,必须创建一个新的数组,长度是原数组的长度-1
把原数组的其他元素复制到新数组中,在把新数组的地址赋值给变量arr,原数组会在内存中销毁(垃圾回收)
首地址:0x88 new int[] {1,2,3};
在堆内存中,频繁的创建数组,复制数组中的元素,销毁数组,效率低下
查询慢:链表中地址不是连续的,每次查询元素,都必须从头开始查询
增删快:链表结构,增加/删除一个元素,对链表的整体结构没有影响,所以增删快
链表中的每一个元素也称之为一个节点
一个节点包含了一个数据源(存储数组),两个指针域(存储地址) 自己的地址、数据、下一个节点的地址
单向链表:链表中只有一条链子,不能保证元素的顺序(存储元素和取出元素的顺序有可能不一致)
双向链表:链表中有两条链子,有一条链子是专门记录元素的顺序,是一个有序的集合
0x11 100 0x72 0x72 300 0x99 0x99 55 0x11
生活中的树:树叶、树枝、根部
计算机中的数(倒着):树根、分支、树叶
二叉树:分支不能超过两个 左孩子/左子树 右孩子/右子树
排序树/查找树:在二叉树的基础上元素是有大小顺序的 左子树小,右子树大 类似猜数字小游戏:1-100之间的数字,从50开始猜,一下减去一半
平衡树:左孩子和右孩子相等
不平衡树:左孩子 != 右孩子
红黑树:
特点:趋近于平衡数,【查询的速度非常的快】,查询叶子节点最大次数和最小次数不能超过2倍
约束: 1. 节点可以是红色的或者黑色的
2. 根节点是黑色的
3. 叶子节点(空节点)是黑色的
4. 每个红色的节点的子节点都是黑色的
5. 任何一个节点到其每一个叶子节点的所有路径上黑色节点数相同