斗地主游戏项目文档
本文档介绍斗地主游戏的设计要求、数据模型、简单测试、视图设计、GUI程序、程序发布等方面的内容,以提供一个全面而清晰的说明。以下是各个部分的详细介绍。
设计要求
斗地主游戏的设计要求如下:
1:实现一个登录注册界面,包括点击生成随机验证码 验证账密等功能
添加更改密码 查看已注册用户功能

2. 实现一个经典的斗地主游戏,包括发牌、抢地主、出牌、倒计时等功能。
3. 支持单人参与游戏,玩家进行操作与两位人机对战。
数据模型
在斗地主游戏中,需要设计以下数据模型:
一: 玩家:包括玩家的姓名、手牌等信息。
二:牌:包括牌的4种花色、大小王与13种序号等信息,进行权重排序。通过牌型比较判断玩家是否能出牌。
三:地主:表示当前的地主玩家,获得初始的3张手牌,率先出牌。
Common类主要包括对扑克牌进行排序、判断牌型、移动牌等功能;
1. 判断牌型:根据输入的扑克牌列表,判断其牌型,如单牌、对子、三张牌等,并返回对应的牌型。
2. 移动牌:提供了移动扑克牌的方法,可以实现带有动画效果的扑克牌移动,牌点击后向上移动20像素,再次点击向下移动20像素
3. 排序:利用扑克牌的牌面大小和花色进行排序,将输入的扑克牌列表按照一定规则进行排序。
4. 重新摆放牌的顺序:根据游戏界面和需要摆放的集合,将扑克牌重新摆放到指定的位置。
登录界面类
在LoginJFrame类中,首先定义了一些成员变量,比如按钮、文本框等,以及一个保存用户信息的列表(userDatabase)。
注册新用户后会创建User类的一个新对象,用户对象实际存储在Userdatabase的List表中
构造方法LoginJFrame(),用于初始化界面、添加组件,并将界面显示出来。
public LoginJFrame(){
//初始化界面
initJFrame();
//初始化组件,在页面中添加内容
initView();
//让当前界面显示出来
this.setVisible(true);
}
initJFrame() 设置窗体的大小、标题
public void initJFrame(){
//设置宽高 标题 关闭后停止运行 居中 置顶 取消默认布局
this.setSize(640,420);
this.setTitle("斗地主游戏登录 Version:1.0.0 ");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
this.setAlwaysOnTop(true);
this.setLayout(null);
}
initView() 添加各种组件,比如标签、输入框、按钮
注意创建完标签,账号密码输入框,验证码,4个按钮后添加组件到面板中,由于本类已经继承了JFrame类,直接用this.getContentPane().add(组件),将组件添加到当前面板
GameJFrame类是一个基于 Java 编写的斗地主游戏的界面部分。它使用了 Swing 库来创建游戏窗口,并包含了玩家操作的按钮、玩家手牌的展示以及倒计时等功能。
在 `GameJFrame` 类中,首先定义了游戏界面的一些基本属性和组件,然后在构造函数中进行了界面的初始化工作。其中通过多线程的方式进行了牌的初始化(备牌、洗牌、发牌),以及播放游戏音乐的操作,避免阻塞主线程。界面初始化完成后,展示了抢地主和不抢地主两个按钮,以及倒计时文本等。
通过 `initView()` 方法,添加了抢地主和不抢地主两个按钮,以及出牌和不要的按钮,同时创建了玩家前的提示文字倒计时显示。
通用功能类
Common是一个扑克牌游戏中的通用功能类,其中包括了对扑克牌进行排序、判断牌型、移动牌等功能。
首先是jugdeType方法,用于判断牌型,包括单张、对子、三不带、炸弹、顺子、连对、飞机、四带二等类型。
然后是move方法,实现了移动牌的动画效果。
接着是order方法,利用牌的价值对集合中的牌进行排序。
rePosition方法用于重新摆放牌的顺序,包括左、中、右三个位置。
验证码类 CodeUtil.getCode()会返回一个 4个英文字符与一个数字字符 拼接成的字符串
位置随机
创建一个ArrayList对象 可以动态改变大小的数组
根据ascii码即字节码中 a – z 与 A – Z的关系
向list表中依次添加大小写共52个字母 例如:aA - zZ
利用Random类 对象的nextInt()方法 向其传入list表长 生成一个随机字母在表中的索引
表.get(索引) 获取索引对应字母
写在for循环中,遍历4次拼接字符串
利用Random类 对象的nextInt()方法 向其传入10 范围即为0-9
1个随机数字暂时拼接在4个随机字母后面
将字符串 转换 为字符数组
定义一个索引 利用Random类 对象的nextInt()方法 向其传入 字符数组长度
空水杯交换 空水杯 = 数字字符;数字字符 = 随机索引对应英文字符;英文字符 = 空水杯
public static String getCode(){
//创建一个集合;
ArrayList<Character> list = new ArrayList<>(); //52 索引范围0-51
//添加字母 a - z A - Z
for(int i=0;i<26;i++){
list.add((char)('a' + i));//类型转换为字符97-a 65-A
list.add((char)('A' + i));
}
//打印集合
//System.out.println(list);
//生成4个随机字母
String result = "";
Random r = new Random();
for(int i=0;i<4;i++){
int randomIndex = r.nextInt(list.size());
result = result + list.get(randomIndex);
}
//长度为4的随机字符串 return result;
//基础上拼接数字0-9
int number = r.nextInt(10);
//把随机数字拼接到result后面
result = result + number;
//把字符串变成字符数组
char[] chars = result.toCharArray();
//生成一个字符数组长度的随机索引
int index = r.nextInt(chars.length);
//末索引4上的数字字符与随机索引上的字符交换 使数字出现在索引0-4的任何位置
char temp = chars[4];
chars[4] = chars[index];
chars[index] = temp;
//字符数组变回字符串
String code = new String(chars);
return code;
}
出牌类型类
枚举类型enum表示一组相关的常量
方便判断出牌是否为同一类型
简单测试
在开发过程中,可以进行简单的测试来验证代码的正确性和可靠性。例如,可以模拟发牌、抢地主、出牌等操作,并检查结果是否符合预期。
测试过程发现音频无法播放,搜索错误得知不支持applet工具类,wav,m4p等音乐格式也不支持。于是导入javazoom下的Player类,构造方法抛出异常与文件无法找到的错误,为使音乐在不同路径下都能播放,采取项目路径与相对路径拼接为字符串,再将字符串传入文件输入流,并预先用缓冲流加载,while(true)死循环使音频不断播放。
又由于音频是在登录成功后跳转的游戏界面播放,因此在游戏界面类构造函数处调用播放音频方法,为避免音乐播放阻塞主程序,将音频播放构造方法添加到异步加载中,
打包后cmd java -jar 包名或直接双击运行jar包,发现游戏界面的扑克与地主图片图片消失,原来是由于默认从src文件夹下找图片,img文件夹不在src里,可以在打包之后把图片文件夹img粘贴至jar包路径处,成功显示图片
打包后音频也无法播放,还是路径原因,原先拼接成的绝对路径改为相对路径,jar包位置创建文件夹src再放置音乐文件夹。
总结,都是取决于原先的图片或音频的路径
视图设计
为了提供友好的用户界面,需要进行视图设计。可以使用图形用户界面(GUI)来展示游戏进程和玩家操作。例如,可以设计游戏桌面、玩家手牌区域、出牌区域等。视图设计应符合用户习惯,界面简洁明了,方便玩家操作。

GUI程序
基于视图设计,可以开发一个GUI程序来实现斗地主游戏。GUI程序应当具备以下功能:
1. 显示游戏进程和玩家操作。
2. 提供按钮或其他交互元素,用于玩家进行抢地主、出牌等操作。
3. 实时更新游戏状态,包括当前玩家、地主玩家、出牌倒计时等信息。
4. 提供可视化的手牌区域和出牌区域,方便玩家查看和选择牌。
5.注册后可以更改密码 或者 查看已注册用户列表

程序发布
完成代码开发后,可以将程序进行发布,以供用户下载和使用。程序发布应包括以下步骤:
对代码进行编译和打jar包,生成可执行文件。

