最近闲暇时间写了个用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;
//比牌panel
JPanel 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() {
@Override
public 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);
}
}
@Override
public 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方法就可以了。
完整源码:
炸金花完整源码(含音效和图片等资源)