大家好,我是小鲍,粉丝说不会做斗地主作业,小鲍在网上寻找了一番并进行了自己的优化,首先我将开发ide进行移植,市面上大多试了java6的jdk与eclipse,这里我改成了idea与jdk8,同时移除了广告和优化了代码乱码问题。
这里我们直接打开文件包即可。
运行main文件。
可以看到抓到的牌全部排序。且提供抢地主,计时功能。
出牌类型支持:单、对子、顺子、炸弹、火箭、4带2、3带1、3带2、飞机、连队。斗地主所有类型基本都支持。
负责卡片的显示
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) { } }
定义卡牌类型。
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//不能出牌 }
负责定义界面与定义逻辑
public class Main extends JFrame implements ActionListener{ 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 Vector[3]; // 当前的出牌 List<Card> playerList[] = new Vector[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); } . . . . . //如果是出牌按钮 if(e.getSource()==publishCard[0]) { List<Card> c=new Vector<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 class Time extends Thread { Main main; boolean isRun = true; int i = 10; public Time(Main m, int i) { this.main = m; this.i = i; } @Override public void run() { while (i > -1 && isRun) { main.time[1].setText("倒计时:" + i--); second(1);// 等一秒 } if (i == -1)// 正常终结,说明超时 main.time[1].setText("不抢"); main.landlord[0].setVisible(false); main.landlord[1].setVisible(false); for (Card card2 : main.playerList[1]) card2.canClick = true;// 可被点击 // 如果自己抢到地主 if (main.time[1].getText().equals("抢地主")) { // 得到地主牌 main.playerList[1].addAll(main.lordList); openlord(true); second(2);// 等待五秒 Common.order(main.playerList[1]); Common.rePosition(main, main.playerList[1], 1); main.publishCard[1].setEnabled(false); setlord(1); } // 判断输赢 public boolean win() { for (int i = 0; i < 3; i++) { if (main.playerList[i].size() == 0) { String s; if (i == 1) { s = "恭喜你,胜利了!"; } else { s = "恭喜电脑" + i + ",赢了!"; } for (int j = 0; j < main.playerList[(i + 1) % 3].size(); j++) main.playerList[(i + 1) % 3].get(j).turnFront(); for (int j = 0; j < main.playerList[(i + 2) % 3].size(); j++) main.playerList[(i + 2) % 3].get(j).turnFront(); JOptionPane.showMessageDialog(main, s); return true; } } return false; } }
手中牌型实体。
public class Model { //一组牌 int value; //权值 int num;// 手数 (几次能够走完,没有挡的情况下) List<String> a1=new Vector<String>(); //单张 List<String> a2=new Vector<String>(); //对子 List<String> a3=new Vector<String>(); //3带 List<String> a123=new Vector<String>(); //连子 List<String> a112233=new Vector<String>(); //连牌 List<String> a111222=new Vector<String>(); //飞机 List<String> a4=new Vector<String>(); //炸弹 }
通用方法。
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 . . . . . . //拆牌循序 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 Vector[4];// 单张 }
可以关注同名公众号获取源码。