Java课程设计-地铁换乘_第1页
Java课程设计-地铁换乘_第2页
Java课程设计-地铁换乘_第3页
Java课程设计-地铁换乘_第4页
Java课程设计-地铁换乘_第5页
已阅读5页,还剩13页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第1章课题概述1.1课题的目的地铁是大城市人们日常生活出行的重要交通工具。但是城市交通资源有限,为引导旅客合理利用线路资源,解决交通瓶颈问题,该城市制定了票价策略:1.每条线路可以单独购票,票价不等。2.允许购买某些两条可换乘线路的联票。联票价格低于分别购票。为了方便使市民出行,通过编写程序构建图形界面为大家提供最优票价的乘车方案。1.2课题的要求1.2.1输入输出的要求(1)程序运行后通过读取票价及站点文件将所有的站点列出,并构建起、终点站文本输入窗口,票价方案文本输出窗口。(2)起点站,终点站应能够从键盘输入,并且可以通过按键不断重复输入、输出。(3)用户每次输入数据并通过提示文本确认后点击“确认”按钮,立即输出票价及乘车方案。(4)方案的输出符合示例要求,所给出的方案是票价最低的方案,如用户输入:五棵松,霍营,程序输出:-(线1,线10)-线8=565。(5)点击窗口关闭按钮后退出程序。1.2.2程序实现的功能要求(1)将地铁站网络通过String[][]二维数组存储,票价通过单线票类和套票类分别存储。(2)给出获取换乘站,各类票价,线名等方法。(3)构建图形界面提供可视化的操作界面。(4)对错误的输入发出提示信息,要求重新输入。第2章概要设计2.1整个程序的模块结构及重点分析。本课题所涉及的难点有两个分别是1.数据的读取与存储2.主算法的设计。根据对java程序一年来的学习并结合课题要求,我将整个程序的模块分为:1.地铁站名数据读取及存储模块。2.票价数据读取及存储。3.图形界面的架构。4.主函数。将每个模块写入一个class文件,并通过方法而调用来实现程序的运行。图2-1整个程序的四大模块2.2数据的读取与存储结构概述2.2.1数据的读取文件的读取是IO章节的内容,在这学期我已经多次练习过并且很熟练了。我在这选择了FileReader提供的方法来读取文件的字节流数据,接着重新构建字符串,最后用String类提供的split方法将站名、票价分解开。2.2.2数据的存储如何将数据合理的存储,使得主函数在调用时方便是这个课题的一个重点,但由于我还没有学习过数据结构,所以只能将数组与数据结合起来思考。(1)地铁网络首先由于文件存储的地铁站名是字符串,户输入的起终点格式也是字符串所以基本不用改变地铁站名的数据类型。其次因为地铁站有1.在哪条线上2.在这条线的哪个位置这两个特性,所以我选择了String[][]二维数组来存储,一维下标表示该地铁站所在的线名,二维下标表示该地铁站在该线的位次。(2)票价由于课题要求计算最划算的票价,所以票价需存储为int类型以方便计算。接下来因为存在单线票价和套票的区别,所以我将单线票价和套票分成两个类:SubwayPriceType1(单线),SubwayPriceType2(套票)来写(方便调用的时候区分)。因为在读取数据的时候已经将2种票价分成了2个数据流,所以将单线票价以int[]数组来存储,一维下标表示线名,套票以int[][]二维数组来存储,一维下标表示换乘前站,二维下标表示换乘后站。这样数据就以合理的形式存储了,为主方法的调用做好准备。2.3图形界面概述图形界面是我通过自学《Eclipse的开发技术详解》一书中的SWT章节来进行架构的,由于是自学所以参照的是计算器的图形界面进行设计的。2.3.1地铁站名的列出将地铁站名按线分组依次创建按钮,只将其作为展示所以没有添加监听器。2.3.2输入输出文本框的构建文本框我使用了TEXT类来进行构建,输入文本框给用户提供了输入界面,输出文本框我设计了2个,分别是输入数据的复核框和最终方案的输出框。复核框提供给用户在按下按键“确认”之前检查自己输入是否合法的检查机会。输出框用来呈现通过主函数获得的最终的票价。2.3.3确认和取消按钮的构建“确认”按钮是本课题的重中之重,用户按键后将输入框获取的数据通过主函数的计算获得方案和票价。“取消”按键则是提供给用户一个清除数据再输入的接口。2.4主函数概述在设计之初我就将主函数定义为:获取起点站,终点站站名,返回字符串给最终方案输出框的方法。由于主函数过于复杂,在此不再赘述,详细参看3.4节。第3章程序功能的实现3.1地铁各站数据的读取与存储结构的实现3.1.1数据读取使用了FileReader,代码如下:FileReaderfis=newFileReader("station.txt");//本段是站名文件,票价类似。for(intb=0;b>=0;b++) { b=fis.read(); if(b==-1) { break; } else { FileData.addElement(b); continue; }}3.1.2存储地铁站名Lines是一个Vector<Stirng>类型的对象,是将数据分解后存储有各条线路所有站名的向量(没有站的线路依然在向量中占据一个位置,值为null),其中的每一个元素是一条线的所有站的站名,通过双重循环向String[][]中赋值,代码如下():String[][]S1=newString[lines.size()][]; for(inti=0;i<lines.size();i++) { String[]S2=lines.get(i).split("\r\n"); S1[i]=newString[S2.length]; for(intj=0;j<S2.length;j++) { S1[i][j]=S2[j]; }}3.1.3地铁网络数据提供的方法(1)返回经过此战的所有线路的线名的数组方法有两个不同参数的方法,第一个方法能将当前线名放在0号元素,第二个方法则是直接返回经过的所有线名并将其从小到大排列,代码如下:publicint[]getLinesNo(Stringstationname,intlineno) { line1.setStations(); crossstation=newVector<Integer>(); crossstation.addElement(lineno); for(inti=0;i<line1.S1.length;i++) { for(intj=0;j<line1.S1[i].length;j++) { if(stationname.equals(line1.S1[i][j])&i!=lineno) { crossstation.addElement(i); } } } int[]linesno=newint[crossstation.size()]; for(inti=0;i<crossstation.size();i++) { linesno[i]=crossstation.get(i); } returnlinesno; } publicint[]getLinesNo(Stringstationname) { line1.setStations(); crossstation=newVector<Integer>(); for(inti=0;i<line1.S1.length;i++) { for(intj=0;j<line1.S1[i].length;j++) { if(stationname.equals(line1.S1[i][j])) { crossstation.addElement(i); } } } int[]linesno=newint[crossstation.size()]; for(inti=0;i<crossstation.size();i++) { linesno[i]=crossstation.get(i); } returnlinesno;}(2)判断两条线是否能换乘的方法因为在查看源数据的时候我发现,存在两条线能换乘但没有套票的情况,为了了满足这种情况,编写了代码如下的方法,返回一个boolean值:publicbooleanLineCango(inta,intb) { line1.setStations(); booleanc=false; for(inti=0;i<line1.S1[a].length;i++) { for(intj=0;j<line1.S1[b].length;j++) { if(line1.S1[a][i].equals(line1.S1[b][j])) { c=true; } } } returnc;}3.2单线票价和套票的数据读取与存储3.2.1单线票价存储单线票价是通过int[]数组来存储的。代码中的subwaypricetype1是一个Vector<String>类型的对象,是将数据分解后存有所有单线票价的向量。方法中我通过单循环向int[]中赋值。其中我对线名进行了解析,使得例如10号线的票价就存储在10号元素中,从而使得调用方便。代码如下:publicvoidsetSubwayPriceType1() { intlength=subwaypricetype1.size();subwaypricetype1.setSize(Integer.parseInt(subwaypricetype1.lastElement().substring(1,3))+1); for(inti=(length-1);i>=0;i--) { subwaypricetype1.set(Integer.parseInt(subwaypricetype1.get(i).substring(1,3)),subwaypricetype1.get(i)); subwaypricetype1.set(i,null); } for(inti=0;i<subwaypricetype1.size();i++) { if(subwaypricetype1.get(i)==null) { subwaypricetype1.set(i,"000000000000"); } } int[]S1=newint[subwaypricetype1.size()]; for(inti=1;i<subwaypricetype1.size();i++) { S1[i]=Integer.parseInt(subwaypricetype1.get(i).substring(4,subwaypricetype1.get(i).length())); } this.S1=S1; }3.2.2套票的存储相对于单线来说套票需要有2个元素,换乘前站和换乘后站,所以我将套票存储在一个int[][]二维数组中,通过双重循环向int[][]中赋值。代码段中的subwaypricetype2是一个Vector<String>类型的对象,是将数据分解后存有所有套票票价的字符串向量。其中我也对线名进行了解析,使得例如10,8号线的套票就存在int[8][10]号元素中,方便方法调用。代码如下:publicvoidsetSubwayPriceType2() { String[][]T1=newString[subwaypricetype2.size()][]; for(inti=0;i<subwaypricetype2.size();i++) { T1[i]=subwaypricetype2.get(i).split("");S1[Integer.parseInt(T1[i][0].substring(1,3))][Integer.parseInt(T1[i][1].substring(1,3))]=Integer.parseInt(T1[i][2].substring(0,T1[i][2].length())); }}3.2.3票价数据提供的方法因为本题中一个人在一条线路上不管怎么乘坐价格是不变的,所以我编写了通过传入线名的int值来调用票价的方法,代码如下:publicintgetLinePrice(intlineno) { returnS1[lineno][0];} publicintgetDiscountPrice(intlineno1,intlineno2) { returnS1[lineno1][lineno2];}3.3窗口的构建3.3.1站名的列出通过添加按键的方式将站名展示在窗口中,代码如下:publicvoidpaintStationList(inti) { GridLayoutlist=newGridLayout(); list.numColumns=12; list.makeColumnsEqualWidth=true; list.horizontalSpacing=5; list.marginWidth=0; list.marginHeight=5; stationlist.setLayout(list); stationlist.setLayoutData(newGridData(GridData.FILL_VERTICAL)); for(intj=0;j<line1.S1[i].length;j++) { Buttonstation=newButton(stationlist,SWT.NONE); station.setText(line1.S1[i][j]); GridDatagridData=newGridData(); gridData.horizontalAlignment=SWT.FILL; gridData.verticalAlignment=SWT.FILL; station.setLayoutData(gridData); }}图3-1站名的列出3.3.2文本框的构建文本框有三个分别是输入框,复核框,输出框,按照课题需要,编写代码如下:publicvoidpaintPriceOutputFrame() { FillLayoutframe=newFillLayout(SWT.HORIZONTAL); frame.marginHeight=5; priceoutputframe.setLayout(frame);priceoutputframe.setLayoutData(newGridData(GridData.FILL_HORIZONTAL)); text=newLabel(priceoutputframe,SWT.BORDER|SWT.LEFT); RGBrgb=newRGB(255,255,255); Colorcc=newColor(display,rgb); text.setBackground(cc); Fontfont=newFont(display,"Arial",14,SWT.NORMAL); text.setFont(font); text.setText("Example:-线01-(线04,线13)=440"); } publicvoidpaintStrategyInputFrame() {strategyinputframe.setLayoutData(newGridData(GridData.FILL_HORIZONTAL)); strategyinputframe.addVerifyListener(newMyListener()); } publicvoidpaintThatStrategyFrame() {thatstrategyframe.setLayoutData(newGridData(GridData.FILL_HORIZONTAL)); thatstrategyframe.setEditable(false);}图3-2文本框的构建3.3.3按键的构建为了实现按键后输出票价方案,就要实现按键的响应和主函数的调用。其中newMainMethod(origination,destination).getStrategy()就是获取方案和票价的方法。按钮的构建和监听器的代码如下:publicvoidpaintButtons() { FillLayoutlist=newFillLayout(); list.type=SWT.HORIZONTAL; list.marginWidth=0; list.marginHeight=5; buttons.setLayout(list);buttons.setLayoutData(newGridData(GridData.FILL_HORIZONTAL)); Buttonaye=newButton(buttons,SWT.PUSH); aye.setText("确认"); aye.addSelectionListener(newMyListener()); Buttoncancel=newButton(buttons,SWT.NONE); cancel.setText("清除"); cancel.addSelectionListener(newMyListener());}publicvoidwidgetSelected(SelectionEventarg0) { Buttonwhether=(Button)arg0.getSource(); Stringthat=whether.getText(); if(that.equals("确认")) { try { stations=thatstrategyframe.getText().split(","); origination=stations[0]; destination=stations[1]; text.setText(newMainMethod(origination,destination).getStrategy()); } catch(Exceptione) { text.setText("本系统尚未完善,交换起、终点站或选择附近站点输入再试。"); } } else//按键是“取消的情况”。 { text.setText("数据已清除。"); strategyinputframe.setText(""); }}图3-2按下“取消”的效果3.4主函数的编写3.4.1站名转换为线名上面说过票价数据提供的方法是传入线名返回票价,所以第一步将站名转化为线名,我们通过调用getLinesNo方法来获取经过该站的所有线名,代码如下:int[]a=crossstation.getLinesNo(origination);int[]b=crossstation.getLinesNo(destination);3.4.2方案的遍历因为起、终点站都有可能是换乘站,所以获取的经过的所有线路的线名是一个数组,我们通过遍历数组来计算所有的方案,代码如下:for(inti=0;i<a.length;i++) { for(intj=0;j<b.length;j++) { intlineno1=a[i]; intlineno2=b[j];//未完3.4.3方案的计算在这个计算中我把所有能够到达的方案和票价添加进两个向量ways和prices之中,在最后再通过比较输出最划算的方案(1)在同一条线上的情况if(lineno1==lineno2) { ways.addElement("线"+lineno1+"="); prices.addElement(subwaypricetype1.getLinePrice(lineno1));}(2)不在同一条线上但两线有套票if(subwaypricetype2.getDiscountPrice(lineno1,lineno2)!=0) { prices.addElement(subwaypricetype2.getDiscountPrice(lineno1,lineno2)); ways.addElement("(线"+lineno1+",线"+lineno2+")=");}(3)不在同一条线上能换乘但没有套票if(crossstation.LineCango(lineno1,lineno2)){ prices.addElement(subwaypricetype1.getLinePrice(lineno1)+subwaypricetype1.getLinePrice(lineno2)); ways.addElement("线"+lineno1+",线"+lineno2+"=");}(4)需要中间站的情况(代码量过大贴出后看不清,参看源代码MainMethod.class中60-120行):(5)所有情况列出后获取最划算方案(代码类似于(6)):(6)在(1)过程结束后再进行一次最划算方案的计算intfinalprice=complexprice.get(0);; if(complexprice.size()==1) { T=complexstrategy.get(0)+complexprice.get(0); } else { for(intk=1;k<complexprice.size();k++) { finalprice=finalprice<complexprice.get(k)?finalprice:complexprice.get(k); } for(intk=0;k<complexprice.size();k++) { if(finalprice==complexprice.get(k)) { T=complexstrategy.get(k)+complexprice.get(k); } }}这样T(String)就传给了文本输出框。第4章程序测试及分析运行程序,窗口呈现

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论