不多说,拷贝就能用

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 stubMahJongGame 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() {@Overridepublic 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=4if (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 stubreturn 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;}}//判断是否是顺子 如果是返回trueprivate 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;}@Overridepublic 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;}@Overridepublic 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;}
}

jpanel麻将自动打牌,碰牌,杠牌相关推荐

  1. swift--广东麻将v2.0(带胡牌、听牌算法和自动打牌功能)

    本程序实现了广东麻将的全部功能:自动摸牌.打牌.碰.杠.听牌.胡牌(其中庄家手动打牌,其它电脑玩家自动打牌),具体功能有: 系统通过骰子确定庄家,然后发牌,最开始从庄家手动打牌. 可以碰,杠,不能吃牌 ...

  2. 麻将算法(三)碰牌以及杠牌

    洗牌,接牌都有了,那就再来个扔牌.扔牌的思路:如果传入的时牌索引直接找到手牌中的这个位置,将个数-1:如果传入的是牌值,通过牌型转换后再进行以上操作:     public static void R ...

  3. java判断麻将听牌_打麻将怎么知道别人是否听牌?这四个细节要牢记

    原标题:打麻将怎么知道别人是否听牌?这四个细节要牢记 在麻将桌上想要达到胡牌的目的,首先需要听牌,但是听牌并不能保证自己可以多赢.只有在了解别家是否听牌的情况下,根据牌局状况进行调整,才能让自己赢牌的 ...

  4. C++实现麻将基本听牌胡牌的算法

    #include <iostream> #include <vector> #include <algorithm> #include <chrono> ...

  5. 百思买禁售华为手机;百度获首批自动驾驶路测号牌;美团打车上线首日被约谈丨价值早报

    第[898]期早报由[周五]赞助播出 01 今日头条 "美国梦"再受挫,百思买将停止销售华为手机 继美国政府部门封杀华为后,这家中国智能手机巨头又在零售商处碰壁. 根据科技媒体CN ...

  6. 麻将高效鬼牌胡牌算法(C++版)

    最近做的一个麻将里面有双鬼牌的玩法,即为8张鬼牌,第一反应是采用N重循环把鬼牌变成一张张牌去遍历是否能胡牌,实际测试在5张牌鬼牌的情况得出结果就需要差不多5,6分钟. 因此自己做了一套用凑牌的方式去判 ...

  7. python tkinter出牌洗牌

    python tkinter 出牌洗牌 利用Tkinter模块设计出扑克牌发牌窗体程序,要求4名牌手打牌,计算机随机将52张牌(不含大小王)发给4名牌手,在屏幕上显示每位牌手的牌.程序运行结果如图所示 ...

  8. php 108张牌洗牌,完美洗牌原理大揭秘 手把手图文教程!呕心沥血的超级干货...

    原标题:完美洗牌原理大揭秘 & 手把手图文教程!呕心沥血的超级干货 先感慨一下,昨晚写到半夜,今天又修改了很多遍,我终于把这篇文章写完了. 然后自夸一下,我敢保证,你从来没有看过像这样的完美洗 ...

  9. java斗地主怎么出牌_斗地主滑动选牌出牌(Cocos Creator)

    本文主要讲解以下几个方面: card model 滑动处理 阴影 选择 出牌 Card Model 首先,牌有两个属性:数字.花型: ps:本文现在是,用数字和花型来组成一张牌,有空可以再用另一种形式 ...

最新文章

  1. 用飞桨做自然语言处理:神经网络语言模型应用实例
  2. 23种设计模式之外观模式(Facade)
  3. MySql中如果某一列中含有NULL,那么包含该列的索引就无效了?
  4. 自定义的OnFileSaveAs函数无法响应
  5. P3174 [HAOI2009]毛毛虫(树形dp)
  6. word List 31
  7. Docker (1) 基本概念和安装
  8. 首届React开发者大会于2018年8月18日在广州举办
  9. Laravel核心解读--Database(四) 模型关联
  10. 一台linux服务器配置多个tomcat应用
  11. Web—sublime安装包、自动生成代码、使用Emmet插件快速编写CSS样式、emmet(快速开发)的使用
  12. 20050611:超级伙伴?
  13. xp系统计算机启动时灰色界面,windows xp系统下屏幕开始按钮变成灰色怎么处理
  14. $.ajax.submit,jQuery中的AjaxSubmit使用讲解
  15. CSS font-family字体大合集
  16. 静默安装oracle11,Oracle11g静默安装
  17. 计算机组装工具以及装机流程,如何组装电脑,图文教程详解电脑组装全过程
  18. (Ⅱ)NexT主题的优化定制修改指南
  19. 小布语音下载安装_oppo语音助手小布小冰安装包app
  20. c语言next函数定义,c语言的数据结构中,next是如何指向下一个元素的?

热门文章

  1. 华为android怎么玩,如何在计算机上使用Android模拟器玩华为帐户手机游戏? ---已回复...
  2. 打豆豆游戏c语言编程,C语言程序打豆豆(函数版)分享!
  3. Unity3D插件 AnyPortrait 2D骨骼动画制作
  4. mysql error 1146错误解决办法
  5. python千锋培训地址
  6. 大数据之Hive函数及案例
  7. mysql中where子句不区分大小写
  8. 夏普电视显示服务器连线异常,夏普电视黑屏的原因?夏普电视常见故障!
  9. windows安装nginx莫名其妙 CreateFile()权限不够创建问题
  10. 软RAID 0的技术概要及实现 v0.1b