关于毕业设计这个总目录
(一定要看,因为JAVA工具,tomcat,MAVEN , idea 下载都在这篇文件当中)
JAVA项目环境必知必会–【大作业及毕设项目】
部分截图如下:(持续增加中)

本系列校训
互相伤害互相卷,玩命学习要你管,天生我才必有用,我命由我不由天!
环境及工具:
本系列环境
| 环境 | win11 |
|---|---|
| 工具 | idea 2017/idea 2018 |
| jdk | 1.8 |
| 数据库 | 无 |
| maven | 无 |
| 项目导入方式 | 打开目录 |
| 数据库前端工具 | 无 |
项目说明
这个游戏工作量适中,类的封装很优秀。算法的部分也提炼的很好。当做学习还是相当的不错的。当毕业设计就有点拿不出手了。但是还是相当的值得学习
总体功能
斗地主这个全国流行的玩法就不用介绍了。
说一下牌型。使用的是枚举类型。
public enum CardType {
c1,//单牌。
c2,//对子。
c3,//3不带。
c4,//炸弹。
c31,//3带1。
c32,//3带2。
c411,//4带2个单,或者一对
c422,//4带2对
c123,//连子。
c1122,//连队。
c111222,//飞机。
c11122234,//飞机带单排.
c1112223344,//飞机带对子.
c0//不能出牌
}
资源文件
这个是另一篇文章里资源文件。
命名也是很规整的《java的21点牌类游戏》

纸牌用的其本就是WINDOWS里的蜘蛛纸牌的图案。
这套项目把大王小王的图案换了个,其它的没动。(毕竟WINDOWS自带的纸牌游戏深入人心)

当然可以把牌背换成自己喜欢的。

项目目录

代码部分
文件编码问题。不太熟悉JAVA的同学请不要随意怀疑本程序运行出错,或不能运行,盲目修改文件
Card 部分封装了牌的显示,贴图等。

使用的是JLabel 的父类。写法很规范。
package example;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
public class Card extends JLabel implements MouseListener{
Main main;//Main类的引用
String name;//图片url名字
boolean up;//是否正反面
boolean canClick=false;//是否可被点击
boolean clicked=false;//是否点击过
public Card(Main m,String name,boolean up){
this.main=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 void turnFront() {
this.setIcon(new ImageIcon("images/" + name + ".gif"));
this.up = true;
}
//反面
public void turnRear() {
this.setIcon(new ImageIcon("images/rear.gif"));
this.up = false;
}
@Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
}
public void mouseEntered(MouseEvent arg0) {}
public void mouseExited(MouseEvent arg0) {}
public void mousePressed(MouseEvent e) {
if(canClick)
{
Point from=this.getLocation();
int step; //移动的距离
if(clicked)
step=-20;
else {
step=20;
}
clicked=!clicked; //反向
//当被选中的时候,向前移动一步/后退一步
Common.move(this,from,new Point(from.x,from.y-step));
}
}
public void mouseReleased(MouseEvent arg0) {
}
}
核心当然是各种牌型的判断:

package example;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Common {
// 判断牌型
public static CardType jugdeType(List<Card> list) {
// 因为之前排序过所以比较好判断
int len = list.size();
// 单牌,对子,3不带,4个一样炸弹
if (len <= 4) { // 如果第一个和最后个相同,说明全部相同
if (list.size() > 0
&& Common.getValue(list.get(0)) == Common.getValue(list
.get(len - 1))) {
switch (len) {
case 1:
return CardType.c1;
case 2:
return CardType.c2;
case 3:
return CardType.c3;
case 4:
return CardType.c4;
}
}
// 双王,化为对子返回
if (len == 2 && Common.getColor(list.get(1)) == 5)
return CardType.c2;
// 当第一个和最后个不同时,3带1
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 CardType.c31;
else {
return CardType.c0;
}
}
// 当5张以上时,连字,3带2,飞机,2顺,4带2等等
if (len >= 5) {// 现在按相同数字最大出现次数
Card_index card_index = new Card_index();
for (int i = 0; i < 4; i++)
card_index.a[i] = new ArrayList<Integer>();
// 求出各种数字出现频率
Common.getMax(card_index, list); // a[0,1,2,3]分别表示重复1,2,3,4次的牌
// 3带2 -----必含重复3次的牌
if (card_index.a[2].size() == 1 && card_index.a[1].size() == 1
&& len == 5)
return CardType.c32;
// 4带2(单,双)
if (card_index.a[3].size() == 1 && len == 6)
return CardType.c411;
if (card_index.a[3].size() == 1 && card_index.a[1].size() == 2
&& len == 8)
return CardType.c422;
// 单连,保证不存在王
if ((Common.getColor(list.get(0)) != 5)
&& (card_index.a[0].size() == len)
&& (Common.getValue(list.get(0))
- Common.getValue(list.get(len - 1)) == len - 1))
return CardType.c123;
// 连队
if (card_index.a[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 CardType.c1122;
// 飞机
if (card_index.a[2].size() == len / 3
&& (len % 3 == 0)
&& (Common.getValue(list.get(0))
- Common.getValue(list.get(len - 1)) == (len / 3 - 1)))
return CardType.c111222;
// 飞机带n单,n/2对
if (card_index.a[2].size() == len / 4
&& ((Integer) (card_index.a[2].get(len / 4 - 1))
- (Integer) (card_index.a[2].get(0)) == len / 4 - 1))
return CardType.c11122234;
// 飞机带n双
if (card_index.a[2].size() == len / 5
&& card_index.a[2].size() == len / 5
&& ((Integer) (card_index.a[2].get(len / 5 - 1))
- (Integer) (card_index.a[2].get(0)) == len / 5 - 1))
return CardType.c1112223344;
}
return CardType.c0;
}
// 移动效果的函数,用于发牌
public static void move(Card card, 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;// 这里主要用的数学中的线性函数
card.setLocation(i, (int) y);
try {
Thread.sleep(5); // 延迟,可自己设置
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
// 位置校准
card.setLocation(to);
}
// 对list排序
public static void order(List<Card> list) {
Collections.sort(list, new Comparator<Card>() {
@Override
public int compare(Card o1, Card o2) {
// TODO Auto-generated method stub
int a1 = Integer.parseInt(o1.name.substring(0, 1));// 花色
int a2 = Integer.parseInt(o2.name.substring(0, 1));
int b1 = Integer.parseInt(o1.name.substring(2, o1.name.length()));// 数值
int b2 = Integer.parseInt(o2.name.substring(2, o2.name.length()));
int flag = 0;
// 如果是王的话
if (a1 == 5)
b1 += 100;
if (a1 == 5 && b1 == 1)
b1 += 50;
if (a2 == 5)
b2 += 100;
if (a2 == 5 && b2 == 1)
b2 += 50;
// 如果是A或者2
if (b1 == 1)
b1 += 20;
if (b2 == 1)
b2 += 20;
if (b1 == 2)
b1 += 30;
if (b2 == 2)
b2 += 30;
flag = b2 - b1;
if (flag == 0)
return a2 - a1;
else {
return flag;
}
}
});
}
// 重新定位 flag代表电脑1 ,2 或者是我
public static void rePosition(Main m, List<Card> 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) {// 我的排序 _y=450 width=830
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++) {
Card card = list.get(i);
Common.move(card, card.getLocation(), p);
m.container.setComponentZOrder(card, 0);
if (flag == 1)
p.x += 21;
else
p.y += 15;
}
}
// 地主牌权值,看是否抢地主
public static int getScore(List<Card> list) {
int count = 0;
for (int i = 0, len = list.size(); i < len; i++) {
Card card = list.get(i);
if (card.name.substring(0, 1).equals("5")) {
// System.out.println(card.name.substring(0, 1));
count += 5;
}
if (card.name.substring(2, card.name.length()).equals("2")) {
// System.out.println(2);
count += 2;
}
}
return count;
}
// 返回花色
public static int getColor(Card card) {
return Integer.parseInt(card.name.substring(0, 1));
}
// 返回值
public static int getValue(Card card) {
int i = Integer.parseInt(card.name.substring(2, card.name.length()));
if (card.name.substring(2, card.name.length()).equals("2"))
i += 13;
if (card.name.substring(2, card.name.length()).equals("1"))
i += 13;
if (Common.getColor(card) == 5)
i += 2;// 是王
return i;
}
// 得到最大相同数
public static void getMax(Card_index card_index, List<Card> list) {
int count[] = new int[14];// 1-13各算一种,王算第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]++;
}
for (int i = 0; i < 14; i++) {
switch (count[i]) {
case 1:
card_index.a[0].add(i + 1);
break;
case 2:
card_index.a[1].add(i + 1);
break;
case 3:
card_index.a[2].add(i + 1);
break;
case 4:
card_index.a[3].add(i + 1);
break;
}
}
}
// 拆牌
public static Model getModel(List<Card> list,int[] orders) {
// 先复制一个list
List list2 = new ArrayList<Card>(list);
Model model = new Model();
for(int i=0;i<orders.length;i++)
showOrders(orders[i], list2, model);
return model;
}
// 拆连子
public static void get123(List<Card> list, Model model) {
List<Card> del = new ArrayList<Card>();// 要删除的Cards
if (list.size() > 0
&& (Common.getValue(list.get(0)) < 7 || Common.getValue(list
.get(list.size() - 1)) > 10))
return;
if (list.size() < 5)
return;
// 先要把所有不重复的牌归为一类,防止3带,对子影响
List<Card> list2 = new ArrayList<Card>();
List<Card> temp = new ArrayList<Card>();
List<Integer> integers = new ArrayList<Integer>();
for (Card card : list2) {
if (integers.indexOf(Common.getValue(card)) < 0) {
integers.add(Common.getValue(card));
temp.add(card);
}
}
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).name + ",";
del.add(temp.get(j));
}
s += temp.get(k).name;
del.add(temp.get(k));
model.a123.add(s);
i = k;
}
}
list.removeAll(del);
}
// 拆双顺
public static void getTwoTwo(List<Card> list, Model model) {
List<String> del = new ArrayList<String>();// 要删除的Cards
// 从model里面的对子找
List<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()));
}
// s0,1,2,3,4 13,9,8,7,6
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)// k=4 i=1
{// 说明从i到k是连队
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(List<Card> list, Model model) {
List<String> del = new ArrayList<String>();// 要删除的Cards
// 从model里面的3带找
List<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) {// 说明从i到k是飞机
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(List<Card> list, Model model) {
List<Card> del = new ArrayList<Card>();// 要删除的Cards
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).name + "," + list.get(1).name); // 按名字加入
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).name);
}
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).name + ",";
s += list.get(i + 1).name + ",";
s += list.get(i + 2).name + ",";
s += list.get(i + 3).name;
model.a4.add(s);
for (int j = i; j <= i + 3; j++)
del.add(list.get(j));
i = i + 3;
}
}
list.removeAll(del);
}
// 拆3带
public static void getThree(List<Card> list, Model model) {
List<Card> del = new ArrayList<Card>();// 要删除的Cards
// 连续3张相同
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).name + ",";
s += list.get(i + 1).name + ",";
s += list.get(i + 2).name;
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(List<Card> list, Model model) {
List<Card> del = new ArrayList<Card>();// 要删除的Cards
// 连续2张相同
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).name + ",";
s += list.get(i + 1).name;
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(List<Card> list, Model model) {
List<Card> del = new ArrayList<Card>();// 要删除的Cards
// 1
for (int i = 0, len = list.size(); i < len; i++) {
model.a1.add(list.get(i).name);
del.add(list.get(i));
}
list.removeAll(del);
}
// 隐藏之前出过的牌
public static void hideCards(List<Card> list) {
for (int i = 0, len = list.size(); i < len; i++) {
list.get(i).setVisible(false);
}
}
// 检查牌的是否能出
public static int checkCards(List<Card> c, List<Card>[] current,Main m) {
// 找出当前最大的牌是哪个电脑出的,c是点选的牌
List<Card> currentlist;
if(m.time[0].getText().equals("不要"))
currentlist=current[2];
else
currentlist=current[0];
CardType cType = Common.jugdeType(c);
CardType cType2=Common.jugdeType(currentlist);
// 如果张数不同直接过滤
if (cType != CardType.c4 && c.size() != currentlist.size())
return 0;
// 比较我的出牌类型
if (cType != CardType.c4&&Common.jugdeType(c) != Common.jugdeType(currentlist)) {
return 0;
}
// 比较出的牌是否要大
// 我是炸弹
if (cType == CardType.c4) {
if(c.size()==2)
return 1;
if(cType2!=CardType.c4)
{
return 1;
}
}
// 单牌,对子,3带,4炸弹
if (cType == CardType.c1 || cType == CardType.c2
|| cType == CardType.c3 || cType == CardType.c4) {
if (Common.getValue(c.get(0)) <= Common
.getValue(currentlist.get(0))) {
return 0;
} else {
return 1;
}
}
// 顺子,连队,飞机裸
if (cType == CardType.c123 || cType == CardType.c1122
|| cType == CardType.c111222) {
if (Common.getValue(c.get(0)) <= Common
.getValue(currentlist.get(0)))
return 0;
else
return 1;
}
// 按重复多少排序
// 3带1,3带2 ,飞机带单,双,4带1,2,只需比较第一个就行,独一无二的
if (cType == CardType.c31 || cType == CardType.c32
|| cType == CardType.c411 || cType == CardType.c422
|| cType == CardType.c11122234 || cType == CardType.c1112223344) {
List<Card> a1 = Common.getOrder2(c); // 我出的牌
List<Card> a2 = Common.getOrder2(currentlist);// 当前最大牌
if (Common.getValue(a1.get(0)) < Common.getValue(a2.get(0)))
return 0;
}
return 1;
}
// 按照重复次数排序
public static List getOrder2(List<Card> list) {
List<Card> list2 = new ArrayList<Card>(list);
List<Card> list3 = new ArrayList<Card>();
List<Integer> list4 = new ArrayList<Integer>();
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, List<Card> 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 Card_index {
List a[] = new ArrayList[4];// 单张
}
找到关键核心代码的方法:
应用软件的核心代码是指这个程序最关键部分的代码。例如WinRAR,它的核心代码就是压缩算法部分,而诸如用户界面、操作系统移植等部分就无足轻重了。
商城类的核心代码是指业务层的代码,比如你商城的核心代码就是:商品、购物车、创建订单、支付这些代码就是核心代码。
作为程序员,我们经常需要看懂别人的代码。特别是在开源社区中,我们需要理解许多优秀的开源项目的代码。而在Gitee这样的代码托管平台上,我们如何快速有效地看懂别人的代码呢?本文将为大家介绍一些方法。
1.阅读README和项目介绍
在Gitee上,许多开源项目都会有自己的README文件或项目介绍。这些文件一般会介绍项目的背景、功能、使用方法等内容,可以帮助我们快速了解这个开源项目的基本情况。如果我们能够从这些文件中找到与自己相关的内容,就可以快速入手这个开源项目的代码。
2.了解项目结构和代码组织
在阅读代码之前,我们需要先了解这个开源项目的代码结构和代码组织方式。通常,开源项目会将不同的功能模块封装到不同的代码文件中,并按照一定的目录结构组织起来。如果我们能够了解这个开源项目的代码组织方式,就能更加快速地找到所需的代码。
3.利用IDE和工具
IDE和一些代码阅读工具可以帮助我们更快速、更高效地阅读代码。例如,Java开发者可以使用Eclipse或IntelliJ IDEA这样的IDE,可以快速打开代码文件、查看类、方法和变量等信息。另外,一些代码阅读工具,如Source Insight、CodeCompare等,可以帮助我们更方便地查看代码的结构和关系,以及快速跳转到相关代码。
4.关注代码注释和文档
良好的代码注释和文档可以帮助我们更快速地理解代码。因此,在阅读别人的代码时,我们可以将注意力放在代码注释和文档上。有些开源项目会提供详细的文档,有些则注重代码注释。如果我们能够针对代码注释和文档有一个系统的阅读和理解,就能更快速地掌握别人的代码。
5.跑通测试和运行项目
如果我们想更深入地了解别人的代码,可以试着跑通相关的测试,或者直接运行这个开源项目。通过跑测试和运行项目,我们可以更加直观地了解代码的实现细节和具体的业务逻辑。
总结:
以上就是在Gitee上快速理解他人代码的一些方法,希望对大家有所帮助。当然,阅读代码是一件需要耐心和细心的事情,需要我们多花一点时间和心思。只有沉下心来,慢慢阅读每一行代码,才能真正理解它们的含义和作用。
牌类的洗牌
很多初学者认为,那就是不停的随机呗。但是,你有没有想过,随机重复的牌呢?
跳过去? 那要这么随机下去,后面的随机数出的得多么的难?得多少次才能随机出还缺的数字?

就是不停的两张两张的交换。
这样子是不是就跟手动的洗牌的动画有点像?
下面的洗一次,应该就是循环了牌的一半的次数(当然了,没有随机的洗的效果好)

这样的洗牌,其实只相当于一次随机的交换牌,效果看上去很花,但是事实上就是老千常用的手法。因为洗N次都可能洗不到最上或最下。按道理,这样洗得洗50次才能有点随机的效果

还是看代码:(完全用老千的手法,只是系统不出老千罢了)
把每一张牌与随机的一张牌交换。
// 方法xipai()用于将所得的随机数组的值赋值给牌的下标
public static void xipai() {
int[] b = new int[54];
b = random(54);// 调用random方法产生一个长度为54的不重复的随机数组
cards = poker.getCard();
Card temp = null;
for (int i = 0; i < b.length; i++) { // 开始遍历数组实现重新排列
int k = b[i];
temp = cards[k];
cards[i] = cards[k];
cards[k] = temp;
}
// 输出洗牌后的扑克
poker.Show();
}
切牌。完全随机的切(完全无老千)
// 方法qiepai()实现扑克的切牌操作
public static void qiepai(int length) {
int number = (int) (Math.random() * length);// 产生一个随机数
System.out.println("随机数为:" + number);// 显示随机数是多少
Card[] temp = new Card[length];
int start = number;// 设置切牌后的起点位置
for (int i = 0; i < length - number; i++) {
temp[i] = cards[start++];// 将切点后面的牌暂时放入temp数组中
}
for (int j = 0; j < number; j++) {
temp[length - number + j] = cards[j];// 将切点前面的牌加入temp数组中
}
for (int k = 0; k < length; k++) {
cards[k] = temp[k];
}
// 输出切牌后的扑克
poker.Show();
}
牌的资源处理
import java.awt.BorderLayout;
import java.net.URL;
import javax.swing.*;
public class ShowImage extends JFrame{
/**
* @param args
*/
public ShowImage() {
JPanel panel=new JPanel(new BorderLayout());
JPanel panel2=new JPanel(new BorderLayout());
JPanel panel3=new JPanel(new BorderLayout());
String urlString="C://rear.gif";
JLabel label=new JLabel(new ImageIcon(urlString));
URL url=getClass().getResource("/images/2-1.gif");
JLabel label2=new JLabel(new ImageIcon(url));
URL url2=getClass().getResource("/images/2-2.gif");
JLabel label3=new JLabel(new ImageIcon(url2));
panel.add(label,BorderLayout.CENTER);
panel2.add(label2,BorderLayout.CENTER);
panel3.add(label3,BorderLayout.CENTER);
this.getContentPane().setLayout(new BorderLayout());
this.getContentPane().add(panel,BorderLayout.CENTER);
this.getContentPane().add(panel2,BorderLayout.SOUTH);
this.getContentPane().add(panel3,BorderLayout.NORTH);
this.setSize(500, 500);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("显示扑克牌");
this.setVisible(true);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
ShowImage showImage=new ShowImage();
}
}
import java.awt.Image;
import java.awt.Toolkit;
public class Poker {
static Card[] cards = new Card[54];
static String[] colors = {"黑桃", "红桃", "梅花" , "方块"};
static String values[] = { "A","2", "3", "4", "5", "6", "7", "8", "9", "10",
"J", "Q", "K" };
private Image pic[] = null; // 扑克牌图片数组
public void getPic() {
pic = new Image[54];
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 13; j++) {
// String urlString="C://rear.gif";
// pic[i * 13 + j]=Toolkit.getDefaultToolkit().getImage(urlString);
pic[i * 13 + j] = Toolkit.getDefaultToolkit().getImage(
"images\\" + (i + 1) + "-" + (j + 1) + ".gif");
pic[52] = Toolkit.getDefaultToolkit()
.getImage("images\\s1.gif"); // 小王
pic[53] = Toolkit.getDefaultToolkit()
.getImage("images\\s2.gif"); // 大王
}
}
}
// 构造方法Poker()用于初始化这副扑克
public Poker() {
getPic();
for (int i = 0; i < colors.length; i++) {
for (int j = 0; j < values.length; j++) {
cards[i * 13 + j] = new Card(colors[i], values[j],pic[i*13+j]);
}
}
cards[52] = new Card("小王",pic[52]);
cards[53] = new Card("大王",pic[53]);
}
// 方法getCard()用于获取一张牌的花色和点数
public Card[] getCard() {
return Poker.cards;
}
// 方法getCard()用于获取一张牌的花色和点数
public Card getCard(int n) {
return Poker.cards[n-1];
}
// 方法Show()用于显示一副新的扑克
public void Show() {
for (int i = 0; i < 54; i++) {
cards[i].print();
}
System.out.println();
}
public void xipai() {//洗牌
int i,j;
Card tc;
for (int k = 1; k <= 500; k++)
{
i = (int) (Math.random() * 54);
j = (int) (Math.random() * 54);
tc = cards[i];
cards[i] = cards[j];
cards[j] = tc;
}
}
}
游戏面板
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.net.URL;
import java.util.ArrayList;
import javax.swing.*;
public class PokerPanel extends JPanel {
Poker p = new Poker();
int n = 1;
ArrayList Mycards = new ArrayList(); // 电脑得到的牌
ArrayList Computercards = new ArrayList();//玩家得到的牌
int Myscore = 0; // 电脑得分
int Computerscore = 0;// 玩家得分
public boolean ComputerContinue = true;
public boolean Computerlose = false; // 电脑输了标志
public boolean Mylose = false; // 玩家输了标志
/**
* @param args
*/
public PokerPanel() {
p.xipai();
p.Show();
setBackground(Color.RED);
this.setVisible(true);
//repaint();
}
public void faCard() {
Mycards.add(p.getCard(n));
calcMyScore();
n++;
repaint();
if (Myscore > 21) {
Mylose = true;
/* 显示提示信息对话框 */
JOptionPane.showMessageDialog(null, "你输了,超过21点", "提示",
JOptionPane.ERROR_MESSAGE);
}
}
public void faCardToComputer() {
calcComputerScore();
if (Computerscore > 21) {
JOptionPane.showMessageDialog(null, "超过21点,电脑输了", "提示",
JOptionPane.ERROR_MESSAGE);
ComputerContinue = false;
Computerlose = true;// 电脑输了
} else if (Computerscore < 17) {
Computercards.add(p.getCard(n));
n++;
repaint();
} else {
/* 显示提示信息对话框 */
JOptionPane.showMessageDialog(null, "电脑不再要牌了", "提示",
JOptionPane.ERROR_MESSAGE);
ComputerContinue = false;
}
}
public void calcComputerScore() {
Computerscore = 0;
for (int i = 0; i < Computercards.size(); i++) {
Card c = (Card) Computercards.get(i);
Computerscore += c.count;
}
}
public void calcMyScore() {
Myscore = 0;
for (int i = 0; i < Mycards.size(); i++) {
Card c = (Card) Mycards.get(i);
Myscore += c.count;
}
}
public void shuying() {
calcComputerScore();
calcMyScore();
if (Computerlose == false)
JOptionPane.showMessageDialog(null, "电脑输了", "提示",
JOptionPane.ERROR_MESSAGE);
else if (Mylose == false)
JOptionPane.showMessageDialog(null, "玩家输了", "提示",
JOptionPane.ERROR_MESSAGE);
else if (Myscore > Computerscore)
JOptionPane.showMessageDialog(null, "玩家赢了", "提示",
JOptionPane.ERROR_MESSAGE);
else
JOptionPane.showMessageDialog(null, "电脑赢了", "提示",
JOptionPane.ERROR_MESSAGE);
}
/**
* 游戏绘图
*/
public void paint(Graphics g) {
g.clearRect(0, 0, this.getWidth(), this.getHeight());
g.drawString("玩家牌", 400, 250);
// 玩家牌在下方
for (int i = 0; i < Mycards.size(); i++) {
Card c = (Card) Mycards.get(i);
c.setPosition(50 * i, 200);
c.print();
c.paint(g,this);
}
System.out.println();
calcMyScore();
g.drawString("玩家牌得分"+Myscore, 400, 300);
g.drawString("电脑牌", 400, 100);
// 电脑牌在上方
for (int i = 0; i < Computercards.size(); i++) {
Card c = (Card) Computercards.get(i);
c.setPosition(50 * i, 50);
c.print();
c.paint(g,this);
}
System.out.println();
calcComputerScore();
g.drawString("电脑牌得分"+Computerscore, 400, 150);
}
public void newGame() {
// TODO Auto-generated method stub
Mycards.clear();
Computercards.clear();
Myscore = 0;
Computerscore = 0;
ComputerContinue = true;
Computerlose = false; // 电脑输了标志
Mylose = false; // 玩家输了标志
//给两家各发两张张牌
for(int i=1;i<=2;i++){
faCard();
faCardToComputer();
repaint();
}
}
}
启动主程序
package example;
import java.awt.Color;
import java.awt.Container;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
public class Main extends JFrame implements ActionListener,Runnable{
public Container container = null;// 定义容器
JMenuItem start, exit, about;// 定义菜单按钮
JButton landlord[]=new JButton[2];//抢地主按钮
JButton publishCard[]=new JButton[2];//出牌按钮
int dizhuFlag;//地主标志
int turn;
JLabel dizhu; //地主图标
List<Card> currentList[] =new ArrayList[3]; // 当前的出牌
List<Card> playerList[] = new ArrayList[3]; // 定义3个玩家表
List<Card> lordList;//地主牌
Card card[] = new Card[56]; // 定义54张牌
JTextField time[]=new JTextField[3]; //计时器
Time t; //定时器(线程)
boolean nextPlayer=false; //转换角色
public Main(){
Init();// 初始化
SetMenu();// 创建菜单 按钮(抢地主,发牌,计时器)
this.setVisible(true);
CardInit();//发牌
getLord(); //发完牌开始抢地主
time[1].setVisible(true);
//线程安全性,把非主线程的UI控制放到里面
t=new Time(this,10);//从10开始倒计时
t.start();
}
// 抢地主
public void getLord(){
//System.out.println(CardType.c0.toString());
for(int i=0;i<2;i++)
landlord[i].setVisible(true);
}
//初始化牌
// 发牌洗牌
public void CardInit() {
int count = 1;
//初始化牌
for (int i = 1; i <= 5; i++) {
for (int j = 1; j <= 13; j++) {
if ((i == 5) && (j > 2))
break;
else {
card[count] = new Card(this, i + "-" + j, false);
card[count].setLocation(350, 50);
container.add(card[count]);
count++;
}
}
}
//打乱顺序
for(int i=0;i<100;i++){
Random random=new Random();
int a=random.nextInt(54)+1;
int b=random.nextInt(54)+1;
Card k=card[a];
card[a]=card[b];
card[b]=k;
}
//开始发牌
for(int i=0;i<3;i++)
playerList[i]=new ArrayList<Card>(); //玩家牌
lordList=new ArrayList<Card>();//地主牌三张
int t=0;
for(int i=1;i<=54;i++)
{
if(i>=52)//地主牌
{
Common.move(card[i], card[i].getLocation(),new Point(300+(i-52)*80,10));
lordList.add(card[i]);
continue;
}
switch ((t++)%3) {
case 0:
//左边玩家
Common.move(card[i], card[i].getLocation(),new Point(50,60+i*5));
playerList[0].add(card[i]);
break;
case 1:
//我
Common.move(card[i], card[i].getLocation(),new Point(180+i*7,450));
playerList[1].add(card[i]);
card[i].turnFront(); //显示正面
break;
case 2:
//右边玩家
Common.move(card[i], card[i].getLocation(),new Point(700,60+i*5));
playerList[2].add(card[i]);
break;
}
//card[i].turnFront(); //显示正面
container.setComponentZOrder(card[i], 0);
}
//发完牌排序,从大到小
for(int i=0;i<3;i++)
{
Common.order(playerList[i]);
Common.rePosition(this,playerList[i],i);//重新定位
}
dizhu=new JLabel(new ImageIcon("images/dizhu.gif"));
dizhu.setVisible(false);
dizhu.setSize(40, 40);
container.add(dizhu);
}
// 初始化窗体
public void Init() {
this.setTitle("斗地主");
this.setSize(830, 620);
setResizable(false);
setLocationRelativeTo(getOwner()); // 屏幕居中
container = this.getContentPane();
container.setLayout(null);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
container.setBackground(new Color(0, 112, 26)); // 背景为绿色
}
// 创建菜单 功能按钮
public void SetMenu() {
JMenuBar jMenuBar = new JMenuBar();
JMenu game = new JMenu("游戏");
JMenu help = new JMenu("帮助");
start = new JMenuItem("新游戏");
exit = new JMenuItem("退出");
about = new JMenuItem("关于");
start.addActionListener(this);
exit.addActionListener(this);
about.addActionListener(this);
game.add(start);
game.add(exit);
help.add(about);
jMenuBar.add(game);
jMenuBar.add(help);
this.setJMenuBar(jMenuBar);
landlord[0]=new JButton("抢地主");
landlord[1]=new JButton("不 抢");
publishCard[0]= new JButton("出牌");
publishCard[1]= new JButton("不要");
for(int i=0;i<2;i++)
{
publishCard[i].setBounds(320+i*100, 400, 60, 20);
landlord[i].setBounds(320+i*100, 400,75,20);
container.add(landlord[i]);
landlord[i].addActionListener(this);
landlord[i].setVisible(false);
container.add(publishCard[i]);
publishCard[i].setVisible(false);
publishCard[i].addActionListener(this);
}
for(int i=0;i<3;i++){
time[i]=new JTextField("倒计时:");
time[i].setVisible(false);
container.add(time[i]);
}
time[0].setBounds(140, 230, 60, 20);
time[1].setBounds(374, 360, 60, 20);
time[2].setBounds(620, 230, 60, 20);
for(int i=0;i<3;i++)
{
currentList[i]=new ArrayList<Card>();
}
}
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if (e.getSource() == exit) {
this.dispose();
}
if (e.getSource() == about) {
JOptionPane.showMessageDialog(this, "斗地主");
}
if (e.getSource() == start) {
// this.restart();
}
if(e.getSource()==landlord[0])
{
time[1].setText("抢地主");
t.isRun=false; //时钟终结
}
if(e.getSource()==landlord[1])
{
time[1].setText("不抢");
t.isRun=false; //时钟终结
}
//如果是不要
if(e.getSource()==publishCard[1])
{
this.nextPlayer=true;
currentList[1].clear();
time[1].setText("不要") ;
}
//如果是出牌按钮
if(e.getSource()==publishCard[0])
{
List<Card> c=new ArrayList<Card>();
//点选出牌
for(int i=0;i<playerList[1].size();i++)
{
Card card=playerList[1].get(i);
if(card.clicked)
{
c.add(card);
}
}
int flag=0;
//如果我主动出牌
if(time[0].getText().equals("不要")&&time[2].getText().equals("不要"))
{
if(Common.jugdeType(c)!=CardType.c0)
flag=1;//表示可以出牌
}//如果我跟牌
else{
flag=Common.checkCards(c,currentList,this);
}
//判断是否符合出牌
if(flag==1)
{
currentList[1]=c;
playerList[1].removeAll(currentList[1]);//移除走的牌
//定位出牌
Point point=new Point();
point.x=(770/2)-(currentList[1].size()+1)*15/2;;
point.y=300;
for(int i=0,len=currentList[1].size();i<len;i++)
{
Card card=currentList[1].get(i);
Common.move(card, card.getLocation(), point);
point.x+=15;
}
//抽完牌后重新整理牌
Common.rePosition(this, playerList[1], 1);
time[1].setVisible(false);
this.nextPlayer=true;
}
}
}
public static void main(String args[]) {
new Thread(new Main()).start();
}
@Override
public void run() {
// TODO Auto-generated method stub
}
}
AI 部分(有点标题 党)不过,这个游戏里确实电脑是有策略的。
而且,电脑也确实存在着不少的胜率。
// 地主牌权值,看是否抢地主
public static int getScore(List<Card> list) {
int count = 0;
for (int i = 0, len = list.size(); i < len; i++) {
Card card = list.get(i);
if (card.name.substring(0, 1).equals("5")) {
// System.out.println(card.name.substring(0, 1));
count += 5;
}
if (card.name.substring(2, card.name.length()).equals("2")) {
// System.out.println(2);
count += 2;
}
}
return count;
}
// 拆牌
public static Model getModel(List<Card> list,int[] orders) {
// 先复制一个list
List list2 = new ArrayList<Card>(list);
Model model = new Model();
for(int i=0;i<orders.length;i++)
showOrders(orders[i], list2, model);
return model;
}
运行的界面

基本上就是只要能打得过,就一定会“打” 这个策略好象有点简单了。

总结
就一句,真的很实用,真的太实用了了。
无论是JAVA的封装,还是牌型
论文参考
《基于java的坦克大战游戏的设计与实现–毕业论文–【毕业论文】》
https://blog.csdn.net/dearmite/article/details/131962993
配套资源
java的21点牌类游戏-自带洗牌与机器AI-太牛了–【课程设计】
https://download.csdn.net/download/dearmite/88219715
课程设计JAVAjava的斗地主牌类游戏
https://download.csdn.net/download/dearmite/91945829
6289

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



