Java小项目之拼图游戏
Posted 我好像在哪见过你
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java小项目之拼图游戏相关的知识,希望对你有一定的参考价值。
首先声明,代码是自创的,如有雷同,不胜荣幸!
先谈谈思路:
1.设计界面。
2.素材的处理。
3.设计图片加载区域的图片加载处理类。
4.设计按钮组中的按钮初始化方法。
5.设计按钮组中的随机图片加载方法。
6.设计重置按钮方法。
7.设计按钮监听器。
8.设计判定胜利的条件的方法。
1.界面的设计:
a.使用了Windows Builder插件,安装网页:WindoswBuilder - http://download.eclipse.org/windowbuilder/WB/integration/4.6/
b.页面的整体整体样式:
一个JFram中添加三个带标题的JPanel,将整个分割为游戏选项区域,图片展示区域和游戏区域。每个区域都有各自的控件,其中需要注意的是图片展示区域放置了一个JLable来加载展示图片。
c.代码:我将源码放在了com.rookie.view包下,并且类名为GameView。
1 package com.rookie.view; 2 3 import java.awt.EventQueue; 4 5 import javax.swing.JFrame; 6 import javax.swing.JPanel; 7 import javax.swing.border.EmptyBorder; 8 import javax.swing.JMenuBar; 9 import javax.swing.JMenu; 10 import javax.swing.JMenuItem; 11 import javax.swing.JOptionPane; 12 13 14 import java.awt.event.ActionListener; 15 import java.util.Timer; 16 import java.util.TimerTask; 17 import java.awt.event.ActionEvent; 18 import javax.swing.GroupLayout; 19 import javax.swing.GroupLayout.Alignment; 20 import javax.swing.border.TitledBorder; 21 22 import com.rookie.dao.PicloadDao; 23 import com.rookie.dao.GameDao; 24 25 import javax.swing.UIManager; 26 import java.awt.Color; 27 import javax.swing.LayoutStyle.ComponentPlacement; 28 import javax.swing.JLabel; 29 import javax.swing.JRadioButton; 30 import javax.swing.ButtonGroup; 31 import javax.swing.JComboBox; 32 import javax.swing.DefaultComboBoxModel; 33 import javax.swing.JTextField; 34 import javax.swing.JButton; 35 import javax.swing.SwingConstants; 36 37 public class GamerView extends JFrame { 38 39 /** 40 * 41 */ 42 private static final long serialVersionUID = 1L; 43 private JPanel mainPanel; 44 private final ButtonGroup buttonGroup = new ButtonGroup(); 45 private static JTextField textField_time; 46 private static JButton bt_GameBegin = null; 47 private static JLabel jl_loadImage = null; 48 private static JComboBox comboBox_SelectPic = null; 49 private static JRadioButton rb_simple = null; 50 private static JRadioButton rb_difficulty = null; 51 private static JPanel panel_beginGame = null; 52 private static GameDao gameChoseDao; 53 private static int time = 0; 54 private static Timer timer; 55 /** 56 * Launch the application. 57 */ 58 public static void main(String[] args) { 59 EventQueue.invokeLater(new Runnable() { 60 public void run() { 61 try { 62 GamerView frame = new GamerView(); 63 frame.setVisible(true); 64 } catch (Exception e) { 65 e.printStackTrace(); 66 } 67 } 68 }); 69 } 70 71 /** 72 * Create the frame. 73 */ 74 public GamerView() { 75 setResizable(false); 76 setTitle("\\u62FC\\u56FE\\u6E38\\u620F(\\u6D4B\\u8BD5\\u7248)"); 77 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 78 setBounds(100, 100, 710, 550); 79 80 JMenuBar menuBar = new JMenuBar(); 81 setJMenuBar(menuBar); 82 83 JMenu m_About = new JMenu("\\u5173\\u4E8E"); 84 menuBar.add(m_About); 85 86 JMenuItem mI_aboutMe = new JMenuItem("\\u56E2\\u961F\\u4ECB\\u7ECD"); 87 mI_aboutMe.addActionListener(new ActionListener() { 88 public void actionPerformed(ActionEvent e) { 89 showAboutActionListener(e); 90 } 91 }); 92 m_About.add(mI_aboutMe); 93 mainPanel = new JPanel(); 94 mainPanel.setBorder(new EmptyBorder(5, 5, 5, 5)); 95 setContentPane(mainPanel); 96 97 JPanel panel_checkGame = new JPanel(); 98 panel_checkGame.setBorder(new TitledBorder(null, "\\u6E38\\u620F\\u9009\\u9879\\uFF1A", TitledBorder.CENTER, TitledBorder.TOP, null, Color.RED)); 99 100 JPanel panel_loadPic = new JPanel(); 101 panel_loadPic.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), "\\u539F\\u56FE\\u52A0\\u8F7D\\uFF1A", TitledBorder.CENTER, TitledBorder.TOP, null, Color.RED)); 102 panel_loadPic.setToolTipText(""); 103 104 panel_beginGame = new JPanel(); 105 panel_beginGame.setBorder(new TitledBorder(null, "\\u6E38\\u620F\\u5F00\\u59CB\\uFF1A", TitledBorder.CENTER, TitledBorder.TOP, null, Color.RED)); 106 GroupLayout gl_mainPanel = new GroupLayout(mainPanel); 107 gl_mainPanel.setHorizontalGroup( 108 gl_mainPanel.createParallelGroup(Alignment.TRAILING) 109 .addGroup(gl_mainPanel.createSequentialGroup() 110 .addContainerGap() 111 .addGroup(gl_mainPanel.createParallelGroup(Alignment.TRAILING) 112 .addComponent(panel_checkGame, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, 674, Short.MAX_VALUE) 113 .addGroup(Alignment.LEADING, gl_mainPanel.createSequentialGroup() 114 .addComponent(panel_loadPic, GroupLayout.PREFERRED_SIZE, 336, GroupLayout.PREFERRED_SIZE) 115 .addPreferredGap(ComponentPlacement.UNRELATED) 116 .addComponent(panel_beginGame, GroupLayout.PREFERRED_SIZE, 332, GroupLayout.PREFERRED_SIZE))) 117 .addContainerGap()) 118 ); 119 gl_mainPanel.setVerticalGroup( 120 gl_mainPanel.createParallelGroup(Alignment.LEADING) 121 .addGroup(gl_mainPanel.createSequentialGroup() 122 .addContainerGap() 123 .addComponent(panel_checkGame, GroupLayout.PREFERRED_SIZE, 83, GroupLayout.PREFERRED_SIZE) 124 .addPreferredGap(ComponentPlacement.UNRELATED) 125 .addGroup(gl_mainPanel.createParallelGroup(Alignment.BASELINE) 126 .addComponent(panel_loadPic, GroupLayout.DEFAULT_SIZE, 377, Short.MAX_VALUE) 127 .addComponent(panel_beginGame, GroupLayout.DEFAULT_SIZE, 377, Short.MAX_VALUE)) 128 .addContainerGap()) 129 ); 130 131 jl_loadImage = new JLabel(""); 132 jl_loadImage.setIcon(null); 133 panel_loadPic.add(jl_loadImage); 134 135 136 137 GroupLayout gl_panel_beginGame = new GroupLayout(panel_beginGame); 138 gl_panel_beginGame.setHorizontalGroup( 139 gl_panel_beginGame.createParallelGroup(Alignment.LEADING) 140 .addGap(0, 320, Short.MAX_VALUE) 141 ); 142 gl_panel_beginGame.setVerticalGroup( 143 gl_panel_beginGame.createParallelGroup(Alignment.LEADING) 144 .addGap(0, 322, Short.MAX_VALUE) 145 ); 146 panel_beginGame.setLayout(gl_panel_beginGame); 147 148 JLabel label = new JLabel("\\u6E38\\u620F\\u96BE\\u5EA6\\uFF1A"); 149 label.setForeground(Color.BLUE); 150 151 rb_simple = new JRadioButton("\\u7B80\\u5355"); 152 buttonGroup.add(rb_simple); 153 154 rb_difficulty = new JRadioButton("\\u56F0\\u96BE"); 155 buttonGroup.add(rb_difficulty); 156 157 rb_simple.setSelected(true); 158 159 JLabel label_1 = new JLabel("\\u56FE\\u7247\\u9009\\u62E9\\uFF1A"); 160 label_1.setForeground(Color.BLUE); 161 162 comboBox_SelectPic = new JComboBox(); 163 comboBox_SelectPic.setModel(new DefaultComboBoxModel(new String[] {"\\u98CE\\u666F", "\\u7F8E\\u5973", "\\u8C6A\\u8F66", "\\u6E38\\u620F"})); 164 comboBox_SelectPic.setMaximumRowCount(5); 165 166 JLabel label_2 = new JLabel("\\u6E38\\u620F\\u65F6\\u95F4\\uFF1A"); 167 label_2.setForeground(Color.BLUE); 168 169 textField_time = new JTextField(); 170 textField_time.setHorizontalAlignment(SwingConstants.RIGHT); 171 textField_time.setText("0"); 172 textField_time.setEditable(false); 173 textField_time.setColumns(10); 174 175 JLabel lblNewLabel = new JLabel("\\u79D2"); 176 lblNewLabel.setForeground(Color.BLUE); 177 178 bt_GameBegin = new JButton("\\u5F00\\u59CB\\u6E38\\u620F"); 179 bt_GameBegin.addActionListener(new ActionListener() { 180 public void actionPerformed(ActionEvent eve) { 181 buttonClickAction(eve); 182 } 183 }); 184 GroupLayout gl_panel_checkGame = new GroupLayout(panel_checkGame); 185 gl_panel_checkGame.setHorizontalGroup( 186 gl_panel_checkGame.createParallelGroup(Alignment.LEADING) 187 .addGroup(gl_panel_checkGame.createSequentialGroup() 188 .addContainerGap() 189 .addComponent(label) 190 .addGap(6) 191 .addGroup(gl_panel_checkGame.createParallelGroup(Alignment.TRAILING) 192 .addComponent(rb_difficulty) 193 .addGroup(gl_panel_checkGame.createSequentialGroup() 194 .addComponent(rb_simple) 195 .addPreferredGap(ComponentPlacement.RELATED))) 196 .addGap(18) 197 .addComponent(label_1) 198 .addPreferredGap(ComponentPlacement.UNRELATED) 199 .addComponent(comboBox_SelectPic, GroupLayout.PREFERRED_SIZE, 69, GroupLayout.PREFERRED_SIZE) 200 .addGap(32) 201 .addComponent(label_2) 202 .addPreferredGap(ComponentPlacement.UNRELATED) 203 .addComponent(textField_time, GroupLayout.PREFERRED_SIZE, 41, GroupLayout.PREFERRED_SIZE) 204 .addPreferredGap(ComponentPlacement.RELATED) 205 .addComponent(lblNewLabel) 206 .addGap(52) 207 .addComponent(bt_GameBegin, GroupLayout.PREFERRED_SIZE, 93, GroupLayout.PREFERRED_SIZE) 208 .addContainerGap(76, Short.MAX_VALUE)) 209 ); 210 gl_panel_checkGame.setVerticalGroup( 211 gl_panel_checkGame.createParallelGroup(Alignment.LEADING) 212 .addGroup(gl_panel_checkGame.createSequentialGroup() 213 .addGroup(gl_panel_checkGame.createParallelGroup(Alignment.LEADING) 214 .addGroup(gl_panel_checkGame.createSequentialGroup() 215 .addComponent(rb_simple) 216 .addPreferredGap(ComponentPlacement.RELATED, 7, Short.MAX_VALUE) 217 .addComponent(rb_difficulty)) 218 .addGroup(gl_panel_checkGame.createSequentialGroup() 219 .addContainerGap() 220 .addGroup(gl_panel_checkGame.createParallelGroup(Alignment.BASELINE) 221 .addComponent(label_1) 222 .addComponent(comboBox_SelectPic, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) 223 .addComponent(textField_time, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) 224 .addComponent(lblNewLabel) 225 .addComponent(label_2) 226 .addComponent(bt_GameBegin, GroupLayout.PREFERRED_SIZE, 38, GroupLayout.PREFERRED_SIZE))) 227 .addGroup(gl_panel_checkGame.createSequentialGroup() 228 .addGap(22) 229 .addComponent(label))) 230 .addContainerGap()) 231 ); 232 panel_checkGame.setLayout(gl_panel_checkGame); 233 mainPanel.setLayout(gl_mainPanel); 234 } 235 236 private void showAboutActionListener(ActionEvent e) { 237 // TODO Auto-generated method stub 238 JOptionPane.showMessageDialog(null, "QQ:523980553"); 239 } 240 241 private void buttonClickAction(ActionEvent eve) { 242 // TODO Auto-generated method stub 243 //设置按钮标题 244 if( bt_GameBegin.getText().equals("开始游戏") ) { 245 beginGame(); 246 timer = new Timer(); 247 timer.scheduleAtFixedRate(new MyTase(), 0, 900); 248 } 249 else { 250 resetGame(); 251 252 } 253 254 } 255 256 public static void beginGame() { 257 bt_GameBegin.setText("重置游戏"); 258 //获取ComBox选项 259 int picId = comboBox_SelectPic.getSelectedIndex(); 260 //加载图片 261 PicloadDao pic = new PicloadDao(); 262 pic.loadPic(picId, jl_loadImage); 263 //获取难易度 264 if(rb_simple.isSelected()) { 265 gameChoseDao = new GameDao(); 266 gameChoseDao.initButton(panel_beginGame); 267 gameChoseDao.randomLoadPic(picId); 268 269 }else if(rb_difficulty.isSelected()) { 270 271 } 272 } 273 274 public static void resetGame() { 275 bt_GameBegin.setText("开始游戏"); 276 rb_simple.setSelected(true); 277 comboBox_SelectPic.setSelectedIndex(0); 278 textField_time.setText(""+0); 279 jl_loadImage.setIcon(null); 280 gameChoseDao.resetButton(); 281 time = 0; 282 timer.cancel(); 283 } 284 285 class MyTase extends TimerTask{ 286 @Override 287 public void run() { 288 // TODO Auto-generated method stub 289 time ++; 290 textField_time.setText("" + time); 291 if(time == 60) { 292 JOptionPane.showMessageDialog(null, "挑战失败!!!"); 293 resetGame(); 294 } 295 } 296 } 297 }
代码被分成了几部分:一部分是界面的初始化,这些都可以通过Windows builder来完成,但是从按下“开始游戏”的按钮后,之后的任务都需要手动写代码,例如事件的处理,开始游戏和重置游戏的方法书写,计时器的书写。都是需要独立完成,技术比较菜,可能代码不是很完善,请原谅。只是基础,不在详细去说。
2.素材的处理。
a.统一规范的素材命名。
b.利用PS将图进行切片,可以完成图片分成均匀的几份。
需要注意的是:如果你使用的是Win8或者Win10,你需要使用管理员权限打开PS。
3.设计图片加载区域的图片加载处理类。
因为我们使用的是png后缀的素材图片,所以需要稍微处理一下。
new ImageIcon(GameVime.class,getResource();
1 package com.rookie.dao; 2 3 import java.io.File; 4 5 import javax.swing.ImageIcon; 6 import javax.swing.JLabel; 7 import javax.swing.JOptionPane; 8 9 import com.rookie.view.GamerView; 10 11 12 public class PicloadDao { 13 14 public PicloadDao() { 15 super(); 16 } 17 18 public void loadPic(int id,JLabel lable) { 19 String imageStr = "/LoadImage"+File.separator+"image_" + id + ".png"; 20 if(lable != null) { 21 try { 22 lable.setIcon(new ImageIcon(GamerView.class.getResource(imageStr))); 23 }catch(NullPointerException e){ 24 JOptionPane.showMessageDialog(null, "图片加载失败!!!"); 25 } 26 } 27 } 28 }
加入了异常处理机制,再出现问题时候可以及时提醒。
4.设计按钮组中的按钮初始化方法。
刚开始的时候想法是给每一个按钮一个标题,但是后来发现标题会影响到图片的布局,所以取消了标题的设计,之后就是用记录每一个按钮初始化时的位置,之后判定胜利的时候更加方便。
1 public void initButton(JPanel panel) { 2 panel.setLayout(null); 3 int wNum = 0; 4 int hNum = 0; 5 for(int i=0;i< buttons.length;i++) { 6 buttons[i] = new JButton(); 7 buttons[i].setVisible(true); 8 p[i] = new Point( y+width*wNum++,x+height*hNum); 9 buttons[i].setBounds(p[i].x, p[i].y, width, height); 10 if((i+1)%3==0) { 11 hNum++; 12 wNum=0; 13 } 14 buttons[i].addActionListener(this); 15 panel.add(buttons[i]); 16 } 17 }
5.设计按钮组中的随机图片加载方法。
这个方法核心在于随机数的产生,while()循环能够保证不出现重复的随机数,不会出现两个或者多个按钮加载了同一张图片。
public void randomLoadPic(int picId) { int rNum = 0; randomNum = new int[9]; for(int i=0;i < buttons.length;i++) { try { rNum = (int)(Math.random()*9); while(buttons[rNum].getIcon() != null) { rNum = (int)(Math.random()*9)%9; } randomNum[i] = rNum; StringBuffer str = new StringBuffer( "/LoadImage/image_" + picId + "/simple/image_" + picId + "_0" + (i+1) + ".png"); buttons[rNum].setIcon(new ImageIcon(GamerView.class.getResource(str.toString()))); buttons[rNum].setActionCommand(""+rNum); randomNum[i] = rNum; }catch(Exception e) { JOptionPane.showMessageDialog(null, "异常错误,即将退出"); System.exit(0); } } }
异常处理机制保证再出现找不到图片或者其他错误是能正常退出游戏,本来用的是String类但是运行的时候一直再报NullPointException错误,所以改用了StringBuffer,完美解决错误。当然,也不排除我开始的时候素材没有处理好。
6.设计重置按钮方法。
1 public void resetButton() { 2 for(int i=0;i < buttons.length;i++) { 3 try { 4 buttons[i].setIcon(null); 5 buttons[i].setVisible(false); 6 buttons[i] = null; 7 }catch(NullPointerException e) { 8 JOptionPane.showMessageDialog(null, "发生错误!!"); 9 } 10 } 11 }
很简单,就是让图片清空,不可见,能够使得界面初始化。
7.设计按钮监听器。
到了最关键的地方:按钮监听时候需要分成两个部分,一个是首次点击,一个是第二次点击,首次点击的时候我们只需要记录当前按下的按钮信息。第二次点击之后需要判定当前按钮是否在之间按钮的上下左右四个位置,如果是的话,就进行交换,如果不是就提示错误。思路就这么简单。
1 public void actionPerformed(ActionEvent e) { 2 if(beFlag == true) { //第一次点击 3 beButton = (JButton)e.getSource(); 4 beFlag = false; 5 }else { 6 JButton nowButton = (JButton)e.getSource(); 7 int nX = nowButton.getX(); 8 int nY = nowButton.getY(); 9 int bX = beButton.getX(); 10 int bY = beButton.getY(); 11 beFlag = false; 12 if((Math.abs(nX-bX)<width && Math.abs(nY-bY)<=height)||(Math.abs(nX-bX)<=width && Math.abs(nY-bY)<height)) { 13 beButton.setBounds(nX, nY, width, height); 14 nowButton.setBounds(bX,bY,width,height); 15 }else { 16 JOptionPane.showMessageDialog(null, "选取错误!!!"); 17 } 18 this.successGame(); 基于Android平台游戏之小拼图