当前位置:文档之家› java斗地主

java斗地主

java斗地主
java斗地主

数据结构

大型程序设计

题目:斗地主

学号:2008112225

对此感兴趣的朋友,请与我交流,邮箱763159993@https://www.doczj.com/doc/b55674785.html,,要源代码的请与我联系

一.需求分析

1.刚开始运行的时候,呈现给用户的是一个登录注册画面(主要是方便以后把它改装成网游)

2.登录后有准备的画面,提示一些信息,有开始按钮,开始按钮开始发牌,退出按钮,

可以重新退回到登录界面。这个界面里有有两个菜单,游戏和关于,游戏包括菜单项开始,

退出,游戏难度设定,声音关和闭,查看历史战线,关于包括菜单项玩法,版权。

3.点击开始按钮后,开始发牌,发完后,要随机选地主,地主选定后就开始出牌,一个人,两个电脑。人通过按钮进行选择,出牌,过牌。任何一方(地主方和非地主方)胜利都将结束游戏,并通过一对话框显示本次登录的得失分情况和询问用户是否继续,继续的话就发牌,否的话就直接退出到登录界面。

二.流程图

三.概要分析

1.数据库设计:

用户信息表:字段名:用户名,密码,用户分数

用户历史记录表:字段名:用户名,登录次数,每次登录得分情况

2.类的概要设计

常量类:定义一些常量,以便修改及维护

数据库连接类:加载数据库及数据库的一些操作

用户类:记录用户的一些信息

登录注册画面类:显示登录画面

扑克类:记录每张扑克的信息

规则类:定义斗地主规则

随机发牌类:生成随机牌,并把牌分成四个数组

每个人的牌类:记录用户和电脑牌的一些共性

用户牌类:记录用户的牌及一些操作

电脑牌类:记录电脑的牌及一些操作

剩余牌及出牌类:记录每个人每次出的牌及显示

菜单类:每个画面的菜单,及菜单的一些事件响应

准备画面类:显示准备画面

打牌的画面类:显示打牌的画面

地主按钮面板类:控制地主按钮的显示及按钮的事件响应

对话框类:为一些对话框的共性

关于对话框:关于软件的一些信息

规则对话框:显示斗地主的规则信息

本次登录后的得分情况对话框类:显示本次登录的得分情况,并提示是否继续历史战绩界面类:显示以往十次的登录画面

声音类:加载声音及控制声音的播放

电脑选底牌的权值判定:当电脑有权拿地主时,判断是否要

电脑出牌类:电脑三种算法出牌的共性,定义一个接口

简单出牌类:简单的让电脑出牌

中等难度出牌类:让电脑有一定的记忆能力

难的出牌类:让电脑具备点人工智能的出牌

3.类之间的关系:

上面的类都是一些基础类,下面的数据成员基本都是上面来的。

4.几个基础类的基本设计

Card类:描述一张牌

数据成员:

Int type 牌的花色

Int number 牌的值

String value 牌上的字符串

String path 牌的画面路径

Int width 牌的宽度

Int height 牌的高度

Int xPos,yPos 牌的坐标

成员函数:

Int getHeight() 得到牌的高度

Int getWidth() 得到牌的宽度

Int getNumber() 得到牌的值

String getPath() 得到牌画面的路径

String setPath() 设置牌的路径

String getValue() 得到牌上的字符

Int getX() 得到牌画的横坐标

Int getY() 得到牌画的纵坐标

Int getType() 得到牌的花色

initCard() 初始化牌面的路径

int toCompare() 两个牌之间大小的比较

void toNumber() 通过牌面字符,转化成权值

Regular类:里面没有数据成员,所以方法都设成静态的。

13种牌型函数(除单张牌没写):

Int flyWithNo(Card[]) 飞机不带牌

Int fourWithTwo(Card[]) 四带二

Boolean isBomb(Card[]) 炸弹

Boolean isDouble(Card[]) 对子

Boolean isDoubleKing(Card[]) 对王

Boolean isStraight(Card[]) 顺子

Boolean isThree(Card[]) 三个

Boolean threeOrMoreDouble(Card[]) 三个以上的对子

