课程设计.docx

上传人:b****5 文档编号:11642093 上传时间:2023-03-29 格式:DOCX 页数:37 大小:185.62KB
下载 相关 举报
课程设计.docx_第1页
第1页 / 共37页
课程设计.docx_第2页
第2页 / 共37页
课程设计.docx_第3页
第3页 / 共37页
课程设计.docx_第4页
第4页 / 共37页
课程设计.docx_第5页
第5页 / 共37页
点击查看更多>>
下载资源
资源描述

课程设计.docx

《课程设计.docx》由会员分享,可在线阅读,更多相关《课程设计.docx(37页珍藏版)》请在冰豆网上搜索。

课程设计.docx

课程设计

实验一用计算机自动求解关系闭包2

一.需求分析2

二.概要设计3

三.详细设计6

四.调试分析:

9

五.测试结果如下;10

六.用户手册10

七.附录11

实验二对保龄球记分12

一.需求分析:

12

二.概要设计:

13

三.详细设计:

16

四.调试分析18

五.测试结果18

六.用户手册19

七.附录21

实验三设计程序为客人提供相关服务21

一.需求分析:

21

二.概要设计21

三.详细设计22

四.设计和调试分析;26

五.用户手册26

六.测试结果:

27

七.附录:

28

实验一用计算机自动求解传递闭包

一.需求分析

(1)用关系矩阵的形式输入一关系R,由计算机自动求解关系R的传递闭包,

并用矩阵的形式予以输出。

(2)在集合X上的二元关系R的传递闭包是包含R的X上的最小的传递关系。

一般用B表示定义在具有n个元素的集合X上关系R的n×n阶矩阵,则传递闭包的矩阵B+可如下计算:

    B+=B+B2+B3+……+(B)n    

式中矩阵运算时所有乘法都用逻辑与代替,所有加法都用逻辑或代替。

上式中的操作次序为B,B(B),B(BB),B(BBB),……,所以在运算的每一步只需简单地把现有结果乘以B,完成矩阵的n次乘法即可。

(3)输入由n个元素组成的关系矩阵M,并置新矩阵A=M,置k=1,对所有正整数i如果A[i,k]=1,则对j=1…n执行:

A[i,j]←A[i,j]∨A[k,j],同时k增1;如果k≤n,则返回重新执行原过程,否则停止。

所得的矩阵A即为关系R的传递闭包t(R)的关系矩阵。

(4)测试数据为:

若输入原矩阵为:

1001

0011

1100

1010

则输出的传递闭包如下所示:

<1,1>,<1,2>,<1,3>,<1,4>,<2,1>,<2,2>,<2,3>,<2,4>,<3,1>,<3,2>,<3,3>

<3,4>,<4,1>,<4,2>,<4,3>,<4,4>

(5)程序执行的命令为:

(1)输入组成关系矩阵R的元素个数;

(2)创建关系R的初始矩阵M;

(3)求解关系R的传递闭包;

(4)用矩阵的形式输出所形成的传递闭包。

二.概要设计

1.数组的顺序存储表示

#include//标准头文件,提供宏va_start,va_arg和va_end,

//用于寸取变长参数表

#defineMAX_ARRAY_DIM8//假设数组维数的最大值为8

typedefstruct{

ElemType*base;//数组元素基址,由InitArray分配

intdim//数组维数

int*bounds;//数组维界基址,由InitArray分配

int*constants;//数组映像函数常量基址,由InitArray分配

}Array;

2.数组的抽象数据类型的定义:

ADTArray{

数组对象:

ji=0,…,bi-1,I=1,2,3,…,n.

D={aj1j2j3…jn|n(>0)称为数组的维数,bi是数组第维的长度,ji是数组元素的第i维下标,aj1j2j3…jn属于ElemSet}

数组元素:

R={R1,R2,…,Rn}

Ri={|

0

0

aj1…ji…jn,aj1…ji+1…jn属于D,i=2,…,n}

基本操作:

InitArray(&A,n,bound1,….boundn)

操作结果;若维数和各维长度合法,则构造相应的数组A,并返回OK.

DestroyArray(&A)

操作结果;销毁数组A.

Value(A,&e,index1,…,indexn)

初始条件;A是n维数组,e为元素变量,随后是n个下标值。

操作结果:

若各下标不超界,则e赋值为所指定的A的元素值,并返回OK.

Assign(&A,e,index1,…,indexn)

初始条件:

A是n维数组,e为元素变量,随后是n个下标值。

操作结果;若下标不超界,则将e的值赋给所指定的A的元素,并返回OK.

}ADTArray

