📄 play.java
字号:
package com.ddpie;
import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.plaf.basic.BasicBorders;
public class Play extends JFrame implements Runnable{
private JPanel mainP = new JPanel();//主面板
private JPanel centerP = new JPanel();//中间面板
private JPanel southP = new JPanel();//下面板
private JPanel leftP = new JPanel();//左面板
private JPanel rightP = new JPanel();//右面板
private JButton startB = new JButton("开始游戏");//开始游戏按钮
private JButton autoGo = new JButton("自动运行");//自动运行按钮
private JButton leftGoB = new JButton("左侧出牌");//左边的出牌按钮
private JButton rightGoB = new JButton("右侧出牌");//右边的出牌按钮
private JSlider jsl = new JSlider(5,500,100);
private JLabel secondsOfJsl = new JLabel("0ms");
private JLabel sumLeft = new JLabel();
private JLabel sumRight = new JLabel();
Image [] img = new Image[54];//54张图片
Card [] card = new Card[54];//52张牌
LinkedList showL = new LinkedList();//中间显示区域牌的链表
LinkedList leftL = new LinkedList();//左边牌的链表
LinkedList rightL = new LinkedList();//右边牌的链表
int whoToGo = 0;//下一步该谁走 1表示左边走 2表示右边走
boolean autoRun = false;//自动运行
boolean gameOver = false;//这一局游戏是否结束
boolean isStarted = false;//是否开始游戏
boolean findCard = false;
boolean run = true;
int find = 0;
int pos = 0;
Thread newThread = null;//线程 主要实现自动运行的动画显示
public Play() throws Exception{
super("拉火车游戏");
//刚开始 让没用的按钮无效
leftGoB.setEnabled(false);
rightGoB.setEnabled(false);
autoGo.setEnabled(false);
//加载图片
MediaTracker mt = new MediaTracker(this);
for(int i=0 ; i<54 ; i++){
int j = i+1;
//加载52张图片 不包括大小王
img[i] = Toolkit.getDefaultToolkit().getImage("image/"+j+".jpg");
mt.addImage(img[i],i);
}
JDialog jd = new JDialog((Frame)null,"正在加载图片,请稍候...");
jd.setSize(250,120);
jd.setResizable(false);
jd.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
jd.add(new JLabel("正在加载图片,请稍候...",SwingConstants.CENTER));
jd.setLocation((Toolkit.getDefaultToolkit().getScreenSize().width - jd.getSize().width) / 2,
(Toolkit.getDefaultToolkit().getScreenSize().height - jd.getSize().height) / 2);
jd.setVisible(true);
mt.waitForAll();//等待所有的图片都加载完毕才向下执行
jd.dispose();
jsl.addChangeListener(new ChangeListener(){
public void stateChanged(ChangeEvent e){
repaint();
}
});
autoGo.addActionListener(new ActionListener(){//自动运行按钮的事件
public void actionPerformed(ActionEvent e){
if(autoRun == false){
autoRun = true;
autoGo.setText("暂停自动运行");
if(newThread==null){
newThread = new Thread(Play.this);//生成新线程,实现动画
newThread.start();
}
else
newThread.resume();
}
else{
autoRun = false;
autoGo.setText("继续自动运行");
if(newThread!=null)
newThread.suspend();
}
}
});
leftGoB.addActionListener(new ActionListener(){//左侧出牌按钮的事件
public void actionPerformed(ActionEvent e){
leftGo();//左边出牌函数
}
});
rightGoB.addActionListener(new ActionListener(){//右侧出牌按钮的事件
public void actionPerformed(ActionEvent e){
rightGo();//右边出牌函数
}
});
startB.addActionListener(new ActionListener(){//开始按钮事件
public void actionPerformed(ActionEvent e){
initPlay();//初始化
}
});
centerP.addMouseListener(new MouseAdapter(){
public void mouseClicked(MouseEvent e){
if(findCard){
if(autoRun)
newThread.resume();
collectCard();
}
}
});
//设置窗体布局
this.getContentPane().add(mainP);
mainP.setLayout(new BorderLayout());
mainP.add(centerP,BorderLayout.CENTER);
mainP.add(southP,BorderLayout.SOUTH);
mainP.add(leftP,BorderLayout.WEST);
mainP.add(rightP,BorderLayout.EAST);
//设置各面板的border
southP.setBorder(new BasicBorders.FieldBorder(Color.DARK_GRAY,Color.BLACK,Color.GRAY,Color.LIGHT_GRAY));
leftP.setBorder(new BasicBorders.FieldBorder(Color.DARK_GRAY,Color.BLACK,Color.GRAY,Color.LIGHT_GRAY));
rightP.setBorder(new BasicBorders.FieldBorder(Color.DARK_GRAY,Color.BLACK,Color.GRAY,Color.LIGHT_GRAY));
centerP.setBorder(new BasicBorders.FieldBorder(Color.DARK_GRAY,Color.BLACK,Color.GRAY,Color.LIGHT_GRAY));
centerP.setBackground(Color.LIGHT_GRAY);
//下面板布局
southP.setLayout(new FlowLayout());
southP.add(startB);
southP.add(new JLabel(" "));
southP.add(autoGo);
southP.add(new JLabel(" "));
southP.add(new JLabel("延时:"));
southP.add(jsl);
southP.add(secondsOfJsl);
leftP.setLayout(new BorderLayout());
leftP.add(leftGoB,BorderLayout.SOUTH);
leftP.add(sumLeft,BorderLayout.NORTH);
rightP.setLayout(new BorderLayout());
rightP.add(rightGoB,BorderLayout.SOUTH);
rightP.add(sumRight,BorderLayout.NORTH);
//设置大小
this.setSize(550,530);
//设置显示位置
this.setLocation((Toolkit.getDefaultToolkit().getScreenSize().width - this.getSize().width) / 2,
(Toolkit.getDefaultToolkit().getScreenSize().height - this.getSize().height) / 2);
this.setResizable(false);//不允许改变大小
this.setVisible(true);
//如果点击关闭,显示提示框
this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
this.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
int flag = JOptionPane.showConfirmDialog(null,"你确定要退出吗?","退出?",
JOptionPane.OK_CANCEL_OPTION,JOptionPane.INFORMATION_MESSAGE);
if(flag == JOptionPane.OK_OPTION)
System.exit(0);
}
});
}
public void initPlay(){
autoRun = false;
gameOver = false;
autoRun = false;
isStarted = true;
findCard = false;
run = true;
find = 0;
pos = 0;
whoToGo = new Random().nextInt(2) + 1;
autoGo.setEnabled(true);//自动运行按钮有效
startB.setText("重新开始");//重设按钮文字
if(newThread!=null)//如果线程存在,强行终止
newThread.stop();
autoRun = false;//自动运行为假
isStarted = true;//开始游戏为真
repaint();
//向card[]数组中发牌,按顺序发
for(int i=1 ; i<=4 ; i++)
for(int j=1 ; j<=13 ; j++){
card[(i-1)*13+j-1] = new Card(j,i);
}
card[52] = new Card(14,5);//小王
card[53] = new Card(15,5);//大王
//随机洗牌
for(int i=0 ; i<10000 ; i++){
int x = new Random().nextInt(54);
int y = new Random().nextInt(54);
Card tempCard = card[x];
card[x] = card[y];
card[y] = tempCard;
}
//各个链表清空
leftL.clear();
rightL.clear();
showL.clear();
newThread = null;
autoGo.setText("自动运行");
//给左右两个链表发牌
for(int i=0 ; i<27 ; i++){
leftL.add(card[i*2]);
rightL.add(card[i*2+1]);
}
}
public void run(){
if(autoRun && run){//如果是自动运行
while(leftL.size()!=0 && rightL.size()!=0 || findCard){//假如没有输家
if(!run)
newThread.suspend();
if(whoToGo==1 && run)
leftGo();
else if(whoToGo==2 && run)
rightGo();
try{
Thread.sleep(jsl.getValue());//暂停5微秒
}
catch(Exception ex){
ex.printStackTrace();
}
}
}
}
private void leftGo(){
whoToGo = 2;//设置下次轮到右边出牌
Card tempC = (Card)leftL.removeFirst();//获得左边链表的第一张牌
showL.addLast(tempC);
for(int i=0 ; i<showL.size()-1 ; i++){//查找中间区域有没有同号的牌
if(tempC.getNum()==((Card)showL.get(i)).getNum()||
(tempC.getColor()==5 && ((Card)showL.get(i)).getColor()==5)){//找到了
findCard = true;
pos = i;
find = 1;
run = false;
break;
}
}
repaint();//重画
}
private void rightGo(){
whoToGo = 1;//设置下次轮到左边出牌
Card tempC = (Card)rightL.removeFirst();//获得右边链表的第一张牌
showL.addLast(tempC);
for(int i=0 ; i<showL.size()-1 ; i++){//查找中间区域有没有同号的牌
if(tempC.getNum()==((Card)showL.get(i)).getNum()||
(tempC.getColor()==5 && ((Card)showL.get(i)).getColor()==5)){//找到了
findCard = true;
pos = i;
find = 2;
run = false;
break;
}
}
repaint();//重画
}
private void collectCard(){
//如果找到了同号的牌
if(find == 1){//把showL中从这张牌开始到最后放到赢家牌的后面
int end = showL.size();
for(int i=pos ; i<end ; i++){
leftL.addLast(showL.remove(pos));
}
whoToGo = 1;//设置下次左边出牌
}
else if(find == 2){
int end = showL.size();
for(int i=pos ; i<end ; i++){
rightL.addLast(showL.remove(pos));
}
whoToGo = 2;//设置下次右边出牌
}
repaint();
find = 0;
findCard = false;
run = true;
}
public void paint(Graphics g){
super.paint(g);
g.setColor(Color.BLACK);
secondsOfJsl.setText(jsl.getValue()+"ms");
//依次画出中间区域应该显示的牌
for(int i=0 ; i<showL.size() ; i++){
g.drawImage(img[((Card)showL.get(i)).getImg()],centerP.getX()+10+i*20,centerP.getY()+30+i*20,120,165,this);
}
int a = 0;
//依次画出左边区域应该显示的牌
for(int i=0 ; i<leftL.size() ; i++){
if((i+1)%14==0){
a = -25*(i+1)/14;
}
g.drawImage(img[((Card)leftL.get(leftL.size()-i-1)).getImg()],leftP.getX()+10+i*2+a,leftP.getY()+60+i*7,leftP.getX()+50+i*2+a,leftP.getY()+110+i*7,10,10,50,105,this);
g.drawRect(leftP.getX()+10+i*2+a,leftP.getY()+60+i*7,40,50);
}
a = 0;
//依次画出右边区域应该显示的牌
for(int i=0 ; i<rightL.size() ; i++){
if((i+1)%14==0){
a = -25*(i+1)/14;
}
g.drawImage(img[((Card)rightL.get(rightL.size()-i-1)).getImg()],rightP.getX()+10+i*2+a,rightP.getY()+60+i*7,rightP.getX()+50+i*2+a,rightP.getY()+110+i*7,10,10,50,105,this);
g.drawRect(rightP.getX()+10+i*2+a,rightP.getY()+60+i*7,40,50);
}
//显示各家剩余牌数
sumLeft.setText(" 拥有"+leftL.size()+"张牌");
sumRight.setText(" 拥有"+rightL.size()+"张牌");
if(whoToGo==1 &&run)
leftGoB.setEnabled(true);
else
leftGoB.setEnabled(false);
if(whoToGo==2 &&run)
rightGoB.setEnabled(true);
else
rightGoB.setEnabled(false);
if(isStarted)
autoGo.setEnabled(true);
else
autoGo.setEnabled(false);
if(!gameOver && !run){
this.setTitle("拉火车游戏--有牌相同了,点击中央面板收牌");
}
else if(whoToGo == 1){
this.setTitle("拉火车游戏--该左侧出牌");
}
else if(whoToGo == 2){
this.setTitle("拉火车游戏--该右侧出牌");
}
else
this.setTitle("拉火车游戏");
//右边赢了
if(leftL.size()==0 && !gameOver && isStarted && !findCard){
JOptionPane.showMessageDialog(this,"游戏结束,右边赢了!");
gameOver = true;
isStarted = false;
whoToGo = 0;
repaint();
}
//左边赢了
else if(rightL.size()==0 && !gameOver && isStarted && !findCard){
JOptionPane.showMessageDialog(this,"游戏结束,左边赢了!");
gameOver = true;
isStarted = false;
whoToGo = 0;
repaint();
}
}
public static void main(String [] args) throws Exception{
new Play();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -