赞
踩
近日,使用Java编写了斗地主单机小游戏,作为经典小游戏,它也给大家带来不少乐趣,通过对这款游戏的简单实现,加深了我对对Java基础算法的理解。
一.思路:
1、首先要了解斗地主的游戏规则,针对游戏整个过程来考虑。从游戏开始后的洗牌,发牌,抢地主,出牌,到游戏结束整个过程。
2、其中要用到的如洗牌算法,出牌时判牌规则编写,电脑端出牌等一系列。
3、发完牌后及出牌需要用排序算法进行排序。
二.代码实现:
1.初始化牌时的洗牌,代码如下:
public void initCard() { int count=0; if(card[0]==null) { for(int i=1;i<=5;i++) { for(int j=1;j<=13;j++) { if(i==5 && j>2) { break; } card[count]=new Card(i+"-"+j, false); card[count].setLocation(350, 50); container.add(card[count]); count++; } } } if(this.t!=null) { this.t.isPublish=true; for(int i=0;i<card.length;i++) { card[i].canClick=false; card[i].clicked=false; } } Random rand=new Random(); for(int i=0;i<card.length;i++) { //洗牌算法 int j=rand.nextInt(card.length-i); Card k=card[i]; card[i]=card[j]; card[j]=k; } }
2、洗完牌后,进入发牌阶段。
public void publishCard() { for(int i=0;i<card.length;i++) { if(i>=51) { Common.move(card[i], card[i].getLocation(), new Point(300+(i-51)*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; } container.setComponentZOrder(card[i], 0); } } public static void move(Card card,Point from,Point to) { //这个是发牌的牌的移动算法,利用线性函数实现。 if(from.x!=to.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) { //e.printStackTrace(); return; } } } card.setLocation(to); }
3、在出牌时,针对玩家需要对各种牌型进行判定,代码如下:
public class Common { @SuppressWarnings("rawtypes") private static List a[]=new List[4]; public static CardType judgeType(List<Card> list) { int len=list.size(); if(len<=4) { if(len>0 && getValue(list.get(0))==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 && getColor(list.get(0))==5 && getColor(list.get(1))==5) { return CardType.c4; } if(len==4 && (getValue(list.get(0))==getValue(list.get(len-2)) || getValue(list.get(1))==getValue(list.get(len-1)))) { return CardType.c31; }else { return CardType.c0; } }else { for(int i=0;i<a.length;i++) { a[i]=new ArrayList<Integer>(); } getMax(list); if(a[2].size()==1 && a[1].size()==1 && len==5) { return CardType.c32; } if(a[3].size()==1 && len==6) { return CardType.c411; } if(a[3].size()==1 && a[1].size()==2 && len==8) { return CardType.c422; } if(getValue(list.get(0))<15 && a[0].size()==len && (getValue(list.get(0))-getValue(list.get(len-1))==len-1)) { return CardType.c123; } if(getColor(list.get(0))!=5 && a[1].size()==len/2 && len%2==0 && (getValue(list.get(0))-getValue(list.get(len-1))==len/2-1)) { return CardType.c1122; } if(a[2].size()==len/3 && len%3==0 && (getValue(list.get(0))-getValue(list.get(len-1))==len/3-1)) { return CardType.c111222; } if(a[2].size()==len/4 && len%4==0 && ((Integer)a[2].get(len/4-1)-(Integer)a[2].get(0)==len/4-1)) { return CardType.c11122234; } if(a[2].size()==len/5 && len%5==0 && a[1].size()==len/5 && ((Integer)a[2].get(len/5-1)-(Integer)a[2].get(0)==len/5-1)){ return CardType.c1112223344; } } return CardType.c0; } 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(i==2 || i==1) { i+=13; } if(getColor(card)==5) { i+=2; } return i; } public static void getMax(List<Card> list) { int[] count=new int[14]; for(int i=0;i<list.size();i++) { if(getColor(list.get(i))==5) { count[count.length-1]++; }else { count[getValue(list.get(i))-3]++; } } for(int i=0;i<count.length;i++) { if(count[i]==0) { continue; } switch (count[i]) { case 1: a[0].add(i+3); break; case 2: a[1].add(i+3); break; case 3: a[2].add(i+3); break; case 4: a[3].add(i+3); break; } } } public static void cardSort(List<Card> list) { Collections.sort(list,new Comparator<Card>() { @Override public int compare(Card o1, Card o2) { 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(b1==2) { b1+=50; } } if(a2==5) { b2+=100; if(b2==2) { b2+=50; } } 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; } } }); } public static void hideCards(List<Card> list) { for(Card card : list) { card.setVisible(false); } } public static int checkCards(List<Card> c,List<Card>[] current) { List<Card> currList=current[0].size()>0 ? current[0] : current[2]; CardType cType=judgeType(c); CardType currType=judgeType(currList); if(cType!=CardType.c4 && (c.size()!=currList.size() || cType!=currType)) { return 0; } if(cType==CardType.c4 && (c.size()==2 || currType!=CardType.c4)) { return 1; } if(currType==CardType.c4 && currList.size()==2) { return 0; } if(cType==CardType.c1 || cType==CardType.c2 || cType==CardType.c3 || cType==CardType.c4) { if(getValue(c.get(0))>getValue(currList.get(0))) { return 1; }else { return 0; } } if(cType==CardType.c123 || cType==CardType.c1122 || cType==CardType.c111222) { if(getValue(c.get(0))<=getValue(currList.get(0))) { return 0; }else { return 1; } } if(cType==CardType.c31 || cType==CardType.c32 || cType==CardType.c411 || cType==CardType.c422 || cType==CardType.c1112223344 || cType==CardType.c11122234) { List<Card> c1=getOrder(c); List<Card> c2=getOrder(currList); if(getValue(c1.get(0))<getValue(c2.get(0))) { return 0; } } return 1; } public static List<Card> getOrder(List<Card> list){ List<Card> newList=new ArrayList<>(); int[] count=new int[18]; for(int i=0;i<list.size();i++) { count[getValue(list.get(i))]++; } f:for(int i=3;i<count.length-1;i++) { int max=3; for(int j=3;j<count.length-i-1;j++) { if(count[j+1]>count[max]) { max=j+1; } } for(int k=0;k<list.size();k++) { if(getValue(list.get(k))==max) { newList.add(list.get(k)); break f; } } } return newList; } }
3、对于电脑端,也有专门的代码处理,这里就不做过多描述了。
4、编写Swing图形界面。
public class Game extends JFrame implements ActionListener{ private static final long serialVersionUID = 1L; public Container container; JMenuItem start,exit,about; JButton[] landlord=new JButton[2]; JButton[] publishCard=new JButton[2]; int dizhuFlag; int turn; boolean nextPlayer; JLabel dizhu; Time t; List<Card> currentList[]=new ArrayList[3]; List<Card> playerList[]=new ArrayList[3]; List<Card> lordList; Card[] card=new Card[54]; JTextField[] time=new JTextField[3]; Thread thread=null; public Game() { init(); setMenu(); this.setVisible(true); initCard(); showLord(); time[1].setVisible(true); this.t=new Time(this, 10); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { thread=new Thread(t); thread.start(); } }); } public void showLord() { for(int i=0;i<2;i++) { landlord[i].setVisible(true); } } public void initCard() { int count=0; if(card[0]==null) { for(int i=1;i<=5;i++) { for(int j=1;j<=13;j++) { if(i==5 && j>2) { break; } card[count]=new Card(i+"-"+j, false); card[count].setLocation(350, 50); container.add(card[count]); count++; } } } if(this.t!=null) { this.t.isPublish=true; for(int i=0;i<card.length;i++) { card[i].canClick=false; card[i].clicked=false; } } Random rand=new Random(); for(int i=0;i<card.length;i++) { int j=rand.nextInt(card.length-i); Card k=card[i]; card[i]=card[j]; card[j]=k; } for(int i=0;i<3;i++) { playerList[i]=new ArrayList<>(); } lordList=new ArrayList<Card>(); int t=0; for(int i=0;i<card.length;i++) { if(i>=51) { Common.move(card[i], card[i].getLocation(), new Point(300+(i-51)*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; } container.setComponentZOrder(card[i], 0); } if(this.t!=null) { this.t.isPublish=false; } for(int i=0;i<3;i++) { Common.cardSort(playerList[i]); Common.rePosition(playerList[i], i,this); } dizhu=new JLabel(new ImageIcon("images/dizhu.gif")); dizhu.setVisible(false); dizhu.setSize(40, 40); container.add(dizhu); } public void init() { this.setTitle("斗地主"); ImageIcon icon=new ImageIcon(this.getClass().getResource("/images/斗地主.jpg")); ImageIcon icon1=new ImageIcon(this.getClass().getResource("/images/card.png")); this.setResizable(false); this.setIconImage(icon1.getImage()); this.setSize(700, 900); JLabel jl = new JLabel(icon); jl.setSize(700, 900); container=this.getContentPane(); container.setLayout(null); container.add(jl); this.setLocationRelativeTo(getOwner()); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setVisible(true); try { Thread.sleep(1500); } catch (InterruptedException e) { e.printStackTrace(); } this.remove(jl); this.setSize(830, 620); this.setLocationRelativeTo(getOwner()); 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++) { landlord[i].setBounds(320+i*100, 400, 75, 20); landlord[i].setBorder(BorderFactory.createRaisedBevelBorder()); publishCard[i].setBounds(320+i*100, 400, 60, 20); publishCard[i].setBorder(BorderFactory.createRaisedBevelBorder()); container.add(landlord[i]); landlord[i].addActionListener(this); landlord[i].setVisible(false); container.add(publishCard[i]); publishCard[i].addActionListener(this); publishCard[i].setVisible(false); } for(int i=0;i<3;i++) { time[i]=new JTextField("倒计时:"); time[i].setVisible(false); time[i].setBorder(BorderFactory.createRaisedBevelBorder()); time[i].setBackground(new Color(255,215,0)); time[i].setFont(new Font("微软雅黑",Font.BOLD,11)); time[i].setHorizontalAlignment(JTextField.CENTER); time[i].setEditable(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<>(); } } public void restart() { if(t!=null && t.isPublish) { JOptionPane.showMessageDialog(this, "发牌阶段不可重开"); return; } if(t!=null && thread!=null) { t.i=10; if(!t.isOver) { t.stopFlag=true; thread.interrupt(); for(int i=0;i<54;i++) { //card[i].setVisible(false); card[i].setLocation(350, 50); card[i].turnRear(); } }else { for(int i=0;i<54;i++) { card[i].setVisible(true); card[i].setLocation(350, 50); card[i].turnRear(); } for(int i=0;i<3;i++) { time[i].setVisible(false); time[i].setText("倒计时:"); } t.isGameOver=true; } }else { JOptionPane.showMessageDialog(this, "发牌阶段不可重开"); } } @Override public void actionPerformed(ActionEvent e) { if(e.getSource()==exit) { this.dispose(); } if(e.getSource()==about) { JOptionPane.showMessageDialog(this, "QQ88888888"); } 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; time[1].setText("不要"); currentList[1].clear(); } if(e.getSource()==publishCard[0]) { List<Card> c=new ArrayList<>(); 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("不要".equals(time[0].getText()) && "不要".equals(time[2].getText())) { if(Common.judgeType(c)!=CardType.c0) { flag=1; } }else { flag=Common.checkCards(c, currentList); } if(flag==1) { currentList[1]=c; playerList[1].removeAll(currentList[1]); Point p=new Point(); p.x=(770/2)-(currentList[1].size()+1)*15/2; p.y=300; for(int i=0;i<currentList[1].size();i++) { Card card=currentList[1].get(i); Common.move(card, card.getLocation(), p); p.x+=15; } Common.rePosition(playerList[1], 1, this); time[1].setVisible(false); this.nextPlayer=true; } } } public static void main(String[] args) { new Game(); } }
5.完成后启动main方法即可。
效果如下:
完整源码:
斗地主游戏完整源码(含图片资源)
创作不易,望大家多多支持。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。