Boolean threeWidthOne(Card[]) 三带一

Int threeWithTwo(Card[]) 三带二

Boolean twoThreeWithOne(Card[]) 两个三个带两单张

Boolean twoThreeWithTwo(Card[]) 两个三个带两对

V oid sortCardByNumber(Card[]) 对牌按照牌值按小到大牌序,一些牌型都是经过牌序之后才判断的Boolean isBig(Card[],Card[]) 前家和本家出的牌进行比较大小

Boolean winAndGo(Card[]) 第一次出牌或赢了一手之后的出牌

String cardType(int) 牌的类型,用字符串表示,主要是以后可以方便的输出牌信息

RandomCard:随机发牌类

数据成员:

Card[] computer1Card 电脑一的牌

Card[] computer2Card 电脑二的牌

Card[] leaveCard 底牌

Card[] userCard 用户的牌

Vector vector 一幅牌的一个集合

成员函数:

Card[] getComputer1Card() 得到电脑一的牌

Card[] getComputer2Card() 得到电脑二的牌

Card[] getLeaveCard() 得到底牌

Card[] getUserCard() 得到用户的牌

void sortCardByNum(Card[]) 对牌排序

EveryPersonCard:每个人牌,主要是三方人员都有的一些属性

数据成员:

ArrayList cardList 每个人牌的集合

Boolean dizhu 每个人地主权限设置,主要是判断每个人有权时是否选择要地主String outType 出的牌型,输出每个人出的牌型信息

成员函数:

V oid outCard(ArrayList) 从牌的集合中除去每次出的牌

void inCard(Card[]) 当为地主时,可以进牌,即将底牌插入到集合来

void update(Graphics) 清除画面,防止重叠

PersonCard: 继承于EveryPersonCard用户的牌

数据成员:

Int clip[] 用户的每个牌的多次点击情况

成员函数:

V oid outCard(ArrayList) 出牌后再初始化牌

void paintComponet(Graphics)绘出用户的牌

void updateCardPos(int)更新电脑某张牌的位置

void initCardPos()初始化电脑牌的位置及点击

ComputerCard:继承于EveryPersonCard:电脑的牌

成员函数:

V oid initCardPos()初始化牌的位置

V oid paintComponent(Graphics) 绘制底牌和出的牌

OutAndLeaveCard:底牌和出牌

数据成员:

ArrayList out

成员函数:

initPos(int) 初始化第几个人出的牌

setCardList(ArrayList)设置出牌集合

sortCardByNum(ArrayList)排序出牌,主要是防止用户点击牌不是按顺充点击的

update和paintComponent函数绘出图形及更新图形

DiZhu:地主面板类,控制地主的显示

数据成员:

JButton no 不叫地主按钮

Jbutton yes 叫地主按钮

PlayHost playHost 打牌的界面类,两个之间进行通信

Jpanel dizhu 按钮的存放

成员函数:

initDiZhu() 在调用构造函数时进行初始化,电脑自动判断是否要地主,用户通过按钮进行选择地主。

isReStart()判断是否重新开始

delay()选地主后,延迟让别人看下底牌

ComputerScore:判断电脑是否适合当地主

数据成员:

Vector vector[4] 存放不相同的牌

Map map[8]存放牌型

成员函数:

Computer(ArrayList)计算某个集合牌的权值,包括大牌权值和牌型权值

OutCard :电脑出牌基类、

数据成员:

Map cardTypeMap[2][8] 存放两个电脑的牌型

ComputerCard computerCard1 电脑一的牌

ComputerCard computerCard2 电脑二的牌

ArrayList integer[2][8] 存放两个电脑牌型所对应的键,以便取出时的操作

成员函数:

firstOut(ArrayList[],int) 某个电脑所对应的牌型的健,int表示是电脑几

outCard(int) int表示对电脑几的牌进行操作,前手已是最大,接着出牌

outCard(ArrayList,int)根据前家出的牌,电脑选择出牌

OutCardEasy :电脑简单出牌

成员函数:

outCard(int) int表示对电脑几的牌进行操作,前手已是该家最大,接着出牌

