有趣的游戏,Java版斗地主游戏实现

近日,使用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方法即可。
效果如下:
在这里插入图片描述
在这里插入图片描述
完整源码:
斗地主游戏完整源码(含图片资源)

创作不易,望大家多多支持。

  • 4
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夜空下的星

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值