马头琴基础教程及马踏棋盘实验报告单(含代码)_第1页
马头琴基础教程及马踏棋盘实验报告单(含代码)_第2页
马头琴基础教程及马踏棋盘实验报告单(含代码)_第3页
马头琴基础教程及马踏棋盘实验报告单(含代码)_第4页
马头琴基础教程及马踏棋盘实验报告单(含代码)_第5页
已阅读5页,还剩37页未读 继续免费阅读

下载本文档

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

文档简介

跟我学马头琴-基础教程击弓这种演奏法是演奏者利用弓子的弹性,用弓毛敲击琴弦弹起后再敲击来演奏的。这种演奏法所获得的音质是轻巧而富有弹性。在马头琴演奏中,常用左半弓或偏左中弓来演奏。演奏时,手腕不能过紧、过僵,也不能过松。主要用下臂和手腕的密切配合来演奏。击弓的符号是“”。为了记谱方便,有时不在每个音上都作出标记,而是用“下同”的标记法来标出需用去弓演奏的乐段跳弓跳弓可分为二种,一种是自然跳弓,另一种是人工跳弓。a.演奏自然跳弓时,人为的力度要小一些,主要是利用弓子自己的弹性。演奏时,右手的各个部位不得紧张,手腕及手指放松到能握住弓子即可。食指和中指松弛地放在弓杆上,无名指和小指勾住弓毛,拇指稍压紧弓柄。运弓要平行。最适合拉自然跳弓的部位是中弓和偏左中引这种弓法演奏比较均匀的快速曲子很适宜。演奏时,弓毛最好不要寓弦。b.演奏人工跳弓时,人为的力度较大些,小臂和手腕及手指稍加控制弓子。与自然跳写的不同之处是弓毛离开琴弦。这种弓法演奏慢一点的乐曲很适宜。还可以演奏渐慢和渐快的乐曲。最适合做人工跳弓演奏的弓子部位是中弓或偏右中弓处。跳弓的符号是“?”长乐段的跳弓也可用“……下同……”标记法表示。对以上两种弓法,可以根据乐曲的速度灵活地交替运用。演奏者还可以根据自已弓子的弹性、乐曲的速度及里外弦的具体情况灵活地运用弓子的不同部位。自然跳弓的练习方法,首先要从运用中弓开始。尽可能用快和短的分弓,把弓子的重心点牢牢均压在弦上,不叫弓子跳动。做第二步练习时,用同一个方法,但不加压力,使弓子自然跳起。这时要注意右手各部位不得紧张僵硬。跳弓时,弓毛不能跳得太高,要求弓毛碰弘时间短促,音质干净、清楚。索格斯日赫弓这种弓法是快而短促的分弓;是马头琴演奏长调歌曲时经常应用的一种弓法。奏法是在一个长时值音的中间或后半部分用弓尖或左半弓迅速地来口拉奏一下,奏出两三个同青反复的装饰音。它的符号是“”。这一弓法实际上就是当一弓拉不完一个长时值音时的补充手段。使用这种弓法时,腕部要放松。同时还要根据乐曲的情绪灵活运用。双弓这种弓法实际上是每个音符奏两弓(一推一拉)的意思,一般出现在快速演奏中,其符号为音符右下方的“`”或乐曲的开头注上“双弓”。指法指法常识马头琴的指法不同于其它各种弓弦乐器。它不但有独特的按弦法,而且有独特的指法,从而形成了自己独特的民族凤格。如果这种特殊指法掌握不好,那么民族风格也就无法体现了现在将指法技巧介绍如下:(1)手指按弦法一般拉弦乐器,演奏时都是从正面压弦,马头琴则不同,它是用食指和中指的指甲根从左向右顶弦,无名指和小指是用指尖从左向右顶弦,小指够不着里弦时,它从外弦底下伸过去顶里弦(奏外弦时直接顶弦)。一般初学者可以把指甲留得稍长,以避免手指从弦上滑落。(2)手指起落手指顶弦奏出不同的乐音后,不要抬得过高,否则会影响演奏速度和人为地造成手指的紧张和僵硬。另外,因为马头琴的音位间隔比较宽,(特别是一、二把位的音位),所以手部要放松,手指自然张开,不要挤在一起,否则容易造成手指不按在音位上,演奏出来的音也就不准了。手指顶弦力量过大,音质会发问,还会造成乐音偏高,而且影响手指的灵活性。顶弦力量过小,则音质不结实、苍白,产生飘音和杂音。所以要在练习中,仔细寻找项弦所需要的最适当的力度。(3)音准问题音准与不准,关键在于手指是否按在准确的音位上。因为演奏时有快慢不同,有时可能按得偏低或偏高,同时马头琴是从侧面顶弦,有时可能顶过劲而使音偏高不准,这一点主要*演奏者的听觉来辨别,这就需要演奏者在平时加强听觉训练,熟悉各种调性、调式的音阶,提高识别音的能力。另外,要养成按规定指法来演奏的习惯,熟悉琴的把位和音位,逐渐达到“触弦即准”的程度。这里,还需要特别提到的是,马头琴是四度定弦乐器,换把是极其频繁的,往往在倒换把位时容易出现音不准的现象,这就需要演奏者在平时努力掌握各把的音位以及音位与音位之间的距离等问题。要做到“触弦即准”,就必须在“练”字上下功夫,逐渐使自己的臂、手、指对移动距离和位置形成直感,并将这种感觉与听觉统一起来,达到发音准确的目的。2.指法技巧(1)换把a.滑指换把。它不但是一种换把方式,也是演奏蒙古族乐曲表现民族风格的一种手段。换把的速度分快慢两种,由乐曲的内容和情绪的需要而定。慢滑指换把一般用在速度较慢的乐曲中,快滑指换把一般用在欢快的乐曲上。b.跳指换把。在蒙古族乐曲中,八度和八度以上的大跳是很多的。遇到这种情况时,要用到跳指换把。在跳指换把时,一种是直接跳到所需要的音位上,另一种是当需要奏出二、三、四指等音位上的乐音时。仍然将一指跳到一指的音位,再用二、三、四指立即接到所需要的音位上。这时的一指只是个“经过音”。这个“经过音”在练习跳指换把时是很重要的,它可以帮助演奏者较为准确地奏出换把后的音来,待熟练后,再把“经过音”去掉,但是一指一定要在“经过音”的位置。在跳指换把过程中,要手指离弦。不带出任何声响(而滑指换把则是手不离弦),一定要减轻手指触弦的力度,否则由于弓子相应增加力度,会发出由弱到强又从强到弱的()滑音。无论使用哪一种换把,演奏时都要注意左腕的带动(提)动作,即无论上跳或下跳的换把都要手腕先行,手指在手腕的带动下进行。待从此把位滑(或跳)至另一把位后,再将。左手腕与左手各部位的姿势还原。否则,手腕如果与手指同时行动,就会造成手腕紧张、僵硬,影响正常换把。在换把过程中,要注意将左手虎口放松,切忌紧夹琴杆,否则,会影响换把速度和灵活性、准确性,给演奏带来不良后果。练习经过音时,请参看下面的例子:(2)同音打弦装饰音(符号是“tr”或“三”、“四”)同音打弦装饰音是是马头琴演奏的特殊技巧之一,同时也是表现蒙古族音乐风格的具体手段之一。这种指法技巧的运用有两种方式,一种是在节拍的后面出现,另一种是在节拍前面出现。它们的特点是在用二度和三度音位时,用二、三、四指打弦。如一指奏着旋律音,那么就用二、三、四指在不同音位上打弦奏出;若二指奏旋律音,则用四指打弦奏出;若三指奏旋律音,也用四指打弦奏出。从音位上讲,虽然是6—6i或6—6i,奏着(或)不同音位的打弦,但奏出的效果是的音响效果。上面虽然是在不同音位打弦,但是所奏出的效果不是所打音位的实音,而是所奏音的同音装饰音。手指打几下弦则是几个同音装饰音。例如打三下,则是66的效果。在演奏四、五连音时,节奏要稍快一点,二、三连音稍慢一点。在马头琴演奏中,一般是一指按弦时三指打弦;二、三指按弦时,四指打弦。但是在三轮按弦四指打弦时,是在高把位应用,因为高把位音位距离短,所以可以打出大小三度音位的打弦。(3)颤指(符号“tr”)颤指的指法技巧,是从西洋小提琴等弦乐器的演奏技巧上移植过来的。一般演奏现代乐曲和其它民族乐曲时应用,在民间和传统演奏中很少应用。它与同音装饰音所不同的是奏出打音的实音,从而同旋律音反复奏出打弦音。演奏时,手指要放松,用手指的弹性来打弦。例如:1=D颤指在练习中,容易出现的毛病有:①拇指过于紧张;②手腕僵硬;③按在弦上的手指过分用力顶弦;④手指抬得过高而影响速度;⑤手指拾得不够高,没有弹力或节奏不稳,忽快忽慢等。纠正方法:手臂、腕部和手指既要放松,同时又要有控制地演奏。(4)同音打弦这种演奏法不同于同音装饰音的地方,只是所打的音不是装饰音,而是旋律中的基本音。在演奏时所用的方法与同音装饰音一样。它也是蒙古族音乐风格的表现手法之一,这种奏法,有着深沉、饱满而又强烈激动的特点。它没有过多换弓造成的断续感觉。同音打弦一般用连弓演奏。例如。在这一例子中,第一小节中的“335”的第二、三个“8”音就是用打弦的方法获得的。同样第二小节的两个“5”音也是用打弦指法获得的。用第几指打弦可以用数字和括号来表示。如前例中的(三)一样。从这一例中,我们可以看到记谱是:“3”音都是三指在“5”音的音位上打孩出来的。第二小节的第一、二个a6”音是第三指在“7”音的音位上打弦奏出的,这的第—指都不抬起。同音打弦法关键在于打弦不改变旋律音的性质,只给旋律音一个“间断”的感觉。手指不是压在弦上,而是打在弦上,需要手指富有弹性,如果是手指压在弦上,就会使原旋律音变成所压音位的实音。(5)滑音马头琴在演奏蒙古族乐曲时,经常运用滑音来表现乐曲的情感。这也是一种特殊的表现手法。一般常用的滑音有三种。①上滑音(符号是“,”)上滑音是从所奏的旋律音滑向上面的旋律音。一般是向它上方三度以上的旋律音跳进时运用上滑音。例如:实际演奏法是:355滑音是用前面演奏的同一手指滑向另一个旋律音的。②下滑音(符号“、”)下滑音是从所演奏的旋律音向下滑到另一个旋律音。实际演奏法是:……。实际演奏法是:③回滑音(符号是“八”)回滑音也是在演奏蒙古族乐曲时常常运用的一种演奏方法。一般以大二度音程关系、小三度音程关系和大已度音程关系的方式出现,同时以快速回滑二、三、四次的方式演奏。演奏时不换把位,常用三指或四指演奏。实际演奏法上:这种回滑音一般用在节拍的最后一拍的前半拍之前,往往是一弓奏出的。在长音处,有时也根据乐曲的情绪在回滑音之前用索格斯日赫弓法。用这种弓法的演奏效果是:这种处理是自由的色彩性处理,往往是由演奏者和歌者的临时情绪的高涨而油然产生的。(6)和音马头琴常常较多地采用双和音来演奏。一般在按一根弦的同时,同另一根空弦形成二三、四、五六、七、八度和音。另一种较为普遍地是用拇指从里弦右侧第二把位上触弦形成纯四度或八度的泛音和音。目前除了采用这些和音方式演奏以外,还吸收了中外弦乐器演奏方法。用双指(一指和二指)同时触弦奏出双弦上的双实音和音,从而可以奏出二三、四、五、六、七、八度的实音和音。(7)揉弦揉弦演奏法是表现乐曲各种感情变化的极有力手法,马头琴的揉弦又有它自己的特殊性。揉弦是用手指上下滚动顶指得到的勇音效果。揉弦的力量主要来自左上臂,再通过下管来带动手腕和手指,是由各部分的有机配合来完成揉弦任务的。探弦时,左手手指顶弦力度要适当,左上管、下臂、腕子和手指要适当放松,不能但硬,要有韧性。这种奏法适合中板或较慢的乐曲,可以表现比较细腻的、深思的及悲伤的乐曲。揉弦时,要根据乐曲的内容和感情的变化来改变揉弦的幅度。速度慢的乐曲,揉弦的幅度要大一些;速度较快的乐曲,揉弦的幅度要小一些。另外,各种情感、情绪的乐曲同用弓的力度有极密切的关系.因此探弦是同一定的音质、音量都互相关联着。一般地讲,在低把位时揉弦幅度要大一些,在高把位时要小一些。揉弦容易出现的问题有以下几种:①顶弦指的力度过小,是因为上臂、下臂以及手腕过分紧张,各部位没有放松。因而力量集中在上臂没有传到手指上。也可能是由于上管、下管及腕部过分放松,没有真正地顶住弦,从而造成了苍白和空飘的音质。纠正的办法是:对于前一种情况,在练习时,上、下管和腕部要适当放松,手指要有韧劲,顶住琴弦,慢慢地练习。对于后一种情况,练习时要适当加强上、下臂和腕部的力度,手指顶好弦后再练。②揉弦时,由于手指和腕部过于僵硬,上、下臂摆动过大,因而造成揉弦的幅度很大,发出来的声音不均匀,不准确,音波忽大忽小、忽高忽低,听起来很不舒服。纠正方法:手腕要放松,缩小下臂的摆动幅度,使手腕和手指更多地参加揉弦动作,让手指的滚动幅度和快慢均匀。(8)保留指保留指的演奏法是在低于正在演奏着的音位上,把其它没有参加演奏的手指,按指法顶在弦上的一种预备指法动作。它的特点在于:把不参加演奏的手指,按音位轻轻地顶在弦上,这样既保证了发音的准确,也不影响速度和换把,同时减少了指法的混乱,因而保证了乐曲进行的速度。当一指卖完二指按弦时,一指不用抬起,继续轻轻顶住弦。当一指滑到上一把位的音位后,也象前一把那样顶弦。特别是速度快起来时,就更没有拾指的机会,如果抬指就会影响速度和乐曲的进行。(9)弹弦(符号是“+”)弹弦是用左手的一指或二指从弦的里面往外弹弦(右手的琴弓同时拉弦)。或者是在弹弦的同时用弓击弦,奏出击鼓节奏。弹弦时,手指要有力度。这是第一种边拉迪弹的形式。这是先弹后击的弹拨击弓奏法。(10)拨弦(符号是“piZZ”)这种技巧是马头琴演奏者为了表现乐曲的需要,从其它乐器上移植过来的。演奏方法是:左手继续顶弦,右手二、三、四指继续握住弓,用右手第一指拨弦。这种演奏法一般用在欢快的乐曲之中。(11)泛音演奏技巧这种演奏法和演奏技巧是从民间江音演奏法中继承过来的。它同单音顶指演奏结合起来运用。演奏法是同前面介绍的江音演奏法(五度定弦演奏法和反四度定弦演奏法)是一样的,主要用一、三、四指指尖,从弦左侧向右顶弦演奏。运弓要有力度,顶弦时要轻轻触弦,这样就能获得江音音响。同时用拇指触弦,同一指结合形成纯四度泛音,同三指结合形成纯八度和音,这两个双和音是比较常用的泛音。在需要演奏高把位的音时,一般不到高把位,而是在原把位或中把位上用江音奏出。从上面的谱例我们可以看到到的“5”音,不是往上把位走,而是回到外弦上的泛音位置,“3”音和“5”音也一样不往上走,而是在外弦的泛音上演奏。从而不换把位,用泛音代替实音,对某些没有江音的实音则奏出实音。因此,所谓泛音技巧,就是泛音同实音交替使用的演奏法(12)“潮尔”演奏技巧这种演奏法,可以在反四度定弦的外弦上演奏。(13)滑音颤指这是一种华彩性的技巧。常常用来模仿马的嘶鸣。一般用在华彩性乐段中。主要是在下行大滑音中运用。演奏法是一个手指触弦滑音,另一个手指颤指滑下。计算机学院《数据结构》课程设计报告课题名称:马踏棋盘 课题负责人(学号/姓名):同组成员名单(姓名):指导教师: 评阅成绩:评阅意见: 提交报告时间:Time\@"yyyy年M月d日"2021年10月8日项目成员序号学号姓名职责任务说明1110520131刘伟小组成员需求分析用户使用说明测试结果2110520121黎贵涛组长概要设计2.详细设计3110520104林建彪小组成员1概要设计2.调试分析一、【问题描述】设计一个国际象棋的马踏棋盘的演示过程。基本要求:将马随机放在国际象棋的8*8棋盘Board[8][8]的某个方格中,马按走棋规则进行移动,要求每个方格只进行一次,走遍整个棋盘的全部64个方格。编制非递归程序,求出马的行走路线,并按求出的行走路线,将数字1,2,…,64依次填入一个8*8的方阵,输出之。测试数据:可自行制定一个马的初始位置(i,j),0<=I,j<=7。二、【实验目的】1、对数据结构基本理论和存储结构及算法设计有更深入的理解;2、了解栈的特性,以便在实际问题背景下灵活运用他们;3、提高在世纪设计操作中系统分析、结构确定、算法选择、数学建模和信息加工的能力。【设计过程】81726354第1步:实现提示一般来说,当马位于位置(i,j)时,可以走到下列8个位置之一:(i-2,j+1),(i-1,j+2)(i+1,j+2),(i+2,j+1)(i+2,j-1),(i+1,j-2)(i-1,j-2),(i-2,j-1)(图-1)但是,如果(i,j)靠近棋盘的边缘,上述有些位置可能要超出棋盘位置,成为不允许的位置。8个可能位置可以用一位数组HTry1[0…7]和HTry2[0…7]来表示:01234567-2-11221-1-21221-1-2-2-1(表-2)位于(i,j)的马可以走到新位置是在棋盘范围内的(i+HTry1[h],j+HTry2[h]),其中h=0…7。第2步:需求分析输入的形式和输入值的范围:输入马的初始行坐标X和列坐标Y,X和Y的范围都是[1,8]。输出形式:以数组下表的形式输入,i为行标,j为列标,用空格符号隔开。以棋盘形式输出,每一格打印马走的步数,这种方式比较直观程序所能达到的功能:让马从任意起点出发都能够遍历整个8*8的棋盘。测试数据,包括正确输入及输出结果和含有错误的输入及其输出结果。数据可以任定,只要1<=x,y<=8就可以了。正确的输出结果为一个二维数组,每个元素的值表示马行走的第几步,若输入有错,则程序会显示:“输入有误!请重新输入……”并且要求用户重新输入数据,直至输入正确为止。第3步,算法设计思想:1、输入马所在初始位置的坐标值,考虑到用户的输入习惯,此处1<=x,y<=8;2、将输入的初始值进栈;3、设置一个while循环,循环条件为count<64;4、取出栈顶元素;5、定义flag标志变量的值;6、按照setpossible函数顺时针顺序优先原则,找栈顶元素周围未被占用的新位置。7、若存在该位置,则令order的值等于该新位置的坐标,并入栈;8、否则弹出栈顶元素;9、再次回到第③步while循环进行判断;10、输出一个8*8的方阵,所示数字即为相应步骤。第4步,算法框图:开始开始输入初始坐标X,Y判断X,Y是否合法?Initstack建立新栈并且将初始位置入栈count<64GetTop取栈顶元素;找出所有可走位置根据for循环及优先原则查找是否存在下一个坐标?调用push函数将其压缩进栈调用DleteTop函数将栈顶元素弹出输出否是否是否是第5步,存储结构设计:(1)、位置的存储表示方式typedefstruct{intx;inty;intfrom;}Point;(2)、栈的存储方式#defineSTACKSIZE70#defineSTACKINCREASE10typedefstructStack{Point*top;Point*base;intstacksize;};第6步,设计功能分析与实现(1)、设定栈的抽象数据类型定义:ADTStack{数据对象:D={ai|ai∈ElemSet,i=1,2,…,n,n≥0}数据关系:R1={<ai-1,ai>|ai-1,ai∈D,i=2,…,n}约定an端为栈顶,ai端为栈顶。基本操作:InitStack(&s)操作结果:构造一个空栈s,DestroyStack(&s)初始条件:栈s已存在。操作结果:栈s被销毁。ClearStack(&s)初始条件:栈s已存在。操作结果:栈s清为空栈。StackEmpty(&s)初始条件:栈s已存在。操作结果:若栈s为空栈,则返回OK,否则返回ERROR。StackLength(s);初始条件:栈s存在。操作结果:返回s的元素个数,即栈的长度。GetTop(s,&e);初始条件:栈s已存在且非空。操作结果:用e返回s的栈顶元素。Push(&s,e)初始条件:栈s已存在。操作结果:插入元素e为新的栈顶元素。DeleteTop(&s,&e)初始条件:栈s存在且非空。操作结果:删除栈顶元素,并用e返回。GetDeep(s)初始条件:栈s存在。操作结果:返回一个int型的整数表示栈深。stackTraverse(s,visit())初始条件:栈s存在且非空。操作结果:从栈底到栈顶依次对s的每个元素调用visit()。一旦visit()失败,则操作失败。}ADTStack(2)、选取对该程序有用的函数。1、InitStack(&s)用于构建空栈实现相应的操作;2、StackEmpty(&s)用于判断空栈情况,已确保循环体能够准确实现;3、GetTop(s,&e)用于取放入栈的栈顶元素,实现把放入的横纵坐标按要求取出;4、Push(&s,e)用于将用户输入的横纵坐标放入栈;5、DeleteTop(&s,&e)用于实现将要求取出的元素取出;6、GetDeep()用于获取栈的深度;7、DestroyStack()用于销毁栈。(3)、主要函数及算法说明。1、函数:voidsetpossible(Pointcur)参数:Pointcur功能:找出当前位置下一步的八个位置,将其赋给g_round[8];算法:接受参数传来的值,按顺时针次序加上g_round[i].x={-2,-1,1,2,2,1,-1,-2};g_round[i].y={1,2,2,1,-1,-2,-2,-1};再根据getpossible函数来判断是否合法;若合法则返回OK,否则返回ERROR.2、函数:Statusgetpossible(inti,Point&pt)参数:inti,Point&pt功能:将所在位置周围八个位置坐标赋予指针变量,并判断其合理性;算法:用以下赋值语句pt.x=g_round[i-1].x;pt.y=g_round[i-1].y;将现在周围8个指定位置赋予指针变量pt,并用if(pt.x<0||pt.y<0||pt.x>7||pt.y>7)条件语句判断其合理性,若合理则返回OK,否则返回ERROR.3、语句:for(inti=cur.from+1;i<=8;i++){if(getpossible(i,next)&&order[next.x][next.y]==0){语句……}}功能:按照顺时针优先规则,选出下一个可用的位置,通过if判断语句来判断所选的下一步是否可用,若可用,则使其进栈,否则运行下面一个语句。4、语句:if(flag==NULL){语句…..while(j<p&&GetDeep(herseVisit)>1){语句…..}}功能:如果当前位置不存在任何新路径,则根据while循环进行退栈,直至退到存在有最佳位置的坐标。但必须保证栈不为空。所以此出栈中设定了intGetDeep的基本操作,就是防止空栈还继续弹东西出来的情况发生。四、【调试程序】(1)、问题:语法错误原因:首次运行语法错误比较多,一般都是由于粗心大意输入有误造成的,还有一些错误属于变量忘记定义之类的,经过认真一个一个调试后这类错误得以解决。下图为第一次运行时的错误(2)、问题:运行后突然停止程序原因:可能是输出不恰当解决:此问题出现后,刚开始不知道为啥,看了很多遍程序就是找不出原由,于是后来请教同学,一起研究后无意中改了输出格式,将printf("%s,%2d",'|',order[i][j]);改成了printf("%d,%f",order[i][j],'|');竟然成功输出了。怀疑是%s使用得不恰当。下图为修改前的运行结果:(3)、问题:将上述问题解决后虽然不会出现程序突然终止的情况,但运行结果如下图,输出结果很乱;原因:输出格式不符解决:将printf("%d,%f",order[i][j],'|');改成printf("|%2d",order[i][j]);(4)、问题:上述问题都搞定后,输入初始坐标后按下Enter键后不会出现棋盘原因:main()函数里flag写成intflage;解决:将intflage改成flag(5)、问题:上述问题都搞定后,输入初始坐标后按下Enter键后会出现棋盘,但是在棋盘上会出现0000的情况,与需要的结果不符。原因:regular.h文件里面获得合理位置的边界位置判定,横坐标和纵坐标的范围少写了ps.x>7||ps.y<0。解决:在regular.h文件里面添加横坐标和纵坐标的范围ps.x>7||ps.y<0(6)、问题:上述问题都搞定后,输入初始坐标后按下Enter键后立即退出了原因:main()函数里有scanf(),当用户输入初始坐标后,将这两个坐标赋予给&begin.x,&begin.y,结果当用户想用Enter键进行确认操作后,Enter本身是一个字符,而这个字符不符合循环要求,所以直接退出解决:多加一个getchar()把Enter键给吸收掉,结果如下图:五、【用户手册】运行程序,程序开始界面,如图所示:输入初始值x,y,如输入(3,7),如图所示:因为(3,7)在(1~8)的范围内,所以程序输出结果如下:按(y/Y)后,程序将跳到输入初始值位置,如图所示:按其他任意键后(如按(n/N)键),将退出程序,如图所示:若输入的初始值没在(1~8)的范围内,如输入(7,9),则将提示错误,并要求重新输入,如图所示:按任意键后,程序将跳回输入初始值的位置,如图所示:六、【实验总结与体会】总结:马踏棋盘,作为一种经典的栈的应用例子,从大方面将,刚看到这名字就知道用栈来实现,但是,当你面对这个题目,打开编译器之后想写的时候,发现又不是那么容易,很多细节需要认真的分析,比如结构体的定义,棋子因为是二维的,所以对于用来存储棋盘的横纵坐标,需要用到两个变量,定义两整型变量x,y。刚开始只定义了这两个变量,后来发现如果找到下一个位置,而下一个位置有很多个都是符合的,如何选取最优的呢?最有的有可能是最先找到的,可找到后还得继续找下去,万一没有比他更优的,则要退回来,如果没有变量from来记录前一位置最优位置,就无法找到之前的点,所以要多加一个变量;其外就是程序的调试,调试确实需要很大的耐心,有时候只是你的大意而输错了字符或输入输出格式不符合就会出现很多看起来不可思议很难发现的错误,这也说明了编程的时候一定要认真有耐心。体会:刚学习栈的时候,觉得并不太难,反正就是先进后出,可是到了实际运用的时候,才发现学到的理论知识要用到实际去还真是个问题,通过这次课程设计的实践,让我对栈有了更深入的理解,也发现一种理论再简单的知识,如果不实际运用一下,对于你的掌握肯定是不够的,因为实际运用中你要适当选取哪些是有用的,哪些不必用到的,而且当你很兴奋的写完代码后,会发现很多错误,当然一般是语法错误,如果你的逻辑没错的话,也有可能是你思想没错,但你的表达不妥当,这也会让你对程序的修改显得很无助;再次,世上没有完美的程序,如今社会上出现的各个软件每到一定的时候就会有升级版也正是这个原因,我承认自己这个程序存在很多漏洞和不足,但一个程序的优化可不是一朝一夕的事,只要求自己能完成基本任务就行了。七、【参考文献】《数据结构(C语言版)》--------严蔚敏、吴伟民编著《C语言设计(第三版)》--------谭浩强著《C语言课程设计(第2版)》-------梁旭、谷晓琳、黄明编著《C语言通用范例金典》-------柳盛,王国全,沈永林编著【程序清单】1.文件horse.h#ifndef__HORSE_H__#define__HORSE_H__#include<stdio.h>#include<malloc.h>#defineOK1#defineERROR0#defineSTACKSIZE70#defineSTACKINCREASE10typedefintStatus;//位置的储存typedefstruct{ intx; inty; intfrom;}Point;//栈的储存typedefstruct{ Point*top; Point*base; intstacksize;}Stack;//建栈StatusInitstack(Stack&s){ s.base=(Point*)malloc(STACKSIZE*sizeof(Point)); if(s.base==NULL)returnERROR; s.top=s.base; s.stacksize=STACKSIZE; returnOK;}//向栈中插入元素eStatusPush(Stack&s,Pointe){ if(s.top-s.base>=s.stacksize) { s.base=(Point*)realloc(s.base, (s.stacksize+STACKINCREASE)*sizeof(Point)); if(s.base==NULL)returnERROR; s.top=s.base+s.stacksize; s.stacksize+=STACKINCREASE; } (*s.top).x=e.x; (*s.top).y=e.y; (*s.top).from=e.from; s.top++; returnOK;}//栈不为空,则删除栈顶元素StatusDeleteTop(Stack&s,Point&e){ if(s.top==s.base)returnERROR; s.top--; e.x=(*s.top).x; e.y=(*s.top).y; e.from=(*s.top).from; returnOK;}//销毁栈StatusDestroyStack(Stack&s){ free(s.base);//free(s); returnOK;}//判断栈是否为空StatusStackEmpty(Stacks){ if(s.base==s.top)returnOK; elsereturnERROR;}//获得栈顶元素StatusGetTop(Stacks,Point&e){ if(s.base==s.top)returnERROR; e.x=(*(s.top-1)).x; e.y=(*(s.top-1)).y; e.from=(*(s.top-1)).from; returnOK;}//获得栈的深度intGetDeep(Stacks){ returns.top-s.base;}#endif文件regular.h#ifndef__REGULAR_H__#define__REGULAR_H__#include"horse.h"Pointh_possible[8]={0,0,0};//查找所有可能的位置,并存入h_possible[8]中voidsetPossible(Pointcon){ Pointround[]= { {con.x-2,con.y+1,0}, {con.x-1,con.y+2,0}, {con.x+1,con.y+2,0}, {con.x+2,con.y+1,0}, {con.x+2,con.y-1,0}, {con.x+1,con.y-2,0}, {con.x-1,con.y-2,0}, {con.x-2,con.y-1,0} }; for(inti=0;i<8;i++) { h_possible[i].x=round[i].x; h_possible[i].y=round[i].y; h_possible[i].from=round[i].from; }}//取得合理的可能位置StatusgetPossible(inti,Point&ps){ ps.x=h_possible[i-1].x; ps.y=h_possible[i-1].y; if(ps.x<0||ps.y>7||ps.x>7||ps.y<0)returnERROR; elsereturnOK;}#endif主函数main.c#include<stdio.h>#include<stdlib.h>#include"horse.h"#include"regular.h"voidmain(){ inti,j,p; ints=1; charyn; StackhorseVisit; Pointcur,next;H1:while(s){ intorder[8][8]={0};//是一个中间变量,用来记录当前位置 intcount=0; Pointbegin; system("color31"); printf("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<马踏棋盘程序演示>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); printf("请输入马在棋盘上的任意初始位置x,y,根据用户习惯,其中x,y为(~8),例如(7):"); scanf("%d%d",&begin.x,&begin.y); printf("\n================================================================================\n"); begin.from=0; while(begin.x>8||begin.y>8||begin.x<1||begin.y<1) { system("cls"); printf("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<输入格式不对,请重新输入...>>>>>>>>>>>>>>>>>>>\n"); getchar(); getchar(); system("cls"); gotoH1; } getchar(); begin.x--;//注意用户输入的坐标(~8),而储存是(~7),这里要自减 begin.y--; Initstack(horseVisit);//创建空栈 Push(horseVisit,begin);//入栈,将用户输入的坐标存入栈中 count++;//计数器加 order[begin.x][begin.y]=count; while(count<64) { GetTop(horseVisit,cur);//取栈顶元素存入cur中 setPossible(cur);//找出位置附近可能的八个位置 intflag=false;//标志 for(inti=cur.from+1;i<=8;i++) { //按照顺时针的顺序,选出下一个可走的新位置

温馨提示

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

评论

0/150

提交评论