3.抽象数据类型稀疏矩阵的定义为:

ADTSparseMatrix{

数据对象:

D={aij|I=1,2,…,m;j=1,2,…,n;

ai,j属于ElemSet,m和n分别称为矩阵的行数和列数}

数据关系;R={Row,Col}

Row={|1

Col={|1

基本操作;

CreateSMatrix(&M);

操作结果;创建稀疏矩阵M。

DestroySMatrix(&M);

初始条件:

稀疏矩阵M存在。

操作结果;销毁稀疏矩阵M.

PrintSMatrix(&M);

初始条件:

稀疏矩阵M存在。

操作结果;输出稀疏矩阵M.。

CopySMatrix(M,&T);

初始条件:

稀疏矩阵M存在。

操作结果;由稀疏矩阵M复制得到T.

AddSMatrix(M,N,&Q);

初始条件:

稀疏矩阵M与N的行数和列数对应相等。

操作结果;求稀疏矩阵的和Q=M+N.

SubSMatrix(M,N,&Q);

初始条件:

稀疏矩阵M与N的行数和列数对应相等。

操作结果;求稀疏矩阵的差Q=M-N.

TrasposeSMatrix(M,&T);

初始条件:

稀疏矩阵M存在

操作结果;求稀疏矩阵M的转置矩阵T.

}ADTSparseMatrix

4.本程序包含for循环的多次嵌套

定义全局变量

主函数main()

{

利用for循环输入欲求传递闭包的关系矩阵;

利用for循环求解已输入关系矩阵的传递闭包;

利用for循环输出所求得到关系。

}

具体过程如下所示:

 

三.详细设计

1.元素类型;

#defineMAX_ARRAY_DIM8//假设数组维数的最大值为8

typedefstruct{

ElemType*base;//数组元素基址,由InitArray分配

intdim//数组维数

int*bounds;//数组维界基址,由InitArray分配

int*constants;//数组映像函数常量基址,由InitArray分配

2,数组中基本操作设置如下;

StatusInitArray(Array&A,intdim,…);

//若维数dim和各维长度合法,则构造相应的数组A,并返回OK.

StatusDestroyArray(Array&A)//销毁数组A.

StatusValue(ArrayA,ElemTypee,…)

//A是n维数组,e为元素变量,随后是n个下标值。

//若各下标不超界,则e赋值为所指定的A的元素值,并返回OK.

StatusAssign(Assign&A,ElemTypee,…)

//A是n维数组,e为元素变量,随后是n个下标值。

//若下标不超界,则将e的值赋给所指定的A的元素,并返回OK.其中部分操作的伪码算法如下:

StatusInitArray(Array&A,intdim,…);

//若维数dim和各维长度合法,则构造相应的数组A,并返回OK.

if(dim<1||dim>MAX_ARRAY_DIM)returnERROR;

A.dom=dom;

A.bounds=(int*)malloc(dim*sizeof(int));

if(!

A.bounds)exit(OVERFLOW);

//若长度合法,则存入A.bounds,并求出的元素总数elemtotal

elemtotal=1;

va_start(ap,dim);

for(i=0;i

A.bounds[i]=va_arg(ap,int);

if(A.bounds[i]<0)returnUNDERFLOW;

elemtotal*=A.bounds[i];

}

va_end(ap);

A.base=(ElemType*)malloc(elemtotal*size(ElemType));

if(!

A.base)exit(OVERFLOW);

//求映像函数的常数ci,并存入A.constants[i-1],I=1,..,dim

A.constants=(int*)malloc(dim*sizeof(int));

if(!

A.constants)exit(OVERFLOW);

A.constants[dim-1]=1;//L=1,指针的增减以元素的大小为单位

for(i=dim-2;i>=0;--I)

A.constants[i]=A.bounds[i+1]*A.constants[i+1];

returnOK;

}

3.程序的实现过程:

#include"stdio.h"

#defineN10//定义全局变量N,指矩阵中所能允许输入的元素的最大个数

主函数部分

main()

{

inti,j,a[N][N],b[N][N],c[N][N],s=0,k,e[N][N],m,n;//定义局部变量,矩阵并对相关变量初始化

printf("Pleaseinputthenumbern(n<=100):

\n");//输入矩阵的元素个数

scanf("%d",&n);//逐个输入数据元素

printf("PleaseinputtheMaxtix:

\n");//输入一矩阵

利用for循环对矩阵进行输入

for(i=0;i

for(j=0;j

{

scanf("%d",&a[i][j]);//输入元素的值

e[i][j]=a[i][j];//将矩阵a[i][j]的值赋值给矩阵e[i][j]

b[i][j]=a[i][j];及矩阵b[i][j]

}

继续利用for循环求矩阵的传递闭包

for(m=1;m

计算到原矩阵的n次方时,经过矩阵的合取即可得到矩阵的传递闭包

{

for(i=0;i

for(j=0;j

{

for(s=0,k=0;k

s+=b[i][m]*a[m][j];

c[i][j]=s;//将求得的元素s赋值给新矩阵c[i][j]

if(e[i][j]==0&&c[i][j]!

=0)

e[i][j]=c[i][j];//将矩阵c[i][j]中值不为0的元素赋值给矩阵e[i][j]

}

利用for循环将得到的结果予以输出

for(i=0;i

for(j=0;j

b[i][j]=c[i][j];

}

for(i=0;i

for(j=0;j

if(e[i][j]!

=0)//若矩阵e[i][j]中元素不为0,则可将其输出

printf("<%d,%d>,",i+1,j+1);

printf("\n");

}

四.调试分析:

1.在求解矩阵的传递闭包时由于思路比较简单,因此相对比较容易解决。

2.在具体实现过程过程中要注意变量的正确定义,使用范围以及for循环的嵌套使用。

3.由于数组一般不作插入及删除操作,即一旦建立了数组,则结构中的数组元素个数和元素之间的关系就不再发生变动,因此在构建数组时通常采用顺序存储结构予以实现。

4.经过离散数学的学习已经知道在求解n阶矩阵的关系闭包时只需要求到矩阵的n次幂即可,而不需要求无数次幂,然后再进行合取求解,因此就减少了程序的复杂程度。

五.测试结果如下;

六.用户手册

1.本程序的运行环境为TC环境。

2.进入演示程序后即显示文本方式的界面。

 

3.当显示出用户界面时,根据相关提示首先输入要输入矩阵中元素的个数,之后输入0或1构造一矩阵。

4.执行完相关命令后,即可得出用户所需求的传递闭包。

5.之后点击键Q即可退出相关界面。

七.附录

源程序如下所示;

#include"stdio.h"

#defineN10

main()

{

inti,j,a[N][N],b[N][N],c[N][N],s=0,k,e[N][N],m,n;

printf("Pleaseinputthenumbern(n<=100):

\n");

scanf("%d",&n);

printf("PleaseinputtheMaxtix:

\n");

for(i=0;i

for(j=0;j

{

scanf("%d",&a[i][j]);

e[i][j]=a[i][j];

b[i][j]=a[i][j];

}

for(m=1;m

{

for(i=0;i

for(j=0;j

{

for(s=0,k=0;k

s+=b[i][k]*a[k][j];

c[i][j]=s;

if(e[i][j]==0&&c[i][j]!

=0)

e[i][j]=c[i][j];

}

for(i=0;i

for(j=0;j

b[i][j]=c[i][j];

}

for(i=0;i

for(j=0;j

if(e[i][j]!

=0)

printf("<%d,%d>,",i+1,j+1);

printf("\n");

}

实验二对保龄球记分

一.需求分析:

(1)用数组的形式对保龄球游戏进行记分;

(2)游戏规则为:

打保龄球是用一个滚球去撞击10个站立的瓶,将瓶击倒。

一局分10轮,每轮可滚球1次或2次,以击到的瓶数为依据计分。

一局得分为10轮得分之和,而每轮的得分不仅与本轮的滚球情况有关,还可能与后一轮或后两轮的滚球情况有关,即:

某轮某次滚球击倒的瓶数不仅要计入本轮得分,还可能会计入前一轮或两轮得分。

(3)计分规则如下:

1)若某一轮的第一次滚球就击倒全部10个瓶,则本轮不再滚球(若是第十轮还需加2次滚球),该轮得分为本次击倒瓶数10与以后2次滚球所击倒瓶数之和;

2)若某一轮的第一次滚球未击倒全部10个瓶,则对剩下未倒的瓶再滚球一次,如果这2次滚球击倒全部10个瓶,则本轮不再滚球(若是第十轮还需加1次滚球),该轮得分为这2次击倒瓶数10与以后1次滚球所击倒瓶数之和;

3)若某一轮2次滚球未击倒全部10个瓶,则本轮不在滚球,该轮得分为这2次滚球所击倒瓶数之和。

(4)具体做法为:

1)模拟1人打保龄球的过程,用一个二维数组:

intx[11][4];存储每轮每次击倒的瓶数和得分以及累计得分。

即:

一行中的4个元素x[i][0]、x[i][1]、x[i][2]、x[i][3]分别记录第i轮的第1次滚球击倒的瓶数、第2次滚球击倒的瓶数、本轮得分和累计得分;

2)输入每轮每次滚球击倒的瓶数,若第1次滚球击倒的瓶数为10,则该轮只输入1次数据;

3)输出每轮每次击倒的瓶数和得分以及累计得分,若仿照例题输入所要测定的值,则输出结果如下所示;

8

10

7

9

9

10

10

8

9

10

8

2

0

2

1

1

0

0

1

1

0

2

20

19

9

19

20

28

19

9

20

20

20

39

48

67

87

115

134

143

163

183

4)程序执行的命令为:

●根据输入的得分数据构造一个二维数组;

●输入的数据计算在每轮中的得分及累积得分;

●出每轮每次击倒的瓶数和得分以及累计得分;

二.概要设计:

1.数组的相关知识链接:

(1)对数组进行定义:

  intcompact(type*Array,intCount)

  数组类型说明在C语言中使用数组必须先进行类型说明。

数组说明的一般形式为:

类型说明符数组名[常量表达式],……;

其中,类型说明符是任一种基本数据类型或构造数据类型。

数组名是用户定义的数组标识符,方括号中的常量表达式表示数据元素的个数,也称为数组的长度。

例如:

inta[10];说明整型数组a,有10个元素。

  floatb[10],c[20];说明实型数组b,有10个元素,实型数组c,有20个元素。

charch[20];说明字符数组ch,有20个元素。

(2)对数组进行声明:

有三种方法声明固定大小的数组,用哪一种方法取决于数组应有的有效范围:

  1)建立公用数组,在模块的声明段用Public语句声明数组。

  2)建立模块级数组,在模块的声明段用Private语句声明数组。

3)建立局部数组,在过程中用Private语句声明数组。

(3)数组的分类:

一维数组:

数据类型数组名[长度];

二维数组:

类型说明符数组名[常量表达式1][常量表达式2]…;

  其中常量表达式1表示第一维下标的长度,常量表达式2表示第二维下标的长度。

二维数组的元素也称为双下标变量,其表示的形式为:

数组名[下标][下标]。

其中下标应为整型常量或整型表达式。

例如:

a[3][4]表示a数组三行四列的元素,下标变量和数组说明在形式中有些相似,但这两者具有完全不同的含义。

数组说明的方括号中给出的是某一维的长度,即可取下标的最大值;而数组元素中的下标是该元素在数组中的位置标识。

前者只能是常量,后者可以是常量,变量或表达式。

字符数组:

用来存放字符量的数组称为字符数组。

字符数组类型说明的形式与前面介绍的数值数组相同。

例如:

charc[10];由于字符型和整型通用,也可以定义为intc[10]但这时每个数组元素占2个字节的内存单元。

  字符数组也可以是二维或多维数组,例如:

charc[5][10];即为二维字符数组。

  字符数组也允许在类型说明时作初始化赋值。

例如:

staticcharc[10]={`c`,``,`p`,`r`,o`,g`,r`,`a`,`m`};赋值后各元素的值为:

数组Cc[0]c[1]c[2]c[3]c[4]c[5]c[6]c[7]c[8]c[9]其中c[9]未赋值,由系统自动赋予0值。

(4)注意事项:

  1)可以只给部分元素赋初值。

当{}中值的个数少于元素个数时,只给前面部分元素赋值。

例如:

staticinta[10]={0,1,2,3,4};表示只给a[0]~a[4]5个元素赋值,而后5个元素自动赋0值。

  2)只能给元素逐个赋值,不能给数组整体赋值。

例如给十个元素全部赋1值,只能写为:

staticinta[10]={1,1,1,1,1,1,1,1,1,1};而不能写为:

staticinta[10]=1;(请注意:

在C语言中是这样,但并非在所有涉及数组的地方都这样)

  3)如不给可初始化的数组赋初值,则全部元素均为0值。

 4)如给全部元素赋值,则在数组说明中,可以不给出数组元素的个数。

例如:

staticinta[5]={1,2,3,4,5};可写为:

staticinta[]={1,2,3,4,5};动态赋值可以在程序执行过程中,对数组作动态赋值。

这时可用循环语句配合scanf函数逐个对数组元素赋值。

`r`,`o`,`g`,`r`,`a`,`m`};这时C数组的长度自动定为9。

2.保龄球计分游戏中所用数组的定义:

二维数组:

类型说明符数组名[常量表达式1][常量表达式2];

  其中常量表达式1表示第一维下标的长度,常量表达式2表示第二维下标的长度。

二维数组的元素也称为双下标变量,其表示的形式为:

数组名[下标][下标]。

其中下标应为整型常量或整型表达式。

例如:

a[3][4]表示a数组三行四列的元素,下标变量和数组说明在形式中有些相似,但这两者具有完全不同的含义。

数组说明的方括号中给出的是某一维的长度,即可取下标的最大值;而数组元素中的下标是该元素在数组中的位置标识。

前者只能是常量,后者可以是常量,变量或表达式。

3.本程序包含四个模块

1)数据输入模块:

在主函数中首先定义一二维数组,然后通过对变量i.j的控制逐个输入在每轮每次的得分数。

2)记录每轮得分模块:

对于每轮的得分要分情况考虑,因为根据计分规则可知若某一轮的第一次滚球就击倒全部10个瓶,则本轮不再滚球(若是第十轮还需加2次滚球),该轮得分为本次击倒瓶数10与以后2次滚球所击倒瓶数之和;若某一轮的第一次滚球未击倒全部10个瓶,则对剩下未倒的瓶再滚球一次,如果这2次滚球击倒全部10个瓶,则本轮不再滚球(若是第十轮还需加1次滚球),该轮得分为这2次击倒瓶数10与以后1次滚球所击倒瓶数之和;若某一轮2次滚球未击倒全部10个瓶,则本轮不在滚球,该轮得分为这2次滚球所击倒瓶数之和。

3)记录累计得分模块:

及每一次的得分都等于该轮得分与前几轮得分的和,因此也同样要用到循环语句予以解决。

4)数据输出模块:

在计算出每轮得分及累计得分后,要进行矩阵转置予以输出新的结果。

各模块间的关系如下所示:

1.主程序模块;

#include"stdio.h"

main()

{

定义变量,并对相关数据进行初始化

for{

对变量进行相关操作

}

}

2.设计程序输入每轮每次的得分

for(i=0;i<11;i++)

{

printf("firstnumber:

");

scanf("%d",&x[i][0]);//输入第i+1轮的第一次得分数

if(x[i][0]!

=10)//如果第i+1轮的第一次得分为10,则不需要进

行第二次击球,否则就要进行第二次击球,计算得分数。

{printf("secondnumber:

");

scanf("%d",&x[i][1]);

}

printf("\n");

}

3.设计程序计算每轮得分数,在此由于第10次比较特殊,故需要单独讨论。

for(i=0;i<9;i++)//在前9次中,通过对i进行处理计算每次的得分数

{

if(x[i][0]==10)//若第i轮中第一次得10分,则不再进行第二次击球

{

x[i][1]=0;

if(x[i+1][0]==10)

x[i][2]=20+x[i+2][0];//在第i轮第一次得10分的基础上,若第i+1

轮第

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 初中教育 > 学科竞赛

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1