jpanel麻将自动打牌,碰牌,杠牌

 不多说,拷贝就能用

package com;

import java.awt.event.ActionEvent;

import javax.swing.*;

import main.MahjongTileInitWrongTypeAndTypeIdException;

public class MahJongGame extends JFrame {

	/**
	 * 
	 */
	private static final long serialVersionUID = -37364652653193128L;
	MyPanel myp = null;
	
	public static void main(String[] args) throws InterruptedException, MahjongTileInitWrongTypeAndTypeIdException {
		// TODO Auto-generated method stub
		MahJongGame mhg = new MahJongGame();
	}

	public MahJongGame() throws InterruptedException, MahjongTileInitWrongTypeAndTypeIdException {
		
		myp = new MyPanel();

		// 启动了mypanel线程
		Thread myt = new Thread(myp);
		myt.start();

		// 先删除旧的面板
		this.remove(myp);
		// 加入新面板
		this.add(myp);
		this.setSize(1000, 600);
		// 刷新JFrame面板
		this.setVisible(true);

	}

	public void actionPerformed(ActionEvent arg0) {
	
	}

}
package com;

import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.*;

import javax.swing.*;

import com.jbutton.RotateImage;
import com.time.TimerLabel;

import main.InitPlayer;
import main.MahjongTileInitWrongTypeAndTypeIdException;
import main.Player;
import main.ShuffleMahJong;

/**
 * 1-9存万 21-29存条 31-39存筒 0,10,20,30,40存东南西北 41-43存中,发,白
 * 
 * @author LiHai
 *
 */
