资源描述
面向对象课程设计1. 需求分析1.1游戏开发的可行性游戏开发至今已经有30多年,在这个短暂的时期里,随着硬件水平的提高,游戏开发新技术层出不穷,经典游戏比比皆是。游戏这个名称一直就存在于每个人的日常生活中,如猜拳游戏、猜谜游戏、大地游戏、球类游戏等,林林总总,不胜枚举,甚至于有些流行歌曲把人生也比喻为游戏,好比“一场游戏一场梦” 。因此,游戏对于现代人的成长历程,绝对是一个不可或缺的重要角色。1.2设计目的综合运用在校期间所学理论知识和技能,设计开发贪吃蛇游戏,使自己熟悉应用系统的开发过程,培养独立思考能力,检验学习效果和动手能力,提高工程实践能力。1.3游戏需求 给出1条小蛇和随机出1个食物当小蛇吃到食物时就加分。1.3.1游戏界面需求良好的用户界面,有分数显示。有存取档功能,并且可以暂停,还有“英雄榜”记录分数排名情况,并且可调节小蛇运动速度。1.3.2游戏形状(方块)需求良好的方块形状设计,绘制小蛇和食物,小蛇由几个方块组成,食物由1个方块组成。1.3.3键盘处理事件小蛇可通过键盘方向键(上、下、左、右键)进行向上、向下、向左、向右移动。1.3.4显示需求当小蛇吃掉几个食物后会变长,并且吃完食物时食物会消失,并立即随机生成1个新的食物。1.3.5 接口控制本软件需求通过键盘进行操作,在Windows的操作系统下,利用键盘的上、下、左、右键对小蛇进行移动操作,要使用键盘的接口事件。2. 功能设计及源程序的主要部分2.1 游戏流程图2.2 功能的实现,类的实现及类层次 2.2.1游戏界面public SnakeFrame() setSize(width, height); /设置窗体大小setTitle(贪吃蛇); /标题SnakePanel panel = new SnakePanel();/游戏面板add(panel); /将面板添加到窗体中setLocation(260, 160); /设置窗体位置setVisible(true);setResizable(false); /禁用窗体最大化2.2.2功能按钮public SnakePanel() /构造函数/添加功能按钮setLayout(null);add(startGame);add(stopGame);add(saveGame);add(listGame);add(newGame);add(exitGame);/设置位置startGame.setBounds(402, 50, 80, 40);stopGame.setBounds(402, 100, 80, 40);saveGame.setBounds(402, 150, 80, 40);listGame.setBounds(402,200, 80, 40);newGame.setBounds(402, 250, 80, 40);exitGame.setBounds(402, 300, 80, 40);/添加监视器ButtonListener btnListener=new ButtonListener();startGame.addActionListener(btnListener);stopGame.addActionListener(btnListener);saveGame.addActionListener(btnListener);listGame.addActionListener(btnListener);newGame.addActionListener(btnListener);exitGame.addActionListener(btnListener);/取消所有 Button 的焦点startGame.setFocusable(false);stopGame.setFocusable(false);saveGame.setFocusable(false);listGame.setFocusable(false);newGame.setFocusable(false);/速度String speed=1,2,3,4,5,预设;combspeed=new JComboBox(speed);combspeed.setBorder(BorderFactory.createTitledBorder(速度);add(combspeed);/添加组合框combspeed.setBounds(402,340,80,46);comboBoxListener comblistener=new comboBoxListener();combspeed.addActionListener(comblistener);/添加监视器combspeed.setFocusable(false); /取消焦点initGame(); /初始化游戏addKeyListener(new Listener();/添加键盘按键监视器setFocusable(true); /将焦点设置在当前面板上 以便通过键盘控制游戏thiswin=this;2.2.3键盘监视器class Listener implements KeyListener public void keyPressed(KeyEvent e) int key = e.getKeyCode();/获得键码if (key = KeyEvent.VK_LEFT & direction != 2)direction = 0; /左else if (key = KeyEvent.VK_UP & direction != 3)direction = 1; /上else if (key = KeyEvent.VK_RIGHT & direction != 0)direction = 2; /右else if (key = KeyEvent.VK_DOWN & direction != 1)direction = 3; /下public void keyReleased(KeyEvent e) Overridepublic void keyTyped(KeyEvent e) public void keyPressed(KeyEvent e) int key = e.getKeyCode();/获得键码if (key = KeyEvent.VK_LEFT & direction != 2)direction = 0; /左else if (key = KeyEvent.VK_UP & direction != 3)direction = 1; /上else if (key = KeyEvent.VK_RIGHT & direction != 0)direction = 2; /右else if (key = KeyEvent.VK_DOWN & direction != 1)direction = 3; /下2.2.4蛇和食物的变化2.2.4.1蛇和食物的产生:public void drawSnake(Graphics g)Graphics2D g2d = (Graphics2D) g;for(int i=0;iarrayList.length;i+)for(int j=0;jarrayListi.length;j+)if(arrayListij = 1) /蛇身g.setColor(frontcolor); /蛇身颜色else if(arrayListij = 2)/蛇头g.setColor(Color.RED); /蛇头颜色else if(arrayListij = 3) /食物g.setColor(foodcolor); /食物颜色if (arrayListij != 0) int curx = border_left + i * 10;int cury = border_top + j * 10;g2d.draw(new Rectangle2D.Double(curx, cury, 8, 8);2.2.4.2小蛇移动和吃掉食物:public boolean Move() /移动if (direction = 0)x -= 1; /左else if (direction = 1)y -= 1; /上else if (direction = 2)x += 1; /右else if (direction = 3)y += 1; /下/向前移动一步if(GameOver()/游戏结束clock.stop();gameover=true;flag=false; /不再产生新的豆豆if(x =arrayList.length | y = arrayList0.length)elsearrayListxy=2; /此时蛇头位置int headx=snakeBody.get(0).x; /头部坐标int heady=snakeBody.get(0).y;arrayListheadxheady=1; /蛇头变蛇身int tailx=snakeBody.get(snakeBody.size()-1).x;/尾部坐标int taily=snakeBody.get(snakeBody.size()-1).y;arrayListtailxtaily=0; /修改尾部return false; /游戏结束arrayListxy=2; /此时蛇头位置int headx=snakeBody.get(0).x; /头部坐标int heady=snakeBody.get(0).y;arrayListheadxheady=1; /蛇头变蛇身snakeBody.add(0,new Point(x,y);/添加新的头部int tailx=snakeBody.get(snakeBody.size()-1).x;/尾部坐标int taily=snakeBody.get(snakeBody.size()-1).y;if(x = foodx & y = foody) /吃掉了豆豆flag=true; /可以产生新的豆豆score+=time; /总分数time=30; /新豆豆的分值elsearrayListtailxtaily=0; /修改尾部snakeBody.remove(snakeBody.size()-1);/删除旧的尾部return true;2.2.5记录游戏的功能2.2.5.1判断是否可进入记录:public boolean enableShow()if(score = 0)return false;if(!new File(Data).exists()/Data 目录不存在return true;if(!new File(Data,list.snake).exists()/list.snake 文件不存在return true;File file=new File(Data,list.snake);try BufferedReader iostream=new BufferedReader(new FileReader(file);String strline=iostream.readLine();if(strline = null)/空文件return true;int row=0;while(strline!=null)String str=strline.split(#);/信息以#分隔成 name 和 score 两部分if(str.length!=2) /格式错误时删除文件iostream.close();/关闭流 否则无法删除文件file.delete(); /删除文件return true;int gain=Integer.parseInt(str1);if(score = gain)return true;strline=iostream.readLine();/读取下一行row+;if(row = 9)return true;iostream.close();/关闭流 catch (FileNotFoundException e) / TODO Auto-generated catch blocke.printStackTrace(); catch (IOException e) / TODO Auto-generated catch blocke.printStackTrace();return false;2.2.5.2保存数据到文件:public void saveDataToFile(String filename)if(gameover) /游戏已结束无法保存return;File file=new File(Data,filename);try BufferedWriter out=new BufferedWriter(new FileWriter(file);/当前矩阵out.write(Matrixn);for(int i=0;iarrayList.length;i+)/矩阵数据for(int j=0;jarrayListi.length;j+)out.write(arrayListij+#);out.write(n);/换行/snakeBodyout.write(snakeBodyn);for(int i=0;isnakeBody.size();i+)/链表数据String str=String.valueOf(snakeBody.get(i).x);str+=,+String.valueOf(snakeBody.get(i).y);out.write(str+n);/头部坐标out.write(headn);out.write(x+,+y+n);/当前食物坐标out.write(foodn);out.write(foodx+,+foody+n);/是否可产生新的食物out.write(flagn);out.write(String.valueOf(flag)+n);/移动方向out.write(directionn);out.write(String.valueOf(direction)+n);/当前总分out.write(scoren);out.write(String.valueOf(score)+n);/当前食物剩余分值out.write(timen);out.write(String.valueOf(time)+n);/关闭流out.close(); catch (IOException e) e.printStackTrace();catch(Exception ee)2.2.5.3从文件中读取数据:public void readDataFromFile(String filename)for(int i=0;iarrayList.length;i+)for(int j=0;jarrayListi.length;j+)arrayListij=0;/全部初始化为空snakeBody.clear();File file=new File(Data,filename);try BufferedReader in=new BufferedReader(new FileReader(file);String str=in.readLine();if(!str.equals(Matrix)JOptionPane.showMessageDialog(this, 文件格式错误:无法读取);return;/读取矩阵元素str=in.readLine();int i=0;while(str!=null)String data=str.split(#);for(int j=0;jdata.length;j+)arrayListij=Integer.parseInt(dataj);i+;/下一行str=in.readLine();if(str.equals(snakeBody)break;/跳出while循环/读取snakeBody数据str=in.readLine();while(str!=null)String data=str.split(,);int x=Integer.parseInt(data0);int y=Integer.parseInt(data1);snakeBody.add(new Point(x,y); /每次都添加到尾部str=in.readLine();if(str.equals(head)break;/读取头部坐标str=in.readLine();if(str!=null)String data=str.split(,);x=Integer.parseInt(data0);y=Integer.parseInt(data1);str=in.readLine();if (str!=null & str.equals(food) /读取当前食物坐标str = in.readLine();if (str != null) String data = str.split(,);foodx = Integer.parseInt(data0);foody = Integer.parseInt(data1);/读取flagstr=in.readLine();if(str!=null & str.equals(flag)str=in.readLine();if(str!=null)flag=Boolean.parseBoolean(str);/读取移动方向str=in.readLine();if(str!=null & str.equals(direction)str=in.readLine();if(str!=null)direction=Integer.parseInt(str);/读取总分str=in.readLine();if(str!=null & str.equals(score)str=in.readLine();if(str!=null)score=Integer.parseInt(str);/读取当前食物剩余分值str=in.readLine();if(str!=null & str.equals(time)str=in.readLine();if(str!=null)time=Integer.parseInt(str);/关闭流in.close();clock.stop();repaint(); /重绘窗体 catch (FileNotFoundException e) JOptionPane.showMessageDialog(this, 文件未找到);catch(Exception ee)2.2.6英雄排行榜的设计2.2.6.1排行榜的构造:public ListFrame()/构造函数setTitle(排行版);setLayout(new BorderLayout();title=new JButton(英雄排行榜);add(BorderLayout.NORTH,title);title.setFocusable(false);for(int i=0;i10;i+)tabledatai0=String.valueOf(i+1);for(int j=1;j3;j+)tabledataij=;2.2.6.2排行榜的排行记录与顺序:public static void main(String args) new ListFrame();/显示记录public static void showList()new ListFrame().table.setEnabled(false);/插入一条新的记录public static void insertNewData(int score)ListFrame listwin=new ListFrame();Object obj=listwin.tabledata;boolean over=false;for(int i=0;i= data)for(int j=9;ji;j-)/依次后移下面的数据objj2=objj-12;objj1=objj-11;obji2=score;obji1=input your name;over=true;listwin.currentrow=i;break;if(!over)/没有超过以前的记录listwin.table.setEnabled(false);/不可编辑return;listwin.table.isCellEditable(listwin.currentrow, 1);listwin.table.editCellAt(listwin.currentrow, 1);/选中当前单元格JTextField editor=(JTextField)listwin.table.getCellEditor().getTableCellEditorComponent(listwin.table, listwin.table.getValueAt(listwin.currentrow, 1), true, listwin.currentrow, 1);editor.selectAll();2.2.6.3排行榜记录文件的读取:public void checkFile(String filename)/检查 Data 目录是否存在if(new File(Data).exists()elsenew File(Data).mkdir();/创建 Data 目录/检查指定 文件是否存在listfile=new File(Data,filename);if(listfile.exists()/文件已经存在else /文件不存在 创建新的文件trylistfile.createNewFile();catch(Exception e)JOptionPane.showMessageDialog(this, 创建排名文件时发生错误!);/从文件中读取排名信息public void readFromFile(String filename)checkFile(filename);try/读取排名信息文件iostream=new BufferedReader(new FileReader(listfile);String strline=iostream.readLine();int row=0;while(strline!=null)String str=strline.split(#);/信息以#分隔成 name 和 score 两部分if(str.length!=2)JOptionPane.showMessageDialog(this, 读入排名文件时发生错误);return;tabledatarow1=str0;/姓名tabledatarow2=str1;/分数row+;if(row = 10)break;strline=iostream.readLine();/读取下一行iostream.close();/关闭流catch(Exception ee)System.out.println(ee);/将数据写入文件public void writeDataToFile()tryBufferedWriter write=new BufferedWriter(new FileWriter(listfile);for(int i=0;i10;i+)String str=tabledatai1+#+tabledatai2+n;if(str.equals(#n)break;write.write(str);write.close();catch (Exception e) 3. 开发平台Java: 1.6.0_07; Java HotSpot(TM) Client VM 10.0-b234. 测试与发布4.1运行测试过程4.1.1开始新游戏4.1.2游戏运行4.1.3 游戏结束4.1.4变化游戏难度4.1.5游戏排行榜4.1.6游戏存取档4.2测试结果游戏运行状况良好,未发现bug。5. 自我评价与总结5.1遇到的问题及解决的办法先是不太清楚图形化界面的设计,后来在同学的帮助和自己的查找下解决了这个问题。后来在蛇的移动的表示上也不太清楚,找了一些资料后发现蛇身由一串基本图形构成,每过一秒,检测前面是什么,如果是空的,那么把头画成普通身体的样子,再在前方(或侧面,如果转弯的话)再画一个头,并将其坐标记入数组,数组要足够大,再把尾巴画成背景色;如果前面是食物,尾巴就不删除,这里的难点是数组里的操作和坐标的表示:把头添在最后一个元素,把第一个元素提取(也就是尾巴)。最后在排行榜和存档的读取问题上遇到了困难,在同学的帮助下解决了这个难题。5.2 心得体会这次java课程设计让我重新认识到了编程的艺术,在学习、使用Java的过程中,通过与以前所学的C/C+内容的对比,让我进一步巩固了C/C+的知识,并更进一步在总体上让我对编程语言有了更新的认识。在不断的设计、调试、修改的过程当中,我对程序的设计与构架在整体上有了长足的进步。在做java课程设计以前,我对Java游戏开发只是停留在理论知识的水平上,是“纸上谈兵”,缺乏实际的软件开发经验。这次通过做java课程设计,我完成了贪吃蛇游戏的软件开发任务。在整个开发过程中遇到了很多问题,如蛇的移动的表示、排行榜和存档的读取问题、屏幕太闪烁的问题、图形化界面的设计问题,但最终都被我一一解决,对其中比较主要的几点体会总结如下。第一,完成了从局部到整体从细节到大局的转变。设计过程中,经常会遇到困难,我学会通过反复思考和测试,然后找出自己的错误并加以改正,再进行下一个步骤。这个程序就是在这样反复过程序中一点一点的完成的。完成之后再来优化整个程序。第二,做课设是一个不断学习新鲜事物的过程,从设计初的不懂到最后能够顺利完成,我体会到在实践中学习的重要性,这对于将来我走上工作岗位具有重要意义。 第三,通过课设使我对Java这门课程有了一定的了解,也对我今后的就业之路打下了一定的基础。经过一个月的不断努力,课设内容已经基本上完成了。回顾这个设计过程,我学到了许多书本上没有学到的知识。通过这次自己制作的软件,丰富了自己的实践技能,扩展了本专业的知识面,使我受益非浅,同时也体验到了搞软件开发的困难度。在这次设计的同时,我又从中学到了许多东西。但由于我对这样的软件开发还只是一个开始,了解的不多,这其中或许还有很多的不足,有些模块做得不是很好,界面的设计及整体的布局还比较简单,没有突出特色出来,这也可能是我这个系统的不足之处,在这里也恳请各位老师能够对我的作品指明不足并加以改正。总之,在这一次的课设过程中,我查阅了大量的资料,对Java有了一点初步的认识,对于软件工程这些辅助性的教材也巩固了不少,为我这次的课设提供了很大的帮助,锻炼了我的能力让我掌握了一门新的程序设计语言:java语言,系统地学习了数据库方面的知识,并更进一步提高了我在程序设计、调试方面的技巧。更重要的是,它还让我认识到了自己的不足,在编程方面,我仅仅是刚刚入门而已,以后的道路任重道远,需要我不断的丰富自己、充实自己,这样才能在程序设计方面有所收获。
展开阅读全文