通过以上介绍,详细阐述了斗地主游戏代码的设计要求、数据模型、简单测试、视图设计、GUI程序、程序发布等方面的内容。希望这个文档能够对开发斗地主游戏的学习和游玩有所帮助
源码分为game main util music四个包
game包下新建类
Common类
import java.awt.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import lynu.rookie.main.Poker;
public class Common {
//四种花色:1"黑桃",2"红桃",3"梅花",4"方块"
//序号5 大小王
//十三种序号:"3","4","5","6","7","8","9","10","J","Q","K","A"序号1,"2"序号2
//判断牌型
public static PokerType jugdeType(ArrayList<Poker> list) {
int len = list.size();
if (len <= 4) {
if (list.size() > 0 && Common.getValue(list.get(0)) == Common.getValue(list.get(len - 1))) {
switch (len) {
case 1:
return PokerType.c1;
case 2:
return PokerType.c2;
case 3:
return PokerType.c3;
case 4:
return PokerType.c4;
}
}
if (len == 2 && Common.getColor(list.get(1)) == 5)
return PokerType.c2;
if (len == 4 && ((Common.getValue(list.get(0)) == Common.getValue(list.get(len - 2)))
|| Common.getValue(list.get(1)) == Common.getValue(list.get(len - 1))))
return PokerType.c31;
else {
return PokerType.c0;
}
}
if (len >= 5) {
PokerIndex pokerIndex = new PokerIndex();
ArrayList<ArrayList<Integer>> indexList = pokerIndex.indexList;
for (int i = 0; i < 4; i++) {
indexList.add(new ArrayList<>());
}
Common.getMax(pokerIndex, list);
if (indexList.get(2).size() == 1 && indexList.get(1).size() == 1 && len == 5)
return PokerType.c32;
if (indexList.get(3).size() == 1 && len == 6)
return PokerType.c411;
if (indexList.get(3).size() == 1 && indexList.get(1).size() == 2 && len == 8)
return PokerType.c422;
if ((Common.getColor(list.get(0)) != 5) && (indexList.get(0).size() == len)
&& (Common.getValue(list.get(0)) - Common.getValue(list.get(len - 1)) == len - 1))
return PokerType.c123;
if (indexList.get(1).size() == len / 2 && len % 2 == 0 && len / 2 >= 3
&& (Common.getValue(list.get(0)) - Common.getValue(list.get(len - 1)) == (len / 2 - 1)))
return PokerType.c112233;
if (indexList.get(2).size() == len / 3 && (len % 3 == 0)
&& (Common.getValue(list.get(0)) - Common.getValue(list.get(len - 1)) == (len / 3 - 1)))
return PokerType.c111222;
if (indexList.get(2).size() == len / 4 && (indexList.get(2).get(len / 4 - 1)
- (indexList.get(2).get(0)) == len / 4 - 1))
return PokerType.c11122234;
if (indexList.get(2).size() == len / 5 && indexList.get(2).size() == len / 5
&& ((indexList.get(2).get(len / 5 - 1)) - (indexList.get(2).get(0)) == len / 5
- 1))
return PokerType.c1112223344;
}
return PokerType.c0;
}
//移动牌(有移动的动画效果) 形参 当前移动牌 目标起始索引 结束索引
public static void move(Poker poker, Point from, Point to) {
if (to.x != from.x) {
double k = (1.0) * (to.y - from.y) / (to.x - from.x);
double b = to.y - to.x * k;
int flag = 0;
if (from.x < to.x)
flag = 20;
else {
flag = -20;
}
for (int i = from.x; Math.abs(i - to.x) > 20; i += flag) {
double y = k * i + b;
poker.setLocation(i, (int) y);
try {
Thread.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
poker.setLocation(to);
}
//利用牌的价值,将集合中的牌进行排序
public static void order(ArrayList<Poker> list) {
//此时可以改为lambda表达式
Collections.sort(list, new Comparator<Poker>() {
@Override
public int compare(Poker o1, Poker o2) {
//获取花色
//1-黑桃 2-红桃 3-梅花 4-方块 5-大小王
int a1 = Integer.parseInt(o1.getName().substring(0, 1));
int a2 = Integer.parseInt(o2.getName().substring(0, 1));
//获取牌上的数字,同时也是牌的价值
//1-A ... 11-J 12-Q 13-K
int b1 = Integer.parseInt(o1.getName().substring(2));
int b2 = Integer.parseInt(o2.getName().substring(2));
//计算牌的价值,利用牌的价值进行排序
//牌上的数字在3~10之间,价值就是3~10
//3:价值3
//...
//10:价值10
//J:价值11
//Q:价值12
//K:价值13
//A:1 + 20 = 21
//2:2 + 30 = 32
//小王:1 + 100 = 101
//大王:2 + 100 = 102
//计算大小王牌的价值
if (a1 == 5) {
b1 += 100;
}
if (a2 == 5) {
b2 += 100;
}
//计算A的价值
if (b1 == 1) {
b1 += 20;
}
if (b2 == 1) {
b2 += 20;
}
//计算2的价值
if (b1 == 2) {
b1 += 30;
}
if (b2 == 2) {
b2 += 30;
}
//倒序排列
int flag = b2 - b1;
//如果牌的价值一样,则按照花色排序
if (flag == 0) {
return a2 - a1;
} else {
return flag;
}
}
});
}
//重新摆放牌的顺序 游戏界面 要摆放的集合 标记0 1 2 左 中 右
public static void rePosition(GameJFrame m, ArrayList<Poker> list, int flag) {
Point p = new Point();
if (flag == 0) {
p.x = 50;
p.y = (450 / 2) - (list.size() + 1) * 15 / 2;
}
if (flag == 1) {
p.x = (800 / 2) - (list.size() + 1) * 21 / 2;
p.y = 450;
}
if (flag == 2) {
p.x = 700;
p.y = (450 / 2) - (list.size() + 1) * 15 / 2;
}
int len = list.size();
for (int i = 0; i < len; i++) {
Poker poker = list.get(i);
Common.move(poker, poker.getLocation(), p);
m.container.setComponentZOrder(poker, 0);
if (flag == 1)
p.x += 21;
else
p.y += 15;
}
}
public static int getScore(ArrayList<Poker> list) {
int count = 0;
for (int i = 0, len = list.size(); i < len; i++) {
Poker poker = list.get(i);
if (poker.getName().substring(0, 1).equals("5")) {
count += 5;
}
if (poker.getName().substring(2).equals("2")) {
count += 2;
}
}
return count;
}
public static int getColor(Poker poker) {
return Integer.parseInt(poker.getName().substring(0, 1));
}
public static int getValue(Poker poker) {
int i = Integer.parseInt(poker.getName().substring(2));
if (poker.getName().substring(2).equals("2"))
i += 13;
if (poker.getName().substring(2).equals("1"))
i += 13;
if (Common.getColor(poker) == 5)
i += 2;
return i;
}
public static void getMax(PokerIndex pokerIndex, ArrayList<Poker> list) {
int count[] = new int[14];
for (int i = 0; i < 14; i++)
count[i] = 0;
for (int i = 0, len = list.size(); i < len; i++) {
if (Common.getColor(list.get(i)) == 5)// 王
count[13]++;
else
count[Common.getValue(list.get(i)) - 1]++;
}
ArrayList<ArrayList<Integer>> indexList = pokerIndex.indexList;
for (int i = 0; i < 14; i++) {
switch (count[i]) {
case 1:
indexList.get(0).add(i + 1);
break;
case 2:
indexList.get(1).add(i + 1);
break;
case 3:
indexList.get(2).add(i + 1);
break;
case 4:
indexList.get(3).add(i + 1);
break;
}
}
}
public static Model getModel(ArrayList<Poker> list, int[] orders) {
ArrayList list2 = new ArrayList<>(list);
Model model = new Model();
for (int i = 0; i < orders.length; i++)
showOrders(orders[i], list2, model);
return model;
}
public static void get123(ArrayList<Poker> list, Model model) {
ArrayList<Poker> del = new ArrayList<>();
if (list.size() > 0 && (Common.getValue(list.get(0)) < 7 || Common.getValue(list.get(list.size() - 1)) > 10))
return;
if (list.size() < 5)
return;
ArrayList<Poker> list2 = new ArrayList<>();
ArrayList<Poker> temp = new ArrayList<>();
ArrayList<Integer> integers = new ArrayList<>();
for (Poker poker : list2) {
if (integers.indexOf(Common.getValue(poker)) < 0) {
integers.add(Common.getValue(poker));
temp.add(poker);
}
}
Common.order(temp);
for (int i = 0, len = temp.size(); i < len; i++) {
int k = i;
for (int j = i; j < len; j++) {
if (Common.getValue(temp.get(i)) - Common.getValue(temp.get(j)) == j - i) {
k = j;
}
}
if (k - i >= 4) {
String s = "";
for (int j = i; j < k; j++) {
s += temp.get(j).getName() + ",";
del.add(temp.get(j));
}
s += temp.get(k).getName();
del.add(temp.get(k));
model.a123.add(s);
i = k;
}
}
list.removeAll(del);
}
public static void getTwoTwo(ArrayList<Poker> list, Model model) {
ArrayList<String> del = new ArrayList<>();
ArrayList<String> l = model.a2;
if (l.size() < 3)
return;
Integer s[] = new Integer[l.size()];
for (int i = 0, len = l.size(); i < len; i++) {
String[] name = l.get(i).split(",");
s[i] = Integer.parseInt(name[0].substring(2, name[0].length()));
}
for (int i = 0, len = l.size(); i < len; i++) {
int k = i;
for (int j = i; j < len; j++) {
if (s[i] - s[j] == j - i)
k = j;
}
if (k - i >= 2) {
String ss = "";
for (int j = i; j < k; j++) {
ss += l.get(j) + ",";
del.add(l.get(j));
}
ss += l.get(k);
model.a112233.add(ss);
del.add(l.get(k));
i = k;
}
}
l.removeAll(del);
}
public static void getPlane(ArrayList<Poker> list, Model model) {
ArrayList<String> del = new ArrayList<>();
ArrayList<String> l = model.a3;
if (l.size() < 2)
return;
Integer s[] = new Integer[l.size()];
for (int i = 0, len = l.size(); i < len; i++) {
String[] name = l.get(i).split(",");
s[i] = Integer.parseInt(name[0].substring(2, name[0].length()));
}
for (int i = 0, len = l.size(); i < len; i++) {
int k = i;
for (int j = i; j < len; j++) {
if (s[i] - s[j] == j - i)
k = j;
}
if (k != i) {
String ss = "";
for (int j = i; j < k; j++) {
ss += l.get(j) + ",";
del.add(l.get(j));
}
ss += l.get(k);
model.a111222.add(ss);
del.add(l.get(k));
i = k;
}
}
l.removeAll(del);
}
public static void getBoomb(ArrayList<Poker> list, Model model) {
ArrayList<Poker> del = new ArrayList<>();
if (list.size() < 1)
return;
if (list.size() >= 2 && Common.getColor(list.get(0)) == 5 && Common.getColor(list.get(1)) == 5) {
model.a4.add(list.get(0).getName() + "," + list.get(1).getName());
del.add(list.get(0));
del.add(list.get(1));
}
if (Common.getColor(list.get(0)) == 5 && Common.getColor(list.get(1)) != 5) {
del.add(list.get(0));
model.a1.add(list.get(0).getName());
}
list.removeAll(del);
for (int i = 0, len = list.size(); i < len; i++) {
if (i + 3 < len && Common.getValue(list.get(i)) == Common.getValue(list.get(i + 3))) {
String s = list.get(i).getName() + ",";
s += list.get(i + 1).getName() + ",";
s += list.get(i + 2).getName() + ",";
s += list.get(i + 3).getName();
model.a4.add(s);
for (int j = i; j <= i + 3; j++)
del.add(list.get(j));
i = i + 3;
}
}
list.removeAll(del);
}
public static void getThree(ArrayList<Poker> list, Model model) {
ArrayList<Poker> del = new ArrayList<>();
for (int i = 0, len = list.size(); i < len; i++) {
if (i + 2 < len && Common.getValue(list.get(i)) == Common.getValue(list.get(i + 2))) {
String s = list.get(i).getName() + ",";
s += list.get(i + 1).getName() + ",";
s += list.get(i + 2).getName();
model.a3.add(s);
for (int j = i; j <= i + 2; j++)
del.add(list.get(j));
i = i + 2;
}
}
list.removeAll(del);
}
public static void getTwo(ArrayList<Poker> list, Model model) {
ArrayList<Poker> del = new ArrayList<>();
for (int i = 0, len = list.size(); i < len; i++) {
if (i + 1 < len && Common.getValue(list.get(i)) == Common.getValue(list.get(i + 1))) {
String s = list.get(i).getName() + ",";
s += list.get(i + 1).getName();
model.a2.add(s);
for (int j = i; j <= i + 1; j++)
del.add(list.get(j));
i = i + 1;
}
}
list.removeAll(del);
}
public static void getSingle(ArrayList<Poker> list, Model model) {
ArrayList<Poker> del = new ArrayList<>();
for (int i = 0, len = list.size(); i < len; i++) {
model.a1.add(list.get(i).getName());
del.add(list.get(i));
}
list.removeAll(del);
}
public static void hideCards(ArrayList<Poker> list) {
for (int i = 0, len = list.size(); i < len; i++) {
list.get(i).setVisible(false);
}
}
public static int checkCards(ArrayList<Poker> c, ArrayList<ArrayList<Poker>> current, GameJFrame m) {
ArrayList<Poker> currentlist;
if (m.time[0].getText().equals("不要"))
currentlist = current.get(2);
else
currentlist = current.get(0);
PokerType cType = Common.jugdeType(c);
PokerType cType2 = Common.jugdeType(currentlist);
if (cType != PokerType.c4 && c.size() != currentlist.size())
return 0;
if (cType != PokerType.c4 && Common.jugdeType(c) != Common.jugdeType(currentlist)) {
return 0;
}
if (cType == PokerType.c4) {
if (c.size() == 2)
return 1;
if (cType2 != PokerType.c4) {
return 1;
}
}
if (cType == PokerType.c1 || cType == PokerType.c2 || cType == PokerType.c3 || cType == PokerType.c4) {
if (Common.getValue(c.get(0)) <= Common.getValue(currentlist.get(0))) {
return 0;
} else {
return 1;
}
}
if (cType == PokerType.c123 || cType == PokerType.c112233 || cType == PokerType.c111222) {
if (Common.getValue(c.get(0)) <= Common.getValue(currentlist.get(0)))
return 0;
else
return 1;
}
if (cType == PokerType.c31 || cType == PokerType.c32 || cType == PokerType.c411 || cType == PokerType.c422
|| cType == PokerType.c11122234 || cType == PokerType.c1112223344) {
List<Poker> a1 = Common.getOrder2(c);
List<Poker> a2 = Common.getOrder2(currentlist);
if (Common.getValue(a1.get(0)) < Common.getValue(a2.get(0)))
return 0;
}
return 1;
}
public static ArrayList getOrder2(List<Poker> list) {
ArrayList<Poker> list2 = new ArrayList<>(list);
ArrayList<Poker> list3 = new ArrayList<>();
int len = list2.size();
int a[] = new int[20];
for (int i = 0; i < 20; i++)
a[i] = 0;
for (int i = 0; i < len; i++) {
a[Common.getValue(list2.get(i))]++;
}
int max = 0;
for (int i = 0; i < 20; i++) {
max = 0;
for (int j = 19; j >= 0; j--) {
if (a[j] > a[max])
max = j;
}
for (int k = 0; k < len; k++) {
if (Common.getValue(list2.get(k)) == max) {
list3.add(list2.get(k));
}
}
list2.remove(list3);
a[max] = 0;
}
return list3;
}
public static void showOrders(int i, ArrayList<Poker> list, Model model) {
switch (i) {
case 1:
Common.getSingle(list, model);
break;
case 2:
Common.getTwo(list, model);
Common.getTwoTwo(list, model);
break;
case 3:
Common.getThree(list, model);
Common.getPlane(list, model);
break;
case 4:
Common.getBoomb(list, model);
break;
case 5:
Common.get123(list, model);
break;
}
}
}
class PokerIndex {
ArrayList<ArrayList<Integer>> indexList = new ArrayList<>();
}
游戏界面GameJFrame类
import javazoom.jl.decoder.JavaLayerException;
import lynu.rookie.main.Poker;
import music.MusicPlayer;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Collections;
public class GameJFrame extends JFrame implements ActionListener{
//获取界面中的隐藏容器
public static Container container = null;
//抢地主和不抢两个按钮 初始
JButton[] landlord= new JButton[2]; //null
//管理出牌和不要两个按钮
JButton[] publishCard = new JButton[2];
int lordFlag;
int turn;
//抢地主后的地主图标
JLabel lord;
//集合嵌套集合 大集合嵌套三个小集合
//小集合装每一个玩家当前要出的牌
//索引 0:左边电脑 1:中间玩家 2:右边电脑
ArrayList<ArrayList<Poker>> currentList = new ArrayList<>();
//小集合中装着每一个玩家的手牌
ArrayList<ArrayList<Poker>> playerList = new ArrayList<>();
//底牌
ArrayList<Poker> lordList = new ArrayList<>();
//牌库,装所有的牌
ArrayList<Poker> pokerList = new ArrayList();
//3个玩家前方的出牌倒计时提示
JTextField time[] = new JTextField[3];
//用户操作 多线程
PlayerOperation po;
boolean nextPlayer = false;
public GameJFrame(){
//设置任务栏地主图标
setIconImage(Toolkit.getDefaultToolkit().getImage("image\\lord.png"));
//设置窗口的基本属性,包括标题、大小、关闭模式、窗口是否可以调节、背景颜色等
initJFrame();
//添加添加界面中需要的组件,如抢地主和不抢地主按钮、玩家前的提示文字等
initView();
//先显示界面再发牌,发牌动画在界面展示前无法展示
this.setVisible(true);
//初始化牌 备-洗-发
//initCard()方法放在新的线程中执行,可以实现在后台进行牌局的初始化操作
new Thread(this::initCard).start();
//进行牌局的初始化,包括创建三个集合装三个玩家要出的牌、展示抢地主和不抢地主两个按钮、展示倒计时文本等
initGame();
//播放音乐
playMusic();
}
//由于登陆成功后游戏界面打开,音乐播放器阻塞游戏界面
//将音乐播放器放在异步加载的线程中,以免阻塞主线程游戏界面的加载
private void playMusic(){
Thread thread = new Thread(() -> {
//播放音乐
try {
new MusicPlayer();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (JavaLayerException e) {
e.printStackTrace();
}
});
thread.start();
}
//初始化 备-洗-发牌
public void initCard(){
//准备牌
//把所有牌添加到牌盒cardList中 4个花色 13个序号 大小王当作第5种花色存两张
for(int i=1;i<=5;i++){
for(int j=1;j<=13;j++){
if(i==5 && j>2){
break;
}else{
//中央牌盒显示为背面
Poker poker = new Poker(this,i + "-" + j,false);
poker.setLocation(350,150);
pokerList.add(poker);
container.add(poker);
}
}
}
//洗牌
Collections.shuffle(pokerList);
//创建三个数据集合装三个玩家的牌,放到大集合管理
ArrayList<Poker> player0 = new ArrayList<>();
ArrayList<Poker> player1 = new ArrayList<>();
ArrayList<Poker> player2 = new ArrayList<>();
for(int i = 0;i<pokerList.size();i++){
//获取当前遍历的牌
Poker poker = pokerList.get(i);
//给地主发三张牌
if(i<=2){
//移动牌 获取牌当前位置 设置新的坐标
Common.move(poker,poker.getLocation(),new Point(270+(75*i),10));
//把底牌添加到集合中
lordList.add(poker);
continue;
}
//给三个玩家发牌
if(i%3 == 0){
Common.move(poker,poker.getLocation(),new Point(50,60+i*5));
player0.add(poker);
}else if(i%3 == 1){
Common.move(poker,poker.getLocation(),new Point(180+i*7,470));
player1.add(poker);
//自己的牌展示为正面
poker.turnFront();
}else if(i%3 == 2){
Common.move(poker,poker.getLocation(),new Point(700,i*5));
player2.add(poker);
}
//把三个装着牌的集合放入大集合管理
playerList.add(player0);
playerList.add(player1);
playerList.add(player2);
//把当前的牌置于顶端,效果:牌依次错开
container.setComponentZOrder(poker,0);
}
//给手牌排序
for(int i=0;i<3;i++){
//排序
Common.order(playerList.get(i));
//重新摆放顺序
Common.rePosition(this,playerList.get(i),i);
}
}
//打牌之前的准备工作
private void initGame(){
//创建三个集合装三个玩家要出的牌
for(int i=0;i<3;i++){
ArrayList<Poker> list = new ArrayList<>();
//添加到大集合
currentList.add(list);
}
//展示抢地主和不抢地主两个按钮
landlord[0].setVisible(true);
landlord[1].setVisible(true);
//展示自己前方倒计时文本
time[1].setVisible(true);
//倒计时10秒
po = new PlayerOperation(this,10);
//开启倒计时
po.start();
}
@Override //0出抢 1不出不抢
public void actionPerformed(ActionEvent e){
if(e.getSource() == landlord[0]){
//点击抢地主
time[1].setText("抢地主");
po.isRun = false;
}else if(e.getSource() == landlord[1]){
//点击不抢
time[1].setText("不抢");
po.isRun = false;
}else if(e.getSource() == publishCard[1]){
//点击不要 清空当前牌列表 轮到下一位玩家
currentList.get(1).clear();
this.nextPlayer = true;
time[1].setText("不要");
}else if(e.getSource() == publishCard[0]){
//点击出牌
//创建一个临时集合 存放当前 要出的牌
ArrayList<Poker> c = new ArrayList<>();
//获取当前 手牌
ArrayList<Poker> player2 = playerList.get(1);
//遍历手牌 要出的牌存放到临时集合
for(int i=0;i<player2.size();i++){
Poker poker = player2.get(i);
if(poker.isClicked()){
c.add(poker);
}
}
int flag = 0;
//判断,如果左右两个玩家都不要
if(time[0].getText().equals("不要") && time[2].getText().equals("不要")){
//判断当前玩家出牌是否合法 PokerType.c0为不出牌
if(Common.jugdeType(c) != PokerType.c0){
flag = 1;
}
} else {
flag = Common.checkCards(c,currentList,this);
}
if(flag == 1){
//牌合法 要出的牌放入大集合管理
currentList.set(1,c);
//手牌中去除已出的牌
player2.removeAll(c);
//计算坐标并移动牌
//移动 使要出的牌出现在手牌上方
Point point = new Point();
point.x = (770/2) - (c.size() + 1) * 15 / 2;
point.y = 300;
for(int i=0,len = c.size();i<len;i++){
Poker poker = c.get(i);
Common.move(poker,poker.getLocation(),point);
point.x += 15;
}
//重新摆放剩余的牌
Common.rePosition(this,player2,1);
//隐藏文本提示
time[1].setVisible(false);
//轮到下一位玩家
this.nextPlayer = true;
}
}
}
//设置界面
public void initJFrame(){
//设置标题
this.setTitle("斗地主");
//设置大小
this.setSize(830,620);
//设置关闭模式
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//设置窗口无法进行调节
this.setResizable(false);
//界面居中
this.setLocationRelativeTo(null);
//container获取界面中的隐藏容器,以后无需再次调用方法获取
container = this.getContentPane();
//取消内部默认的居中放置
container.setLayout(null);
//设置背景颜色
container.setBackground(Color.LIGHT_GRAY);
}
//添加组件
public void initView(){
//创建抢地主的按钮
JButton robBut = new JButton("抢地主");
//设置位置
robBut.setBounds(320,400,75,20);
//添加点击事件
robBut.addActionListener(this);
robBut.setVisible(false);
landlord[0] = robBut;
container.add(robBut);
//创建不抢的按钮
JButton noBut = new JButton("不 抢");
//设置位置
noBut.setBounds(420,400,75,20);
//添加点击事件
noBut.addActionListener(this);
noBut.setVisible(false);
//添加到数组中管理
landlord[1] = noBut;
container.add(noBut);
//创建出牌的按钮
JButton outCardBut = new JButton("出牌");
outCardBut.setBounds(320,400,60,20);
outCardBut.addActionListener(this);
outCardBut.setVisible(false);
publishCard[0] = outCardBut;
container.add(outCardBut);
//创建不要的按钮
JButton noCardBut = new JButton("不要");
noCardBut.setBounds(420, 400, 60, 20);
noCardBut.addActionListener(this);
noCardBut.setVisible(false);
publishCard[1] = noCardBut;
container.add(noCardBut);
//创建玩家前的提示文字 倒计时
for (int i = 0; i < 3; i++) {
time[i] = new JTextField("倒计时");
//输入框不可编辑
time[i].setEditable(false);
time[i].setVisible(false);
//三个输入框添加到容器界面
container.add(time[i]);
int x = 150 + 235 * i;
int y = 230 + (i==1 ? 130 : 0);
time[i].setBounds(x, y, 60, 20);
}
//创建地主图标 先不设置位置
lord = new JLabel(new ImageIcon("image/lord.png"));
lord.setVisible(false);
lord.setSize(40,40);
container.add(lord);
}
}
登录注册类LoginJFrame
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
//继承JFrame类 鼠标监听接口
public class LoginJFrame extends JFrame implements MouseListener {
private String newcodeStr = ""; //保存codeStr的值的变量 newcodeStr为全局变量 封装后仅有本类可以访问 可以在本类不同方法传递
private static List<User> userDatabase = new ArrayList<>();
//静态方法getUser(String userName) 从userDatabase列表中根据用户名查找用户对象
//在登录和修改密码的事件监听器中
//根据用户名从数据库中获取对应的用户对象
private static User getUser(String userName){
for(User user: userDatabase){
//for-each 循环来遍历 userDatabase 列表中的每个用户对象
if(user.getUserName().equals(userName)){
return user;
}
}
return null;
}
JButton loginButton = new JButton();
JButton registerButton = new JButton();
JButton changePasswordButton = new JButton();
JButton showUserListButton = new JButton();
JTextField usernameText = new JTextField(20);
JPasswordField passwordText = new JPasswordField(20);
JTextField codeText = new JTextField(6);
//正确的验证码
JLabel rightCode = new JLabel();
public LoginJFrame(){
//初始化界面
initJFrame();
//初始化组件,在页面中添加内容
initView();
//让当前界面显示出来
this.setVisible(true);
}
public void initJFrame(){
//设置宽高 标题 关闭后停止运行 居中 置顶 取消默认布局
this.setSize(640,420);
this.setTitle("斗地主游戏登录 Version:1.0.0 ");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
this.setAlwaysOnTop(true);
this.setLayout(null);
}
public void initView(){
//添加用户名文字 Font字体样式大小 JLabel标签 setForeground设置前景颜色 setFont传入定义字体 setBounds设置字边框大小
//getContentPane(添加标签).add() 获取内容窗格
Font usernameFont = new Font("微软雅黑",1,16);
JLabel usernameLabel = new JLabel("用户名");
usernameLabel.setForeground(Color.white);
usernameLabel.setFont(usernameFont);
usernameLabel.setBounds(140,55,55,22);
this.getContentPane().add(usernameLabel);
//添加用户名输入框
usernameText.setBounds(223,46,200,30);
this.getContentPane().add(usernameText);
//添加密码文字
Font passwordFont = new Font("微软雅黑",1,16);
JLabel passwordLabel = new JLabel("密码");
passwordLabel.setForeground(Color.white);
passwordLabel.setFont(passwordFont);
passwordLabel.setBounds(197,95,40,22);
this.getContentPane().add(passwordLabel);
//添加密码输入框
passwordText.setBounds(263,87,160,30);
this.getContentPane().add(passwordText);
//验证码文字
Font codeFont = new Font("微软雅黑",1,16);
JLabel codeLabel = new JLabel("验证码");
codeLabel.setForeground(Color.white);
codeLabel.setFont(codeFont);
codeLabel.setBounds(215,142,55,22);
this.getContentPane().add(codeLabel);
//验证码输入框
codeText.setBounds(291,133,100,30);
this.getContentPane().add(codeText);
//获取正确的验证码
String codeStr = CodeUtil.getCode();
Font rightCodeFont = new Font("微软雅黑",1,15);
//设置颜色
rightCode.setForeground(Color.white);
//设置字体
rightCode.setFont(rightCodeFont);
//设置内容
rightCode.setText(codeStr);
newcodeStr = codeStr; //组件初始化时,调用CodeUtil.getCode()方法获取随机验证码保存到codeStr中 再将codeStr的值赋给newCodeStr
//绑定鼠标事件
rightCode.addMouseListener(this);
//设置位置和宽高
rightCode.setBounds(400,133,100,30);
//添加到界面
this.getContentPane().add(rightCode);
//添加登录按钮
loginButton.setBounds(50,310,128,47);
loginButton.setIcon(new ImageIcon("D:\\CHINESEPOKER\\image\\login\\登录按钮.png"));
//去除按钮的边框背景
loginButton.setBorderPainted(false);
loginButton.setContentAreaFilled(false);
//给登录按钮绑定鼠标事件
loginButton.addMouseListener(this);
loginButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("点击了登录按钮");
// 获取用户名输入框与密码输入框内容
String usernameInput = usernameText.getText();
String passwordInput = new String(passwordText.getPassword());
String codeInput = codeText.getText();
User user = getUser(usernameInput);
//Java中,当一个对象为null时,如果我们试图调用该对象的方法或访问其属性,就会抛出空指针异常
//检查getUser()返回的user对象是否为null,以避免空指针异常
if(codeInput.length() != 0 && codeInput.equals(newcodeStr)){
System.out.println("验证码正确");
if (user != null && user.getUserName().equals(usernameInput) && user.getPassWord().equals(passwordInput)) {
showJDialog("登录成功");
//关闭当前登录界面并打开游戏界面
closeOpenGameWindow();
usernameText.setText("");
passwordText.setText("");
codeText.setText("");
} else {
showJDialog("用户名或密码错误");
}
}else{
showJDialog("验证码错误");
}
}
});
this.getContentPane().add(loginButton);
//添加注册按钮 大小图标
registerButton.setBounds(190,310,128,47);
registerButton.setIcon(new ImageIcon("D:\\CHINESEPOKER\\image\\login\\注册按钮.png"));
//去除按钮的边框背景
registerButton.setBorderPainted(false);
registerButton.setContentAreaFilled(false);
//给注册按钮绑定鼠标事件
registerButton.addMouseListener(this);
registerButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("点击了注册按钮");
String usernameInput = usernameText.getText();
String passwordInput = new String(passwordText.getPassword());
String codeInput = codeText.getText();
if(codeInput.length() !=0 && codeInput.equals(newcodeStr)){
System.out.println("验证码正确");
if(usernameInput.length() != 0 && passwordInput.length() !=0){
User user = getUser(usernameInput);
if(user == null){
user = new User(usernameInput,passwordInput);
userDatabase.add(user);
showJDialog("注册成功");
//更换验证码
String code = CodeUtil.getCode();
rightCode.setText(code);
newcodeStr = code;
//如果没有newCoderStr保存改变验证码的值 那么rightCode标签变化CodeStr值不变 登录验证码不匹配
usernameText.setText("");
passwordText.setText("");
codeText.setText("");
} else {
showJDialog("用户已存在");
}
} else {
showJDialog("用户名或密码为空");
}
}else{
showJDialog("验证码错误");
}
}
});
this.getContentPane().add(registerButton);
//添加修改密码按钮 大小图标
changePasswordButton.setBounds(330,310,128,47);
changePasswordButton.setIcon(new ImageIcon("D:\\CHINESEPOKER\\image\\login\\修改密码按钮.png"));
//去除按钮边框背景
changePasswordButton.setBorderPainted(false);
changePasswordButton.setContentAreaFilled(false);
//给按钮绑定鼠标事件和监听器
changePasswordButton.addMouseListener(this);
changePasswordButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String usernameInput = usernameText.getText();
User user = getUser(usernameInput);
if(user != null && user.getUserName().equals(usernameInput)){
String newPassword = new String(passwordText.getPassword());
if(newPassword != null && !newPassword.isEmpty()){
user.setPassword(newPassword); // 更新用户密码
showJDialog("更改密码成功");
} else {
showJDialog("密码不能为空");
}
} else {
showJDialog("用户不存在");
}
}
});
this.getContentPane().add(changePasswordButton);
//添加用户列表按钮 大小图标
showUserListButton.setBounds(470,310,128,47);
showUserListButton.setIcon(new ImageIcon("D:\\CHINESEPOKER\\image\\login\\用户列表按钮.png"));
//去除按钮边框背景
showUserListButton.setBorderPainted(false);
showUserListButton.setContentAreaFilled(false);
//给按钮添加鼠标事件和监听
showUserListButton.addMouseListener(this);
showUserListButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
StringBuilder userList = new StringBuilder("注册用户名列表:\n");
if (!userDatabase.isEmpty()) {
for (User user : userDatabase) {
userList.append(user.getUserName()).append("\n");
}
showJDialog(userList.toString());
} else {
showJDialog("未注册用户");
}
}
});
this.getContentPane().add(showUserListButton);
//添加背景图片
JLabel background = new JLabel(new ImageIcon("D:\\CHINESEPOKER\\image\\login\\background.png"));
background.setBounds(0,0,633,423);
this.getContentPane().add(background);
}
public void closeOpenGameWindow(){
this.dispose();
new GameJFrame();
}
//弹窗方法
public void showJDialog(String content){
//创建一个弹窗对象
JDialog jDialog = new JDialog();
//给弹窗设置大小
jDialog.setSize(260,150);
//给弹窗置顶
jDialog.setAlwaysOnTop(true);
//让弹窗居中
jDialog.setLocationRelativeTo(null);
//弹窗不关闭无法操作下面界面
jDialog.setModal(true);
//设置弹窗背景颜色
jDialog.getContentPane().setBackground(Color.LIGHT_GRAY);
//设置边框
jDialog.getRootPane().setBorder(BorderFactory.createLineBorder(Color.GRAY,2));
//创建JLabel对象 添加文字到弹窗上
JLabel warning = new JLabel(content,SwingConstants.CENTER);
warning.setFont(new Font("微软雅黑",Font.BOLD,16));
warning.setBounds(0,0,200,150);
jDialog.getContentPane().add(warning);
//添加重试按钮
JPanel widowPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
jDialog.add(widowPanel,BorderLayout.SOUTH);
JButton closeButton = new JButton("重试");
closeButton.setFocusPainted(false);
closeButton.setFont(new Font("微软雅黑",Font.BOLD,16));
widowPanel.add(closeButton);
closeButton.addActionListener(e -> jDialog.dispose());
//显示弹窗
jDialog.setVisible(true);
}
@Override //鼠标点击 e.getSource()方法获取用户单击的组件
public void mouseClicked(MouseEvent e) {
if(e.getSource() == rightCode){
System.out.println("更换了验证码");
//更换验证码
String code = CodeUtil.getCode();
rightCode.setText(code);
newcodeStr = code;
}
}
@Override //按下不松
public void mousePressed(MouseEvent e) {
if(e.getSource() == loginButton){
loginButton.setIcon(new ImageIcon("D:\\CHINESEPOKER\\image\\login\\登录按下.png"));
}else if(e.getSource() == registerButton){
registerButton.setIcon(new ImageIcon("D:\\CHINESEPOKER\\image\\login\\注册按下.png"));
}else if(e.getSource() == changePasswordButton){
changePasswordButton.setIcon(new ImageIcon("D:\\CHINESEPOKER\\image\\login\\修改密码按下.png"));
}else if(e.getSource() == showUserListButton){
showUserListButton.setIcon(new ImageIcon("D:\\\\CHINESEPOKER\\\\image\\\\login\\\\用户列表按下.png"));
}
}
@Override //松开按钮
public void mouseReleased(MouseEvent e) {
if(e.getSource() == loginButton){
loginButton.setIcon(new ImageIcon("D:\\CHINESEPOKER\\image\\login\\登录按钮.png"));
}else if(e.getSource() == registerButton){
registerButton.setIcon(new ImageIcon("D:\\CHINESEPOKER\\image\\login\\注册按钮.png"));
}else if(e.getSource() == changePasswordButton){
changePasswordButton.setIcon(new ImageIcon("D:\\CHINESEPOKER\\image\\login\\修改密码按钮.png"));
}else if(e.getSource() == showUserListButton){
showUserListButton.setIcon(new ImageIcon("D:\\\\CHINESEPOKER\\\\image\\\\login\\\\用户列表按钮.png"));
}
}
@Override //鼠标划入
public void mouseEntered(MouseEvent e) {
}
@Override //鼠标划出
public void mouseExited(MouseEvent e) {
}
}
Model类
import java.util.ArrayList;
public class Model {
int value; //极值
int num; //过手数
ArrayList<String> a1 = new ArrayList<>(); //单张
ArrayList<String> a2 = new ArrayList<>(); //对子
ArrayList<String> a3 = new ArrayList<>(); //三带
ArrayList<String> a123 = new ArrayList<>(); //连子
ArrayList<String> a112233 = new ArrayList<>(); //连牌
ArrayList<String> a111222 = new ArrayList<>(); //飞机
ArrayList<String> a4 = new ArrayList<>(); //炸弹
}
游戏操作类PlayerOperation
import lynu.rookie.main.Poker;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
public class PlayerOperation extends Thread {
//游戏主界面
GameJFrame gameJFrame;
//是否能走
boolean isRun = true;
//倒计时
int i;
public PlayerOperation(GameJFrame m, int i) {
this.gameJFrame = m;
this.i = i;
}
@Override
public void run() {
while (i > -1 && isRun) {
gameJFrame.time[1].setText("倒计时:" + i--);
sleep(1);
}
if (i == -1){
gameJFrame.time[1].setText("不抢");
}
gameJFrame.landlord[0].setVisible(false);
gameJFrame.landlord[1].setVisible(false);
for (Poker poker2 : gameJFrame.playerList.get(1)){
poker2.setCanClick(true);// 可被点击
}
if (gameJFrame.time[1].getText().equals("抢地主")) {
gameJFrame.playerList.get(1).addAll(gameJFrame.lordList);
openlord(true);
sleep(2);
Common.order(gameJFrame.playerList.get(1));
Common.rePosition(gameJFrame, gameJFrame.playerList.get(1), 1);
gameJFrame.publishCard[1].setEnabled(false);
setlord(1);
} else {
if (Common.getScore(gameJFrame.playerList.get(0)) < Common.getScore(gameJFrame.playerList.get(2))) {
gameJFrame.time[2].setText("抢地主");
gameJFrame.time[2].setVisible(true);
setlord(2);
openlord(true);
sleep(3);
gameJFrame.playerList.get(2).addAll(gameJFrame.lordList);
Common.order(gameJFrame.playerList.get(2));
Common.rePosition(gameJFrame, gameJFrame.playerList.get(2), 2);
openlord(false);
} else {
gameJFrame.time[0].setText("抢地主");
gameJFrame.time[0].setVisible(true);
setlord(0);
openlord(true);
sleep(3);
gameJFrame.playerList.get(0).addAll(gameJFrame.lordList);
Common.order(gameJFrame.playerList.get(0));
Common.rePosition(gameJFrame, gameJFrame.playerList.get(0), 0);
openlord(false);
}
}
gameJFrame.landlord[0].setVisible(false);
gameJFrame.landlord[1].setVisible(false);
turnOn(false);
for (int i = 0; i < 3; i++) {
gameJFrame.time[i].setText("不要");
gameJFrame.time[i].setVisible(false);
}
gameJFrame.turn = gameJFrame.lordFlag;
while (true) {
if (gameJFrame.turn == 1) {
if (gameJFrame.time[0].getText().equals("不要") && gameJFrame.time[2].getText().equals("不要"))
gameJFrame.publishCard[1].setEnabled(false);
else {
gameJFrame.publishCard[1].setEnabled(true);
}
turnOn(true);
timeWait(30, 1);
turnOn(false);
gameJFrame.turn = (gameJFrame.turn + 1) % 3;
if (win())
break;
}
if (gameJFrame.turn == 0) {
computer0();
gameJFrame.turn = (gameJFrame.turn + 1) % 3;
if (win())
break;
}
if (gameJFrame.turn == 2) {
computer2();
gameJFrame.turn = (gameJFrame.turn + 1) % 3;
if (win())
break;
}
}
}
//定义一个方法用来暂停N秒
//参数为等待的时间
//因为线程中的sleep方法有异常,直接调用影响阅读
public void sleep(int i) {
try {
Thread.sleep(i * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void openlord(boolean is) {
for (int i = 0; i < 3; i++) {
if (is)
gameJFrame.lordList.get(i).turnFront();
else {
gameJFrame.lordList.get(i).turnRear();
}
gameJFrame.lordList.get(i).setCanClick(true);
}
}
public void setlord(int i) {
Point point = new Point();
if (i == 1) {
point.x = 80;
point.y = 430;
gameJFrame.lordFlag = 1;
}
if (i == 0) {
point.x = 80;
point.y = 20;
gameJFrame.lordFlag = 0;
}
if (i == 2) {
point.x = 700;
point.y = 20;
gameJFrame.lordFlag = 2;
}
gameJFrame.lord.setLocation(point);
gameJFrame.lord.setVisible(true);
}
public void turnOn(boolean flag) {
gameJFrame.publishCard[0].setVisible(flag);
gameJFrame.publishCard[1].setVisible(flag);
}
public void computer0() {
timeWait(1, 0);
ShowCard(0);
}
public void computer2() {
timeWait(1, 2);
ShowCard(2);
}
public void ShowCard(int role) {
int orders[] = new int[] { 4, 3, 2, 1, 5 };
Model model = Common.getModel(gameJFrame.playerList.get(role), orders);
ArrayList<String> list = new ArrayList<>();
if (gameJFrame.time[(role + 1) % 3].getText().equals("不要") && gameJFrame.time[(role + 2) % 3].getText().equals("不要")) {
if (model.a123.size() > 0) {
list.add(model.a123.get(model.a123.size() - 1));
} else if (model.a3.size() > 0) {
if (model.a1.size() > 0) {
list.add(model.a1.get(model.a1.size() - 1));
} else if (model.a2.size() > 0) {
list.add(model.a2.get(model.a2.size() - 1));
}
list.add(model.a3.get(model.a3.size() - 1));
} else if (model.a112233.size() > 0) {
list.add(model.a112233.get(model.a112233.size() - 1));
} else if (model.a111222.size() > 0) {
String name[] = model.a111222.get(0).split(",");
if (name.length / 3 <= model.a1.size()) {
list.add(model.a111222.get(model.a111222.size() - 1));
for (int i = 0; i < name.length / 3; i++)
list.add(model.a1.get(i));
} else if (name.length / 3 <= model.a2.size()) {
list.add(model.a111222.get(model.a111222.size() - 1));
for (int i = 0; i < name.length / 3; i++)
list.add(model.a2.get(i));
}
} else if (model.a2.size() > (model.a111222.size() * 2 + model.a3.size())) {
list.add(model.a2.get(model.a2.size() - 1));
} else if (model.a1.size() > (model.a111222.size() * 2 + model.a3.size())) {
list.add(model.a1.get(model.a1.size() - 1));
} else if (model.a4.size() > 0) {
int sizea1 = model.a1.size();
int sizea2 = model.a2.size();
if (sizea1 >= 2) {
list.add(model.a1.get(sizea1 - 1));
list.add(model.a1.get(sizea1 - 2));
list.add(model.a4.get(0));
} else if (sizea2 >= 2) {
list.add(model.a2.get(sizea1 - 1));
list.add(model.a2.get(sizea1 - 2));
list.add(model.a4.get(0));
} else {
list.add(model.a4.get(0));
}
}
} else {
if (role != gameJFrame.lordFlag) {
int f = 0;
if (gameJFrame.time[gameJFrame.lordFlag].getText().equals("不要")) {
f = 1;
}
if ((role + 1) % 3 == gameJFrame.lordFlag) {
if ((Common.jugdeType(gameJFrame.currentList.get((role + 2) % 3)) != PokerType.c1
|| Common.jugdeType(gameJFrame.currentList.get((role + 2) % 3)) != PokerType.c2)
&& gameJFrame.currentList.get(gameJFrame.lordFlag).size() < 1)
f = 1;
if (gameJFrame.currentList.get((role + 2) % 3).size() > 0
&& Common.getValue(gameJFrame.currentList.get((role + 2) % 3).get(0)) > 13)
f = 1;
}
if (f == 1) {
gameJFrame.time[role].setVisible(true);
gameJFrame.time[role].setText("不要");
return;
}
}
int can = 0;
if (role == gameJFrame.lordFlag) {
if (gameJFrame.playerList.get((role + 1) % 3).size() <= 5 || gameJFrame.playerList.get((role + 2) % 3).size() <= 5)
can = 1;
} else {
if (gameJFrame.playerList.get(gameJFrame.lordFlag).size() <= 5)
can = 1;
}
ArrayList<Poker> player;
if (gameJFrame.time[(role + 2) % 3].getText().equals("不要"))
player = gameJFrame.currentList.get((role + 1) % 3);
else
player = gameJFrame.currentList.get((role + 2) % 3);
PokerType cType = Common.jugdeType(player);
if (cType == PokerType.c1) {
if (can == 1)
model = Common.getModel(gameJFrame.playerList.get(role), new int[] { 1, 4, 3, 2, 5 });
AI_1(model.a1, player, list, role);
} else if (cType == PokerType.c2) {
if (can == 1)
model = Common.getModel(gameJFrame.playerList.get(role), new int[] { 2, 4, 3, 5, 1 });
AI_1(model.a2, player, list, role);
} else if (cType == PokerType.c3) {
AI_1(model.a3, player, list, role);
} else if (cType == PokerType.c4) {
AI_1(model.a4, player, list, role);
} else if (cType == PokerType.c31) {
if (can == 1)
model = Common.getModel(gameJFrame.playerList.get(role), new int[] { 3, 1, 4, 2, 5 });
AI_2(model.a3, model.a1, player, list, role);
} else if (cType == PokerType.c32) {
if (can == 1)
model = Common.getModel(gameJFrame.playerList.get(role), new int[] { 3, 2, 4, 5, 1 });
AI_2(model.a3, model.a2, player, list, role);
} else if (cType == PokerType.c411) {
AI_5(model.a4, model.a1, player, list, role);
}
else if (cType == PokerType.c422) {
AI_5(model.a4, model.a2, player, list, role);
}
else if (cType == PokerType.c123) {
if (can == 1)
model = Common.getModel(gameJFrame.playerList.get(role), new int[] { 5, 3, 2, 4, 1 });
AI_3(model.a123, player, list, role);
}
else if (cType == PokerType.c112233) {
if (can == 1)
model = Common.getModel(gameJFrame.playerList.get(role), new int[] { 2, 4, 3, 5, 1 });
AI_3(model.a112233, player, list, role);
}
else if (cType == PokerType.c11122234) {
AI_4(model.a111222, model.a1, player, list, role);
}
else if (cType == PokerType.c1112223344) {
AI_4(model.a111222, model.a2, player, list, role);
}
if (list.size() == 0 && can == 1) {
int len4 = model.a4.size();
if (len4 > 0)
list.add(model.a4.get(len4 - 1));
}
}
gameJFrame.currentList.get(role).clear();
if (list.size() > 0) {
Point point = new Point();
if (role == 0)
point.x = 200;
if (role == 2)
point.x = 550;
if (role == 1) {
point.x = (770 / 2) - (gameJFrame.currentList.get(1).size() + 1) * 15 / 2;
point.y = 300;
}
point.y = (400 / 2) - (list.size() + 1) * 15 / 2;
ArrayList<Poker> temp = new ArrayList<>();
for (int i = 0, len = list.size(); i < len; i++) {
List<Poker> pokers = getCardByName(gameJFrame.playerList.get(role), list.get(i));
for (Poker poker : pokers) {
temp.add(poker);
}
}
temp = Common.getOrder2(temp);
for (Poker poker : temp) {
Common.move(poker, poker.getLocation(), point);
point.y += 15;
gameJFrame.container.setComponentZOrder(poker, 0);
gameJFrame.currentList.get(role).add(poker);
gameJFrame.playerList.get(role).remove(poker);
}
Common.rePosition(gameJFrame, gameJFrame.playerList.get(role), role);
} else {
gameJFrame.time[role].setVisible(true);
gameJFrame.time[role].setText("不要");
}
for (Poker poker : gameJFrame.currentList.get(role))
poker.turnFront();
}
public List getCardByName(List<Poker> list, String n) {
String[] name = n.split(",");
ArrayList cardsList = new ArrayList();
int j = 0;
for (int i = 0, len = list.size(); i < len; i++) {
if (j < name.length && list.get(i).getName().equals(name[j])) {
cardsList.add(list.get(i));
i = 0;
j++;
}
}
return cardsList;
}
public void AI_3(List<String> model, List<Poker> player, List<String> list, int role) {
for (int i = 0, len = model.size(); i < len; i++) {
String[] s = model.get(i).split(",");
if (s.length == player.size() && getValueInt(model.get(i)) > Common.getValue(player.get(0))) {
list.add(model.get(i));
return;
}
}
}
public void AI_4(List<String> model1, List<String> model2, List<Poker> player, List<String> list, int role) {
player = Common.getOrder2(player);
int len1 = model1.size();
int len2 = model2.size();
if (len1 < 1 || len2 < 1)
return;
for (int i = 0; i < len1; i++) {
String[] s = model1.get(i).split(",");
String[] s2 = model2.get(0).split(",");
if ((s.length / 3 <= len2) && (s.length * (3 + s2.length) == player.size())
&& getValueInt(model1.get(i)) > Common.getValue(player.get(0))) {
list.add(model1.get(i));
for (int j = 1; j <= s.length / 3; j++)
list.add(model2.get(len2 - j));
}
}
}
public void AI_5(List<String> model1, List<String> model2, List<Poker> player, List<String> list, int role) {
player = Common.getOrder2(player);
int len1 = model1.size();
int len2 = model2.size();
if (len1 < 1 || len2 < 2)
return;
for (int i = 0; i < len1; i++) {
if (getValueInt(model1.get(i)) > Common.getValue(player.get(0))) {
list.add(model1.get(i));
for (int j = 1; j <= 2; j++)
list.add(model2.get(len2 - j));
}
}
}
public void AI_1(List<String> model, List<Poker> player, List<String> list, int role) {
for (int len = model.size(), i = len - 1; i >= 0; i--) {
if (getValueInt(model.get(i)) > Common.getValue(player.get(0))) {
list.add(model.get(i));
break;
}
}
}
public void AI_2(List<String> model1, List<String> model2, List<Poker> player, List<String> list, int role) {
player = Common.getOrder2(player);
int len1 = model1.size();
int len2 = model2.size();
if (len1 > 0 && model1.get(0).length() < 10) {
list.add(model1.get(0));
System.out.println("王炸");
return;
}
if (len1 < 1 || len2 < 1)
return;
for (int len = len1, i = len - 1; i >= 0; i--) {
if (getValueInt(model1.get(i)) > Common.getValue(player.get(0))) {
list.add(model1.get(i));
break;
}
}
list.add(model2.get(len2 - 1));
if (list.size() < 2)
list.clear();
}
public void timeWait(int n, int player) {
if (gameJFrame.currentList.get(player).size() > 0)
Common.hideCards(gameJFrame.currentList.get(player));
if (player == 1) {
int i = n;
while (gameJFrame.nextPlayer == false && i >= 0) {
gameJFrame.time[player].setText("倒计时:" + i);
gameJFrame.time[player].setVisible(true);
sleep(1);
i--;
}
if (i == -1 && player == 1) {
ShowCard(1);
}
gameJFrame.nextPlayer = false;
} else {
for (int i = n; i >= 0; i--) {
sleep(1);
gameJFrame.time[player].setText("倒计时:" + i);
gameJFrame.time[player].setVisible(true);
}
}
gameJFrame.time[player].setVisible(false);
}
public int getValueInt(String n) {
String name[] = n.split(",");
String s = name[0];
int i = Integer.parseInt(s.substring(2, s.length()));
if (s.substring(0, 1).equals("5"))
i += 3;
if (s.substring(2, s.length()).equals("1") || s.substring(2, s.length()).equals("2"))
i += 13;
return i;
}
public boolean win() {
for (int i = 0; i < 3; i++) {
if (gameJFrame.playerList.get(i).size() == 0) {
String s;
if (i == 1) {
s = "恭喜你,胜利了!";
} else {
s = "恭喜电脑" + i + ",赢了! 你的智商有待提高哦";
}
for (int j = 0; j < gameJFrame.playerList.get((i + 1) % 3).size(); j++)
gameJFrame.playerList.get((i + 1) % 3).get(j).turnFront();
for (int j = 0; j < gameJFrame.playerList.get((i + 2) % 3).size(); j++)
gameJFrame.playerList.get((i + 2) % 3).get(j).turnFront();
JOptionPane.showMessageDialog(gameJFrame, s);
return true;
}
}
return false;
}
}
出牌类型PokerType 枚举 一些有相同关系的常量
public enum PokerType {
c0,//不出牌
c1,//单张牌
c2,//二张相同牌,对子
c3,//三张相同牌
c4,//四张相同牌,炸弹
c31,//三张相同牌与单张牌,三带一
c32,//三张相同牌与二张相同牌,三带二
c411,//4张相同牌与二张牌
c422,//4张相同牌与二对牌
c123,//连牌
c112233,//连对
c111222,//飞机
c11122234,//飞机带二张牌
c1112223344,//飞机带对子
}
main包下新建类
Poker类
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
public class Poker extends JLabel implements MouseListener {
//游戏的主界面
GameJFrame gameJFrame;
//牌的名字
String name;
//牌显示正面还是反面
boolean up;
//是否可点击
boolean canClick = false;
//当前状态,是否已经被点击
boolean clicked = false;
public Poker(GameJFrame m, String name, boolean up) {
this.gameJFrame = m;
this.name = name;
this.up = up;
//判断当前的牌是显示正面还是背面
if (this.up){
this.turnFront();
}else {
this.turnRear();
}
//设置牌的宽高大小
this.setSize(71, 96);
//把牌显示出来
this.setVisible(true);
//给每一张牌添加鼠标监听
this.addMouseListener(this);
}
public Poker() {
}
public Poker(GameJFrame gameJFrame, String name, boolean up, boolean canClick, boolean clicked) {
this.gameJFrame = gameJFrame;
this.name = name;
this.up = up;
this.canClick = canClick;
this.clicked = clicked;
}
//显示正面
public void turnFront() {
this.setIcon(new ImageIcon("image\\poker\\" + name + ".png"));
this.up = true;
}
//显示背面
public void turnRear() {
this.setIcon(new ImageIcon("image\\poker\\rear.png"));
this.up = false;
}
//出牌时,需要点击牌
//被点击之后,牌向上移动20个像素
//再次被点击,牌回落20个像素
@Override
public void mouseClicked(MouseEvent e) {
if (canClick) {
Point from = this.getLocation();
int step;
if (clicked){
step = 20;
}else {
step = -20;
}
clicked = !clicked;
Point to = new Point(from.x, from.y + step);
this.setLocation(to);
}
}
public void mouseEntered(MouseEvent arg0) {
}
public void mouseExited(MouseEvent arg0) {
}
public void mouseReleased(MouseEvent arg0) {
}
public void mousePressed(MouseEvent e) {
}
/**
* 获取
* @return gameJFrame
*/
public GameJFrame getGameJFrame() {
return gameJFrame;
}
/**
* 设置
* @param gameJFrame
*/
public void setGameJFrame(GameJFrame gameJFrame) {
this.gameJFrame = gameJFrame;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return up
*/
public boolean isUp() {
return up;
}
/**
* 设置
* @param up
*/
public void setUp(boolean up) {
this.up = up;
}
/**
* 获取
* @return canClick
*/
public boolean isCanClick() {
return canClick;
}
/**
* 设置
* @param canClick
*/
public void setCanClick(boolean canClick) {
this.canClick = canClick;
}
/**
* 获取
* @return clicked
*/
public boolean isClicked() {
return clicked;
}
/**
* 设置
* @param clicked
*/
public void setClicked(boolean clicked) {
this.clicked = clicked;
}
public String toString() {
return "Poker{gameJFrame = " + gameJFrame + ", name = " + name + ", up = " + up + ", canClick = " + canClick + ", clicked = " + clicked + "}";
}
}
User类
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
public class User {
// 每当用户注册时,会创建一个新的User对象
// 用户对象实际中存储在userDatabase的List列表中
private String username;
private String password;
public User(String username,String password){
this.username = username;
this.password = password;
}
/*
获取
*/
public String getUserName(){
return username;
}
public String getPassWord(){
return password;
}
/*
设置
*/
public void setUsername(String username){
this.username = username;
}
public void setPassword(String password) { this.password = password;}
@Override
public boolean equals(Object o){
if(this == o) return true;
if(o == null || getClass() != o.getClass()) return false;
User user = (User)o;
return Objects.equals(username,user.username) &&
Objects.equals(password,user.password);
}
@Override
public int hashCode(){
return Objects.hash(username,password);
}
public String toString(){ //{"内为变量"}
return "User{username = " + username +
", password = " + password +"}";
}
}
util包下新建类
验证码CodeUtil类
import java.util.ArrayList;
import java.util.Random;
public class CodeUtil {
public static String getCode(){
//创建一个集合;
ArrayList<Character> list = new ArrayList<>(); //52 索引范围0-51
//添加字母 a - z A - Z
for(int i=0;i<26;i++){
list.add((char)('a' + i));//类型转换为字符97-a 65-A
list.add((char)('A' + i));
}
//打印集合
//System.out.println(list);
//生成4个随机字母
String result = "";
Random r = new Random();
for(int i=0;i<4;i++){
int randomIndex = r.nextInt(list.size());
result = result + list.get(randomIndex);
}
//长度为4的随机字符串 return result;
//基础上拼接数字0-9
int number = r.nextInt(10);
//把随机数字拼接到result后面
result = result + number;
//把字符串变成字符数组
char[] chars = result.toCharArray();
//生成一个字符数组长度的随机索引
int index = r.nextInt(chars.length);
//末索引4上的数字字符与随机索引上的字符交换 使数字出现在索引0-4的任何位置
char temp = chars[4];
chars[4] = chars[index];
chars[index] = temp;
//字符数组变回字符串
String code = new String(chars);
return code;
}
}
music包下新建类
MusicPlayer类
音乐可自行替换 javazoom需要配置jar包 jlayer-1.0.1-1.jar 搜索下载
package music;
import javazoom.jl.decoder.JavaLayerException;
import javazoom.jl.player.Player;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class MusicPlayer {
public MusicPlayer() throws FileNotFoundException, JavaLayerException {
Player player;
//工作目录路径拼接音乐的相对路径
String str = System.getProperty("user.dir")+"/src/music/Omeo.mp3";
//BufferedInputStream对象,用于读取音乐文件。将文件路径传递给FileInputStream的构造函数,
// 将其包装在BufferedInputStream中,以提高文件读取的效率
while(true){
BufferedInputStream name = new BufferedInputStream(new FileInputStream(str));
player = new Player(name);
player.play();
}
}
}
src下新建App类
import rookie.game.LoginJFrame;
public class App {
public static void main(String[] args) {
new LoginJFrame();
}
}
本文档围绕Java实现的斗地主游戏项目展开,涵盖设计要求,如登录注册、游戏功能等;介绍数据模型,包括玩家、牌等;还提及简单测试中音频和图片路径问题的解决,以及视图设计、GUI程序开发和程序发布等内容,为开发该游戏提供参考。
995

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