public class MyPanel extends JPanel implements Runnable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	public static long timedate = 3;

	Image image = null;

	// 初始化按钮
	ArrayList<JButton> bt = new ArrayList<JButton>();

	JButton b0, b1, b2, b3;
	// 定义存放麻将的集合
	Vector<Image> tupWeizhi = new Vector<Image>();

	// 初始化玩家
	InitPlayer initPlayer = null;

	// 四个玩家
	Player player = new Player();
	Player computer1 = new Player();
	Player computer2 = new Player();
	Player computer3 = new Player();
	// 麻将
	ShuffleMahJong shuffleMahJong = new ShuffleMahJong();

	int t = 1;
	TimerLabel tlaber = new TimerLabel(5);

	public MyPanel() throws InterruptedException, MahjongTileInitWrongTypeAndTypeIdException {
		// Scanner scanner = new Scanner(System.in);
		setLayout(null);// 必须为设置为null,你的setBouds();才可以有作用

		// 初始化按钮
		this.jbutton();
		this.setOpaque(false);
		// 设置整副牌的开始位置
		ShuffleMahJong.maJiangsIndex = 0;
		// 移动起始位置前的牌到list末尾
		ShuffleMahJong.moveMahJongs();
		// 玩家
		initPlayer = new InitPlayer();
		// 第一次起牌
		initPlayer.haveFirstBoard();

		// 输出牌局中的整副牌(剩余的牌)
		System.out.println("【此时牌局中的剩余的牌:】");
		ShuffleMahJong.printMahJongs();
		// 第二次起牌:跳庄
		initPlayer.haveJumpBoard();
		// 输出此时玩家手中的牌
		initPlayer.printPlayer();
		player = InitPlayer.players.get(0);
		// 摸第一张牌
		player.gainMaJiang(0);
		// 设置为出牌状态
		player.setRunzt(true);
		initPlayer.printPlayer(player);
		// 输出牌局中的整副牌(剩余的牌)
		System.out.println("【此时牌局中的剩余的牌:】");
		ShuffleMahJong.printMahJongs();
		player = InitPlayer.players.get(0);
		computer1 = InitPlayer.players.get(1);
		computer2 = InitPlayer.players.get(2);
		computer3 = InitPlayer.players.get(3);
		System.out.println("【您先出牌:[待打出牌对应的顺序,例如:1表示打出第一张牌],[非数字输入:退出游戏]】");

		image = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/image/image1.jpg"));
		for (int i = 0; i <= 43; i++) {
			// System.out.println("/image/"+i+".jpg");
			tupWeizhi.add(Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/image/" + i + ".png")));
		}
		// tlaber.setBounds(220, 220, 220, 220);
		this.add(tlaber, BorderLayout.CENTER);
		tlaber.start();
	}

	public void paint(Graphics g) {
		super.paint(g);
		g.fillRect(0, 0, 400, 300);

		// 重绘子组件,不然会出现异常“有个按钮需要鼠标移动到它上边才显示”
		super.paintChildren(g);
		// 固定背景图片,允许这个JPanel可以在图片上添加其他组件
		g.drawImage(image, 0, 0, this.getWidth(), this.getHeight(), this);
		// 画出牌文字信息
		this.drawenzi(g);
		// 确保该函数只能被调用一次
		for (int i = 0; i < t; i++) {
			// deal(g);
			t--;
			// System.out.println("该集合牌的数量" + tupWeizhi.size());
		}
//		int i1=player.getPlayerMaJiangs().get(0).getType();
//		int i2=player.getPlayerMaJiangs().get(0).getTypeId();
//		System.out.println(i1+"-"+i2);

		// 画玩家麻将
		this.drawmajiang(g);

	}

	private void drawmajiang(Graphics g) {
		// 画西家的牌
		for (int i = 0; i < InitPlayer.players.get(2).getPlayerMaJiangs().size(); i++) {
			int p = ((InitPlayer.players.get(2).getPlayerMaJiangs().get(i).getType() * 10)
					+ InitPlayer.players.get(2).getPlayerMaJiangs().get(i).getTypeId());
			// JButton b= new JButton(); // // 实例化按钮对象,并且设置按钮上显示图片
			// ImageIcon ico = new ImageIcon(getClass().getResource("/image/"+p+".png"));
			// ico.setImage(ico.getImage().getScaledInstance(32, 70, Image.SCALE_DEFAULT));
			// Image image = ico.getImage(); b.setBounds(110 + 33 * u,40,34, 70);
			// b.setIcon(ico); this.add(b);
			if (i < 13) {
				g.drawImage(RotateImage.Rotate(tupWeizhi.get(p), 180), 600 - 30 * i, 50, 31, 70, this);
			} else {
				g.drawImage(RotateImage.Rotate(tupWeizhi.get(p), 180), 600 - 50 - 30 * i, 50, 31, 70, this);
			}
		}

		// 画电脑东家
		for (int i = 0; i < InitPlayer.players.get(0).getPlayerMaJiangs().size(); i++) {
			int p = ((InitPlayer.players.get(0).getPlayerMaJiangs().get(i).getType() * 10)
					+ InitPlayer.players.get(0).getPlayerMaJiangs().get(i).getTypeId());
			if (i >= 13) {
				g.drawImage(tupWeizhi.get(p), 143 + 50 + 30 * i, 430, 29, 70, this);
			} else {
				g.drawImage(tupWeizhi.get(p), 143 + 30 * i, 430, 30, 70, this);
			}

		}

		// 画电脑北家
		for (int i = 0; i < InitPlayer.players.get(1).getPlayerMaJiangs().size(); i++) {
			int p = ((InitPlayer.players.get(1).getPlayerMaJiangs().get(i).getType() * 10)
					+ InitPlayer.players.get(1).getPlayerMaJiangs().get(i).getTypeId());
			new RotateImage();
			if (i < 13) {
				g.drawImage(RotateImage.Rotate(tupWeizhi.get(p), 270), 680, 480 - 30 * i, 70, 30, this);
			} else {
				g.drawImage(RotateImage.Rotate(tupWeizhi.get(p), 270), 680, 480 - 50 - 30 * i, 70, 30, this);
			}

		}
		// 画电脑南家
		for (int i = 0; i < InitPlayer.players.get(3).getPlayerMaJiangs().size(); i++) {
			int p = ((InitPlayer.players.get(3).getPlayerMaJiangs().get(i).getType() * 10)
					+ InitPlayer.players.get(3).getPlayerMaJiangs().get(i).getTypeId());
			new RotateImage();
			if (i < 13) {
				g.drawImage(RotateImage.Rotate(tupWeizhi.get(p), 90), 50, 50 + 30 * i, 70, 30, this);
			} else {
				g.drawImage(RotateImage.Rotate(tupWeizhi.get(p), 90), 50, 50 + 50 + 30 * i, 70, 30, this);

			}

		}
	}

	private void drawenzi(Graphics g) {
		Font ft = new Font("宋体", Font.BOLD, 30);
		g.setFont(ft);
		g.setColor(Color.LIGHT_GRAY);
		if (InitPlayer.players.get(0).isRunzt()) {
			g.setColor(Color.green);
			g.drawString(InitPlayer.players.get(0).getPlayerMaJiangs().size() + "东", 300, 420);
			g.setColor(Color.LIGHT_GRAY);
		} else {
			g.drawString(InitPlayer.players.get(0).getPlayerMaJiangs().size() + "东", 300, 420);
		}
		if (InitPlayer.players.get(1).isRunzt()) {
			g.setColor(Color.green);
			g.drawString(InitPlayer.players.get(1).getPlayerMaJiangs().size() + "南", 560, 300);
			g.setColor(Color.LIGHT_GRAY);
		} else {
			g.drawString(InitPlayer.players.get(1).getPlayerMaJiangs().size() + "南", 560, 300);
		}
		if (InitPlayer.players.get(2).isRunzt()) {
			g.setColor(Color.green);
			g.drawString(InitPlayer.players.get(2).getPlayerMaJiangs().size() + "西", 300, 160);
			g.setColor(Color.LIGHT_GRAY);
		} else {
			g.drawString(InitPlayer.players.get(2).getPlayerMaJiangs().size() + "西", 300, 160);
		}
		if (InitPlayer.players.get(3).isRunzt()) {
			g.setColor(Color.green);
			g.drawString(InitPlayer.players.get(3).getPlayerMaJiangs().size() + "北", 120, 300);
			g.setColor(Color.LIGHT_GRAY);
		} else {
			g.drawString(InitPlayer.players.get(3).getPlayerMaJiangs().size() + "北", 120, 300);
		}

		g.setFont(new Font("宋体", Font.BOLD, 50));
		g.setColor(Color.red);
		if (player.isHul()) {
			g.drawString("胡", 360, 420);
		}
		if (computer1.isHul()) {

			g.drawString("胡", 630, 300);
		}
		if (computer2.isHul()) {

			g.drawString("胡", 360, 160);
		}
		if (computer3.isHul()) {
			g.drawString("胡", 180, 300);
		}

		// 出牌倒计时
		if (tlaber.getCount() > 0) {
			g.setColor(Color.BLUE);
			g.drawString(tlaber.getCount() + "", 380, 300);
		}
		g.setColor(Color.darkGray);
		g.drawString("剩:" + ShuffleMahJong.maJiangs.size(), 380, 250);

	}

	/**
	 * 设置按钮图片缩放
	 * 
	 * @param file
	 * @param iconButton
	 */
	public void setIcon(String file, JButton iconButton) {
		ImageIcon icon = new ImageIcon(file);
		icon.getImage();
		Image temp = icon.getImage().getScaledInstance(iconButton.getWidth(), iconButton.getHeight(),
				Image.SCALE_DEFAULT);
		icon = new ImageIcon(temp);
		iconButton.setIcon(icon);
	}

	public void jbutton() {

		// 创建按钮对象
		for (int i = 0; i < 14; i++) {
			b2 = new JButton("b2 " + i);
			b2.addMouseListener(new EventListeners(b2));
			// 把按钮容器添加到JFrame容器上
			if (i < 13) {
				b2.setBounds(600 - 30 * i, 50, 31, 70);
			} else {
				b2.setBounds(600 - 50 - 30 * i, 50, 31, 70);
			}
			// 设置按钮透明
			b2.setContentAreaFilled(false);
			add(b2);
		}
		for (int i = 0; i < 14; i++) {
			b0 = new JButton("b0 " + i);
			b0.addMouseListener(new EventListeners(b0));
			// 把按钮容器添加到JFrame容器上
			if (i < 13) {
				b0.setBounds(143 + 30 * i, 430, 31, 70);
			} else {
				b0.setBounds(193 + 30 * i, 430, 31, 70);
			}
			// 设置按钮透明
			b0.setContentAreaFilled(false);
			add(b0);
		}
		for (int i = 0; i < 14; i++) {
			b3 = new JButton("b3 " + i);
			b3.addMouseListener(new EventListeners(b3));
			// 把按钮容器添加到JFrame容器上
			if (i < 13) {
				b3.setBounds(50, 50 + 30 * i, 70, 31);
			} else {
				b3.setBounds(50, 50 + 50 + 30 * i, 70, 31);
			}
			// 设置按钮透明
			b3.setContentAreaFilled(false);
			add(b3);
		}
		for (int i = 0; i < 14; i++) {
			b1 = new JButton("b1 " + i);
			b1.addMouseListener(new EventListeners(b1));
			// 把按钮容器添加到JFrame容器上
			if (i < 13) {
				b1.setBounds(680, 480 - 30 * i, 70, 31);
			} else {
				b1.setBounds(680, 480 - 50 - 30 * i, 70, 31);
			}
			// 设置按钮透明
			b1.setContentAreaFilled(false);
			add(b1);
		}

	}

	public void run() {

		while (true) {
			try {
				this.repaint();
				Thread.sleep(100);
				synchronized (this) {

					// 检测是否胡牌
					if (player != null) {
						player.huCards();
						computer1.huCards();
						computer2.huCards();
						computer3.huCards();
					}
					// 判断玩家是否超时 超时自动打牌
					if (tlaber.getCount() == 0 && tlaber.isStart()) {

						int numb = 0;
						if (initPlayer.zdchupai() > 1 && initPlayer.zdchupai() != 0) {
							numb = initPlayer.zdchupai();
						}

						// 判断该哪一个玩家出牌
						if (InitPlayer.players.get(0).isRunzt()) {
							int jj;
							// 打牌
							InitPlayer.players.get(0).discardMaJiang(numb);
							// 把该牌删掉
							InitPlayer.players.get(0).Remove(numb);
							// 排序
							InitPlayer.players.get(0).printMaJiangs();
							// 关闭上一个线程
							tlaber.stop();
							InitPlayer.players.get(0).setRunzt(false);
							// 碰牌检测
							Player playerto = InitPlayer.touchDetection();
							if (playerto == null) {
								// 下一家摸牌
								InitPlayer.players.get(1).gainMaJiang(0);
								InitPlayer.players.get(1).setRunzt(true);

							} else {

								playerto.setRunzt(true);
							}
//							//启动新线程
//							tlaber=new TimerLabel(5);
//							tlaber.start();
						} else if (InitPlayer.players.get(1).isRunzt()) {
							InitPlayer.players.get(1).discardMaJiang(numb);
							// 排序
							InitPlayer.players.get(1).printMaJiangs();
							// 把该牌删掉
							InitPlayer.players.get(1).Remove(numb);
							// 关闭上一个线程
							tlaber.stop();
							InitPlayer.players.get(1).setRunzt(false);
							// 碰牌检测
							Player playerto = InitPlayer.touchDetection();
							if (playerto == null) {
								// 下一家摸牌
								InitPlayer.players.get(2).gainMaJiang(0);
								InitPlayer.players.get(2).setRunzt(true);

							} else {

								playerto.setRunzt(true);
							}
//							//启动新线程
//							tlaber=new TimerLabel(5);
//							tlaber.start();
						} else if (InitPlayer.players.get(2).isRunzt()) {
							InitPlayer.players.get(2).discardMaJiang(numb);
							// 排序
							InitPlayer.players.get(2).printMaJiangs();
							// 把该牌删掉
							InitPlayer.players.get(2).Remove(numb);
							// 关闭上一个线程
							tlaber.stop();
							InitPlayer.players.get(2).setRunzt(false);
							// 碰牌检测
							Player playerto = InitPlayer.touchDetection();
							if (playerto == null) {
								// 下一家摸牌
								InitPlayer.players.get(3).gainMaJiang(0);
								InitPlayer.players.get(3).setRunzt(true);

							} else {

								playerto.setRunzt(true);
							}
//							//启动新线程
//							tlaber=new TimerLabel(5);
//							tlaber.start();
						} else if (InitPlayer.players.get(3).isRunzt()) {
							InitPlayer.players.get(3).discardMaJiang(numb);
							// 排序
							InitPlayer.players.get(3).printMaJiangs();
							// 把该牌删掉
							InitPlayer.players.get(3).Remove(numb);
							// 关闭上一个线程
							tlaber.stop();
							InitPlayer.players.get(3).setRunzt(false);
							// 碰牌检测
							Player playerto = InitPlayer.touchDetection();
							if (playerto == null) {
								// 下一家摸牌
								InitPlayer.players.get(0).gainMaJiang(0);
								InitPlayer.players.get(0).setRunzt(true);

							} else {
								playerto.setRunzt(true);
							}
//							//启动新线程
//							tlaber =new TimerLabel(5);
//							tlaber.start();
						}
						// 没牌了停止线程
						if (ShuffleMahJong.maJiangs.size() <= 0) {
							tlaber.stop();
						} else {
							// 启动新线程
							tlaber = new TimerLabel(0);
							tlaber.start();
						}
					}
				}
			} catch (InterruptedException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
		}

	}

	class EventListeners extends MouseAdapter {
		// 获取按钮信息
		JButton b;
		TimerLabel label;

		public EventListeners(JButton b) {
			this.b = b;
		}

		public void mouseClicked(MouseEvent e) {
			String outStr = "";

			if (e.getClickCount() == 2) {

				// 获取后两位数
				int btnum = Integer
						.parseInt((b.getText().substring(b.getText().length() - 2, b.getText().length())).trim());
				// 拿到前两位字符串
				String btstr = b.getText().substring(0, 2);
				int numb = 3;
				// 检测是否胡牌
				if (player != null) {
					player.huCards();
					computer1.huCards();
					computer2.huCards();
					computer3.huCards();
				}
				// 满足牌数为二倍,判断是否是该玩家,判断是否到该玩家出牌
				if (btstr.equals("b0") && InitPlayer.players.get(0).isRunzt()) {
					// 打牌
					InitPlayer.players.get(0).discardMaJiang(btnum);
					// 把该牌删掉
					InitPlayer.players.get(0).Remove(btnum);
					// 排序
					InitPlayer.players.get(0).printMaJiangs();
					// 碰牌检测
					Player playerto = InitPlayer.touchDetection();

					tlaber.stop();
					InitPlayer.players.get(0).setRunzt(false);
					if (playerto == null) {
						// 下一家摸牌
						InitPlayer.players.get(1).gainMaJiang(0);
						InitPlayer.players.get(1).setRunzt(true);

					} else {

						playerto.setRunzt(true);
					}
//					//启动新线程
					tlaber = new TimerLabel(numb);
					tlaber.start();
				} else if (btstr.equals("b1") && InitPlayer.players.get(1).isRunzt()) {
					// 打牌
					InitPlayer.players.get(1).discardMaJiang(btnum);
					// 把该牌删掉
					InitPlayer.players.get(1).Remove(btnum);
					// 排序
					InitPlayer.players.get(1).printMaJiangs();
					// 碰牌检测
					Player playerto = InitPlayer.touchDetection();
					tlaber.stop();
					InitPlayer.players.get(1).setRunzt(false);
					if (playerto == null) {
						// 下一家摸牌
						InitPlayer.players.get(2).gainMaJiang(0);
						InitPlayer.players.get(2).setRunzt(true);

					} else {

						playerto.setRunzt(true);
					}
//					//启动新线程
					tlaber = new TimerLabel(numb);
					tlaber.start();
				} else if (btstr.equals("b2") && InitPlayer.players.get(2).isRunzt()) {
					// 打牌
					InitPlayer.players.get(2).discardMaJiang(btnum);
					// 把该牌删掉
					InitPlayer.players.get(2).Remove(btnum);
					// 排序
					InitPlayer.players.get(2).printMaJiangs();
					// 碰牌检测
					tlaber.stop();
					InitPlayer.players.get(2).setRunzt(false);
					Player playerto = InitPlayer.touchDetection();
					if (playerto == null) {
						// 下一家摸牌
						InitPlayer.players.get(3).gainMaJiang(0);
						InitPlayer.players.get(3).setRunzt(true);

					} else {

						playerto.setRunzt(true);
					}
//					//启动新线程
					tlaber = new TimerLabel(numb);
					tlaber.start();
				} else if (btstr.equals("b3") && InitPlayer.players.get(3).isRunzt()) {
					// 打牌
					InitPlayer.players.get(3).discardMaJiang(btnum);
					// 把该牌删掉
					InitPlayer.players.get(3).Remove(btnum);
					// 排序
					InitPlayer.players.get(3).printMaJiangs();
					tlaber.stop();
					InitPlayer.players.get(3).setRunzt(false);
					// 碰牌检测
					Player playerto = InitPlayer.touchDetection();
					if (playerto == null) {
						// 下一家摸牌
						InitPlayer.players.get(0).gainMaJiang(0);
						InitPlayer.players.get(0).setRunzt(true);

					} else {

						playerto.setRunzt(true);
					}
//					//启动新线程
					tlaber = new TimerLabel(numb);
					tlaber.start();
				}
				outStr = outStr + "双击" + b.getText();
			}

			// System.out.print("label=="+label);
		}

	}

}
package com.jbutton;
 
import java.awt.*;
import java.awt.image.BufferedImage;
 
/**
 * 图片旋转工具类
 */
public class RotateImage {
 
    /**
     * 对图片进行旋转
     *
     * @param src   被旋转图片
     * @param angel 旋转角度
     * @return 旋转后的图片
     */
    public static BufferedImage Rotate(Image src, int angel) {
        int src_width = src.getWidth(null);
        int src_height = src.getHeight(null);
        // 计算旋转后图片的尺寸
        Rectangle rect_des = CalcRotatedSize(new Rectangle(new Dimension(
                src_width, src_height)), angel);
        BufferedImage res = null;
        try {
        	 res = new BufferedImage(rect_des.width, rect_des.height,
                     BufferedImage.TYPE_INT_RGB);
        	 Graphics2D g2 = res.createGraphics();
             // 进行转换
             g2.translate((rect_des.width - src_width) / 2,
                     (rect_des.height - src_height) / 2);
             g2.rotate(Math.toRadians(angel), src_width / 2, src_height / 2);
      
             g2.drawImage(src, null, null);
           
		} catch (Exception e) {
			// TODO: handle exception
		}

        return res;
    }
 
    /**
     * 计算旋转后的图片
     *
     * @param src   被旋转的图片
     * @param angel 旋转角度
     * @return 旋转后的图片
     */
    public static Rectangle CalcRotatedSize(Rectangle src, int angel) {
        // 如果旋转的角度大于90度做相应的转换
        if (angel >= 90) {
            if (angel / 90 % 2 == 1) {
                int temp = src.height;
                src.height = src.width;
                src.width = temp;
            }
            angel = angel % 90;
        }
 
        double r = Math.sqrt(src.height * src.height + src.width * src.width) / 2;
        double len = 2 * Math.sin(Math.toRadians(angel) / 2) * r;
        double angel_alpha = (Math.PI - Math.toRadians(angel)) / 2;
        double angel_dalta_width = Math.atan((double) src.height / src.width);
        double angel_dalta_height = Math.atan((double) src.width / src.height);
 
        int len_dalta_width = (int) (len * Math.cos(Math.PI - angel_alpha
                - angel_dalta_width));
        int len_dalta_height = (int) (len * Math.cos(Math.PI - angel_alpha
                - angel_dalta_height));
        int des_width = src.width + len_dalta_width * 2;
        int des_height = src.height + len_dalta_height * 2;
        return new Rectangle(new Dimension(des_width, des_height));
    }
}
package com.time;

import java.awt.Font;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import java.lang.Thread.State;

/**
 * 计时标签package text.run;
 * 
 * @author Jeky
 */
public class TimerLabel extends JLabel {

	private int maxTime;
	public Thread getThread() {
		return thread;
	}

	private int count;
	private static final int SECOND = 1000;
	private static final int FONT_SIZE = 36;
	private Thread thread;
	private boolean pause;
	private boolean start;

	/**
	 * 新建一个计时标签
	 * 
	 * @param maxTime 倒计时起始时间
	 */
	public TimerLabel(int maxTime) {
		this.setHorizontalAlignment(JLabel.CENTER);
		this.setFont(new Font("Times New Roman", Font.BOLD, FONT_SIZE));
		this.pause = false;
		setMaxTime(maxTime);
	}

	/**
	 * 修改倒计时起始时间
	 * 
	 * @param maxTime 新的起始时间
	 */
	public void setMaxTime(int maxTime) {
		if (this.start) {
			return;
		}
		this.maxTime = maxTime;
		this.count = maxTime;
		initText();
		this.thread = new Thread(new Runnable() {

			@Override
			public void run() {
				while (count != 0) {
					try {
						if (!start) {
							count = 0;
							//initText();
							//System.out.println("count=11="+count+start);
							break;
						}
						if (!pause) {
							Thread.sleep(SECOND);
							count--;
							//System.out.println("pause=11="+count+pause);
							//initText();
						}
					} catch (InterruptedException ex) {
						pause = true;
					}
				}
				//done();
			}
		});
		this.start = false;
	}

	/**
	 * 倒计时完成后调用此方法
	 */
	public void done() {
		JOptionPane.showMessageDialog(this, "结束!");
	}

	/**
	 * 标签字符由此方法设置
	 */
	public void initText() {
		String min = String.valueOf(count / 60);
		String sec = String.valueOf(count % 60);
		while (min.length() < 2) {
			min = "0" + min;
		}
		while (sec.length() < 2) {
			sec = "0" + sec;
		}
		this.setText(sec);
	}

	/**
	 * 暂停
	 */
	public void pause() {
		if (start) {
			thread.interrupt();
		}
	}

	/**
	 * 检测标签倒计时是否开始
	 * 
	 * @return 如果开始返回true
	 */
	public boolean isStart() {
		return start;
	}

	/**
	 * 得到倒计时起始时间
	 * 
	 * @return 倒计时起始时间
	 */
	public int getMaxTime() {
		return maxTime;
	}

	/**
	 * 检测标签倒计时是否暂停
	 * 
	 * @return 倒计时暂停返回true
	 */
	public boolean isPause() {
		return pause;
	}

	/**
	 * 从暂停中恢复计时
	 */
	public void continueDo() {
		if (this.pause) {
			this.pause = false;
		}
	}

	/**
	 * 取消计时
	 */
	public void stop() {
		if (start) {
			//thread.interrupt();
			this.count=-11;
			start = false;
		}
		
	}

	/**
	 * 开始计时
	 */
	public void start() {
		if (thread.getState().equals(State.NEW)) {
			start = true;
			thread.start();
		} else if (thread.getState().equals(State.TERMINATED)) {
			setMaxTime(maxTime);
			start = true;
			thread.start();
		}
	}

	public int getCount() {
		// TODO 自动生成的方法存根
		return count;
	}
}

//演示程序 Test.java
package main;

import java.util.*;
/**
 * 
 * @author Administrator 初始化玩家:创建四个玩家(包括3个电脑)
 */
public class InitPlayer {
	/**
	 * 4个玩家的信息都存放在List中,下标为0是人,其余的为电脑
	 */
	public static List<Player> players = new ArrayList<Player>();

	private static Player player = null;

	private static Player computer1 = null;

	private static Player computer2 = null;

	private static Player computer3 = null;

	public InitPlayer() {
		// 创建4个玩家
		createPlayer();
	}
	
	/**
	 * 自动打出其他玩家能碰,杠的牌
	 * @return
	 */
	public int zdchupai() {
		if(player.isRunzt()) {
			List<MahjongTile> list=player.getPlayerMaJiangs();
			//遍历自己的集合
			for (MahjongTile mahjongTile : list) {
				if(Player.frequency(computer1.getPlayerMaJiangs(), mahjongTile)>1) {
					//System.out.println(computer1+"="+list.indexOf(mahjongTile)+"="+Player.frequency(computer1.getPlayerMaJiangs(), mahjongTile));
					return list.indexOf(mahjongTile);//返回第一个出现元素 O 的位置;
				}
				if(Player.frequency(computer2.getPlayerMaJiangs(), mahjongTile)>1) {
					//System.out.println(computer2+"="+list.indexOf(mahjongTile)+"="+Player.frequency(computer2.getPlayerMaJiangs(), mahjongTile));
					return list.indexOf(mahjongTile);//返回第一个出现元素 O 的位置;
				}
				if(Player.frequency(computer3.getPlayerMaJiangs(), mahjongTile)>1) {
					//System.out.println(computer2+"="+list.indexOf(mahjongTile)+"="+Player.frequency(computer3.getPlayerMaJiangs(), mahjongTile));
					return list.indexOf(mahjongTile);//返回第一个出现元素 O 的位置;
				}
				
			}
		}
		if(computer1.isRunzt()) {
			List<MahjongTile> list=computer1.getPlayerMaJiangs();
			//遍历自己的集合
			for (MahjongTile mahjongTile : list) {
				if(Player.frequency(player.getPlayerMaJiangs(), mahjongTile)>1) {
					return list.indexOf(mahjongTile);//返回第一个出现元素 O 的位置;
				}
				if(Player.frequency(computer2.getPlayerMaJiangs(), mahjongTile)>1) {
					return list.indexOf(mahjongTile);//返回第一个出现元素 O 的位置;
				}
				if(Player.frequency(computer3.getPlayerMaJiangs(), mahjongTile)>1) {
					return list.indexOf(mahjongTile);//返回第一个出现元素 O 的位置;
				}
				
			}
		}
		if(computer2.isRunzt()) {
			List<MahjongTile> list=computer2.getPlayerMaJiangs();
			//遍历自己的集合
			for (MahjongTile mahjongTile : list) {
				if(Player.frequency(player.getPlayerMaJiangs(), mahjongTile)>1) {
					return list.indexOf(mahjongTile);//返回第一个出现元素 O 的位置;
				}
				if(Player.frequency(computer1.getPlayerMaJiangs(), mahjongTile)>1) {
					return list.indexOf(mahjongTile);//返回第一个出现元素 O 的位置;
				}
				if(Player.frequency(computer3.getPlayerMaJiangs(), mahjongTile)>1) {
					return list.indexOf(mahjongTile);//返回第一个出现元素 O 的位置;
				}
				
			}
		}
		if(computer3.isRunzt()) {
			List<MahjongTile> list=computer3.getPlayerMaJiangs();
			//遍历自己的集合
			for (MahjongTile mahjongTile : list) {
				if(Player.frequency(player.getPlayerMaJiangs(), mahjongTile)>1) {
					return list.indexOf(mahjongTile);//返回第一个出现元素 O 的位置;
				}
				if(Player.frequency(computer2.getPlayerMaJiangs(), mahjongTile)>1) {
					return list.indexOf(mahjongTile);//返回第一个出现元素 O 的位置;
				}
				if(Player.frequency(computer1.getPlayerMaJiangs(), mahjongTile)>1) {
					return list.indexOf(mahjongTile);//返回第一个出现元素 O 的位置;
				}
				
			}
		}
		
		return 0;
	}
	
	/**
	 * 检测是否有可以碰的牌
	 * @return
	 */
	public static Player touchDetection() {
		//检测是否有杠的牌 不做处理直接杠牌
		if(player.barCards()) {
			//摸牌
			player.gainMaJiang(0);
			return player;
		}
		else if(computer1.barCards()) {
			computer1.gainMaJiang(0);
			return computer1;
		}
		else if(computer2.barCards()) {
			computer2.gainMaJiang(0);
			return computer2;
		}
		else if(computer3.barCards()) {
			computer3.gainMaJiang(0);
			return computer3;
		}
		
		//检测是否有碰的牌 不做处理直接碰牌
		if(player.touchCards()) {
			
			return player;
		}
		if(computer1.touchCards()) {
			return computer1;
		}
		if(computer2.touchCards()) {
			return computer2;
		}
		if(computer3.touchCards()) {
			return computer3;
		}
		
		
		return null;

	}
	
	/**
	 * 创建4个玩家
	 */
	private void createPlayer() {
		player = new Player();
		computer1 = new Player();
		computer2 = new Player();
		computer3 = new Player();
		player.setName("玩家");
		computer1.setName("电脑1");
		computer2.setName("电脑2");
		computer3.setName("电脑3");
		players.add(player);
		players.add(computer1);
		players.add(computer2);
		players.add(computer3);
	}

	/**
	 * 输出四个玩家手中的牌
	 */
	public void printPlayer() {

		// 输出当前玩家手中的牌
		System.out.println("【当前玩家手中的牌如下:】");
		System.out.print(player);
		player.printMaJiangs();
		System.out.print(computer1);
		computer1.printMaJiangs();
		System.out.print(computer2);
		computer2.printMaJiangs();
		System.out.print(computer3);
		computer3.printMaJiangs();
	}
	
	public void printPlayer(Player players) {

		// 输出当前玩家手中的牌
		//System.out.println("【当前玩家手中的牌如下:】");
		System.out.println(players.getPlayerMaJiangs());
	}
	/**
	 * 输出四个玩家手中的牌
	 */


	/**
	 * 第一次起牌:轮流起牌,每次起4张,一共起3轮
	 */
	public void haveFirstBoard() {
		// 共3轮
		for (int i = 0; i < 3; i++) {
			// 玩家,每次起4张
			for (int j = 0; j < 4; j++) {
				player.gainMaJiang(ShuffleMahJong.maJiangsIndex);
			}
			// 电脑1,每次起4张
			for (int j = 0; j < 4; j++) {
				computer1.gainMaJiang(ShuffleMahJong.maJiangsIndex);
			}
			// 电脑2,每次起4张
			for (int j = 0; j < 4; j++) {
				computer2.gainMaJiang(ShuffleMahJong.maJiangsIndex);
			}
			// 电脑3,每次起4张
			for (int j = 0; j < 4; j++) {
				computer3.gainMaJiang(ShuffleMahJong.maJiangsIndex);
			}
		}
	}

	/**
	 * 第二次起牌:跳庄(玩家拿第1和第5张,电脑1拿第2张,电脑2拿第3张,电脑3拿第4张)
	 */
	public void haveJumpBoard() {
		player.gainMaJiang(0);
		computer1.gainMaJiang(1);
		computer2.gainMaJiang(2);
		computer3.gainMaJiang(3);
	}

	/**
	 * 翻癞子(癞子可以当成是任何一张牌)
	 */
	public void haveWildBoard() {
		System.out.println("【癞子是:" + ShuffleMahJong.maJiangs.get(5) + "】");
		// 直接移除第6张牌
		ShuffleMahJong.maJiangs.remove(5);
	}
}

package main;

import java.util.*;

/**
 * 
 * @author LiHai
 *
 */
public class MahjongStaticTool {

	static int nextPlayer = 0;

	/**
	 * 复制牌的集合
	 * 
	 * @param mahjongTiles
	 * @param indexs
	 * @return
	 */
	private static MahjongTile[] removeSomeMahjongTiles(MahjongTile[] mahjongTiles, int[] indexs) {

		/*
		 * indexs表示万筒条的大小1~9的数组; mahjongTiles.length原来长度为14 indexs.length长度为3
		 */
		int lenNew = mahjongTiles.length - indexs.length;
		// System.out.println("mahjongTiles.length=="+mahjongTiles.length+"
		// indexs.length=="+indexs.length);
		if (lenNew > 0) {
			MahjongTile[] mahjongTilesNew = new MahjongTile[lenNew];

			int index = 0;
			for (int i = 0; i < mahjongTiles.length; i++) {
				boolean isAppend = true;
				for (int j = 0; j < indexs.length; j++) {
					/*
					 * 如果i==indexs[j]该函数将不参与mahjongTilesNew的复制
					 */
					if (i == indexs[j]) {
						//System.out.println("indexs[" + i + "]==" + indexs[j] + "mahjongTiles[i]=" + mahjongTiles[i]);
						isAppend = false;
						break;
					}
				}
				if (isAppend) {
					/*
					 * 把mahjongTiles集合复制到mahjongTilesNew数组 实现删除
					 */
					mahjongTilesNew[index] = mahjongTiles[i];
					//System.out.println("mahjongTilesNew[" + index + "]==" + mahjongTilesNew[index]);
					index++;
				}
			}
			return mahjongTilesNew;
		}
		return null;
	}

	/**
	 * 比较一对将 从数组长度为arrayLen的整形数组中任意抽取两个元素, 
	 * 把所有可能的组合的索引列成一个二位数组返回出来
	 * 
	 * @param arrayLen
	 * @return
	 */
	private static int[][] siphonTwoIndexs(int arrayLen) {
		int len = (arrayLen * (arrayLen - 1)) / 2;
		if (len > 0) {
			int[][] indexs = new int[len][2];
			int index = 0;
			for (int i = 0; i < arrayLen; i++) {
				for (int j = (i + 1); j < arrayLen; j++) {
					indexs[index][0] = i;
					indexs[index][1] = j;
					index++;
				}
			}

			return indexs;
		} else {
			return null;
		}
	}

	/**
	 * 比较三张连牌或者三张同样的牌 从数组长度为arrayLen的整形数组中任意抽取两个元素, 把所有可能的组合的索引列成一个二位数组返回出来
	 * 
	 * @param arrayLen
	 * @return
	 */
	private static int[][] siphonThreeIndexs(int arrayLen) {
		int len = (arrayLen * (arrayLen - 1) * (arrayLen - 2)) / 6;
		// System.out.println("循环次数len====="+len+"="+arrayLen+"*"+(arrayLen-1)+"*"+(arrayLen-2)+"/6");
		if (len > 0) {
			int[][] indexs = new int[len][3];
			int index = 0;
			for (int i = 0; i < arrayLen; i++) {
				for (int j = (i + 1); j < arrayLen; j++) {
					for (int k = (j + 1); k < arrayLen; k++) {
						indexs[index][0] = i;
						indexs[index][1] = j;
						indexs[index][2] = k;
						// System.out.println("indexs["+index+"][0],indexs["+index+"][1],indexs["+index+"][2]="+indexs[index][0]+","+indexs[index][1]+","+indexs[index][2]);
						index++;
					}
				}
			}
			return indexs;
		} else {
			return null;
		}
	}

	/**
	 * 传进玩家牌的二维集合,和三张牌 复制集合
	 * 
	 * @param saveMahjongTileses
	 * @param mahjongTiles
	 * @return
	 */
	private static MahjongTile[][] appendSomeMahjongTiles(MahjongTile[][] saveMahjongTileses,
			MahjongTile[] mahjongTiles) {
		if (saveMahjongTileses == null) {
			MahjongTile[][] mahjongTilesesReturn = new MahjongTile[1][];
			mahjongTilesesReturn[0] = mahjongTiles;
			return mahjongTilesesReturn;
		} else {
			// 创建一个比原来集合更长的集合
			MahjongTile[][] mahjongTilesesReturn = new MahjongTile[saveMahjongTileses.length + 1][];
			/*
			 * arraycopy(Object src,int srcPos,Object dest, int destPos,int length)
			 * src表示源数组,srcPos表示源数组要复制的起始位置, desc表示目标数组,length表示要复制的长度。
			 */
			//System.arraycopy(saveMahjongTileses, 0, mahjongTilesesReturn, 0, saveMahjongTileses.length);
			mahjongTilesesReturn[saveMahjongTileses.length] = mahjongTiles;
			return mahjongTilesesReturn;
		}
	}

	public static MahjongTile[][] tryCombination(MahjongTile[] mahjongTiles, int twoNum, int threeNum) {
		// mahjongTiles表示玩家手中的所有牌的
		return MahjongStaticTool.tryCombination(mahjongTiles, twoNum, threeNum, null);
	}

	/**
	 * 把数组牌转为list牌集
	 * 
	 * @param paiArr
	 */
	public static List<Integer> arrToList(int[][] paiArr) {
		List<Integer> paiList = new ArrayList<>();
		for (int i = 0; i < paiArr.length; i++) {
			for (int j = 0; j < paiArr[i].length; j++) {
				int paiNum = paiArr[i][j];// 根据每一张牌的数量逆转
				if (paiNum <= 0) {
					continue;
				}
				for (int k = 0; k < paiArr[i][j]; k++) {
					paiList.add((i + 1) + j);
				}
			}
		}
		return paiList;
	}

	/**
	 * 判断是否胡牌的方法 mahjongTiles玩家所有的牌 twoNum表示一对将 threeNum表示3个连着的牌或者三张同样的牌
	 * 
	 * @param mahjongTiles
	 * @param twoNum
	 * @param threeNum
	 * @param saveMahjongTileses
	 * @return
	 */
	private static MahjongTile[][] tryCombination(MahjongTile[] mahjongTiles, int twoNum, int threeNum,
			MahjongTile[][] saveMahjongTileses) {
		if (mahjongTiles == null) {
			if (twoNum == 0 && threeNum == 0) {
				return saveMahjongTileses;
			} else {
				return null;
			}
		}
		// 第一次固定twoNum=1 threeNum=4
		if (mahjongTiles.length == ((twoNum * 2) + (threeNum * 3))) {

			if (threeNum > 0) {
				// 通过siphonThreeIndexs获得十三张牌的所有三张顺子或者刻子的组合
				int[][] indexs = siphonThreeIndexs(mahjongTiles.length);

				// System.out.println("indexs大小==" + indexs.length);
				for (int i = 0; i < indexs.length; i++) {
					for (int j = 0; j < indexs[i].length; j++) {
						if (i != 0) {
							// System.out.print(" ");
						}
						// System.out.print(indexs[i][j]);
					}
				}
				// 遍历indexs数组
				for (int[] index : indexs) {

					/*
					 * 如果mahjongTiles[index[0]],mahjongTiles[index[1]],
					 * mahjongTiles[index[2]]相等返回true 三张牌相同
					 * 如果mahjongTiles[index[0]],mahjongTiles[index[1]], mahjongTiles[index[2]]是顺子
					 * 返回true 三张牌为 1,2,3或者5,6,7
					 * 
					 */
					// 当出现三张同样或者顺子时
					if (mahjongTiles[index[0]].isCanThree(mahjongTiles[index[1]], mahjongTiles[index[2]])) {
//						System.out.println("mahjongTiles[" + index[0] + "]==" + mahjongTiles[index[0]]
//								+ " mahjongTiles[" + index[1] + "]==" + mahjongTiles[index[1]] + " mahjongTiles["
//								+ index[2] + "]==" + mahjongTiles[index[2]] + " mahjongTiles.length=="
//								+ mahjongTiles.length);
						// 传进一个牌的集合,三张同样的麻将
						// 利用该函数appendSomeMahjongTiles把三张牌重新复制到二维集合saveMahjongTilesesCache中
						MahjongTile[][] saveMahjongTilesesCache = appendSomeMahjongTiles(saveMahjongTileses,
								new MahjongTile[] { mahjongTiles[index[0]], mahjongTiles[index[1]],
										mahjongTiles[index[2]] });
						// 使用removeSomeMahjongTiles获得新的MahjongTile[]
						MahjongTile[][] mahjongTilesesReturn = MahjongStaticTool.tryCombination(
								removeSomeMahjongTiles(mahjongTiles, new int[] { index[0], index[1], index[2] }),
								twoNum, threeNum - 1, saveMahjongTilesesCache);
						if (mahjongTilesesReturn != null) {
							return mahjongTilesesReturn;
						}
					}
				}
			} else if (twoNum > 0) {
				// 通过该数据获得所有可能是一对 将 的组合
				int[][] indexs = siphonTwoIndexs(mahjongTiles.length);
				if (indexs == null) {

					return null;
				}
				for (int[] index : indexs) {
					if (mahjongTiles[index[0]].isCanTwo(mahjongTiles[index[1]])) {
						MahjongTile[][] saveMahjongTilesesCache = appendSomeMahjongTiles(saveMahjongTileses,
								new MahjongTile[] { mahjongTiles[index[0]], mahjongTiles[index[1]] });
						MahjongTile[][] mahjongTilesesReturn = MahjongStaticTool.tryCombination(
								removeSomeMahjongTiles(mahjongTiles, new int[] { index[0], index[1] }), twoNum - 1,
								threeNum, saveMahjongTilesesCache);
						if (mahjongTilesesReturn != null) {
							return mahjongTilesesReturn;
						}
					}
				}
			} else {
				return saveMahjongTileses;
			}
		}
		return null;
	}

	/**
	 * 测试
	 * 
	 * @param args
	 * @throws MahjongTileInitWrongTypeAndTypeIdException
	 * @throws MahjongTileInitWrongNameException
	 * @throws InterruptedException
	 */
	public static void main(String[] args) throws InterruptedException, MahjongTileInitWrongTypeAndTypeIdException {

		MahjongTile[] mahjongTiles = new MahjongTile[] {
				new MahjongTile(1, 1), 
				new MahjongTile(1, 1),
				 };

		//System.out.println("检查所有下列牌:");
		for (int i = 0; i < mahjongTiles.length; i++) {
			if (i != 0) {
				System.out.print(",");
			}
			System.out.print(mahjongTiles[i]); 
		}
		System.out.println("");
		MahjongTile[][] mahjongTileses = tryCombination(mahjongTiles, 1, 0);
		if (mahjongTileses != null) {
			System.out.println("检查通过!");
			System.out.println("组合结果如下:");
			int twoIndex = 1;
			int threeIndex = 1;
			for (MahjongTile[] mahjongTilesRow : mahjongTileses) {
				if (mahjongTilesRow.length == 2) {
					System.out.print("第" + twoIndex + "对组合:");
					for (int j = 0; j < mahjongTilesRow.length; j++) {

						if (j != 0) {
							System.out.print(",");
						}
						//System.out.print(mahjongTilesRow[j]);
					}
					System.out.println("");
					twoIndex++;
				} else if (mahjongTilesRow.length == 3) {
					System.out.print("第" + threeIndex + "趟组合:");
					for (int j = 0; j < mahjongTilesRow.length; j++) {

						if (j != 0) {
							System.out.print(",");
						}
						//System.out.print(mahjongTilesRow[j]);
					}
					System.out.println("");
					threeIndex++;
				}
			}
		} else {
			System.out.println("检查未通过!");
		}

	}
}

package main;
 
import java.util.*;
import java.util.Comparator;
 
/**
 * 单张麻将牌
 * @author LiHai
 *
 */

public class MahjongTile implements Comparable<MahjongTile>
{
	//万
    public static int MAHJONG_TILE_TYPE_TEN_THOUSAND = 1;
    //筒
    public static int MAHJONG_TILE_TYPE_PIE = 3;
    //条
    public static int MAHJONG_TILE_TYPE_STRIP = 2;
    public static int MAHJONG_TILE_TYPE_WIND = 4;
    public static int MAHJONG_TILE_TYPE_MESS = 5;
    public static int MAHJONG_TILE_TYPE_FLOWER = 6;

    /**
     * 标准麻将的各种牌的名称,该名称为一个三维数组,第一维为各套独立的名称
     * 第二维为每套名称中的不同类别,例如万和桶属于不同类型的牌
     * 第三维维具体的名称
     * String[1][1][1] 表示一万
     * String[2][1][1] 表示一万
     * String[2][2][2]表示二饼
     */
    public final static String[][][] STANDARD_MAHJONG_NAMES = {
    
        new String[][]{
            {"一万","二万","三万","四万","五万","六万","七万","八万","九万"},
            {"一条","二条","三条","四条","五条","六条","七条","八条","九条"},
            {"一桶","二桶","三桶","四桶","五桶","六桶","七桶","八桶","九桶"},
            {"东风","南风","西风","北风"},
            {"红中","发财","白板"},
            {"春","夏","秋","冬","梅","兰","竹","菊"}
        },
        new String[][]{
            {"一万","二万","三万","四万","五万","六万","七万","八万","九万"},
            {"一条","二条","三条","四条","五条","六条","七条","八条","九条"},
            {"一饼","二饼","三饼","四饼","五饼","六饼","七饼","八饼","九饼"},
            {"东风","南风","西风","北风"},
            {"红中","发财","白板"},
            {"春","夏","秋","冬","梅","兰","竹","菊"}
        }
    };
    //表示麻将种类 共两种
    private final int type;
    //表示麻将ID号 万筒条的一万还是二万
    private final int typeId;
    private final int uniqueId;
 
    
    


	public MahjongTile(int type, int typeId) throws MahjongTileInitWrongTypeAndTypeIdException
    {
        this.uniqueId = computeUniqueId(type, typeId);
        this.type = type;
        this.typeId = typeId;
    }
    
    public MahjongTile(String name) throws MahjongTileInitWrongTypeAndTypeIdException, MahjongTileInitWrongNameException
    {
        for (String[][] standardMahjongName : STANDARD_MAHJONG_NAMES)
        {
            for (int j = 0; j < standardMahjongName.length; j++)
            {
                for (int k = 0; k < standardMahjongName[j].length; k++)
                {
                    if (standardMahjongName[j][k].equals(name))
                    {
                        this.type = j + 1;
                        this.typeId = k + 1;
                        this.uniqueId = computeUniqueId(type, typeId);
                        return;
                    }
                }
            }
        }
        throw new MahjongTileInitWrongNameException(name);
    }
 
    /**
     * 排序
     */
	public int compareTo(MahjongTile o) {
		// TODO Auto-generated method stub
		return this.typeId-o.typeId;
	}
 
    private int computeUniqueId(int type, int typeId) throws MahjongTileInitWrongTypeAndTypeIdException
    {
        initCheck(type, typeId);
        if (type == MAHJONG_TILE_TYPE_TEN_THOUSAND)//MAHJONG_TILE_TYPE_TEN_THOUSAND=1
        {
            return typeId;
            //万 1 2 3 4 5 6 7 8 9
        }
        else if (type == MAHJONG_TILE_TYPE_PIE)//MAHJONG_TILE_TYPE_PIE=3
        {
            return typeId + 18;
            //筒 10 11 12 13 14 15 16 17 18
        }
        else if (type == MAHJONG_TILE_TYPE_STRIP)//2
        {
            return typeId + 9;
            //条 19 20 21 22 23 24 25 26 27 
        }
        else if (type == MAHJONG_TILE_TYPE_WIND)//4
        {
            return typeId + 27;
            //东南西北 28 29 30 31
        }
        else if (type == MAHJONG_TILE_TYPE_MESS)//5
        {
            return typeId + 31;
            //红中发财白板 32 33 34 
        }
        else
        {
            return typeId + 34;
            //35 36 37 38 39 40 41 42
        }
    }
 
    public int getType()
    {
        return type;
    }
 
    public int getTypeId()
    {
        return typeId;
    }
 
    public int getUniqueId()
    {
        return typeId;
    }
 
    private void initCheck(int type, int typeId) throws MahjongTileInitWrongTypeAndTypeIdException
    {
        if (STANDARD_MAHJONG_NAMES[0].length < type || type < 1)
        {
            throw new MahjongTileInitWrongTypeAndTypeIdException(type, typeId, true);
        }
        else if (STANDARD_MAHJONG_NAMES[0][type - 1].length < typeId || typeId < 1)
        {
            throw new MahjongTileInitWrongTypeAndTypeIdException(type, typeId, false);
        }
    }
 
    //表示百搭
    public boolean isCanAny()
    {
        if (type == 1 && typeId == 9)
        {
            return true;
        }
        return false;
    }
 
    public boolean isCanThree(MahjongTile mahjongTileOne, MahjongTile mahjongTileTwo)
    {
    	//判断第一个和第二个是否是 万筒条 的同一种类型
        if (type == mahjongTileOne.type && type == mahjongTileTwo.type)
        {
        	//判断是否是刻子
            if (typeId == mahjongTileOne.typeId && typeId == mahjongTileTwo.typeId)
            {
                return true;
            }
            //isIdLink判断是否是顺子 如果是返回true并且type不等于 4,5,6 因为4,5,6不表示万筒条
            else if (isIdLink(typeId, mahjongTileOne.typeId, mahjongTileTwo.typeId) && type != MAHJONG_TILE_TYPE_WIND && type != MAHJONG_TILE_TYPE_MESS && type != MAHJONG_TILE_TYPE_FLOWER)
            {
                return true;
            }
 
        }
        //isCanAny()表示百搭
//        if (isCanAny())
//        {
//            if (mahjongTileOne.isCanAny() || mahjongTileTwo.isCanAny())
//            {
//                return true;
//            }
//            else if (Math.abs(mahjongTileOne.typeId - mahjongTileTwo.typeId) <= 2 && mahjongTileOne.type == mahjongTileTwo.type)
//            {
//                return true;
//            }
//        }
//        else if (mahjongTileOne.isCanAny())
//        {
//            if (isCanAny() || mahjongTileTwo.isCanAny())
//            {
//                return true;
//            }
//            else if (Math.abs(typeId - mahjongTileTwo.typeId) <= 2 && type == mahjongTileTwo.type)
//            {
//                return true;
//            }
//        }
//        else if (mahjongTileTwo.isCanAny())
//        {
//            if (mahjongTileOne.isCanAny() || isCanAny())
//            {
//                return true;
//            }
//            else if ((Math.abs(typeId - mahjongTileOne.typeId) <= 2) && type == mahjongTileOne.type)
//            {
//                return true;
//            }
//        }
 
        return false;
    }
    
    public boolean isCanTwo(MahjongTile mahjongTile)
    {
        if (isCanAny() || mahjongTile.isCanAny())
        {
            return true;
        }
        else
        {
            return uniqueId == mahjongTile.uniqueId;
        }
    }
 
    //判断是否是顺子 如果是返回true
    private boolean isIdLink(int id1, int id2, int id3)
    {
        int[] ids =
        {
            id1, id2, id3
        };
        Arrays.sort(ids);
        if (ids[2] - ids[1] != 1)
        {
            return false;
        }
        else if (ids[1] - ids[0] != 1)
        {
            return false;
        }
        return true;
    }

	@Override
    public String toString()
    {
        String name = STANDARD_MAHJONG_NAMES[0][type - 1][typeId - 1];
        if (isCanAny())
        {
            name = name + "(百搭)";
        }
        return name;
    }


 
    
}

package main;
 
/**
 * 
 * @author LiHai
 *
 */
@SuppressWarnings("serial")
public class MahjongTileInitWrongNameException extends Exception
{
    private final String wrongName;
    public MahjongTileInitWrongNameException(String wrongName)
    {
        this.wrongName = wrongName;
    }
    
    public String getWrongName()
    {
        return wrongName;
    }
    
    public String[][][] standardMahjongNames()
    {
        return MahjongTile.STANDARD_MAHJONG_NAMES;
    }
}

package main;
/**
 * 麻将参数
 * @author LiHai
 *
 */
@SuppressWarnings("serial")
public class MahjongTileInitWrongTypeAndTypeIdException extends Exception
{
    private final int type;
    private final int typeId;
    private final boolean isTypeWrong;
    
    public MahjongTileInitWrongTypeAndTypeIdException(int type,int typeId,boolean isTypeWrong)
    {
        this.type = type;
        this.typeId = typeId;
        this.isTypeWrong = isTypeWrong;
    }
    
    public int type()
    {
        return type;
    }
    
    public int typeId()
    {
        return typeId;
    }
    
    public boolean isTypeWrong()
    {
        return isTypeWrong;
    }
}
package main;

import java.util.*;
/**
 * 玩家信息和牌 判断碰,杠,胡 及摸牌,出牌
 * @author LiHai
 *
 */
public class Player {

	/**
	 * 玩家姓名
	 */
	private String name;
	/**
	 * 每个玩家的牌都放在playerMaJiangs中
	 */
	private List<MahjongTile> playerMaJiangs = new ArrayList<MahjongTile>();

	/**
	 * 用来指示“每个玩家的牌”在playerMaJiangs中的下标
	 */
	private int playerMaJiangsIndex = 0;

	/**
	 * 是否到该玩家出牌 运行状态
	 */
	private boolean runzt = false;
	//玩家没胡
	private boolean hul=false;

	public boolean isHul() {
		return hul;
	}

	public void setHul(boolean hul) {
		this.hul = hul;
	}

	public boolean isRunzt() {
		return runzt;
	}

	public void setRunzt(boolean runzt) {
		this.runzt = runzt;
	}

	public int getPlayerMaJiangsIndex() {
		return playerMaJiangsIndex;
	}

	public void setPlayerMaJiangsIndex(int playerMaJiangsIndex) {
		this.playerMaJiangsIndex = playerMaJiangsIndex;
	}

	public Player() {
		super();
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public List<MahjongTile> getPlayerMaJiangs() {
		return playerMaJiangs;
	}

	public void setPlayerMaJiangs(List<MahjongTile> playerMaJiangs) {
		this.playerMaJiangs = playerMaJiangs;
	}

	@Override
	public String toString() {
		return "[" + name + "]";
	}

	
	
	/**
	 *  摸牌:从ShuffleMaJiang中的maJiangs中取一粒麻将,放入到自己的playerMaJiangs中
	 * @param index
	 * @return
	 */
	public boolean gainMaJiang(int index) {

		// System.out.println("剩余 "+ShuffleMahJong.maJiangs.size()+" 张牌");
		if (ShuffleMahJong.maJiangs.size() != 0) {
			if (ShuffleMahJong.maJiangs.get(index) != null) {
				playerMaJiangs.add(playerMaJiangsIndex, ShuffleMahJong.maJiangs.get(index));
				playerMaJiangsIndex++;
				// 原来的ShuffleMaJiang的maJiangs中的牌减少这一张
				//System.out.println(this.getName() + "摸到: " +ShuffleMahJong.maJiangs.get(index));
				ShuffleMahJong.maJiangs.remove(index);
			}
			
		} else {
			System.out.println("没牌了");
			return true;
		}
		return false;
	}

	/**
	 * 打牌:从自己的playerMaJiangs中取一张牌,放入到ShuffleMaJiang中的river中
	 * @param index
	 * @return
	 */
	public MahjongTile discardMaJiang(int index) {
		// System.out.println(playerMaJiangs + " 数入的数" + index);
		if ((index > playerMaJiangs.size()) || (index < 0)) {
			System.out.println(index + "输入的牌不存在" + playerMaJiangs.size());
			return null;
		}
		// 从自己的playerMaJiangs中取一粒牌,放入到ShuffleMaJiang中的river中

		ShuffleMahJong.river.add(ShuffleMahJong.riverIndex, playerMaJiangs.get(index));
		ShuffleMahJong.riverIndex++;
		// 自己的playerMaJiangs中减少这一粒牌
		//System.out.println(this.getName() + "打出:" + playerMaJiangs.get(index));
		// playerMaJiangs.remove(index);
		// 出牌后下标减少
		playerMaJiangsIndex--;

		return playerMaJiangs.get(index);
	}

	/**
	 *  该玩家拥有的牌进行排序
	 */
	public void printMaJiangs() {
		// 第一次排序牌的顺序
		// Collections.sort(playerMaJiangs);
		// 第一次排序牌的顺序
		for (int i = 0; i < playerMaJiangs.size(); i++) {

			for (int j = 0; j < playerMaJiangs.size() - 1 - i; j++) {
				if (playerMaJiangs.get(j).getType() > playerMaJiangs.get(j + 1).getType()) {
					MahjongTile temp = playerMaJiangs.get(j);
					playerMaJiangs.set(j, playerMaJiangs.get(j + 1));
					playerMaJiangs.set(j + 1, temp);
				}
			}
		}
		// 第二次排序牌数值小到大,例如:从1万到9万排序
		for (int i = 0; i < playerMaJiangs.size(); i++) {

			for (int j = 0; j < playerMaJiangs.size() - 1 - i; j++) {
				if (playerMaJiangs.get(j).getType() == playerMaJiangs.get(j + 1).getType()) {
					MahjongTile temp = playerMaJiangs.get(j);
					if (playerMaJiangs.get(j).getTypeId() > playerMaJiangs.get(j + 1).getTypeId()) {
						playerMaJiangs.set(j, playerMaJiangs.get(j + 1));
						playerMaJiangs.set(j + 1, temp);
					}

				}
			}
		}

		// 输出玩家拥有的牌
		for (MahjongTile maJiang : playerMaJiangs) {

			int type = maJiang.getType();
			// System.out.print(maJiang + ",");

		}
		// System.out.println("共" + playerMaJiangs.size() + "张");

	}

	/**
	 * 碰牌:河里刚打出的牌,在玩家手中有两张同样的牌,就可以碰牌
	 * @return
	 */
	public boolean touchCards() {
		// 获取河里刚打出的牌
		MahjongTile riverLastJiang = ShuffleMahJong.river.get(ShuffleMahJong.riverIndex - 1);
		// 遍历自己的所有的牌,是否包含上面的牌,并且有两张
		int frequency = frequency(playerMaJiangs, riverLastJiang);

		if (frequency >= 2&&!runzt) {
			Iterator<MahjongTile> it = playerMaJiangs.iterator();
			while (it.hasNext()) {
				MahjongTile mj = it.next();
				if ((mj.getType() == riverLastJiang.getType()) && (mj.getTypeId() == riverLastJiang.getTypeId())) {
					it.remove();
					System.out.println(this.name + "【碰牌成功】【删牌】"+mj);
					playerMaJiangsIndex--;
				}
			}

			return true;
		} else {
			// System.out.println("河里的牌=" + riverLastJiang+" "+this.name + "该牌数量=" +
			// frequency+"【碰牌失败】");
			return false;
		}

	}

	/**
	 * 取得玩家相同牌的数量
	 * @param c
	 * @param o
	 * @return
	 */
	public static int frequency(List<MahjongTile> c, MahjongTile o) {

		int result = 0;
		if (o == null) {
			for (MahjongTile e : c)
				if (e == null)
					result++;
		} else {
			for (MahjongTile e : c)
				if ((o.getType() == e.getType()) && (o.getTypeId() == e.getTypeId()))
					result++;
		}
		return result;
	}

	/**
	 * 杠牌:河里刚打出的牌,在玩家手中有3张同样的牌,就可以杠牌
	 * @return
	 */
	public boolean barCards() {
		// 获取河里刚打出的牌
		MahjongTile riverLastJiang = ShuffleMahJong.river.get(ShuffleMahJong.riverIndex - 1);
		// 遍历自己的所有的牌,是否包含上面的牌,并且有三张
		int frequency = frequency(playerMaJiangs, riverLastJiang);

		if (frequency >= 3&&!runzt) {
			Iterator<MahjongTile> it = playerMaJiangs.iterator();
			while (it.hasNext()) {
				MahjongTile mj = it.next();
				if ((mj.getType() == riverLastJiang.getType()) && (mj.getTypeId() == riverLastJiang.getTypeId())) {
					System.out.println(name + "【杠牌成功】【删除】"+mj);
					it.remove();
					playerMaJiangsIndex--;
				}
			}
			return true;
		} else {
			// System.out.println("河里的牌=" + riverLastJiang+" "+this.name + "该牌数量=" +
			// frequency+"【碰牌失败】");
			return false;
		}

	}

	/**
	 * 胡牌:满足胡牌的规则
	 * @return
	 */
	public boolean huCards() {
		int mjnumber = 0;
		MahjongTile[] mahjong = playerMaJiangs.toArray(new MahjongTile[1]);
		if (mahjong.length == 14) {
			mjnumber = 4;
		} else if (mahjong.length == 11) {
			mjnumber = 3;
		} else if (mahjong.length == 8) {
			mjnumber = 2;
		} else if (mahjong.length == 5) {
			mjnumber = 1;
		} else if (mahjong.length == 3) {
			mjnumber = 0;
		} else {
			
		}
		// System.out.println("【留局】="+mjnumber);
		MahjongTile[][] mahjongTileses = MahjongStaticTool.tryCombination(mahjong, 1, mjnumber);

		if (mahjongTileses != null) {
			System.out.println(this.getName() + "胡了!");
			hul=true;
			int twoIndex = 1;
			int threeIndex = 1;
			for (MahjongTile[] mahjongTilesRow : mahjongTileses) {
//				if (mahjongTilesRow.length == 2) {
//					System.out.print("第" + twoIndex + "对组合:");
//					for (int j = 0; j < mahjongTilesRow.length; j++) {
//
//						if (j != 0) {
//							System.out.print(",");
//						}
//						System.out.print(mahjongTilesRow[j]);
//					}
//					System.out.println("");
//					twoIndex++;
//				} else if (mahjongTilesRow.length == 3) {
//					System.out.print("第" + threeIndex + "趟组合:");
//					for (int j = 0; j < mahjongTilesRow.length; j++) {
//
//						if (j != 0) {
//							System.out.print(",");
//						}
//						System.out.print(mahjongTilesRow[j]);
//					}
//					System.out.println("");
//					threeIndex++;
//				}
			}
			return true;
		} else {
			// System.out.println("\n没有胡!");
			return false;
		}

	}

	/**
	 * 删除该牌
	 */
	public void Remove(int integer) {
		playerMaJiangs.remove(integer);
	}
}
package main;
import java.util.*;

/**
 * 创建麻将
 * @author LiHai
 *
 */
public class ShuffleMahJong {
    /**
     * 牌局中所有的牌:使用List放所有的牌
     */
    public static List<MahjongTile> maJiangs=new ArrayList<MahjongTile>();
    /**
     * 用来指示“牌局中所有的牌”的当前下标
     */
    public static int maJiangsIndex=0;
    /**
     * 河:用来存放玩家打出的牌
     */
    public static List<MahjongTile> river=new ArrayList<MahjongTile>();
    /**
     * 用来指示“河”的当前下标
     */
    public static int riverIndex=0;
    
    public static List<MahjongTile> getMaJiangs() {
		return maJiangs;
	}

	public ShuffleMahJong() throws InterruptedException, MahjongTileInitWrongTypeAndTypeIdException {
        //创建一副麻将
        createMahJongs();
        //输出此时的所有的牌
        System.out.println("【初始化所有的牌:】");
       printMahJongs();
        //把初始牌打乱
        chaosMahJongs();
        //输出此时的所有的牌
        //System.out.println("【洗牌后所有的牌:】");
        printMahJongs();
       // System.out.println("【按照东南西北四个方向输出的牌(牌局里的牌):】");
        //printMaJiangs(1);
        //下标恢复
        riverIndex=0;
        maJiangsIndex=135;
    }

	/*
	 * 创建一副麻将
	*/
    private void createMahJongs() throws MahjongTileInitWrongTypeAndTypeIdException {
    	MahjongTile mj=null;
    	//i代表万筒条 j代表1~9 k代表有几张同样的牌
		for(int i=1;i<=3;i++) {
			if(i<=3) {
			for(int j=1;j<=4;j++) {
				for(int k=1;k<=30;k++) {
					mj=new MahjongTile(i,j);
					maJiangs.add(maJiangsIndex,mj);
					maJiangsIndex++;
				}
			}
			}else if(i==4) {
				//东南西北
				for(int j=1;j<=4;j++) {
					for(int k=1;k<=4;k++) {
						mj=new MahjongTile(i,j);
						maJiangs.add(maJiangsIndex,mj);
						maJiangsIndex++;
					}
				}
			}else if(i==5) {
				//红中发财白板
				for(int j=1;j<=3;j++) {
					for(int k=1;k<=4;k++) {
						mj=new MahjongTile(i,j);
						maJiangs.add(maJiangsIndex,mj);
						maJiangsIndex++;
					}
				}
			}
		}
		
		
    }
    
    /**
     * 整副麻将
     */
    public static void printMahJongs() {
    	for (Iterator iterator = maJiangs.iterator(); iterator.hasNext();) {
			MahjongTile mahjongTile = (MahjongTile) iterator.next();
			//System.out.print(mahjongTile+"="+mahjongTile.getType()+"-"+mahjongTile.getTypeId()+"-"+mahjongTile.getUniqueId()+"   ");
		}
    	System.out.println("剩:"+maJiangs.size()+"");
    }
    
    /**
     * 把初始牌打乱
     */
    private void chaosMahJongs() {
    	Collections.shuffle(maJiangs);
    }

	/**
     * 由于第一次起牌很有可能是在整副牌的中间位置开始起牌的,然后再向后起牌。此时需要把起始位置前的牌,重新放到maJiangs中的最后,来保证整副牌的完整性
     * @throws InterruptedException 
     */
    public static void moveMahJongs() throws InterruptedException{
        //把开始位置前的牌复制到list的末尾
        for (int i = 0; i < maJiangsIndex; i++) {
            maJiangs.add(maJiangs.size(),maJiangs.get(i));
        }
        //复制后,把开始位置前的牌删除
        for (int i = 0; i < maJiangsIndex; i++) {
            maJiangs.remove(i);
        }
        //输出移动位置后的整副牌
        System.out.println("【移动位置后的整副牌:】");
        printMahJongs();
        //移动过后,起始位置变为了第一张牌,需要把下标复位
        maJiangsIndex=0;
    }
}

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值