outCard(ArrayList ,int ) 根据前家出的牌,电脑选择出牌

Constants:常量类

常量:

public static final int BLACK=1;//黑桃

public static final int RED=2;//红桃

public static final int MEIHUAI=3;//梅花

public static final int FANKUAI=4;//方块

public final static String

backpathString="F:\\workspace\\Card\\src\\images\\back\\back.jpg";//牌的背面路径public final static String path="F:\\workspace\\Card\\src\\images\\";//牌的正面路径

public final static int appletWidth=1130;//小程序的长和宽

public final static int appletHeight=850;

public final static int width=90;//牌画面的长和宽

public final static int height=140;

public final static int gap=30;//牌与牌之间的距离

public final static int increment=20;//点击牌时移动增量

//对西家牌的面板进行设置

public final static int westPanelX=100;//西家第一张牌的位置

public final static int westPanelY=40;

public final static int westPanelWid=width+20;

public final static int westPanelHeI=height+19*gap;

//对东家牌的面板进行设置

public final static int eastPanelX=appletWidth-westPanelX-width;//东家第一张牌的位置public final static int eastPanelY=westPanelY;

public final static int eastPanelWid=width+20;

public final static int eastPanelHeI=19*gap+height;

//对玩家牌的面板进行设置

public final static int southPanelX=westPanelX+width+30;//玩家第一张牌的位置

public final static int southPanelY=appletHeight-height-150;

public final static int southPanelWidI=19*gap+width;

public final static int southPanelHeI=height+increment;

//对中心面板,即底牌和出牌的显示位置,进行参数设置

public final static int midPanelWid=500;

public final static int midPanelHeI=350;

public final static int midPanelX=(appletWidth-midPanelWid)/2;

public final static int midPanelY=(appletHeight-midPanelHeI)/2-100;

对地主面板进行参数设置

对出牌按钮进行设置

public final static int passWidth=80;

public final static int passHeight=30;

public final static int passX=(appletWidth-passWidth)/2;

public final static int passY=southPanelY-35;

public final static int weight[]={2,3,4,5};//设定大牌的权值,分别表示2,小王,大王,炸弹public final static int sum[]={6,5};//表示电脑多少权值就可拿地主,分别表示电脑大牌权值,牌型权值

PlayHost:主程序类

数据成员:

PersonCard personCard 用户的牌

ComputerCard computerCard1,computerCard2 电脑的牌

OutAndLeaveCard outAndLeaveCard 出的牌和底牌

OutCard outCard 电脑出牌的难易程度

JButton pass 过牌和出牌的按钮

ArrayList outArrayList,firstArrayList 后家出的牌集合,前家出牌集合

JLabel jLabel=new JLabel("出牌信息:")

JLabel InformLabel=new JLabel() 显示出牌信息

JPanel jpanel=new JPanel() 面板放jLabel2和InformLabel

boolean start=false判断是否开始,开始后才可出牌

JPanel dizhuPanel 地主的面板

int temp 随机生成数把地主分配给谁

RandomCard randomCar 随机生成牌

User user 用户信息

JLabel jLabel2[]=new JLabel[3] 三方都有一个标签,来显示过牌

ComputerScore computerScore1 计算电脑一的牌的权值

ComputerScore computerScore2 计算电脑二的牌的权值

成员函数:

PlayHost()不带参的构造函数

PlayHost(OutCard)带参的构造函数,从准备画面传来一个出牌难度

PlayHost(User)带参的构造函数,从准备画面传来一个用户信息

PlayHost(OutCard ,User)传出牌难度和用户信息

Void computerOutCard() 调用电脑出牌函数

Void actionPerformed(ActionEvetn event) 按钮的事件响应,主要是对用户的出牌和过牌按钮

Void mouseReleased(MouseEvent event) 鼠标事件响应,主要是根据用户点击鼠标的位置,来判断点击的是哪张牌,然后更新牌的位置

5.简单设计思路

a.对需求作了分析以后,要解决的问题就基本明确了。确定语言,用面向对象的语言分析,就要确定哪些类(即涉及的物),

