用Java实现一个简易的炸金花小游戏
最近闲暇时间写了个用Java实现的简易版的炸金花小游戏,还是很有趣的,下面具体来介绍下具体实现。
下面这个是初始化页面。
一、设计思路
1、首先要了解炸金花的游戏规则,针对整个游戏过程来考虑。从游戏开始后的抽牌选出庄家,再到洗牌及发牌阶段,接着投注或比牌,最终决出胜者。
2、在这整个过程中需要涉及洗牌算法,及比牌时的规则编写,电脑端投注或比牌等一系列操作。
3、在整个过程中需要考虑到各种情况,比如弃牌后不能再参与,首轮不能直接比牌等等。
游戏实际运行主界面如下:
二、代码实现:
1.初始化过程中的选出庄家,代码如下:
public void initGame() {Random rand=new Random();List<Integer> reduce=new ArrayList<>();if(this.t!=null) {this.t.isPublish = true;}for(int i=0;i<playerList.length;i++) {int j=0;if(reduce.isEmpty()) {j=rand.nextInt(card.length);reduce.add(j);}else {j=rand.nextInt(card.length);while(reduce.contains(j)) {j=rand.nextInt(card.length);}reduce.add(j);} switch (i) {case 0:CommonUtil.move(card[j], card[j].getLocation(), new Point(100, 200));card[j].turnFront();break;case 1:CommonUtil.move(card[j], card[j].getLocation(), new Point(390, 515));card[j].turnFront();break;case 2:CommonUtil.move(card[j], card[j].getLocation(), new Point(800, 200));card[j].turnFront();break;case 3: CommonUtil.move(card[j], card[j].getLocation(), new Point(390, 60));card[j].turnFront();break;}playerList[i].add(card[j]);container.setComponentZOrder(card[j], 0);}try {Thread.sleep(2000);} catch (InterruptedException e) {return;}if(this.t!=null) {this.t.isPublish = false;}confirmBanker(playerList);for(Integer index : reduce) { card[index].turnRear();card[index].setLocation(400, 250);}for(int i=0;i<inigoldLabel.length;i++) {inigoldLabel[i].setVisible(true);container.setComponentZOrder(inigoldLabel[i],0);playerGold[i]-=initGold;playergoldLabel[i].setText(playerGold[i]+"");}//设置开、放位置openCardIcon[0].setLocation(95, 185);quitCardIcon[0].setLocation(135, 185);//openCardIcon[1].setLocation(125, 210);quitCardIcon[1].setLocation(545, 520);openCardIcon[2].setLocation(795, 185);quitCardIcon[2].setLocation(835, 185);openCardIcon[3].setLocation(535, 80);quitCardIcon[3].setLocation(575, 80);}
2.选出庄家后开始发牌,代码如下:
public void publishCard() {for(int i=0;i<4;i++) {isFirst[i]=false;currPlayerGold[i]=10;}int t=0;int count=0;if(this.t!=null) {this.t.isPublish = true;}for(int i=currIndex;i<card.length;i++) {if(count==12) {currIndex=i-1;break;}switch (t++%4) {case 0:CommonUtil.move(card[i], card[i].getLocation(), new Point(90, 250+i*4));playerList[0].add(card[i]);break;case 1:CommonUtil.move(card[i], card[i].getLocation(), new Point(420+i*6, 510));playerList[1].add(card[i]);break;case 2:CommonUtil.move(card[i], card[i].getLocation(), new Point(810, 250+i*4));playerList[2].add(card[i]);break;case 3:CommonUtil.move(card[i], card[i].getLocation(), new Point(420+i*6, 50));playerList[3].add(card[i]);break;}container.setComponentZOrder(card[i], 0);count++;}if(this.t!=null) {this.t.isPublish = false;}for(int i=0;i<4;i++) {CommonUtil.cardSort(playerList[i]);CommonUtil.rePosition(playerList[i], i,this);} if(bankerFlag==1) {container.setComponentZOrder(laid,0);laid.setVisible(true);}if(bankerFlag==1) {time[1].setVisible(true); }}
3.在比牌时需要判断双方之间牌面大小,代码实现:
public static int checkCards(List<Card> clist,List<Card> chooselist) {CardType cType=judgeCard(clist);CardType chooseType=judgeCard(chooselist);if(cType==CardType.c3 && getValue(clist.get(0))==14) {return 1;}if(chooseType==CardType.c3 && getValue(chooselist.get(0))==14) {return 0;}if(cType==CardType.c3 && chooseType!=CardType.c3) {return 1;}if(cType!=CardType.c3 && chooseType==CardType.c3) {return 0;}if(cType==chooseType) {if(cType==CardType.c3 && getValue(clist.get(0))>getValue(chooselist.get(0))) {return 1;}else if(cType==CardType.c2) {List<Card> c1=getOrder(clist);List<Card> c2=getOrder(chooselist);if(getValue(c1.get(0))>getValue(c2.get(0))) {return 1;}if(getValue(c1.get(0))==getValue(c2.get(0))) {//比较大小、花色if(getValue(c1.get(1))==getValue(c2.get(1))) {if(getColor(c1.get(1))<getColor(c2.get(1))) {return 1;}}else {if(getValue(c1.get(1))>getValue(c2.get(1))) {return 1;}}}else {if(getValue(c1.get(0))>getValue(c2.get(0))) {return 1;}}}else if(cType==CardType.c30123) {if(getValue(clist.get(0))>getValue(chooselist.get(0))) {return 1;}else {if(getValue(clist.get(0))==getValue(chooselist.get(0))) {//相同if(getColor(clist.get(0))<getColor(chooselist.get(0))) {return 1;}}}}else if(cType==CardType.c30 || cType==CardType.c1) {if(isSameCard(clist, chooselist)) {if(getColor(clist.get(0))<getColor(chooselist.get(0))) {return 1; }}else {return compareCard(clist, chooselist);}}else if(cType==CardType.c123) {if(getValue(clist.get(0))>getValue(chooselist.get(0))) {return 1;}} }else {if(cType==CardType.c30123) {return 1;}if(cType==CardType.c30 && chooseType!=CardType.c30123) {return 1;}if(cType==CardType.c123 && chooseType!=CardType.c30123 && chooseType!=CardType.c30) {return 1;}if(cType==CardType.c2 && chooseType!=CardType.c30123 && chooseType!=CardType.c30 && chooseType!=CardType.c123) {return 1;}}return 0;}
接着编写Swing主界面:
public class GameMain extends JFrame implements ActionListener,MouseListener{private static final long serialVersionUID = 1L;public Container container=null;int initGold=10;int[] playerGold=new int[4];int[] currPlayerGold=new int[4];//每轮投入金币数int[] currRoundPlayerGold = new int[4];JMenuItem restart,exit,about;JPanel goldPanel;//比牌panelJPanel comparePanel;JLabel[] goldLabel=new JLabel[4];JLabel[] compareLabel=new JLabel[4];JLabel[] inigoldLabel=new JLabel[4];JLabel[] playergoldLabel=new JLabel[4];public static final int START=0;public static final int RUNNING=1;public static final int OVER=2;public static int state=START;JButton laid,addLaid,followLaid,compareCard,openCard,discard;int bankerFlag;boolean nextPlayer;boolean laidIsClick=false;boolean addlaidIsClick=false;boolean compareCardIsClick=false;int currIndex=0;JLabel banker;JLabel[] openCardIcon=new JLabel[4];JLabel[] quitCardIcon=new JLabel[4];int[] openFlag=new int[4];int[] quitFlag=new int[4];List<Card> playerList[]=new ArrayList[4];Card[] card=new Card[52];JTextField[] time=new JTextField[4];JLabel jl=null;JMenuBar jMenuBar=null;Timer t;Thread thread;JLabel[] player=new JLabel[4];boolean[] isFirst=new boolean[4];int turn;int roundNum=1;public GameMain() throws InterruptedException {init();setMenu();this.setVisible(true);initCard();state = RUNNING;this.t=new Timer(this, 10,true);SwingUtilities.invokeLater(new Runnable() { @Overridepublic void run() {thread=new Thread(t);thread.start(); }});}public void initCard() {int count=0;for(int i=1;i<=4;i++) {for(int j=1;j<=13;j++) {card[count]=new Card(i+"-"+j, false);card[count].setLocation(350, 200);card[count].setVisible(false);container.add(card[count]);count++;}}Random rand=new Random();for(int i=0;i<card.length;i++) {int j=rand.nextInt(card.length-i);Card k=card[i];card[i]=card[j];card[j]=k;}}public void init() {container=this.getContentPane();this.setTitle("炸金花");this.setSize(900, 506);this.setLocationRelativeTo(getOwner());this.setResizable(false);container.setLayout(null);container.setBackground(new Color(80, 90, 255));this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);jl=new JLabel(new ImageIcon("images/金花.png"));jl.setSize(900, 506);jl.setVisible(true);//jl.addMouseListener(this);container.add(jl);}public void setMenu() {jMenuBar=new JMenuBar();JMenu game=new JMenu("游戏");JMenu help=new JMenu("帮助");restart=new JMenuItem("重新开始");exit=new JMenuItem("退出");about=new JMenuItem("关于");exit.addActionListener(this);about.addActionListener(this);restart.addActionListener(this);game.add(restart);game.add(exit);help.add(about);jMenuBar.add(game);jMenuBar.add(help);jMenuBar.setVisible(false);this.setJMenuBar(jMenuBar);laid=new JButton("下注");addLaid=new JButton("加注");followLaid=new JButton("跟注");compareCard=new JButton("比牌");openCard=new JButton("看牌");discard=new JButton("弃牌");laid.setBounds(350, 455, 60, 20);laid.addActionListener(this);laid.setFocusPainted(false);laid.setVisible(false);container.add(laid);addLaid.setBounds(420, 455, 60, 20);addLaid.addActionListener(this);addLaid.setFocusPainted(false);addLaid.setVisible(false); container.add(addLaid);followLaid.setBounds(490, 455, 60, 20);followLaid.addActionListener(this);followLaid.setFocusPainted(false);followLaid.setVisible(false); container.add(followLaid);compareCard.setBounds(560, 455, 60, 20);compareCard.addActionListener(this);compareCard.setFocusPainted(false);compareCard.setVisible(false); container.add(compareCard);openCard.setBounds(630, 455, 60, 20);openCard.addActionListener(this);openCard.setFocusPainted(false);openCard.setVisible(false); container.add(openCard);discard.setBounds(700, 455, 60, 20);discard.addActionListener(this);discard.setFocusPainted(false);discard.setVisible(false);container.add(discard);goldPanel=new JPanel();goldPanel.setVisible(false);goldPanel.setBounds(300, 415, 240, 50);goldPanel.setOpaque(false);container.add(goldPanel);comparePanel = new JPanel();comparePanel.setVisible(false);comparePanel.setBounds(300, 415, 240, 50);comparePanel.setOpaque(false);container.add(comparePanel);for(int i=0;i<4;i++) {time[i]=new JTextField("倒计时:");time[i].setVisible(false);container.add(time[i]);player[i]=new JLabel(new ImageIcon("images/玩家"+i+".png"));player[i].setVisible(false);container.add(player[i]);openCardIcon[i]=new JLabel(new ImageIcon("images/开.png"));openCardIcon[i].setSize(40, 40);openCardIcon[i].setVisible(false);container.add(openCardIcon[i]);quitCardIcon[i]=new JLabel(new ImageIcon("images/放弃.png"));quitCardIcon[i].setSize(40, 40);quitCardIcon[i].setVisible(false);container.add(quitCardIcon[i]);ImageIcon originalGoldIcon = new ImageIcon("images/gold.png");Image goldImage = originalGoldIcon.getImage();ImageIcon resizedGoldIcon = new ImageIcon(goldImage.getScaledInstance(25, 25, Image.SCALE_SMOOTH));goldLabel[i]=new JLabel((i+1)+"X", resizedGoldIcon, SwingConstants.CENTER);goldLabel[i].setBounds(i*65, 5, 45, 25);goldPanel.add(goldLabel[i]);goldLabel[i].addMouseListener(this);if (i!=1) {compareLabel[i]=new JLabel("玩家"+i);compareLabel[i].setForeground(Color.CYAN);compareLabel[i].setFont(new Font("黑体",Font.BOLD,13));if (i>0) {compareLabel[i].setBounds((i-1)*65, 5, 45, 25);}else {compareLabel[i].setBounds(i*65, 5, 45, 25);}compareLabel[i].setVisible(false);comparePanel.add(compareLabel[i]);}ImageIcon originalInitIcon = new ImageIcon("images/gold.png");Image initImage = originalInitIcon.getImage();ImageIcon resizedIcon = new ImageIcon(initImage.getScaledInstance(30, 30, Image.SCALE_SMOOTH));inigoldLabel[i]=new JLabel(initGold+"", resizedIcon, SwingConstants.CENTER);inigoldLabel[i].setFont(new Font("黑体",Font.BOLD,14));inigoldLabel[i].setForeground(Color.yellow);inigoldLabel[i].setVisible(false);container.add(inigoldLabel[i]);}inigoldLabel[0].setBounds(220, 280, 60, 40);inigoldLabel[1].setBounds(390, 350, 60, 40);inigoldLabel[2].setBounds(620, 280, 60, 40);inigoldLabel[3].setBounds(390, 205, 60, 40);time[0].setBounds(175, 235, 120, 20);time[1].setBounds(360, 395, 120, 20);time[2].setBounds(610, 230, 120, 20);time[3].setBounds(400, 165, 120, 20);}public void startGame() {container.remove(jl);this.setSize(1050, 720);jl = new JLabel(new ImageIcon("images/back.jpg"));jl.setSize(1050, 720);jl.setVisible(true);container.add(jl, 0);this.setLocationRelativeTo(getOwner());jMenuBar.setVisible(true);for (int i = 0; i < card.length; i++) {card[i].setVisible(true);}player[0].setBounds(30, 250, 50, 50);player[1].setBounds(330, 535, 50, 50);player[2].setBounds(740, 250, 50, 50);player[3].setBounds(330, 90, 50, 50);for (int i = 0; i < 4; i++) {playerList[i] = new ArrayList<>();container.setComponentZOrder(player[i], 0);player[i].setVisible(true);playerGold[i] = 1000;ImageIcon originalIcon = new ImageIcon("images/gold.png");Image image = originalIcon.getImage();ImageIcon resizedIcon = new ImageIcon(image.getScaledInstance(20, 20, Image.SCALE_SMOOTH));playergoldLabel[i] = new JLabel(playerGold[i] + "", resizedIcon, SwingConstants.CENTER);playergoldLabel[i].setVisible(true);playergoldLabel[i].setFont(new Font("黑体", Font.BOLD, 13));playergoldLabel[i].setForeground(Color.yellow);container.add(playergoldLabel[i]);container.setComponentZOrder(playergoldLabel[i], 0);}playergoldLabel[0].setBounds(20, 225, 60, 20);playergoldLabel[1].setBounds(320, 510, 60, 20);playergoldLabel[2].setBounds(730, 225, 60, 20);playergoldLabel[3].setBounds(320, 65, 60, 20);ImageIcon originalBankerIcon = new ImageIcon("images/庄主.png");Image originalBankerImage = originalBankerIcon.getImage();Image newBankerImage = originalBankerImage.getScaledInstance(25, 25, Image.SCALE_SMOOTH);ImageIcon resizeBankerIcon = new ImageIcon(newBankerImage);banker = new JLabel(resizeBankerIcon);banker.setSize(45, 40);banker.setVisible(false);container.add(banker);}public void initGame() {Random rand=new Random();List<Integer> reduce=new ArrayList<>();if(this.t!=null) {this.t.isPublish = true;}for(int i=0;i<playerList.length;i++) {int j=0;if(reduce.isEmpty()) {j=rand.nextInt(card.length);reduce.add(j);}else {j=rand.nextInt(card.length);while(reduce.contains(j)) {j=rand.nextInt(card.length);}reduce.add(j);} switch (i) {case 0:CommonUtil.move(card[j], card[j].getLocation(), new Point(100, 200));card[j].turnFront();break;case 1:CommonUtil.move(card[j], card[j].getLocation(), new Point(390, 515));card[j].turnFront();break;case 2:CommonUtil.move(card[j], card[j].getLocation(), new Point(800, 200));card[j].turnFront();break;case 3: CommonUtil.move(card[j], card[j].getLocation(), new Point(390, 60));card[j].turnFront();break;}playerList[i].add(card[j]);container.setComponentZOrder(card[j], 0);}try {Thread.sleep(2000);} catch (InterruptedException e) {return;}if(this.t!=null) {this.t.isPublish = false;}confirmBanker(playerList);for(Integer index : reduce) { card[index].turnRear();card[index].setLocation(400, 250);}for(int i=0;i<inigoldLabel.length;i++) {inigoldLabel[i].setVisible(true);container.setComponentZOrder(inigoldLabel[i],0);playerGold[i]-=initGold;playergoldLabel[i].setText(playerGold[i]+"");}//设置开、放位置openCardIcon[0].setLocation(95, 185);quitCardIcon[0].setLocation(135, 185);//openCardIcon[1].setLocation(125, 210);quitCardIcon[1].setLocation(545, 520);openCardIcon[2].setLocation(795, 185);quitCardIcon[2].setLocation(835, 185);openCardIcon[3].setLocation(535, 80);quitCardIcon[3].setLocation(575, 80);}public void confirmBanker(List<Card> playerList[]) {int role= CommonUtil.compareCardSize(playerList);bankerFlag=role;switch (bankerFlag) {case 0:banker.setLocation(20, 185);break;case 1:banker.setLocation(320, 470);break;case 2:banker.setLocation(730, 185);break;case 3:banker.setLocation(320, 25);break;}banker.setVisible(true);container.setComponentZOrder(banker,0);for(int i=0;i<4;i++) {playerList[i].clear();}}public void publishCard() {for(int i=0;i<4;i++) {isFirst[i]=false;currPlayerGold[i]=10;}int t=0;int count=0;if(this.t!=null) {this.t.isPublish = true;}for(int i=currIndex;i<card.length;i++) {if(count==12) {currIndex=i-1;break;}switch (t++%4) {case 0:CommonUtil.move(card[i], card[i].getLocation(), new Point(90, 250+i*4));playerList[0].add(card[i]);break;case 1:CommonUtil.move(card[i], card[i].getLocation(), new Point(420+i*6, 510));playerList[1].add(card[i]);break;case 2:CommonUtil.move(card[i], card[i].getLocation(), new Point(810, 250+i*4));playerList[2].add(card[i]);break;case 3:CommonUtil.move(card[i], card[i].getLocation(), new Point(420+i*6, 50));playerList[3].add(card[i]);break;}container.setComponentZOrder(card[i], 0);count++;}if(this.t!=null) {this.t.isPublish = false;}for(int i=0;i<4;i++) {CommonUtil.cardSort(playerList[i]);CommonUtil.rePosition(playerList[i], i,this);} if(bankerFlag==1) {container.setComponentZOrder(laid,0);laid.setVisible(true);}if(bankerFlag==1) {time[1].setVisible(true); }}@Overridepublic void actionPerformed(ActionEvent e) {if(e.getSource()==exit) {this.dispose();System.exit(0);}if(e.getSource()==restart) {Constants.executor.execute(()-> Constants.SUBJECT_AUDIO.closePlay());thread.interrupt();thread.stop();thread=null;t=null;this.dispose();container.removeAll();//System.exit(0);for (int i=0;i<4;i++) {time[i].setVisible(false);playerList[i].clear();}int count =0;for(int i=1;i<=4;i++) {for(int j=1;j<=13;j++) {card[count]=null;count++;}}container.remove(jl);this.remove(container);try {Thread.sleep(500);} catch (InterruptedException ex) {ex.printStackTrace();}try {new GameMain();} catch (InterruptedException ex) {ex.printStackTrace();}}if(e.getSource()==openCard) {Constants.executor.execute(()->Constants.SEE_MAN_AUDIO.play());for(Card card : playerList[1]) {card.turnFront();}openFlag[1]=1;openCard.setVisible(false); }if(e.getSource()==discard) {Constants.executor.execute(()->Constants.DISCARD_AUDIO.play());discard.setVisible(false);quitFlag[1]=1;quitCardIcon[1].setIcon(new ImageIcon("images/放弃.png"));container.setComponentZOrder(quitCardIcon[1],0);quitCardIcon[1].setVisible(true);addLaid.setVisible(false);followLaid.setVisible(false);compareCard.setVisible(false);openCard.setVisible(false);laid.setVisible(false);t.isRun=false;nextPlayer=true;}if(e.getSource()==laid) {laidIsClick=!laidIsClick;if(laidIsClick) {container.setComponentZOrder(goldPanel,0);goldPanel.setVisible(true);}else {goldPanel.setVisible(false);} }if(e.getSource()==addLaid) {addlaidIsClick=!addlaidIsClick;if(addlaidIsClick) {container.setComponentZOrder(goldPanel,0);goldPanel.setVisible(true);}else {goldPanel.setVisible(false);} }if(e.getSource()==followLaid) {Constants.executor.execute(()->Constants.FOLLOW_MAN_AUDIO.play());playerGold[1]-=initGold; currPlayerGold[1]+=initGold;inigoldLabel[1].setText(""+currPlayerGold[1]);playergoldLabel[1].setText(""+playerGold[1]);t.isRun=false;followLaid.setVisible(false);nextPlayer=true;}if(e.getSource()==compareCard) {compareCardIsClick=!compareCardIsClick;for(int i=0;i<quitFlag.length;i++) {if (i!=1) {compareLabel[i].setVisible(false);}if(quitFlag[i]==0 && i!=1) {compareLabel[i].setVisible(true);compareLabel[i].addMouseListener(this);}}if (compareCardIsClick) {container.setComponentZOrder(comparePanel,0);comparePanel.setVisible(true);}else {comparePanel.setVisible(false);}}}public static void main(String[] args) throws InterruptedException {new GameMain();}...........
}
完成后启动main方法就可以了。
完整源码:
炸金花完整源码(含音效和图片等资源)