前言
嗯~怎么说呢,就是心血来潮想练下基础,但又不知道练什么好。就干脆做个小游戏玩一玩。
一、设计
首页斗地主有这么几个需要的东西:
- 玩家
- 扑克牌
- 发牌的??
每局游戏玩家需要3个,扑克牌每3个人一套,而发牌的就叫庄家了吧,也是每三人一个。
综上所述,程序运行需要的对象有
- 庄家:有一套完整的牌和三个玩家
- 玩家:有一套自己的牌
- 扑克牌:有牌的大小和类型(对子,炸弹啥的)
二、流程
- 初始化54张牌
- 选定谁是地主
- 发牌(每人17张牌)
- 剩余3张牌给地主
- 地主出牌
- 按顺序下一位出牌
- 重复5-6至有人手牌全部出完
- 宣布胜利者
三、方法定义
- 初始化54张牌
- 选定谁是地主
- 发牌(每人17张牌)
- 剩余3张牌给地主
- 地主出牌
- 按顺序下一位出牌
- 重复5-6至有人手牌全部出完
- 宣布胜利者
- 这个当然是庄家初始化,也就是庄家对象需要初始化54张牌的方法
- 谁是地主也是庄家选定的,专家对象需要一个选定地址的方法
- 发牌也是庄家干的事,但发给玩家,玩家需要拿到牌,也就是庄家需要一个发牌的方法,玩家需要一个收牌的方法
- 没啥好说的
- 出牌也就是玩家需要一个出牌的方法
- 决定出牌的顺序和记录上一个出牌的玩家也是庄家需要的方法
- 循环,交给主程序
- 最后的输出也交给主程序
整理成代码:
扑克牌
**
* @author: ljp
* @description: 牌
* @date:
*/
public class Brand {
/**
* 扑克牌数字
*/
private static final String[] NUMBER = new String[] { "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A",
"2", "joker" };
/**
* 扑克牌花色
*/
private static final String[] COLOUR = new String[] { "♥", "♠", "♣", "♦" };
/**
* 卡牌数组
*/
public static final String[] DEFAULT_BRAND = new String[54];
/**
* 初始化
*/
static {
}
/** 类型-1错误类型0-单1-对子2-王炸3-三带一4-三带二5-顺子6-连队7-炸弹 */
private int type = -1;
/** 牌的大小-组 */
private int[] brandSize = new int[20];
/** 数组大小 */
private int brandLength = 0;
/** 存储重复出现次数的数组 */
private int[] brandNum = new int[NUMBER.length];
/**
* 创建牌对象
* @param brands 可以有多张牌
*/
public Brand(String... brands) {
}
/**
* 排序
*
*/
public void sort() {
}
/**
* 计算类型
*/
public void updateType() {
type = -1;
}
/**
* 获取牌下标
*/
public static int getBrandIndex(String brand) {
return -1;
}
/**
* 根据下标获取牌
*/
public static String getBrandByIndex(int index) {
return "大王";
}
/**
* 获取牌的大小
*/
public static int getBrandSize(String brand) {
return 0;
}
/**
* 比较牌大小
*
* @return -true 大于,false 无法判断或小于等于
*/
public boolean extent(Brand brand) {
return true;
}
}
玩家
/**
* @author: ljp
* @description: 玩家
* @date:
*/
public class User {
/**
* 初始化
*
* @param userName
*/
public User(String userName) {
this.userName = userName;
}
/** 用户名 */
private String userName;
/** 卡牌数 */
private int brandNumber = 0;
/** 是否地主 */
private boolean isLord = false;
/** 用户持有卡牌 */
private String[] userp = new String[20];
/**
* 发牌
*/
public void deal(String brand) {
}
/**
* 出牌
*
* @param index 用户牌下标
* @return
*/
public void outBrand(int[] indexs) {
}
/**
* 排序
*/
public void sort() {
}
/**
* 输出手牌
*/
public String getBrand() {
}
/**
* 输出手牌序号
*/
public String getBrandNo() {
}
public String getUserName() {
return userName;
}
public Integer getBrandNumber() {
return brandNumber;
}
public Boolean isLord() {
return isLord;
}
public void setIsLord(Boolean isLord) {
this.isLord = isLord;
}
}
庄家
/**
* @author: ljp
* @description: 庄家
* @date:
*/
public class Maker {
/**
* 卡牌数组
*/
private String[] p = new String[54];
/**
* 用户出的牌
*/
private Brand brand;
/**
* 出牌的用户下标
*/
private int uIndex = -1;
/**
* 地主下标
*/
private int lordIndex = -1;
/**
* 初始化54张牌
*/
public Maker() {
}
/** 玩家 */
private User[] user = new User[3];
/**
* 伪随机洗牌
*/
public void washBrand() {
}
/**
* 发牌
*/
public void start() {
}
/**
* 用户出牌
*
* @param uIndex 用户下标
* @param pIndex 用户牌下标
*/
public boolean outBrand(int uIndex, int[] pIndex) {
}
/**
* 输出玩家出的牌
*/
public String getOutBrand(Integer lordIndex) {
}
public User[] getUser() {
return user;
}
public void setUser(User[] user) {
this.user = user;
}
public Integer getLordIndex() {
return lordIndex;
}
}
主程序
/**
* @author: ljp
* @description:
* @date:
*/
public class Main {
public static void main(String[] args) {
Maker m = new Maker();
m.setUser(new User[] { new User("天天"), new User("可可儿"), new User("水煮鱼") });
m.washBrand();
// 开始发牌
m.start();
// 打印用户的手牌
for (User user : m.getUser()) {
System.out.println(user.getBrand());
}
// 第一次出牌玩家的下标
int lordIndex = m.getLordIndex();
int roundNumber = 1;
Scanner in = new Scanner(System.in);
System.out.println("=======================================");
while (true) {
System.out.println(m.getOutBrand(lordIndex));
System.out.println("请出牌,出多张牌用空格隔开");
// 输出玩家手牌
System.out.println(m.getUser()[lordIndex].getBrand());
System.out.println(m.getUser()[lordIndex].getBrandNo());
try {
String[] split = in.nextLine().split(" ");
int[] indexs = new int[split.length];
for (int i = 0; i < split.length; i++) {
indexs[i] = Integer.valueOf(split[i]).intValue();
}
if(check(indexs)){
System.out.println("输入有误,请重新输入");
continue;
}
if (!m.outBrand(lordIndex, indexs)) {
System.out.println("输入有误,请重新输入");
continue;
}
if (m.getUser()[lordIndex].getBrandNumber() == 0) {
System.out.println("恭喜玩家:" + m.getUser()[lordIndex].getUserName() + "获胜");
roundNumber++;
break;
}
lordIndex = (lordIndex + 1) % 3;
roundNumber++;
} catch (Exception e) {
in = new Scanner(System.in);
System.out.println("输入有误,请重新输入");
continue;
}
}
in.close();
System.out.println("总回合数为:" + roundNumber);
}
/**
* 是否有重复
* @param indexs
* @return
*/
private static boolean check(int[] indexs){
if(indexs.length < 2){
return false;
}
for(int i=0;i<indexs.length;i++){
for(int j=i+1;j<indexs.length;j++){
if(indexs[i] == indexs[j]){
return true;
}
}
}
return false;
}
}
思路整理的那么好,这还能翻!!这还能翻??这都能翻o_O
额,好吧。过了两天了我还是没有写完
四、遇到的问题
小bug小bug,一个练基础用的小游戏而已啦,不会搞得太复杂的,只是一直拿不到好的牌害我测试各种情况费了点劲。最大的问题就是牌的大小判断,一开始代码写的是真的low各种if判断看的我自己都发疯。最后还是花了4-5天终于是写完了。
五、完整代码
玩家
/**
* @author: ljp
* @description: 玩家
* @date:
*/
public class User {
/**
* 初始化
*
* @param userName
*/
public User(String userName) {
this.userName = userName;
}
/** 用户名 */
private String userName;
/** 卡牌数 */
private int brandNumber = 0;
/** 是否地主 */
private boolean isLord = false;
/** 用户持有卡牌 */
private String[] userp = new String[20];
/**
* 发牌
*/
public void deal(String brand) {
userp[brandNumber] = brand;
brandNumber++;
}
/**
* 获取出牌
*
* @param index 用户手牌下标
* @return 用户出的牌
*/
public String[] getOutBrandIndex(int[] indexs) {
String[] brands = new String[indexs.length];
for (int i = 0; i < indexs.length; i++) {
if (indexs[i] < 0 || indexs[i] >= this.brandNumber) {
brands[i] = "";
} else {
brands[i] = userp[indexs[i]];
}
}
return brands;
}
/**
* 出牌
*
* @param index 用户牌下标
* @return
*/
public void outBrand(int[] indexs) {
for (int index : indexs) {
userp[index] = null;
}
sort();
brandNumber-=indexs.length;
}
/**
* 排序
*/
public void sort() {
String ch;
int beginIndex = -1;
int endIndex = -1;
for (int i = 0; i < brandNumber - 1; i++) {
for (int n = i + 1; n < brandNumber; n++) {
beginIndex = Brand.getBrandIndex(userp[i]);
endIndex = Brand.getBrandIndex(userp[n]);
if (beginIndex == -1 || (endIndex != -1 && beginIndex > endIndex)) {
ch = userp[n];
userp[n] = userp[i];
userp[i] = ch;
}
}
}
}
/**
* 输出手牌
*/
public String getBrand() {
sort();
StringBuilder result = new StringBuilder();
result.append(userName);
if (this.isLord) {
result.append("(地主)");
}
result.append("的手牌:");
for (int i = 0; i < brandNumber; i++) {
result.append(userp[i]).append(",");
}
return result.substring(0, result.length() - 1);
}
/**
* 输出手牌序号
*/
public String getBrandNo() {
sort();
StringBuilder result = new StringBuilder();
result.append(userName);
if (this.isLord) {
result.append("(地主)");
}
result.append("的牌号:");
for (int i = 0; i < brandNumber; i++) {
for (int n = 0; n < userp[i].length() - String.valueOf(i).length(); n++) {
result.append("♥");
}
result.append(""+i).append(",");
}
return result.substring(0, result.length() - 1);
}
public String getUserName() {
return userName;
}
public Integer getBrandNumber() {
return brandNumber;
}
public Boolean isLord() {
return isLord;
}
public void setIsLord(Boolean isLord) {
this.isLord = isLord;
}
}
庄家
/**
* @author: ljp
* @description: 庄家
* @date:
*/
public class Maker {
/**
* 卡牌数组
*/
private String[] p = new String[54];
/**
* 用户出的牌
*/
private Brand brand;
/**
* 出牌的用户下标
*/
private int uIndex = -1;
/**
* 地主下标
*/
private int lordIndex = -1;
/**
* 初始化
*/
public Maker() {
for (int i = 0; i < p.length; i++) {
p[i] = Brand.DEFAULT_BRAND[i];
}
}
/** 玩家 */
private User[] user =new User[3];
/**
* 伪随机洗牌
*/
public void washBrand() {
String ch;
int off;
long time = System.currentTimeMillis();
// n=洗牌次数
for (int n = -1; n < time % p.length; n++) {
for (int i = 0; i < p.length; i++) {
// 新位置
off = (int) ((time | n & p.hashCode() | p[i].hashCode()) % p.length);
off = off < 0 ? -off : off;
ch = p[off];
p[off] = p[i];
p[i] = ch;
}
}
}
/**
* 发牌
*/
public void start() {
int lord = (int) ((System.currentTimeMillis() | user.hashCode()) % user.length);
if (lord < 0) {
lord = -lord;
}
// 发地主
user[lord].setIsLord(true);
this.lordIndex = lord;
for (int i = 0; i < p.length; i++) {
if (i > p.length - 4) {
user[lord].deal(p[i]);
} else {
user[i % 3].deal(p[i]);
}
}
}
/**
* 用户出牌
*
* @param uIndex 用户下标
* @param pIndex 用户牌下标
*/
public boolean outBrand(int uIndex, int[] pIndex) {
// 校验越界
Brand brand = new Brand(user[uIndex].getOutBrandIndex(pIndex));
if (brand.isOff()) {
// 有用户出牌大不起时才返回true
return this.brand != null && this.uIndex != uIndex;
}
if (this.brand == null || this.uIndex == uIndex) {
// 1.第一次出牌或全pass
user[uIndex].outBrand(pIndex);
this.brand = brand;
this.uIndex = uIndex;
return true;
}
// 2.比较大小
if (brand.extent(this.brand)) {
user[uIndex].outBrand(pIndex);
this.brand = brand;
this.uIndex = uIndex;
return true;
}
return false;
}
/**
* 输出玩家出的牌
*/
public String getOutBrand(Integer lordIndex) {
if (this.brand == null || this.uIndex == lordIndex) {
return "";
}
StringBuilder out = new StringBuilder();
User user = this.user[this.uIndex];
out.append(user.getUserName());
if (user.isLord()) {
out.append("(地主)");
}
out.append("出的牌:");
out.append(this.brand.printBrand());
return out.toString();
}
public User[] getUser() {
return user;
}
public void setUser(User[] user) {
this.user = user;
}
public Integer getLordIndex() {
return lordIndex;
}
}
扑克牌
/**
* @author: ljp
* @description: 牌
* @date: 2022年12月8日 上午9:27:01
*/
public class Brand {
/**
* 扑克牌数字
*/
private static final String[] NUMBER = new String[] { "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A",
"2", "joker" };
/**
* 扑克牌花色
*/
private static final String[] COLOUR = new String[] { "♥", "♠", "♣", "♦" };
/**
* 卡牌数组
*/
public static final String[] DEFAULT_BRAND = new String[54];
/**
* 初始化
*/
static {
DEFAULT_BRAND[52] = "小王";
DEFAULT_BRAND[53] = "大王";
for (int i = 0; i < DEFAULT_BRAND.length - 2; i++) {
DEFAULT_BRAND[i] = COLOUR[i % 4] + NUMBER[i / 4];
}
}
/** 类型-1错误类型0-单1-对子2-王炸3-三带一4-三带二5-顺子6-连队7-炸弹 */
private int type = -1;
/** 牌的大小-组 */
private int[] brandSize = new int[20];
/** 数组大小 */
private int brandLength = 0;
/** 存储重复出现次数的数组 */
private int[] brandNum = new int[NUMBER.length];
public Brand(String... brands) {
brandLength = brands.length;
for (int i = 0; i < brands.length; i++) {
brandSize[i] = getBrandIndex(brands[i]);
if (brandSize[i] < 0) {
return;
}
}
// 初始化出现次数
for (int i = 0; i < brandLength; i++) {
brandNum[brandSize[i] / 4]++;
}
// 计算出类型
updateType();
// 排序
sort();
}
/**
* 排序
*
*/
public void sort() {
int ch;
int beginIndex = -1;
int endIndex = -1;
for (int i = 0; i < brandLength - 1; i++) {
for (int n = i + 1; n < brandLength; n++) {
beginIndex = brandNum[brandSize[i] / 4];
endIndex = brandNum[brandSize[n] / 4];
if (beginIndex == -1 || (endIndex != -1 && beginIndex < endIndex)) {
ch = brandSize[n];
brandSize[n] = brandSize[i];
brandSize[i] = ch;
} else if (beginIndex == endIndex && brandSize[i] > brandSize[n]) {
ch = brandSize[n];
brandSize[n] = brandSize[i];
brandSize[i] = ch;
}
}
}
}
/**
* 计算类型
*/
public void updateType() {
// 0-单
if (judgeType(1, 0, 1)) {
type = 0;
return;
}
// 1-对子
if (judgeType(2, 0, 2)) {
if(brandSize[0] > 51 && brandSize[1] > 51) {
// 2-王炸
type =2;
}else {
type = 1;
}
return;
}
// 3-三带一
if (judgeType(4, 0, 3)) {
type = 3;
return;
}
// 4-三带二
if (judgeType(5, 0, 3) && judgeType(5, 0, 2)) {
type = 4;
return;
}
// 5-顺子
if (judgeType(0, 5, 1) && judgeType(brandLength, brandLength, 1)) {
type = 5;
return;
}
// 6-连队
if (brandLength % 2 == 0 && judgeType(0, 4, 2) && judgeType(brandLength, brandLength / 2, 2)) {
type = 5;
return;
}
// 7炸弹
if (judgeType(4, 0, 4)) {
type = 7;
return;
}
type = -1;
}
/**
* 判断类型
*
* @param len 长度 0-为不判断长度
* @param seriesNum 连续次数 0-不连续
* @param repeatNum 牌重复的次数 0-不判断
* @return
*/
public boolean judgeType(int len, int seriesNum, int repeatNum) {
if (len != 0 && brandLength != len) {
return false;
}
// 是否满足重复次数
boolean isRepeat = false;
// 是否满足连续次数
boolean isSeries = false;
// 连续次数
int count = 0;
for (int brand : brandNum) {
if (repeatNum == 0 || brand == repeatNum) {
isRepeat = true;
count++;
if (count >= seriesNum) {
isSeries = true;
}
} else {
count = 0;
}
}
return isRepeat && isSeries;
}
/**
* 获取牌下标
*/
public static int getBrandIndex(String brand) {
for (int i = 0; i < DEFAULT_BRAND.length; i++) {
if (DEFAULT_BRAND[i].equals(brand)) {
return i;
}
}
return -1;
}
/**
* 根据下标获取牌
*/
public static String getBrandByIndex(int index) {
if (index == 52) {
return "小王";
}
if (index == 53) {
return "大王";
}
return COLOUR[index % 4] + NUMBER[index / 4];
}
/**
* 获取牌的大小
*/
public static int getBrandSize(String brand) {
int index = getBrandIndex(brand);
if (index > 51) {
return index;
}
return index / 4;
}
/**
* 比较牌大小
*
* @return -true 大于,false 无法判断或小于等于
*/
public boolean extent(Brand brand) {
if (this.type == -1) {
return false;
}
if (brand == null || brand.type == -1 || this.type == 2) {
return true;
}
if (this.type == brand.type && this.brandLength == brand.brandLength) {
return this.brandSize[0] > brand.brandSize[0];
}
if (this.type == 7) {
return true;
}
return false;
}
/**
* 输出牌组
*/
public String printBrand() {
StringBuilder result = new StringBuilder();
for (int i = 0; i < brandLength; i++) {
result.append(getBrandByIndex(brandSize[i]));
}
return result.toString();
}
public boolean isOff() {
return this.type == -1;
}
}
六、游戏体验

总结
还是有点意思的。



2217

被折叠的 条评论
为什么被折叠?