面向过程,要分析哪些过程。这里用的是面向对象,找对象初步一般是找需求分析里面的名词,当然详细分析的时候还要看是否合适,

还有没有其它的对象。

b.斗地主既然是牌类游戏,涉及到牌,在面向对象的语言里,自然就免不了要定义一个牌类,封装一张牌的一些信息,对

单个牌的一些操作。所以这是最基础的。后面定义的一些对象都是在这个基础上进行操作的。

c.另外就是斗地主中一些规则的制定。出牌是否符合规则,这里主要包括两点,一个是没有前家出牌的情况下的出牌,一

个是有前家出的牌,本家与前家出牌大小规则的制定。

主要是通过牌的张数来判断出牌的可能牌型,然后再看是否符合规则。比牌大小是在出牌符合规则情况下,对应牌型的大小。

d.斗地主发牌。斗地主发牌,定义一个集合,用两个循环,一个控制牌的权值,一个控制牌的花色,一张牌就确定下来了,

把每张牌加入到集合中,另外再加上大小王。但是这样生成的牌集合是基本有序的。对这个集合进行操作,随机生成两个数,这两个数表示要交换集合里面的两张牌的位置,交换一百次。然后再把这个集合划分四份。三份相等的,另外一份三张,分别分给四个数组。

e.斗地主有三方牌,两个电脑,一个用户,但他们都有一些共性,像都包含一个集合啊,

都包括出牌,还有如果是地主的话,就要进牌。

f.图形界面设计。最好是用小应用程序,因为它可以运行在网页上,微软的用户也可以玩,但小应用程序没有菜单啊,应

用程序又不能加载图片。

g.电脑地主的判断。主要是从两个方面考虑,一个是大牌数量,一个是牌型的好坏。大牌包括2,大小王,及炸弹。牌型

主要是飞机,三个,顺子,几连队的分数计算。牌型怎样组织最好?牌型分值怎样设置才算合理。按照人的思维来想的话,先把大牌放到一边,然后再看有没有飞机,或者三个,再看有没有几连队,再看顺子,如果有顺子话,就更好,如果没有,则看还差哪些牌,如果差一两张的话,并且,差的牌对子里面有或者三个里面有,则从对子里面取或三个里面取,如果差

多了,就不打顺子了。有几手牌就基本确定了。牌型的权值定也不好搞,首先牌的张数要考虑,牌的大小要考虑,所以就用大小加张数来定,但是问题是如果有两手牌,一手是345678910jq,一手是10jqka,哪个好呢?当然是第一个了,但是电脑会认为二的。所以在大小和张数里,哪个更重要,张数,所以就用大小的一半再加上张数来确定每个牌型的分数,暂时想不出好的解决方案。还有另外一种想法,就是先设定一个判断牌型的权值函数,当然这个函数要足够好,

然后让电脑自动搜索可能组合的所有牌型,权值最大就行,但是这样难度大。

h.电脑出牌。包括三项,简单的出牌,中等难度的出牌,难的出牌。简单的出牌,只要电脑能够跟的出牌就行了。中等难

度的出牌,就要电脑有记忆能力,能够记住别人出的牌,然后分析出自己出牌胜的可性。难的出牌方案,就要电脑会根据用户出的牌,来推测用户有什么牌之类的,要电脑能够预测牌面的局势,能够根据自己所在的位置来出牌,以便帮助队友。

不过最好的,还是让电脑能够有学习的功能,当电脑和用户有一样的牌时,电脑就和用户打一样牌,当然这要求,其它两方也要有一样的牌,这样牌的局势就基本相同了,也就是说把每局的牌都存放在数据库里,用户出了什么牌也存放在数据库里,然后当电脑和用户有相同的牌时,电脑就搜索数据库里用户出的牌,让电脑和用户出一样的牌,最好打斗地主高手来打牌,让电脑有高手的决策。

四.大型作业进度表

第十六周:

需求分析:<2天>

数据库设计:<1天>

类的概要设计:<4天>

第十七周:

类的详细设计:<2天>

数据库的完成:<1天>

CreateConnection数据库类的完成:<2天>

User用户信息类的完成:

LogonFrame登录界面的完成:

Constants常量类的完成:<1天>

Card单张牌类的完成:

Regular规则类的完成:<1天>

第十八周:

RandomCard随机产生牌并且分配给每个人的类的完成:<1天>

EveryPersonCard每个人需要继承的牌类完成:<2天>

PersonCard玩家牌类的完成:

ComputerCard电脑牌类的完成:

SoundClip声音加载类的完成:<3天>

MenuOption几个界面共有的菜单类完成:

PrepareFrame准备界面的完成:

PlayHost游戏类的完成:

第十九周:

ComputerScore计算电脑牌的总权值类的完成:<1天>

电脑出牌功能的完成:<2天>

测试:

五.详细设计

1.Regular规则类

刚开始没有定义这些牌型函数,只是在写程序的时候,才发现都要重复用到。另外都把牌型函数返回值都定义成布尔型,但写在后面的时候发觉有些不行了。这里主要有几种牌型需要注意。三带一,三带二,飞机带一,飞机带二,四带二,因为这里有带牌,由于在判断牌型前,已经对这手牌进行排序,所以就有几种情况。写三带一和三带二还好说,只有两种情况,但飞机带牌就有六种情况,所以写的时候要把牌型函数返回值标志成是六种情况的哪种,但最后在比较的牌大小的时候,还要搜索牌的权值大小,所以返回值就干脆定义决定牌型的那种牌的最小值。

/**前家出牌,本家一定要比前家大,主要是测试玩家的牌是否比电脑大

* @param first

* 前家出的牌

* @param last

* 本家出的牌

* @return

*/

public static boolean isBig(Card first[],Card last[])

{

对前家和后家的牌进行排序;

If(如果前家了一张牌)

{本家出一张比前家大的牌;

本家出一对王;

本家了一个炸弹;

}

Else if(前家出了两张牌)

{

If(前家出了一对王)返回假;

If(前家出了一个对子)

{本家出了两张比前家大的对子;

本家出了一个炸弹;

}

}

Else if(前家出了三张牌)

{

前家出了三张相等,本家可能出三张相等并且比前家大,可能出对王或炸弹;

}

Else if(前家出了四张牌)

{

本家出了对王,返回真;

前家出了炸弹,本家出了炸弹并且比前家大;

前家出三带一,本家出了三带一并且比前家大;

}

Else if(前家出了五张牌)

{

本家出对王或者炸弹,都返回真;

前家出三带一对,本家出三带一对并且比前家大,则返回真;

前家出顺子,本家出和前家有相同张数的顺子,并且比前家大;

}

Else if (前家出了大于六张的牌)

{

如果本家出了对王或或者炸弹,则返回真;

如果前家出了几连队,则本家也出几连队,并且比前家大;

如果前家出了顺子,则本家也出顺子,并且比前家大

如果前家出了飞机不带,则本家也出飞机不带,并且比前家大;

如果前家出了飞机带单张,则本家也出同样的牌,并且比前家大;

如果前家出了飞机带对子,则本家也出同样的牌,并且比前家大;

}

返回假;

}

2.RandomCard:随机生成牌类

private Card userCard[]=new Card[17];//用户的牌

private Card computer1Card[]=new Card[17];//电脑一的牌

private Card computer2Card[]=new Card[17];//电脑二的牌

private Card leaveCard[]=new Card[3];//最后三张牌

private Vector vector;//用于存储无序牌的容器

public RandomCard()

