PlayBoard.java
上传用户:jennyfly
上传日期:2021-08-10
资源大小:735k
文件大小:18k
源码类别:

游戏

开发平台:

Java

  1. package view;
  2. import java.awt.BorderLayout;
  3. import java.awt.Color;
  4. import java.awt.FlowLayout;
  5. import java.awt.Font;
  6. import java.awt.Point;
  7. import java.awt.Toolkit;
  8. import java.awt.event.ActionListener;
  9. import java.awt.event.MouseListener;
  10. import java.util.Observable;
  11. import java.util.Observer;
  12. import javax.swing.ImageIcon;
  13. import javax.swing.JButton;
  14. import javax.swing.JComboBox;
  15. import javax.swing.JLabel;
  16. import javax.swing.JOptionPane;
  17. import javax.swing.JPanel;
  18. import model.Model;
  19. /**
  20.  * 程序的游戏面板
  21.  * 
  22.  * @author 何晓飞
  23.  * @version 2.0
  24.  */
  25. public class PlayBoard extends JPanel implements Observer {
  26. private static final long serialVersionUID = 1L;
  27. private ImageIcon iInfo, iStart,iSave,iBack;
  28. private ImageIcon iDemo, iStop;
  29. private ImageIcon iPause, iBegin;
  30. private ImageIcon iSoundPlay, iSoundMuse;
  31. private ImageIcon iRemind0, iRemind1, iRemind2, iRemind3, iRemind4,
  32. iRemind5, iRemind6,iRemind7,iRemind8;
  33. /* 背景声音 */
  34. private Sound bgSound;
  35. /* 所使用的图片的文件名 */
  36. private String picFile;
  37. /* 游戏中播放的音乐 */
  38. private String gameMusic;
  39. /* 图片选项下拉菜单显示的内容 */
  40. private String[] picStrings = { "图片选项", "水果", "国旗" };
  41. /* 音乐下拉菜单里显示的内容 */
  42. private String[] mStrings = { "背景音乐", "泰坦尼克", "柠檬树", "奇幻旋律", "梦中婚礼" };
  43. /* 6个JButton 分别用来控制游戏的暂停,关于,提示,演示,开始,保存 */
  44. private JButton btnifo, btnPause;
  45. private JButton btnRemind, btnDemo, btnStart,btnSave;
  46. private JLabel lblRemind;
  47. /* 音乐下拉菜单和图片下拉菜单 */
  48. private JComboBox cbMusic, cbPic;
  49. /* 音乐开关 */
  50. private JButton btnSound;
  51. private JButton btnBack;
  52. /* 图片面板 */
  53. private PicBoard pb;
  54. /* 4个JLabel分别显示当前关历史纪录,剩余可消去图片对数,已用时和剩余时间 */
  55. private JLabel lblHistory;
  56. private JLabel lblPairs;
  57. private JLabel lblTimePass;
  58. private JLabel lblTimeLeft;
  59. /* 显示当前关数 */
  60. private JLabel lblLevel;
  61. private JLabel lblLevelName;
  62. /* 显示得分 */
  63. private JLabel lblScore;
  64. // 创建一个Icon用于覆盖游戏界面
  65. ImageIcon coverIcon;
  66. // 创建一个包含Icon的label
  67. JLabel cover = new JLabel(coverIcon);
  68. /* 游戏运行模式 */
  69. private Model model;
  70. /* 操作面板 */
  71. private JPanel setPanel;
  72. /* 状态面板 */
  73. private JPanel statPanel;
  74. /**
  75.  * 初始化各组件和相关参数
  76.  * 
  77.  * @param model
  78.  *            游戏运行时的逻辑控制
  79.  */
  80. public PlayBoard(Model model) {
  81. this.model = model;
  82. // 初始化
  83. gameMusic = "梦中婚礼.mid";
  84. // 游戏中的背景音乐
  85. bgSound = new Sound(gameMusic);
  86. initComponents();
  87. // 将按钮添加至设置面板
  88. setPanel.add(btnifo);
  89. setPanel.add(btnStart);
  90. setPanel.add(btnRemind);
  91. setPanel.add(lblRemind);
  92. setPanel.add(btnDemo);
  93. setPanel.add(btnPause);
  94. setPanel.add(btnSave);
  95. setPanel.add(cbPic);
  96. setPanel.add(cbMusic);
  97. setPanel.add(btnSound);
  98. setPanel.add(btnBack);
  99. // 设置设置面的板背景色
  100. setPanel.setBackground(Model.BG_COLOR);
  101. // 将标签添加至状态面板
  102. statPanel.add(lblLevel);
  103. statPanel.add(lblLevelName);
  104. statPanel.add(lblScore);
  105. statPanel.add(lblTimePass);
  106. statPanel.add(lblTimeLeft);
  107. statPanel.add(lblPairs);
  108. statPanel.add(lblHistory);
  109. // 设置状态面板的背景色
  110. statPanel.setBackground(Model.BG_COLOR);
  111. // 设置大小
  112. setSize(820, 553);
  113. // 设置布局管理器
  114. setLayout(new BorderLayout());
  115. // 设置各Panel方位
  116. add(setPanel, BorderLayout.NORTH);// setPanel占据北边
  117. add(pb, BorderLayout.CENTER);// 个Panel占据中间
  118. add(statPanel, BorderLayout.SOUTH);// statPanel占据南边
  119. // 自定义鼠标
  120. try {
  121. setCursor(Toolkit.getDefaultToolkit().createCustomCursor(
  122. ImageLoader.getCursorImage(), new Point(0, 0), "cursor"));
  123. } catch (Exception e) {
  124. e.printStackTrace();
  125. }
  126. }
  127. // 给不同的对象添加不同的监听
  128. public void addController(Object obj) {
  129. // 只监听图片面板的鼠标事件
  130. if (obj instanceof MouseListener) {
  131. pb.addMouseListener((MouseListener) obj);
  132. }
  133. // 给各按钮添加监听
  134. if (obj instanceof ActionListener) {
  135. ActionListener al = (ActionListener) obj;
  136. btnifo.addActionListener(al);
  137. btnStart.addActionListener(al);
  138. btnRemind.addActionListener(al);
  139. btnDemo.addActionListener(al);
  140. btnPause.addActionListener(al);
  141. btnSound.addActionListener(al);
  142. btnBack.addActionListener(al);
  143. btnSave.addActionListener(al);
  144. cbPic.addActionListener(al);
  145. cbMusic.addActionListener(al);
  146. }
  147. }
  148. /**
  149.  * 设置音乐
  150.  * 
  151.  * @param music
  152.  *            目标音乐文件名
  153.  */
  154. private void changeMusic(String music) {
  155. bgSound.stop();
  156. gameMusic = music;
  157. /*
  158.  * 新建背景音乐改变音乐开关状态并设置音乐
  159.  */
  160. bgSound = new Sound(gameMusic);
  161. btnSound.setText("关");
  162. bgSound.play(true);// 开始游戏音乐
  163. btnSound.setIcon(iSoundMuse);
  164. model.setMusic(gameMusic);
  165. }
  166. /**
  167.  * 改变图片
  168.  * 
  169.  * @param pic
  170.  *            目标文件夹名
  171.  */
  172. private void changePic(String pic) {
  173. /*
  174.  * 设置图片文件名
  175.  */
  176. model.setPictureFile(pic);
  177. /*
  178.  * 重新开始游戏
  179.  */
  180. model.restartGame();
  181. }
  182. // 初始化各组件
  183. private void initComponents() {
  184. // 初始化各组件,设置字体,ActionCommand
  185. lblTimePass = new JLabel();
  186. lblTimePass.setForeground(new Color(34, 139, 34));
  187. lblTimeLeft = new JLabel();
  188. lblTimeLeft.setForeground(new Color(61, 50, 167));
  189. lblPairs = new JLabel();
  190. lblPairs.setForeground(new Color(34, 139, 34));
  191. lblHistory = new JLabel();
  192. lblHistory.setForeground(new Color(34, 139, 34));
  193. lblLevel = new JLabel();//
  194. lblLevel.setForeground(new Color(238, 25, 59));
  195. lblLevelName=new JLabel();
  196. lblLevelName.setForeground(new Color(238, 25, 59));
  197. lblScore = new JLabel();
  198. lblScore.setForeground(new Color(34, 139, 34));
  199. // 设置字体
  200. lblTimePass.setFont(new Font("华文楷体", Font.PLAIN,18));
  201. lblTimeLeft.setFont(new Font("华文楷体", Font.PLAIN,18));
  202. lblPairs.setFont(new Font("华文楷体", Font.PLAIN, 18));
  203. lblHistory.setFont(new Font("华文楷体", Font.PLAIN,18));
  204. lblLevel.setFont(new Font("华文行楷", Font.PLAIN,18));
  205. lblLevelName.setFont(new Font("华文行楷", Font.PLAIN,18));
  206. lblScore.setFont(new Font("华文楷体", Font.PLAIN, 18));
  207. iInfo = new ImageIcon(ImageLoader.getImage("about.gif"));
  208. iStart = new ImageIcon(ImageLoader.getImage("restart.gif"));
  209. iSave=new ImageIcon(ImageLoader.getImage("save.gif"));
  210. iBack=new ImageIcon(ImageLoader.getImage("back.gif"));
  211. iDemo = new ImageIcon(ImageLoader.getImage("demo.gif"));
  212. iStop = new ImageIcon(ImageLoader.getImage("Stop.gif"));
  213. iPause = new ImageIcon(ImageLoader.getImage("pause.gif"));
  214. iBegin = new ImageIcon(ImageLoader.getImage("begin.gif"));
  215. iSoundPlay = new ImageIcon(ImageLoader.getImage("play.jpg"));
  216. iSoundMuse = new ImageIcon(ImageLoader.getImage("muse.jpg"));
  217. iRemind0 = new ImageIcon(ImageLoader.getImage("0.gif"));
  218. iRemind1 = new ImageIcon(ImageLoader.getImage("1.gif"));
  219. iRemind2 = new ImageIcon(ImageLoader.getImage("2.gif"));
  220. iRemind3 = new ImageIcon(ImageLoader.getImage("3.gif"));
  221. iRemind4 = new ImageIcon(ImageLoader.getImage("4.gif"));
  222. iRemind5 = new ImageIcon(ImageLoader.getImage("5.gif"));
  223. iRemind6 = new ImageIcon(ImageLoader.getImage("6.gif"));
  224. iRemind7=new ImageIcon(ImageLoader.getImage("7.gif"));
  225. iRemind8=new ImageIcon(ImageLoader.getImage("8.gif"));
  226. btnifo = new JButton(iInfo);// 关于按钮
  227. btnifo.setActionCommand("about");// 设置actionCommand
  228. btnStart = new JButton(iStart);// 重新开始按钮
  229. btnStart.setActionCommand("restart");// 设置actionCommand
  230. btnRemind = new JButton(iRemind6);// 提示按钮
  231. btnRemind.setActionCommand("remind");// 设置actionCommand
  232. lblRemind=new JLabel("次提示");
  233. lblRemind.setFont(new Font("华文行楷",Font.PLAIN,20));
  234. btnDemo = new JButton(iDemo);// 演示按钮
  235. btnDemo.setActionCommand("demo");// 设置actionCommand
  236. btnPause = new JButton(iPause);// 暂停按钮
  237. btnPause.setActionCommand("pause");// 设置actionCommand
  238. btnSave=new JButton(iSave);
  239. btnSave.setActionCommand("save");
  240. cbPic = new JComboBox(picStrings);// 图片下拉菜单
  241. cbPic.setSelectedIndex(0);// 设置默认选项
  242. cbPic.setActionCommand("pic");// 设置actionCommand
  243. cbMusic = new JComboBox(mStrings);// 音乐下拉菜单
  244. cbMusic.setSelectedIndex(0);// 设置默认选项
  245. cbMusic.setActionCommand("music");// 设置actionCommand
  246. btnSound = new JButton("开", iSoundPlay);// 声音按钮
  247. btnSound.setActionCommand("sound");// 设置 actionCommand
  248. btnBack=new JButton(iBack);
  249. btnBack.setActionCommand("back");
  250. coverIcon = new ImageIcon(ImageLoader.getCover());//创建一个背景
  251. cover = new JLabel(coverIcon);//创建一个label
  252. pb = new PicBoard(model);// gPanel面板
  253. // 创建GamePanel实例
  254. setPanel = new JPanel();
  255. // 设置位置
  256. setPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
  257. statPanel = new JPanel();
  258. // 设置布局
  259. statPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
  260. }
  261. // 显示工作组信息
  262. private void showifo() {
  263. JOptionPane.showMessageDialog(this, "连连看2.0" + "n" + "本游戏非开源软件" + "n"
  264. + "仅限学习及参考所用" + "n" + "请勿用于商业运作" + "n" + "如有问题及建议请mail到"
  265. + "n" + "kevin1987725@163.com" + "n" + "修改日期:2008 12月" + "n"
  266. + "<html><font color=#228B22>作者:何晓飞</font></html>", "关于本程序",
  267. JOptionPane.INFORMATION_MESSAGE, new ImageIcon(ImageLoader
  268. .getImage("info.jpg")));
  269. }
  270. // observer 必须写的方法用于动态更新数据和界面
  271. public void update(Observable obs, Object obj) {
  272. /*
  273.  * 根据不同的消息产生不同的响应
  274.  */
  275. if (obj instanceof String) {
  276. if (obj.equals("link")) {
  277. /*
  278.  * 画线
  279.  */
  280. pb.drawLink();
  281. /*
  282.  * 释放关键点
  283.  */
  284. model.freeKeyPoints();
  285. }
  286. /*
  287.  * 更新关数,包括该关的名字
  288.  */
  289. else if (obj.equals("level")) {
  290. lblLevel.setText("第" + model.getLevel() + "关:  ");
  291. lblLevelName.setText(model.getLevelName());
  292. }
  293. /*
  294.  * 介于得分,剩余时间,可消除对数更新的比较快,故 采取与时间更新同步的策略。
  295.  */
  296. else if (obj.equals("timer")) {
  297. // 如果是timer
  298. lblScore.setText("得分: " + model.getCurrentScore()+"  ");// 设置得分
  299. lblTimePass.setText("已用时"+model.getPlayTime()+"秒  ");//设置流失时间
  300. lblTimeLeft.setText("剩余时间: " + model.getTimeLeft() + "秒  ");// 设置剩余时间
  301. lblPairs.setText(" 可消除: " + model.solutionCount() + "对  ");// 设置剩余对数
  302. }
  303. /*
  304.  * 显示当前关的历史记录
  305.  */
  306. else if (obj.equals("record")) {
  307. lblHistory.setText("本关纪录: " + model.getRecord(model.getLevel())
  308. + "秒  ");
  309. }
  310. /*
  311.  * 超过游戏时间游戏结束
  312.  */
  313. else if (obj.equals("over")) {
  314. int response = JOptionPane
  315. .showConfirmDialog(this,
  316. "你已经超过规定时间,是否重新开始游戏 ?n点否直接退出游戏!", "  友情提示",
  317. JOptionPane.YES_NO_OPTION,
  318. JOptionPane.QUESTION_MESSAGE);
  319. if (response == JOptionPane.YES_OPTION) {
  320. model.restartGame();
  321. } else if (response == JOptionPane.NO_OPTION) {
  322. System.exit(0);
  323. }
  324. }
  325. /*
  326.  * 重新开始游戏
  327.  */
  328. else if (obj.equals("restart")) {
  329. int response = JOptionPane.showConfirmDialog(this,
  330. "该操作会使游戏返回第一关,n" + "您是否决定继续这样的操作?",
  331. "           请 确 认", JOptionPane.YES_NO_OPTION,
  332. JOptionPane.QUESTION_MESSAGE);
  333. if (response == JOptionPane.YES_OPTION) {
  334. model.restartGame();
  335. }
  336. }
  337. /*
  338.  * 打破历史记录
  339.  */
  340. else if (obj.equals("breakrecord")) {
  341. // 如果是breakRecorder
  342. JOptionPane.showMessageDialog(this, "恭喜打破纪录!" + "n原来纪录:"
  343. + model.getRecord(model.getLevel()) + "秒" + "n你用时间:"
  344. + model.getPlayTime() + "秒");
  345. }
  346. /*
  347.  * 提示
  348.  */
  349. else if (obj.equals("remind")) {
  350. int reminds = model.getReminds();// 剩余提示次数
  351. // 点击次数变化,提示变化
  352. ImageIcon icon;
  353. switch(reminds){
  354. case 8:
  355. icon=iRemind8;
  356. break;
  357. case 7:
  358. icon=iRemind7;
  359. break;
  360. case 6:
  361. icon=iRemind6;
  362. break;
  363. case 5:
  364. icon=iRemind5;
  365. break;
  366. case 4:
  367. icon=iRemind4;
  368. break;
  369. case 3:
  370. icon=iRemind3;
  371. break;
  372. case 2:
  373. icon=iRemind2;
  374. break;
  375. case 1:
  376. icon=iRemind1;
  377. break;
  378. default:
  379. icon=iRemind0;
  380. break;
  381. }
  382. btnRemind.setIcon(icon);
  383. }
  384. // 如果是演示
  385. else if (obj.equals("demo")) {
  386. if (btnDemo.getIcon().equals(iDemo)) {// 如果是"演示"则弹出确认对话框
  387. int response = JOptionPane.showConfirmDialog(this,
  388. "是否进入演示模式?", "           请 确 认",
  389. JOptionPane.YES_NO_OPTION,
  390. JOptionPane.QUESTION_MESSAGE);
  391. if (response == JOptionPane.YES_OPTION) {// 经确认后
  392. btnDemo.setIcon(iStop);
  393. // 锁定其它按钮
  394. btnifo.setEnabled(false);
  395. btnPause.setEnabled(false);
  396. btnRemind.setEnabled(false);
  397. btnStart.setEnabled(false);
  398. btnSave.setEnabled(false);
  399. cbPic.setEnabled(false);
  400. cbMusic.setEnabled(false);
  401. btnSound.setEnabled(false);
  402. btnBack.setEnabled(false);
  403. // 开始演示
  404. model.startDemo();
  405. }
  406. } else if (btnDemo.getIcon().equals(iStop)) {// 如果是停止则弹出确认对话框
  407. int response = JOptionPane.showConfirmDialog(this,
  408. "是否退出演示模式?", "           请 确 认",
  409. JOptionPane.YES_NO_OPTION,
  410. JOptionPane.QUESTION_MESSAGE);
  411. if (response == JOptionPane.YES_OPTION) {// 经确认后
  412. model.stopDemo();// 停止演示
  413. btnDemo.setIcon(iDemo);
  414. // 其它按钮激活
  415. btnifo.setEnabled(true);
  416. btnPause.setEnabled(true);
  417. btnRemind.setEnabled(true);
  418. btnStart.setEnabled(true);
  419. btnSave.setEnabled(true);
  420. btnBack.setEnabled(true);
  421. cbPic.setEnabled(true);
  422. cbMusic.setEnabled(true);
  423. btnSound.setEnabled(true);
  424. }
  425. }
  426. }
  427. /*
  428.  * 演示完成
  429.  */
  430. else if (obj.equals("demofinished")) {
  431. // 如果是demoFinished
  432. JOptionPane.showMessageDialog(this, "演示完成!");
  433. btnDemo.setIcon(iDemo);
  434. // 其它按钮激活
  435. btnifo.setEnabled(true);
  436. btnPause.setEnabled(true);
  437. btnRemind.setEnabled(true);
  438. btnStart.setEnabled(true);
  439. btnSave.setEnabled(true);
  440. btnBack.setEnabled(true);
  441. cbPic.setEnabled(true);
  442. cbMusic.setEnabled(true);
  443. btnSound.setEnabled(true);
  444. model.IsDemo=false;
  445. model.startGame(true);
  446. /*
  447.  * 改变图片
  448.  */
  449. else if (obj.equals("pic")) {
  450. int index = cbPic.getSelectedIndex();
  451. String picture = model.getPictureFile();
  452. switch (index) {
  453. case 1:
  454. picFile = "fruit";
  455. break;
  456. case 2:
  457. picFile = "flag";
  458. break;
  459. default:
  460. break;
  461. }
  462. if (!picture.equals(picFile)) {
  463. changePic(picFile);
  464. }
  465. }
  466. // 如果是音乐下拉菜单
  467. else if (obj.equals("music")) {
  468. int index = cbMusic.getSelectedIndex();
  469. String music = model.getMusic();
  470. switch (index) {
  471. case 1:
  472. gameMusic = "我心永恒.mid";
  473. break;
  474. case 2:
  475. gameMusic = "柠檬树.mid";
  476. break;
  477. case 3:
  478. gameMusic = "奇幻旋律.mid";
  479. break;
  480. case 4:
  481. gameMusic = "梦中婚礼.mid";
  482. break;
  483. default:
  484. break;
  485. }
  486. if (!music.equals(gameMusic)) {
  487. changeMusic(gameMusic);
  488. }
  489. }
  490. // 如果是音乐开关
  491. else if (obj.equals("sound")) {
  492. if (btnSound.getText().equals("开")) {
  493. btnSound.setText("关");
  494. bgSound.play(true);// 开始游戏音乐
  495. btnSound.setIcon(iSoundMuse);
  496. } else if (btnSound.getText().equals("关")) {
  497. btnSound.setText("开");
  498. bgSound.stop();
  499. btnSound.setIcon(iSoundPlay);
  500. }
  501. // 如果是暂停
  502. else if (obj.equals("pause")) {
  503. if (btnPause.getIcon().equals(iPause)) {
  504. long currentTime = System.currentTimeMillis();
  505. model.setPauseTime(currentTime);
  506. btnPause.setIcon(iBegin);
  507. // 设置picBoard不可见
  508. pb.setVisible(false);
  509. // 加入cover 
  510. add(cover);
  511. // 其它按钮锁定
  512. btnifo.setEnabled(false);
  513. btnDemo.setEnabled(false);
  514. btnRemind.setEnabled(false);
  515. btnStart.setEnabled(false);
  516. btnSave.setEnabled(false);
  517. btnBack.setEnabled(false);
  518. cbPic.setEnabled(false);
  519. cbMusic.setEnabled(false);
  520. btnSound.setEnabled(false);
  521. model.IsPlaying = false;
  522. } else if (btnPause.getIcon().equals(iBegin)) {
  523. model.pauseDuration();
  524. btnPause.setIcon(iPause);
  525. // 设置picBoard可见
  526. pb.setVisible(true);
  527. //移除cover
  528. remove(cover);
  529. // 其它按钮激活
  530. btnifo.setEnabled(true);
  531. btnDemo.setEnabled(true);
  532. btnRemind.setEnabled(true);
  533. btnStart.setEnabled(true);
  534. btnSave.setEnabled(true);
  535. btnBack.setEnabled(true);
  536. cbPic.setEnabled(true);
  537. cbMusic.setEnabled(true);
  538. btnSound.setEnabled(true);
  539. model.IsPlaying = true;
  540. }
  541. }
  542. // 如果是无解
  543. else if (obj.equals("nosolution")) {
  544. JOptionPane.showMessageDialog(this, "单击确定后自动刷新", "死锁",
  545. JOptionPane.ERROR_MESSAGE);
  546. } else if (obj.equals("about")) {
  547. showifo();
  548. } else if (obj.equals("save")) {
  549. int response = JOptionPane
  550. .showConfirmDialog(this, "保存将会覆盖上次保存的内容!n是否保存?",
  551. "   友情提示", JOptionPane.YES_NO_OPTION,
  552. JOptionPane.QUESTION_MESSAGE);
  553. if (response == JOptionPane.YES_OPTION) {
  554. model.saveGame();
  555. }
  556. } else if (obj.equals("accomplish")) {
  557. JOptionPane.showMessageDialog(this, "恭喜通关!", "通关",
  558. JOptionPane.INFORMATION_MESSAGE);
  559. }
  560. /*
  561.  * 征求玩家意见重新开始游戏或者退出游戏
  562.  */
  563. else if (obj.equals("option")) {
  564. int response = JOptionPane.showConfirmDialog(this, "是否重新开始游戏",
  565. "友情提示", JOptionPane.YES_NO_OPTION,
  566. JOptionPane.QUESTION_MESSAGE);
  567. if (response == JOptionPane.YES_OPTION) {
  568. model.restartGame();
  569. } else {
  570. model.cancel();
  571. }
  572. }
  573. }
  574. else {
  575. pb.repaint();
  576. }
  577. }
  578. }