博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java应用——斗地主(二:抢地主的过程)
阅读量:3976 次
发布时间:2019-05-24

本文共 11226 字,大约阅读时间需要 37 分钟。

写代码的思路:
    1.将留下的三张地主排重新定位
    2.将每个玩家手里的牌进行排序:在将牌加入到每个玩家的链表时,就进行好排序
    3.启动三个玩家的线程,根据排序好了的卡牌重新定位
    4.进行抢地主:庄家在桌面添加组件,三个计时器(线程),抢地主的按钮。添加按钮监听器
    5.在按钮监听事件中,将底牌添加到地主手中的牌里,并进行重新定位(不抢:要做判断是将卡牌给0号玩家还是2号玩家)
    5.在桌面上添加组件:抢完地主后,在相应的地方添上地主的标志,并且在桌面上移除己方玩家的抢地主按钮,添上己方玩家出牌的按钮
    6.计时器:线程,三个倒计时框,当刚开始抢地主时,己方玩家计时器开始计时,无论按下“抢地主”还是“不抢”哪个按钮,计时器都停下计时,而当倒计时数到0时,己方不能抢地主

最开始的界面类:

package b_landTwo;import java.awt.Color;import java.awt.Container;import javax.swing.JFrame;public class AViewJFrame extends JFrame {	public static Container table;	public static void main(String[] args) {		new AViewJFrame().initJframe();	}	private void initJframe() {		setSize(800, 700);		setLocationRelativeTo(null);		setResizable(false);		setDefaultCloseOperation(1);		table = getContentPane();		// 绝对定位		table.setLayout(null);		table.setBackground(new Color(0, 112, 26));		setVisible(true);		// 创建一个庄家对象		BBanker banker = new BBanker();		banker.hold();	}}
封装的卡牌对象:

package b_landTwo;import javax.swing.ImageIcon;import javax.swing.JLabel;public class BCards extends JLabel {	private String name;	// 定下协议:花色值suit 0(黑桃),1(红桃),2(梅花),3(方块),4(大小王)	// 牌面值value:0~14,表示3~10,J,Q,K,A,2,小王,大王;	private int suit, value;	public BCards(String name, int suit, int value) {		this.name = name;		this.suit = suit;		this.value = value;		setSize(71, 96);		// 设置牌面默认为背面		setIcon(new ImageIcon("images/rear.gif"));	}	public void overturn() {		setIcon(new ImageIcon("images/" + name + ".gif"));	}	public String getName() {		return name;	}	public void setName(String name) {		this.name = name;	}	public int getSuit() {		return suit;	}	public void setSuit(int suit) {		this.suit = suit;	}	public int getValue() {		return value;	}	public void setValue(int value) {		this.value = value;	}}

然后的庄家:

package b_landTwo;import java.awt.Container;import java.awt.Point;import java.util.LinkedList;import java.util.Random;import javax.swing.JButton;public class BBanker {	public static BCards[] card = new BCards[54];	// 创建一个随机数对象	private Random random = new Random();	// 三个玩家	public BPlayer Player;	/*	 * 做庄函数	 */	public void hold() {		for (int i = 0; i < 5; i++) {			for (int j = 0; j < 13; j++) {				// 准备阶段,创建54个卡牌对象,卡牌分成五堆,放在桌面上				int value = j;				if (i == 4 && j > 1) {					break;				}				if (i == 4 && j < 2) {					value = value + 13;				}				BCards cards = new BCards(i + "-" + value, i, value);				cards.setLocation(300 + i * 30, 30);				AViewJFrame.table.add(cards);				new Thread() {					public void run() {						while (true) {							AViewJFrame.table.repaint();							try {								Thread.sleep(10);							} catch (InterruptedException e) {								e.printStackTrace();							}						}					};				}.start();				// 洗牌阶段,即每张牌随机存入数组				shuffle(cards);			}		}		// 创建三个玩家		Player = new BPlayer(card);		// 发牌阶段		deal();		// 玩家对象进行相关操作:将牌重新定位		Player.operate();	}	/*	 * 洗牌的函数	 */	private void shuffle(BCards cards) {		int ran = random.nextInt(54);		while (card[ran] != null) {			ran = random.nextInt(54);		}		card[ran] = cards;	}	/*	 * 发牌的函数	 */	private void deal() {		int c = 0, f = 0, s = 0, t = 0, d = 0;		for (int i = 0; i < 54; i++) {			BCards cards = card[i];			if (i < 51) {				switch ((c++) % 3) {				case 0:					CMoving.move(cards, cards.getLocation(), new Point(25, 50 + (f++) * 20));					int indexf = CMoving.getIndex(cards, BPlayer.linkedList0);					BPlayer.linkedList0.add(indexf, cards);					break;				case 1:					CMoving.move(cards, cards.getLocation(), new Point(137 + (s++) * 25, 550));					int indexs = CMoving.getIndex(cards, BPlayer.linkedList1);					BPlayer.linkedList1.add(indexs, cards);					break;				case 2:					CMoving.move(cards, cards.getLocation(), new Point(700, 50 + (t++) * 20));					int indext = CMoving.getIndex(cards, BPlayer.linkedList2);					BPlayer.linkedList2.add(indext, cards);					break;				}				cards.overturn();				AViewJFrame.table.setComponentZOrder(cards, 0);			} else {				// 留下三张地主牌,三张地主牌重新定位				cards.setLocation(280 + (d++) * 80, 30);			}		}	}}
庄家要用到的的移动方法:

package b_landTwo;import java.awt.Point;import java.util.LinkedList;import javax.swing.ImageIcon;import javax.swing.JLabel;public class CMoving {	public static void move(BCards cards, Point start, Point end) {		if (start.x != end.x) {			// 默认向左移动			int speed = -10;			if (start.x < end.x) {				// 向右边移动				speed = -speed;			}			double tangent = ((double) end.y - start.y) / Math.abs(end.x - start.x);			while (Math.abs(end.x - start.x) > 20) {				start.x += speed;				start.y += Math.abs(speed) * tangent;				cards.setLocation(start.x, start.y);				try {					Thread.sleep(1);				} catch (InterruptedException e) {					e.printStackTrace();				}			}			// 最后校准位置			cards.setLocation(end);		}	}		public static void grab(int type, int[] number, LinkedList
linkedList) { // 翻开三张底牌 BBanker.card[51].overturn(); BBanker.card[52].overturn(); BBanker.card[53].overturn(); for (int i = 0; i < 3; i++) { int adr = i + 51; int index = getIndex(BBanker.card[adr], linkedList); number[BBanker.card[adr].getValue()]++; linkedList.add(index, BBanker.card[adr]); } // 地主的标志 JLabel landlord = new JLabel(); landlord.setSize(40, 40); landlord.setIcon(new ImageIcon("images/dizhu.gif")); // 重新定位 for (int i = 0; i < linkedList.size(); i++) { BCards cards = linkedList.get(i); switch (type) { case 0: CMoving.move(cards, cards.getLocation(), new Point(27, 50 + i * 20)); landlord.setLocation(120, 200); break; case 1: CMoving.move(cards, cards.getLocation(), new Point(137 + i * 25, 550)); landlord.setLocation(315, 470); break; case 2: CMoving.move(cards, cards.getLocation(), new Point(698, 50 + i * 20)); landlord.setLocation(615, 200); break; } AViewJFrame.table.setComponentZOrder(cards, 0); AViewJFrame.table.add(landlord); } } /* * 获取插入到链表位置的索引 */ public static int getIndex(BCards cards, LinkedList
linkedList) { for (int i = 0; i < linkedList.size(); i++) { BCards bCards = linkedList.get(i); if (cards.getValue() > bCards.getValue()) { return i; } } return linkedList.size(); }}
庄家之后是玩家:

package b_landTwo;import java.awt.Color;import java.awt.Container;import java.awt.Point;import java.util.LinkedList;import javax.swing.JButton;import javax.swing.JLabel;import javax.swing.JTextField;/* * 一个类三个玩家对象,三个玩家类对象共同有的功能: * 1.将手中的牌排序,2.分析牌型和拆牌 */public class BPlayer {	public BCards[] card;	// 一个玩家一个链表放卡牌	public static LinkedList
linkedList0 = new LinkedList<>(); public static LinkedList
linkedList1 = new LinkedList<>(); public static LinkedList
linkedList2 = new LinkedList<>(); // 一个玩家一个数组计算手中的各点数牌的排数 public static int[] number0 = new int[15]; public static int[] number1 = new int[15]; public static int[] number2 = new int[15]; // 三个计时器 public static JTextField[] jText = new JTextField[3]; // 按钮 public static JButton jBloot, jblnot; public BPlayer(BCards[] card) { this.card = card; } public void operate() { // 将排序好了的(没考虑花色)卡牌重新定位 rank(0, linkedList0); rank(1, linkedList1); rank(2, linkedList2); // 清算每个玩家手中的卡牌 liquad(number0, linkedList0); liquad(number1, linkedList1); liquad(number2, linkedList2); // 叫地主 grab(); BTimer bTimer = new BTimer(); bTimer.start(); // 玩家之间进行出牌的游戏,地主先出牌 JButton jBplay = new JButton("出牌"); JButton jbpass = new JButton("不要"); jBplay.setBounds(280, 520, 80, 20); jbpass.setBounds(431, 520, 80, 20); CButListener cButListener = new CButListener(); jBplay.addActionListener(cButListener); jbpass.addActionListener(cButListener); AViewJFrame.table.add(jBplay); AViewJFrame.table.add(jbpass); } /* * 排序的函数 */ private void rank(int type, LinkedList
linkedList) { for (int i = 0; i < linkedList.size(); i++) { BCards cards = linkedList.get(i); switch (type) { case 0: CMoving.move(cards, cards.getLocation(), new Point(30, 50 + i * 20)); break; case 1: CMoving.move(cards, cards.getLocation(), new Point(137 + i * 25, 550)); break; case 2: CMoving.move(cards, cards.getLocation(), new Point(695, 50 + i * 20)); break; } AViewJFrame.table.setComponentZOrder(cards, 0); } } /* * 清算卡牌的函数 */ private void liquad(int[] number, LinkedList
linkedList) { for (int i = 0; i < linkedList.size(); i++) { BCards cards = linkedList.get(i); int value = cards.getValue(); number[value]++; } } /* * 抢地主的函数 */ private void grab() { // 添加三个线程计时器 for (int i = 0; i < 3; i++) { jText[i] = new JTextField("倒计时:"); AViewJFrame.table.add(jText[i]); } jText[0].setBounds(120, 250, 60, 40); jText[1].setBounds(365, 470, 60, 40); jText[2].setBounds(615, 250, 60, 40); // 抢地主的按钮 jBloot = new JButton("抢地主"); jblnot = new JButton("不抢"); jBloot.setBounds(280, 520, 80, 20); jblnot.setBounds(431, 520, 80, 20); CButListener cButListener = new CButListener(); jBloot.addActionListener(cButListener); jblnot.addActionListener(cButListener); AViewJFrame.table.add(jBloot); AViewJFrame.table.add(jblnot); }}
玩家抢地主要用到监听器:

package b_landTwo;import java.awt.Container;import java.awt.Point;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.util.LinkedList;import javax.swing.ImageIcon;import javax.swing.JButton;import javax.swing.JLabel;public class CButListener implements ActionListener {	public static boolean cont = true;	public void actionPerformed(ActionEvent e) {		String command = e.getActionCommand();		if ("抢地主".equals(command)) {			// 将三张底牌加入己方的卡牌,重新进行洗牌和定位			CMoving.grab(1, BPlayer.number1, BPlayer.linkedList1);			BPlayer.jText[1].setText("stop");			cont = false;			AViewJFrame.table.remove(BPlayer.jBloot);			AViewJFrame.table.remove(BPlayer.jblnot);		} else if ("不抢".equals(command)) {			// 将三张底牌加到王和2的卡牌数量多的一方玩家手中,如果数量相同,默认加到0号玩家			int player0 = BPlayer.number0[12] + BPlayer.number0[13] + BPlayer.number0[14];			int player2 = BPlayer.number2[12] + BPlayer.number2[13] + BPlayer.number2[14];			if (player0 >= player2) {				CMoving.grab(0, BPlayer.number0, BPlayer.linkedList0);			} else {				CMoving.grab(2, BPlayer.number2, BPlayer.linkedList2);			}			BPlayer.jText[1].setText("stop");			cont = false;			AViewJFrame.table.remove(BPlayer.jBloot);			AViewJFrame.table.remove(BPlayer.jblnot);		}else if ("出牌".equals(command)) {		} else if ("不要".equals(command)) {		}	}}
还有三个计时器,是用的线程:

package b_landTwo;import java.awt.Container;public class BTimer extends Thread {	private int time = 15;	public void run() {		while (time > 0 && CButListener.cont) {			BPlayer.jText[1].setText("倒计时:" + (time--));			try {				Thread.sleep(1000);			} catch (InterruptedException e) {				e.printStackTrace();			}		}		if (CButListener.cont) {			BPlayer.jText[1].setText("stop");			AViewJFrame.table.remove(BPlayer.jBloot);			AViewJFrame.table.remove(BPlayer.jblnot);			// 将三张底牌加到王和2的卡牌数量多的一方玩家手中,如果数量相同,默认加到0号玩家			int player0 = BPlayer.number0[12] + BPlayer.number0[13] + BPlayer.number0[14];			int player2 = BPlayer.number2[12] + BPlayer.number2[13] + BPlayer.number2[14];			if (player0 >= player2) {				CMoving.grab(0, BPlayer.number0, BPlayer.linkedList0);			} else {				CMoving.grab(2, BPlayer.number2, BPlayer.linkedList2);			}		}	}}
不足:
    1.刚开始发牌时,窗体的加载和庄家类的发牌好像都要抢占窗体对象,感觉卡顿(已经解决,解决方案:将桌面放在静态块)
    2.代码运行时有时会抛出空指针异常,有时不会抛,我没找到哪行代码出了问题
    3.没有解决好三张底牌翻开时应该在桌面上停一会的需求,加了单线程睡眠也没用。
    4.没有处理好类与类之间的关系,有很多重复的代码

最后是运行的结果图:

你可能感兴趣的文章
优化VMware提高虚拟机运行速度的技巧
查看>>
gcc编译器命令使用详解
查看>>
gcc编译动态库和静态库的详细说明
查看>>
linux下用gcc生成静态库和动态库
查看>>
linux下的动态库和静态库
查看>>
JpGraph中文乱码问题
查看>>
JpGrap引入以及中文乱码问题
查看>>
用$(window).load(function(){...})而不用body.onload()的几个理由
查看>>
使用secure CRT的SFTP在LINUX与WINDOWS下交换文件
查看>>
如何使用PHP开发高效的WEB系统
查看>>
linux下查看系统配置的命令
查看>>
linux 链接的使用 创建和删除符号连接(软、硬链接)
查看>>
linux修改系统时间详解
查看>>
linux下设置IP为什么每次重启后会自动变?
查看>>
php导出数据到excel,防止身份证等数字字符格式变成科学计数的方法
查看>>
shell操作mysql
查看>>
netcat
查看>>
Linux下如何查看CPU信息, 包括位数和多核信息
查看>>
Linux命令行访问网页
查看>>
VMware网络连接 桥接、NAt、host-only模式
查看>>