《数独游戏).doc》由会员分享,可在线阅读,更多相关《数独游戏).doc(22页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、【精品文档】如有侵权,请联系网站删除,仅供学习与交流数独游戏).精品文档.数独游戏 益智类游戏是一种比较流行的游戏,其画面都比较简单,很少有复杂的游戏特效,但是通常用到人工智能的算法来控制游戏的难度。而算法的优化是开发该类游戏的难点。这类游戏游戏主要包括棋牌类游戏和智力测试类游戏,例如麻将,扫雷、五子棋、扑克牌等。数独就是益智游戏的一种,玩法简单单数字的排列方式千变万化,很多人认为数独是练头脑的绝佳方式。本章通过讲解数独游戏在java平台的设计与实现,使读者了解此类游戏的开发过程,掌握实用的开发技巧,学会此类游戏的开发。1游戏的背景及功能概述本文在整体上对数独游戏进行了简单的介绍,使读者了解数
2、独游戏的发展,知道什么是数独游戏,以及该游戏的玩法。1.1背景概述数独的前身为“九宫格”,最早起源于中国。但当时的算法比现在的更为复杂,要求纵向、横向、斜向上的三数之和等于15,而不只是数字的不能重复。儒家典籍易经中的“九宫图”也是来源于此。到了18世纪末,瑞士数学家莱昂哈德欧拉又发明了一种叫做“拉丁方块”的游戏,之后不久,美国的一家数学逻辑游戏杂志开始刊登这类游戏,使此类游戏得到良好的发展,之后又在日本得到广泛的传播。2004年,第一个“数独”游戏被刊登上了英国泰晤士报的封面,此时开始数独游戏才真正为世界所知晓。由于此类游戏操作简单,不需要特定的语言基础,也不需要进行数字运算且可玩性高、锻炼
3、思维、开发大脑,所以很快风靡全球。之后由其衍生的游戏也越来越多,例如杀手数独、角线数独等。1.2功能及简介数独游戏的规则很简单,只需在空格处填入19的数字,并保证每个数字在每个九宫格内只能出现一次,且每个数字在每一行、每一列也只能出现一次,而一般的游戏过成功是系统随机生成一个棋局,然后玩家需在空白处填上相应的数字使其满足游戏规则。本文设计的功能如下: 菜单一些常用的操作都放在菜单里面。 显示时间可以正确显示用户游戏时间。 主界面可以通过键盘来输入19数字信息。 必要提示可以通过按钮的不同颜色提示用户信息。 绿色:表示该格的数字目前没有与任何数字有冲突。 黄色:表示该格的数字于同行、同列或是同九
4、宫格中的数字有冲突。可以通过改变其本身的数字或者是与其相关各自的数字来消除。 粉色:表示该格的数字是题目。 白色:表示该格目前没有数字。 同时也可以提示游戏胜利、用户自定义题目存在矛盾、不是唯一解、 用户自定义题目和游戏存档名称不合法等提示信息。 快速开始:可以按照用户设置的难度随机初始化一局有唯一解的游戏。 计时功能:开局的同时开始计时,计算用户玩完一局游戏所用的时间。 重玩:清空所有用户已填数据,重新开始计时。 智能解题:根据题目计算出答案,填满剩下的空单元格。 新建题目:初始化时,所有单元格都是空的,让用户自己填入数字新建题目,并且新建题目的时候也考虑了数独游戏的数字不能冲突特点,不能随
5、便填入数字,也需要确保新建自定义的题目只有唯一解才能进行保存。 保存题目:可以保存用户新建的题目到puzzle目录下。 选局:可以打开你保存的题目并开始一局游戏。 设置难度:提供用户选择随机产生题目的难度,分为“容易、标准、困难、骨灰”。 随机初始化游戏题目时,根据用户选择的难度初始化不同难度的题目。 (不同难度的题目,初始化时给出空格的数量是不一样的,容易:15个空格,标准:30个空格,困难:45个空格,骨灰:在确定只有唯一答案的情况下给出最多的空格)。保存和导入:保存游戏的中间结果,并可导入保存的结果并继续游戏。(游戏存档在save目录下) /排行榜功能:设置排行榜。每次游戏成功完成时,若
6、耗时比先前纪录的第三名短, /将记录玩家姓名和用时。在游戏完成时会显示排行榜,榜上列出耗时长短列出前三名玩家(包括名次、姓名、耗时)。 2 总体设计(5) 数独游戏共由7个部分组成,分别是:MainFrame.java、Checker.java、Creator.java、MyReader.java、Saver.java、Solver.java、TimeKeeper.java。(1) MainFrame.java 构造方法:构造出主界面,并添加按钮、计时器以及菜单,并且初始化。 clear方法:清空游戏数据。无返回值。 ExitListener内部类:监听“退出游戏”菜单选项,并执行退出游戏。
7、ReplayListener内部类:监听“重玩”菜单选项,并执行清空用户填入数据,只保留题目。 DifficultyListener内部类:监听“难度设定”菜单中的所有选项,并在选中难度前显示,将表示难度的变量设定为相应值。 StartListener内部类:监听“快速开始”菜单选项,调用clear方法并调用Creator类的creator方法产生随机题目,对菜单选项进行是否可用的设置并开始计时。设定需要进行胜利判定。 SaveListener内部类:监听“保存题目”菜单选项,调用Checker类的checkCustom方法对自定义题目进行检查和保存。 SaveInGameListener内部
8、类:监听“即时存档”菜单选项,调用Saver类中的save方法进行游戏进度的保存。 LoadListener内部类:监听“载入题目并开局”菜单选项,调用clear方法并调用MyReader类中的read方法读取先前保存的自定义题目,对菜单选项进行是否可用的设置并开始计时。设定需要进行胜利判定。 LoadInGameListener内部类:监听“载入先前存档并开局”菜单选项,调用clear方法并调用MyReader类中的read方法读取先前保存的游戏存档,对菜单选项进行是否可用的设置并开始按照保存的时间进行计时。设定需要进行胜利判定。 AnswerListener内部类:监听“显示答案”菜单选项
9、,调用Solver类中solve方法显示当前题目的答案,对菜单选项进行是否可用的设置并停止计时。ButtonListener内部类:监听按钮是否被点击。获取哪个按钮被点击,并且如果左击按钮就将按钮的数字加一,右击就减一,若显示9时左击或者显示1时右击将会清楚该格数字,成为未填入状态,如此循环。同时调用Checker类的checkWin方法进行胜利判定。main方法:实例化MainFrame类,并且设定主界面位置、大小和标题等信息。(2) Checker.java check方法:依次判断输入数字所在的按钮所在行、所在列、所在九宫格内是否有与填入数字相同的数字,如果存在相同数字,便将输入数字的按
10、钮以及矛盾数字的按钮设置为黄色。如果没有冲突,便将输入数字的按钮设置为绿色。无返回值。 checkGap方法:对现存所有数字为0的的按钮进行19的试填,并且利用与check方法相同的对于冲突性判定的方法进行判断,如果存在一个按钮无法填入19中的任意数字,则该按钮无法填入任何数字,将这个按钮设置为红色。无返回值。 checkCustom方法:调用check方法和checkGap方法检查自定义题目是否存在冲突或是无法填入任何数字的按钮,同时调用Solver类中的solve方法以及solveC方法进行正向和反向的解题,如果解出不同的答案表明不是唯一解,这样将弹出相关提示。如果检查没有问题,就调用Sa
11、ver类中的save方法保存自定义题目。无返回值。 checkRandom方法:利用与checkCustom方法相同的方法检查随机产生的题目是否具有解答的唯一性。返回代表是否具有答案唯一性的布尔型。 checkWin方法:检查是否所有按钮都被填了数字,以及是否没有出现红色和黄色两种代表填入数字不正确的颜色。如果是的话便显示游戏胜利信息和用户所用时间,并读取排行榜文件。把用户用时与排行榜中冠亚季军的成绩作比较。如果打破记录便提示用户输入姓名并将排行榜文件进行相应的改写。最后无论是否破纪录都将显示当前的排行榜。返回代表是否游戏胜利的布尔型。(3)Creator.javacopy方法:将数组A复制给
12、数组B。无返回值。creator方法:产生指定难度的随机题目。先在随机位置填入19各一个,然后解出答案。然后挖掉难度要求的空格。没挖一个测试一下题目是否具有答案的唯一性,如果不是便将挖掉的格子原样填上。最后将所有有数字的按钮设定为表示题目的粉色。无返回值。(4)MyReader.java 构造方法:获得读取存档或是自定义题目的目录。 read方法:在指定目录的位置使用FileChooser读取文件。按照储存的格式读取数据并且进行按钮的文字颜色设定。无返回值。(5) Saver.java 构造方法:获得储存存档或是自定义题目的目录。 save方法:提示用户输入想要保存的文件名,并在指定目录下新建
13、存档文件。如果出现同名文件便提示用户是否需要覆盖。同时进行文件名是否是由字母或者数字组成的判断,若不合法将弹出提示。无返回值。 dataWrite方法:按照一定格式向存档文件写入数据。无返回值。(6) Solver.java solve方法:对现存所有数字为0的的按钮进行19的试填,并且利用与check方法相同的对于冲突性判定的方法进行判断,如果有冲突便填入下一个数字。如果没有冲突将运用递归的手段查看是否后续会出现冲突,如果后续会出现冲突就将该按钮上的数字清空。若没有问题就将该按钮设置为浅蓝色。返回布尔型,表明是否存在冲突。 solveC方法:与solve方法相同。只是试填的时候是进行91倒序
14、的试填。该方法与solve方法一起使用能检测题目是否具有答案唯一性。(7)TimeKeeper.java 构造方法:设定显示时间的字体。 paintComponent方法:清空先前的时间并画出当前时间。无返回值。 start方法:计时器开始计时。无返回值。 pause方法:计时器暂停。无返回值。 stop方法:计时器停止计时。无返回值。 getSecond方法:获取当前游戏时间(用秒表示)。返回整形。 setSecond方法:设定当前游戏时间(读档时使用)。无返回值。 TimerListener内部类:定时器。每隔一秒画出当前时间。3 代码实现3.1 MainFrame.javaMainFra
15、me.java的作用为生成数独游戏的主界面,实现对界面中的菜单栏中的各组件、文本、按钮的事件监听。其代码如下:import javax.swing.*;import java.awt.*;import java.awt.event.*;import java.io.*;import java.util.*;public class MainFrame extends JFrame public JPanel pnlGame; public JTextField txtGame;boolean start = false;/是否开始计时boolean winCheck = false;/是否要进
16、行胜利判定int difficulty = 30;/随机产生题目的难度(即随机产生有多少个空格的题目)。默认为/产生30个空格的题目MyReader mr = new MyReader();/读档器Solver my = new Solver();/解题器 Creator c = new Creator();/随机出题器int origin = new int 99;/题目数字。int matrix = new int 99;/当前游戏数字填入情况的数据。 Timekeeper time = new Timekeeper();/计时器JMenuItem jmi1 = new JMenuItem
17、(退出);JMenuItem jmi2 = new JMenuItem(快速开局);JMenuItem jmi3 = new JMenuItem(自定义题目);JMenuItem jmi4 = new JMenuItem(显示答案);JMenuItem jmi5 = new JMenuItem(保存题目);JMenuItem jmi6 = new JMenuItem(载入题目);JMenuItem jmi7 = new JMenuItem(即时存档);JMenuItem jmi8 = new JMenuItem(载入先前存档);JMenuItem jmi9 = new JMenuItem(简单
18、);JMenuItem jmi10 = new JMenuItem(标准);JMenuItem jmi11 = new JMenuItem(困难);JMenuItem jmi12 = new JMenuItem(骨灰);JMenuItem jmi13 = new JMenuItem(重玩);JButton but1=new JButton(PLAY); JButton but2=new JButton(暂停); JButton but3=new JButton(00:00:00); JButton but4=new JButton(完成);public MainFrame()/主界面 pnlG
19、ame = new JPanel9; txtGame = new JTextField99; BorderLayout b1=new BorderLayout(5,5); setLayout(b1); JMenuBar jmb=new JMenuBar(); JMenu jm1 = new JMenu(模式); JMenu jm2 = new JMenu(游戏); JMenu jm3 = new JMenu(自定义题目); JMenu jm4 = new JMenu(难度设定); ActionListener exitListener = new ExitListener(); ActionL
20、istener startListener = new StartListener(); ActionListener customListener = new CustomListener(); ActionListener loadListener = new LoadListener(); ActionListener saveInGameListener = new SaveInGameListener(); ActionListener answerListener = new AnswerListener(); ActionListener saveListener = new S
21、aveListener(); ActionListener loadInGameListener = new LoadInGameListener(); ActionListener difficultyListener = new DifficultyListener(); ActionListener replayListener = new ReplayListener(); MouseListener buttonListener = new ButtonListener(); / MouseListener textfieldListener = new TextFieldListe
22、ner(); jmi1.addActionListener(exitListener);jmi2.addActionListener(startListener);jmi3.addActionListener(customListener);jmi6.addActionListener(loadListener);jmi4.addActionListener(answerListener);jmi5.addActionListener(saveListener);jmi7.addActionListener(saveInGameListener);jmi8.addActionListener(
23、loadInGameListener);jmi9.addActionListener(difficultyListener);jmi10.addActionListener(difficultyListener);jmi11.addActionListener(difficultyListener);jmi12.addActionListener(difficultyListener);jmi13.addActionListener(replayListener);jm1.add(jmi2);jm1.add(jmi6);jm1.add(jmi3);jm1.add(jmi8);jm1.add(j
24、mi1);jm2.add(jmi4);jm2.add(jmi7);jm2.add(jmi13);jm3.add(jmi5);jm4.add(jmi10);jm4.add(jmi9);jm4.add(jmi11);jm4.add(jmi12);jmb.add(jm1);jmb.add(jm2);jmb.add(jm3);jmb.add(jm4);add(jmb,b1.NORTH);JPanel mainPanel1 = new JPanel();JPanel mainPanel2 = new JPanel();JPanel mainPanel3 = new JPanel();JPanel mai
25、nPanel4 = new JPanel();add(mainPanel1,b1.CENTER); time.setPreferredSize(new Dimension(80,300);add(time,b1.EAST); mainPanel2.add(but1);mainPanel2.add(but3);mainPanel2.add(but2);mainPanel2.add(but4);add(mainPanel2,b1.SOUTH); mainPanel1.setLayout(new GridLayout(3,3); for(int i = 0;i 9;i+) pnlGamei = ne
26、w JPanel(); pnlGamei.setBorder(BorderFactory.createLineBorder(Color.black); pnlGamei.setLayout(new GridLayout(3,3); for(int j = 0;j 9;j+) txtGameij = new JTextField();txtGameij.setBorder(BorderFactory.createEtchedBorder();txtGameij.setFont(new Font(Dialog, Font.ITALIC, 20);/设置字体大小txtGameij.setHorizo
27、ntalAlignment(JTextField.CENTER);/设置字体居中 mainPanel1.add(pnlGamei); for(int i = 0;i 3;i+) pnlGame0.add(txtGamei0); pnlGame0.add(txtGamei1); pnlGame0.add(txtGamei2); pnlGame1.add(txtGamei3); pnlGame1.add(txtGamei4); pnlGame1.add(txtGamei5); pnlGame2.add(txtGamei6); pnlGame2.add(txtGamei7); pnlGame2.ad
28、d(txtGamei8); for(int i = 3;i 6;i+) pnlGame3.add(txtGamei0); pnlGame3.add(txtGamei1); pnlGame3.add(txtGamei2); pnlGame4.add(txtGamei3); pnlGame4.add(txtGamei4); pnlGame4.add(txtGamei5); pnlGame5.add(txtGamei6); pnlGame5.add(txtGamei7); pnlGame5.add(txtGamei8); for(int i = 6;i 9;i+) pnlGame6.add(txtG
29、amei0); pnlGame6.add(txtGamei1); pnlGame6.add(txtGamei2); pnlGame7.add(txtGamei3); pnlGame7.add(txtGamei4); pnlGame7.add(txtGamei5); pnlGame8.add(txtGamei6); pnlGame8.add(txtGamei7); pnlGame8.add(txtGamei8); but1.addMouseListener(buttonListener); but2.addMouseListener(buttonListener); but4.addMouseL
30、istener(buttonListener);for(int i = 0;i 9;i+) /设定每个按钮大小、是否可用等参数for(int j = 0;j 9;j+)if (matrixij = 0)txtGameij.setText();else txtGameij.setText( + matrixij); txtGameij.setBackground(null); txtGameij.setSize(50,50); txtGameij.setEditable(false);/最开始时不能点击void clear() /在重新开局之后清空上次游戏的数据for(int i = 0;i 9
31、;i+)for(int j = 0;j 9;j+)matrixij = 0;originij = 0;txtGameij.setText();txtGameij.setEditable(false);txtGameij.setBackground(Color.WHITE); private class ExitListener implements ActionListener /退出游戏public void actionPerformed(ActionEvent e)System.exit(0);private class ReplayListener implements ActionL
32、istener /重玩本局 public void actionPerformed(ActionEvent e)time.stop();for(int i = 0;i 9;i+) for(int j = 0;j 9;j+) if(txtGameij.getBackground().equals(Color.WHITE) matrixij = 0; txtGameij.setText(); txtGameij.setEditable(false); time.setSecond(0);private class DifficultyListener implements ActionListen
33、er /难度设定。选中难度的菜单选项前将会出现 public void actionPerformed(ActionEvent e)jmi9.setText(简单);jmi10.setText(标准);jmi11.setText(困难);jmi12.setText(骨灰);if(e.getSource().equals(jmi9)jmi9.setText(简单);difficulty = 15;if(e.getSource().equals(jmi10)jmi10.setText(标准);difficulty = 30;if(e.getSource().equals(jmi11)jmi11.s
34、etText(困难);difficulty = 45;if(e.getSource().equals(jmi12)jmi12.setText(骨灰);difficulty = 81; /在确定解答的情况下尽可能多的挖掉格子。 private class StartListener implements ActionListener /开始随机游戏.public void actionPerformed(ActionEvent e)jmi4.setEnabled(true);/将每个模式可以使用的和不可用的菜单命令进行设定,下同.jmi5.setEnabled(false);jmi7.setEn
35、abled(true);jmi13.setEnabled(true);start = true;clear();c.creator(origin,txtGame,difficulty);/产生随即题目c.copy(origin,matrix);/将结果复制给matrix数组winCheck = true;/需要进行胜利判定time.setSecond(0);/计时器清零 private class SaveListener implements ActionListener /检验自定义题目并储存题目。public void actionPerformed(ActionEvent e)Chec
36、ker c = new Checker();c.checkCustom(txtGame,matrix); /检查题目是否有冲突以及是否有唯一解并保存private class SaveInGameListener implements ActionListener /游戏中保存进度。public void actionPerformed(ActionEvent e) Saver saver = new Saver(save); /将保存目录设定为save saver.save(txtGame,matrix,time.getSecond();/保存private class LoadInGame
37、Listener implements ActionListener /即时读档。public void actionPerformed(ActionEvent e)jmi4.setEnabled(true);jmi5.setEnabled(false);jmi7.setEnabled(true);jmi13.setEnabled(true);start = true;clear();int saveTime = 0;mr = new MyReader(save); /告诉读档器应该从save目录去读游戏存档saveTime = mr.read(txtGame,matrix,origin);
38、/读取游戏存档以及时间winCheck = true;/需要进行胜利判定time.setSecond(saveTime); /将计时器时间设定为保存的时间 private class LoadListener implements ActionListener /载入自定义题目public void actionPerformed(ActionEvent e)jmi4.setEnabled(true);jmi5.setEnabled(false);jmi7.setEnabled(true);jmi13.setEnabled(true);clear();mr = new MyReader(puz
39、zle); /告诉读档器应该从puzzle目录去读自定义题目mr.read(txtGame,matrix,origin);/读取题目c.copy(origin,matrix);/把题目复制给originstart = true;winCheck = true;/需要进行胜利判定time.setSecond(0);/计时器清零 private class CustomListener implements ActionListener /进入自定义题目模式public void actionPerformed(ActionEvent e)jmi4.setEnabled(false);jmi5.s
40、etEnabled(true);jmi7.setEnabled(false);jmi13.setEnabled(false);clear();for(int i = 0;i 9;i+)for(int j = 0;j 9;j+)txtGameij.setBackground(Color.WHITE);txtGameij.setEditable(true);start = true;time.stop();winCheck = false;/不需要进行胜利判定private class ButtonListener extends MouseAdapter /监听鼠标动作public void m
41、ouseClicked(MouseEvent e)Checker myChecker = new Checker();if(e.getSource() = but2)time.pause();if(e.getSource() = but1)for(int i = 0;i 9;i+)for(int j = 0;j 9;j+)if(matrixij = 0)txtGameij.setText();txtGameij.setEditable(true);time.start();if(e.getSource() = but4)for (int i = 0; i 9; i +) for (int j = 0; j 9; j +) if (txtGameij.getText().compareTo() != 0) matrixij=(int)Integer.parseInt(txtGameij.getText();txtGameij.setText(+matrixij); else matrixij = 0; txt