摘 要 所谓单链表,就是是使用任一种存储单元来对线性表中的数据元素加以保存。扑克牌数据结构程序设计一般包括构建和输入纸牌信息、分牌的具体方式以及最终形成的分牌结果和余牌的算法。整体而言是为更好的理解和掌握理论学习中提到的接种基本抽象数据类别的逻辑、储存架构以及实际的操作和算法,还有上述在程序中如何应用。设计多种类且达成各种模块间的调取,了解和学会通常的软件设计一般形式,锻炼学生设计规范软件的能力。
【关键词】数据结构 程序设计 单链表
1 绪论
1.1 问题重述
现有N套扑克牌,由于时间久远张数已经不全,将其完全混合,希望拼凑成M套完整的扑克牌(大小王不做区分)。
要求:输入数据的首行是一数字N(1≤N≤20),代表原来有N套牌,从次行开始,每四行都用来叙述牌组中不同花色(以黑桃、红桃、梅花、方块为序)的当前张数(各个行的首位数)以及牌号i(1≤i≤13)(每一行的其他数字,乱序)。每输出一行,就认定其可以拼出的1套牌数。依照花色来输出低i(1≤i≤N)套扑克里剩余的扑克,并且所有花色依照其点数进行输出。
实现要求:单链表,具备表头结点。
1.2 单链表的定义和基本操作
单链表,也就是线性表的链式存储,他能够以任一组存储单元将线性表中的数据元素加以储存。为构建起数据元素间的线型联系。要对所有链表节点,除去存储元素自身的讯息,也需要存储一个能起到指向后继作用的指针。它的基本操作包括:通过头插法、尾插法构建单链表;通过序号找出、插入、和删去节点值;求表长操作。
2 概要设计
2.1 抽象数据类型
对于此题,要设计的类大致有下面几个。
2.1.1 Card类
任一张牌所包括的信息有dot(int类,代表特定牌的点数,从1到13)、type(int类,代表牌的花色,以1、2、3、4分别代表黑桃、红桃、梅花、方块)。
2.1.2 Poker类
一套扑克牌类。存储这套牌的全部卡牌有三个方式,分别起到加牌、寻牌和删牌的作用。
2.1.3 pokerDistributor类
分牌器工作目标,将全部残缺牌组织凑齐。
2.1.4 LEArrayList:链表类
操作包括加入元素、去除元素、运算单链表长等。
2.1.5 Test类
主程序类。
2.2 主程序流程
主程序可以对数据输入/输出模块、分牌模块进行调用,让程序保持其完整性和连贯性。先调用输入模块,使用户给出扑克数据,并就输入的数据进行处理。把这些数据封装成实体类后,再对分牌模块进行调用,把牌分好。最后在调用起输出模块,把剩余无用的牌数据输出。
2.3 程序模块的调用
2.3.1 数据输入模块
这一模块的职责是在控制台将用户提供的数据进行分装,成为三种对象。以便于它被其余模块所使用。
2.3.2 分牌模块
把数据输入模块分装好的数据进行读取和分配。
2.3.3 数据输出模块
分牌模块工作完成后会给出可凑齐扑克的套数。以及每副牌剩下的卡牌。本模块的作用就是将剩余牌的数据按照一定格式进行输出。
3 详细设计
3.1 带表头结点的单链表设计
应用泛型,编写能够存储所有数据的、有表头结点的单链表类。
Publicclass LEArrayList
这里T属于泛型,属于单链表存储的数据形式。在建立单链表对象时被调用者所设定。LEArrayList类有着如下信息。
3.1.1 一个内部类
链表结点是privateclass Item的对象类。这里的data字段意思是代表结点数据,next字段则代表下个结点。
3.1.2 一个字段
private Item head是此单链表的表头结点,任何搜索均必须由这一表头结点起始。
3.1.3 四个方法
(1)新增节点,它的思路是要先把应该加入的节点构建一个Item结点对象a,而后再找出现在单键对中的末尾结点b,把b的next字段向a指;
(2)去除节点,它的思路是要先找出需要去除结点的前继/后续结点找出,把前继结点的next字段向后续节点指;
(3)找出预设下标的节点。它的思路是要从head起始循环通过next往下搜索,调用n次next获得的节点下标应是n-1;
(4)读取当前链表长,他的一般思路是自head起始来调用next,一直到获得的節点是null结束,这时调用next的次数就是链表长。
3.2 所有类的设计思想
3.2.1 Card类
Card类:因为最后输出要依照点数来对余牌进行排列,所以完成Comparable接口。它有这样两种字段:privateintdot、privateinttype,包涵以下方法。
(1)是从Object类的equals方法中继承得来,这种方式可以判定两张牌是不是一样,如果其花色和点数的数据相同,就认定其为同一张牌。
(2)完成Comparable接口的途径compareTo,这种措施可以用在对两张牌大小的判别上,设定点数更多的牌是大牌。
3.2.2 Poker类
存储这套扑克中全部的牌,按照项目需要,这里应用单链表LEArrayiLst,并预设数据类型是card。现在给出几个方法。
(1)新增牌:参数c对应某一张牌,调用单链表中新增元素的方式把将牌加进单链表。
(2)找出牌:从链表中找出指定牌c,按顺序选出链表中的全部牌,同时调用Equals方式和C做出对比,判定牌是否一样。
(3)删去牌:和新增牌相像,只需调取链表中的删去元素的方式就可以。
(4)重新编写Object类的方式otsitrng,以便于结束时给出多余牌,这里要重写otsitrng方法,把Poker类的字符串表现模式更替成下面给出的样式:PokerDistributor类。此处编写和Poker相像,通过链表存储全部扑克牌的对象。一般包涵两种方式:新增扑克的方式、分拣扑克的方式。其中后者是本设计中分牌模块的主体方法,收到一参数boolean,如果参数值是false,那么就会转为判定分牌器中有无可能凑齐一副整套扑克。若参数是true,出来判定之外,也会从Poker中删去牌。基本的完成思路是通过两重循环各自负责对花色以及点数进行循环,使用花色和点数构建出一张牌。然后按顺序判定剩余牌中里有没有这张牌,如果剩余牌中有所有的牌,就可认为还可分拣出≥1套的完整牌。如果有任一张牌在余牌中找不到,就不能分拣出整套扑克。
4 设计和调试
在分析时发现的严重问题集中在下面两方面。
4.1 分牌模块
刚着手设计时,Extract方法的效果是能够把牌进行分拣,而没有先判定可不可以分出一整套牌,致使分拣后获取的余牌要少于实际余牌。改良后会在判断完成后再分牌,也就是先循环一遍判定可否凑齐整套牌,如果可以的话再进入到分牌步骤中。
4.2 数据读取模块中的问题
起初时调用in.nextLine()获取控制台输入的数据,不过导致了异常。分析后发现是程序读取\r\n导致了阅读中断。当输入首位数就是余牌的数值时,点击Enter时程序读取换行符后终止,致使读取到了空数据。修正后使用下列代码来对控制台数据进行读取:
while((line=in.nextLine())。isEmpty())
如果数据是空的,就跳到读下行数据进行读取,直至读取数据不为空结束。
4.3 设计缺陷
本设计并不完美,还有部分的缺点:
(1)未设计提示性语句和精美界面,若在输入之前有语句能对用户的输入形式进行提示,那么错误就能避免一大部分。
(2)在输入数据时,如果重复输入(例如一副牌中输入多张梅花A),程序界面不会提示输入错误。
4.4 用户应用说明
(1)本程序使用环境myeelipse对主程序运行。
(2)录入数据时,首行应输入数字N。N代表设定有N套残牌。
(3)次行需要输入首套残牌里黑桃花色当前的数量(1-13内数值)。然后录入这些牌的牌号,以这种形式录入所有残牌花色的数量和牌号。
(4)运行程序。输出结果的首行是能够凑齐的扑克牌数,下面几行则为第i(1≤i≤N)套扑克里残余的扑克,并依照牌的大小来给出。
5 总结
本文设计了一种挑选扑克牌的数据结构程序,遇到了一定问题。但这种综合性训练,在帮助笔者巩固理论知识的同时,也数熟悉和掌握了面对对象程序的设计步骤,让笔者获得了一些相关经验。
参考文献
[1]张素霞.基于数据结构的程序递归算法设计[J].硅谷,2012(12):48+108.
[2]何芳.C程序設计与数据结构课程整合分析[J].数字技术与应用,2012(10):212+214.
[3]耿国华.程序设计能力培养模式的探索与实践[J].中国大学教学,2013(03):30-32.
[4]余金山.逻辑程序设计中的数据结构[J].计算机应用,2015(05):8-11.
[5]仲萃豪,冯玉琳.程序设计方法学[J].计算机研究与发展,2014(03):1-60.
作者单位
张树根(1995-),男,山西省晋中市人。大学本科学历。
作者单位
山西农业大学信息学院 山西省晋中市 030801endprint