{

//将五十四张基本有序的数列存储在一个向量中

vector=new Vector(54);

Card tempCard;//中间变量,存储生成的牌

for(int i=1;i<14;i++) //牌的假权值,因为A 2还要转换一下

for(int j=1;j<5;j++) //牌的花色

{

tempCard=new Card(new Integer(i).toString(),j);//生成一眚

vector.addElement(tempCard);//将生成的牌添加到向量中}

vector.addElement(new Card("small",1));//将小王添加到向量中

vector.addElement(new Card("big",1));//将大王添加到向量中

randomCard();//随机打乱这个有序的牌

setComputer1Card();//设置电脑一的牌

setComputer2Card();//设置电脑二的牌

setUserCard();//设置用户的牌

setLeaveCard();//设置底牌

}

把已经有的一个牌随机打乱,随机交换两张牌的位置,交换一百次

Public void randomCard()

{

根据当前的时间,生成一个随机数生成对象;

For(int i=0;i<100;i++)

{

随机生成两个数,如果这两个数不相等,则交换这两张牌的位置;

}

}

3.EveryPersonCard:每个人的牌类

String outType;//牌型字符串

public boolean dizhu=true;//假设优先权分配给谁时,谁就要地主

ArrayList cardList;//每个人的牌集合

public EveryPersonCard(Card[])

{调用无参构造函数;

将参数Card[]加入到集合cardList;

}

第一次出牌或者赢一手后接着出牌

Public void outCard(ArrayList outArrayList)

{将出的牌outArrayList从cardList集合中移走;

}

Public void outCard(Card[] first,Card[] last)

{如果本家出的牌比前家大,则将本家的牌从cardList集合中移走;

}

一方是地主后,底下三张牌加入到该方的cardList集合来

Public void inCard(Card card[])

{将card加入到集合,加入到集合后,要保证集合仍然有序;

}

4.PersonCard:继承于EveryPersonCard用户牌类

Public int clip[] 用户的多次点击情况

Public PersonCard(Card card[])//构造函数

{

Super(card);//调用父类构造函数

initCardPos();//初始化牌的位置

}

Public void initCardPos()

{牌的Y纵坐标都是一样的;

牌的X纵坐标是它所处位置的线性递增函数;

初始化clip的值,每次都初始化为-1,即为该张牌未被点击;

}

某张牌被点击后,更新牌的位置

Public void updateCardPos(Int i)

{从集合中得到第I 张牌;

将第i张牌的纵坐标设成setYpos(以前的位置+clip[i]*Constants.increment);

更新后重新绘出用户牌的位置;

}

玩家赢后出牌或第一次出牌

Public void outCard(ArrayList outArrayList)

{从集合中除去出的牌;

重新初始化牌的位置;

更新后绘出用户牌的图形;

}

https://www.doczj.com/doc/b55674785.html,puterScore:电脑牌权值计算,看电脑是否适合拿底牌

Map map[]=new Map[8];//定义几个容器,分别表示单张,对子,单顺,几连队,三个,飞机,四个,对王

Map vector[]=new Map[4];//创造四个容器分别存储不同的牌,因为牌相同的最大张数为四

Public int[]computer(ArrayList computerCard)

{

初始化大牌权值和牌型权值的总和分别为0;

将computerCard里面的集合cardList的牌添加到vector,依次从低维到高维,即要添加的牌,低维里面已经有了,则向高维添加;

看第一个向量是否包括大小王,如果包括,则在大牌权值里加上相应的分数,并且如果是对王,则把对王移入到map[7]中;

看第四个向量是否包括元素,如果有,则在大牌权值上加上相应的分数,并将所有元素移入到map[6]中;

从高维到低维扫描vector看是否找到包括2,则把2移入到相应的牌型(即看2有几张),并在大牌权值上加上相应的分数;

再来看第三个向量中是否有元素,如果有,是否有飞机的,有的话加入到map[5]中;

有三个的,把三个加入到map[4]中;

再来看第二维向量中,是否有元素,如果有,看是否有几连队的,如果有连队,则将对应的元素加入到map[3]中,如果没有则将对子加入到map[1]中;

再来看第一维向量中,即都是单张的,看是否有顺子,如果有则加入到map[2]中,如果没有则把该维元素加入到map[0]中;

从不是几连队的队子或不是飞机的三个中,有时甚至从四个中,添加牌到map[0]中,如果有组成五张顺子的,则把顺子加入到map[2]中,如果在对子中找牌超过三张,则不组成顺子;

牌型就基本上这样组织,然后算权值,主要算顺子,几连队,飞机和三个的权值;

}

六.一些重要功能算法实现

1.Regular类:

//前面出了五张牌,可能包括三带二,五张顺子

else if(first.length==5)

{

//如果本家出大王或者炸弹

if(isBomb(last)||isDoubleKing(last))

return true;

//如果前家出的三带二,并且带牌在后面

if(threeWithTwo(first)==1)

{

//如果本家出的三带二,并且带牌在前面

if(threeWithTwo(last)==2)

if(last[2].getNumber()>first[0].getNumber())

return true;

//如果本家出的三带二,并且带牌在后面

if(threeWithTwo(last)==1)

if(last[0].getNumber()>first[2].getNumber())

return true;

}

//如果前家出的三带二,并且带牌在前面

if(threeWithTwo(first)==2)

{

//如果本家出的三带二,并且带牌在前面

if(threeWithTwo(last)==2)

if(last[2].getNumber()>first[2].getNumber())

return true;

//如果本家出的三带二,并且带牌在后面

if(threeWithTwo(last)==1)

if(last[0].getNumber()>first[2].getNumber())

return true;

}

//如果前家出的是五张顺子

if(isStraight(first))

{

if(last.length==5)

if(last[0].getNumber()>first[0].getNumber())//本家第一张牌要大于前家

if(isStraight(last)&&last[0].getNumber()+last.length-1

Card("2",1).getNumber())

return true;

return false;

}

}

else

{

//不管前家出什么牌,只要本家出了对王或者炸弹就大

if(isBomb(last)||isDoubleKing(last))

return true;

//如果前家出的是大于五张的顺子

if(isStraight(first))

if(last.length==first.length)//判断前家和本家的牌数是否相等

if(last[0].getNumber()>first[0].getNumber())//首先本家的第一张牌要大于前家的第一张牌

if(isStraight(last)&&last[0].getNumber()+last.length-1

Card("2",1).getNumber())//本家也是顺子,且最大牌不能大于A

return true;

//如果前家出的是大于五张的其它牌

//如果前家出的是几连对

if(threeOrMoreDouble(first))

if(last.length==first.length)

if(last[0].getNumber()>first[0].getNumber())

if(threeOrMoreDouble(last))

return true;

//如果前家出了两个三只带一(八张牌),如果安照上面的三带二的方式判断的话,这个判断就很复杂

if(twoThreeWithOne(first)>0)//前家牌为两个三带一

if(twoThreeWithOne(last)>0)//本家牌为两个三带一

if(twoThreeWithOne(last)>twoThreeWithOne(first))

return true;

//如果前家出了两个三只带两对

if(twoThreeWithTwo(first)>0)

if(twoThreeWithTwo(first)>twoThreeWithTwo(last))

return true;

//如果前家出了四带二

if(fourWithTwo(first)>0&&fourWithTwo(first)

return true;

}

/**判断是不是顺子

* @param card 出的该手牌

* @return

*/

public static boolean isStraight(Card card[])

{

if(card.length>=5)

{

int temp=card[0].getNumber(); //得到第一张牌的值

for(int i=1;i

{

if(card[i].getNumber()==temp+1) //如果手一张牌比前一张牌大一

{

temp=card[i].getNumber();

continue;

}

else

return false;

}

if(card[0].getNumber()+card.length-1

return true;

}

return false;

}

//判断是不是几连对

public static boolean threeOrMoreDouble(Card card[])

{

//首先判断牌数是不是偶数

if(card.length%2==0&&card.length>=6)

{

int length=card.length;

//相邻的两张牌是否相等

for(int i=0;i

{

if(card[i].getNumber()==card[i+1].getNumber())

continue;

else

return false;

}

//还要判断间隔的牌是否有序

int temp=card[0].getNumber();

for(int i=2;i

{

if(card[i].getNumber()==temp+1)

{

temp=card[i].getNumber();

continue;

}

else

return false;

}

//最大不能大于2

if(temp

return true;

}

return false;

}

/**判断是否是四带二,是的话返回大于零

* @param card

* 判断的牌

* @return

* 返回四带二中四张牌的值

*/

public static int fourWithTwo(Card card[])

{

if(card.length==6)

{

for(int j=0;j<3;j++)//j表示四个出现的第一个位置

{

int num=0;//num表示该牌中出现的相同牌数

for(int i=j;i

if(card[j].getNumber()==card[i+1].getNumber())

{

num++;

if(num==3)

return card[j].getNumber();

}

}

}

return 0;

}

/**本家一手牌大后继续或者第一次出牌的规则

* @param go

* 准备出的牌

* @return

* 通过整型值的不同得到牌的类型,同时可判断是否符合规则

*/

public static int winAndGo(Card go[])

{

sortCardByNum(go);

if(go.length==1)//一张牌合法

return 1;

if(isDouble(go))//一个对子合法

return 2;

if(threeWithTwo(go)>0)//三带一对合法

return 3;

if(threeWithOne(go))//三带一合法

return 4;

if(isStraight(go))//顺子合法

return 5;

if(threeOrMoreDouble(go))//几连队合法

return 6;

if(isBomb(go))//炸弹合法

return 7;

if(isDoubleKing(go))//一对王合法

return 8;

if(twoThreeWithOne(go)>0)//两个三只带一只合法

return 9;

if(isThree(go))//三只相等合法

return 10;

if(fourWithTwo(go)>0)//四带二合法

return 11;

if(twoThreeWithTwo(go)>0)//两个三只带对子合法

return 12;

if(flyWinthNo(go)>0)//飞机不带

return 13;

return 0;

}

2.RandomCard:随机生成牌类,并分成四份

//随机产生牌

public void randomCard()

{

//随机把牌交换一百次

Random random=new Random(System.currentTimeMillis()*1000);

for(int i=0;i<100;i++)

{

Card tempCard=new Card();//中间变量,存储要交换的牌

int first=random.nextInt(53);//得到要交换的第一张牌的位置

int last=random.nextInt(53);//得到要交换的第二张牌的位置

if(first!=last)

{

tempCard=vector.remove(first);//从集合中得到却掉的第一张牌

vector.insertElementAt( vector.remove(last),first);//把后一张牌插入到第一张牌的位置

vector.insertElementAt( tempCard,last);//将第一牌插入到最后一张牌的位置}

}

}

//对牌进行排序

public void sortCardByNum(Card card[])

{

int leI=card.length;//得到牌的长度

for(int i=0;i

{

int kJ=i;//假设每次循环的第一个位置最小

for(int j=kJ+1;j

{

if(card[kJ].getNumber()>card[j].getNumber())

kJ=j;

}

if(kJ!=i)

{

Card card2=card[i];

card[i]=card[kJ];

card[kJ]=card2;

}

}

}

3.EveryPersonCard:每个人的牌类

/**接牌

* @param card

* 本家出的牌

* @param first

* 前家出的牌

*/

public void outCard(Card card[],Card first[])

{

if(Regular.isBig(first, card))

{

for(int i=0;i

cardList.remove(card[i]);

}

}

/**地主进牌,插入到原来的牌中,并且对牌进行排序

* @param card

* 底下三张牌

*/

public void inCard(Card card[])

{

for(int i=0;i

{

int j;

for(j=0;j

if(cardList.get(j).getNumber()>card[i].getNumber())

break;

cardList.add(j,card[i]);

}

}

4.PersonCard:用户牌类(在此提供一个完整的类的设计)package src.card;

import java.awt.Graphics;

import java.awt.Image;

import java.util.ArrayList;

import src.other.Constants;

/**用户的牌类继承于EveryPersonCard类

* @author Administrator

*

*/

public class PersonCard extends EveryPersonCard{ private static final long serialVersionUID = 1L;

public int clip[];

public PersonCard()

{

}

/**初始化牌

* @param card

*/

public PersonCard(Card card[])

{

super(card);

initCardPos();

}

/**初始化牌的位置

*

*/

public void initCardPos()

{

for(int i=0;i

{

Card card=cardList.get(i);

card.setXpos(i*Constants.gap);

card.setYpos(Constants.increment);

}

clip=new int[cardList.size()];

for(int i=0;i

{

clip[i]=-1;

}

}

public ArrayList getCardList() {

return cardList;

}

/**点击牌的时候,更新牌的位置

* @param i

* 需要更新牌的位置

相关主题
文本预览
相关文档 最新文档