程序设计基础课程设计报告模版
《程序设计基础》
课程设计报告
院 (系): 信息科学与工程学院 专业班级: 软件工程xx 学生姓名: xxx 学 号: xxxxx 指导教师: xxxx
20 14 年 9 月 3 日至20 14 年 9 月 26 日
程序设计基础 课程设计任务书
目 录
1制作万年历……………………………………………………………………………页码 1.1需求与总体设计………………………………………………………………………页码 1.2详细设计………………………………………………………………………页码 1.3编码实现………………………………………………………………………页码 1.4运行结果………………………………………………………………………页码 2井字棋游戏………………………………………………………………………………页码 2.1需求与总体设计………………………………………………………………………页码 2.2详细设计………………………………………………………………………页码 2.3编码实现………………………………………………………………………页码 2.4运行结果………………………………………………………………………页码 3员工工资管理系统(学生学籍管理系统、班级成绩管理系统)…………………页码 3.1需求与总体设计………………………………………………………………………页码 3.2详细设计………………………………………………………………………页码 3.3编码实现………………………………………………………………………页码 3.4运行结果………………………………………………………………………页码 总结…………………………………………………………………………………页码
(要求:目录题头用三号黑体字居中书写,隔行书写目录内容。目录中各级题序及题标用
小
四
号
黑
体
字
)
1 制作万年历
1.1需求与总体设计
需求描述:1.显示公元后任何年份的日历 2.日历以月份顺序排列 3.每月以星期顺序排列 4.类似于一般挂历上的格式
参考如下格式:输入年份:2010
2010年 一月
星期日 星期一 星期二 星期三 星期四 星期五 星期六 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 … …
十二月
星期日 星期一 星期二 星期三 星期四 星期五 星期六 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
26 27 28 29 30
总体设计:本系统包括3个模块,分别是功能控制模块、打印输出模块、日历显示模块。 (1) 功能控制模块。该模块用于实现日期有效性检查、判断是否是闰年,某月是大月还是小月,二月是闰月还是平月,某年距离公元1年1日有多少天,某日对应的是星期几。 (2) 打印输出模块。该模块主要是进行输出显示,包括打印指定个数的空格、打印分隔线以及换行。
(3) 日历显示模块。该模块是用来显示指定年份所有月份的月历。
1.2详细设计
描述系统包含的主函数和子函数; 根据历法,可得出如下结论。
闰年条件:年份能被4整除,并且年份不能被100整除,或者年份能被400整除。 闰年天数:366。 平年天数:365。 闰年2月份天数:29。 平年2月份天数:28。
为方便起见,分别定义如下函数:
int GetMonthDays(int y,int m);/*y年m月份的天数*/ int GetYearDays(int y);/*年份y的天数*/
int DateToMun(int year,int month,int day);/*返回从公元1年1月1日起的天数*/ int Week(int year,int month,int day);/*求日期是星期几*/
用函数GetMonthDays()返回某年某月的天数时,可根据是否是大月(第1,3,5,7,8,10,12月为大月)与小月(第4,6,9,11月为小月),如是2月,还要根据是否为平年进行判断,平年2月份天数为28天,闰年2月份天数为29天。
用函数GetYearDays()返回某年天数时,根据是否为闰年进行判断,闰年天数为366天,平年天数为365天。
用函数DateToNum()求从公元1年1月1日起的某年某月某日天数时,先累加某年之前各年的天数,在累加某年某月之前各月的天数,再加上某月已过的天数即可。
用函数Week()返回求日期是星期几时,首先求出返回从公元1年1月1日起到某日期的天数,再根据公元1年1月1日是星期1,因此某日期是星期几的公式为: DateToNum(y,m,d)%7
解释各个功能模块的软件功能;
画系统的总体流程图,某种查询、插入、删除程序实现的子函数流程图,要求采用标准流程图图符至少画两个流程图。 功能控制模块:
功能控制是系统的核心模块,程序首先根据year,month判断其是否是闰年,该月有多少天。然后进行闰年平年的判断,再进行该年某月某日距离公元1年1日起的天数的判断,最后求出该年某月某日是星期几。 日历显示模块:
日历显示实现的是输入一个年份,判断该年份是否满足条件年份不能为负,然后显示输入的年份,根据循环条件,输出该年12个月的月历。 下图即为万年历制作的N-S图:
初始化指针数组的元素输入year
Year
for(month=1;month
输出一条横线输出月份输出星期日到星期六for(i=0;i
输出若干空格
for(day=1;day
day!=1&&Week(year,month,day)==0Y换行
输出第day天输出一条横线(1)main函数
N
n=0
for(y=1;y
n+=GetMonthDays(y)
for(m=1;m
n+=GetMonthDays(y,m)
m
1
3
5
731
810124
6
810
Y29
闰闰
2闰闰
28
30
1.3编码实现
只能使用C语言,源程序编写格式要按照缩进方式,源程序要有详细的注释,使程序容易阅读。
源程序编写格式的规范和注释体现程序员的素质,必须从本课程设计开始培养。 #include #include {
int n; switch(m) {
/*天数*/
/*标准输入输出头文件*/ /*标准函数库头文件*/ /*y年m月份的天数*/
int GetMonthDays(int y,int m)
case 1: case 3: case 5: case 7: case 8: case 10: case 12: n=31; */
break;
/*第1,3,5,7,8,10,12月为大月
case 4: case 6: case 9: case 11:
n=30;
break; case 2: if (y%4==0&&y%100!=0||y%400==0)
n=29;
else
n=28;
}
return n;
}
int GetYearDays(int y) { if(y%4==0 && y%100!=0 || y%400==0) return 366; else
return 365;
}
int DateToNum(int year,int month,int day) { int y,m,n=0; for(y=1;y
*/ n+= GetYearDays(y);
for(m=1;m
n+=GetMonthDays(y,m);
n+=day;
return n;
}
/*第4,6,9,11月为小月*/
/*闰年2月有29天*/
/*平年2月28天*/ /*返回当前的月份天数*/
/*年份y的天数*/
/*闰年366天*/
/*平年365天*/
/*返回从公元1月1日起的天数*/
/*年份,月份,天数*/
/*累加从公元1年到year-1的天数
/*累加从公元1月到month-1的天数*/ /*累加当前月过的的天数*/ /*返回当前天数*/
int Week(int year,int month,int day) { }
int main(void) {
/*求日期是星期几*/
/*返回日期是星期几*/
return DateToNum(year,month,day)%7;
/*主函数是main()*/
char* monthName[]={"一月","二月","三月","四月","五月","六月","七月","八月int year,month,day; int i; do {
printf("输入年:"); scanf("%d",&year);
/*输入年*/
/*要求输入的年月不能为负*/ /*显示年份*/
/*输出这一年的每一月*/
/*年月日*/
","九月","十月","十一月","十二月",}; /*月份中文名称*/
/*临时变量*/
}while (year
printf("%25d年\n",year); {
for(month=1;month
printf("------------------------------------------------------------------
printf("%27s\n",monthName[month-1]); /*显示月份*/
printf(" 星期日 星期一 星期二 星期三 星期四 星期五 星期六\n");for(i=0;i
printf(" ");
/*输出若干格*/
for(day=1;day
/*输出一个月的每一天*/
/*星期日*/
/*输出第day天*/
if(day!=1&&Week(year,month,day)==0)printf("\n"); printf("%8d",day);
------------\n");
/*显示月份*/
printf("\n----------------------------------------------------------------}
system("PAUSE");
------------\n");
/*调用库函数system(),输出系统提
示信息*/ }
return 0;
1.4运行结果
包括输入数据的结果,查询、修改、删除的结果。 可以将输出的结果以截屏方式呈现到课程设计报告中。
2井字棋游戏
2.1需求与总体设计
需求描述:
1.一个3×3方格的棋盘,一个玩家选择一个棋格画×,紧接着另一个玩家选择一个空棋格画○,双方轮流走棋,直到一个玩家占领一行,一列或一条对角线获胜,这时比赛结束
2. 程序实现人与计算机玩井字棋游戏
3. 计算机画×, 人画○,人可选择是否先走 4. 井子棋的棋盘如图所示:
总体设计:在下棋过程中棋盘为棋局,对于一个棋局,某个选手的状态可能的胜,负,平或没结束。设计一个子函数让选手进行选择是否先下,在定义一个子函数输出每次下棋后的棋盘状态,定义函数判断选手和计算机的胜利条件,最重要的是定义一个函数确定计算机的走法。通过main函数调用子函数达到下棋的目的。 数据结构:
在下棋过程中期盼为棋局,对于一个棋局,某个选手的状态可能是胜、负、平或下棋还没有结束,因此定义表示选手棋局状态的类型如下: typedef enum
{/*状态: WIN(胜),LOSE(负),TIE(平),UNEND(还没结束) */
WIN,LOSE,TIE,UNEND }StatusType;
为了可读性强,用枚举类型表示选手,定义如下: typedef enum
{/*选手:HUMAN(真人),COMPUTER(计算机)*/
HUMAN,COMPUTER }piayertype;
为了表示棋格的位置,用棋格的行号与列号来表示,具体定义如下: typedef struct {/*位置*/
int row;/*行号*/ int col;/*列号*/
}PositionType;
2.2详细设计
可采用函数来实现主要功能模块,具体函数如下: (1) StatusType ChessStatus()函数
函数原型:StatusType ChessStatus(PlayerType, player) 函数功能:选手当前的棋局状态 (2)PositionType SelectByComputer()函数
函数原型:PositionType SelectByComputer(void); 函数功能:计算机选手选择的走法 (3)PositionType SelectByHuman()函数
函数原型:PositionType SelectByHuman(void); 函数功能:真人选手选择的走法 (4)void Display()函数
函数原型:void Display(void); 函数功能:显示棋局 (5)int main ()函数
函数原型:int main(void)
函数功能:确定玩家是否先走以及判断玩家与计算机谁胜谁负 为了计算机走棋,为棋盘上的每个棋格打分,打分规则如下: 如果棋格上没有棋子,则得0分。
如果棋格上没有棋子,但棋格所在行、列或对角线有两个X,则得6分。 如果棋格上没有棋子,但棋格所在行、列或对角线有两个O,则得5分。 如果棋格上没有棋子,但棋格所在行、列或对角线其中有一个X,一个没有棋子,则得4分。
如果棋格上没有棋子,但棋格所在行、列或对角线其中有一个O,一个没有棋子,则得3分。
如果棋格上没有棋子,但棋格所在行、列或对角线没有棋子,则得2分。 如果棋格上没有棋子,但棋格所在行、列或对角线其中有一个X,一个O,则得1分。
选择分值高的为计算机的走棋,为了更灵活,有几个棋格的分值一样都最高,则随机选择一个分值最高的棋格作为计算机的走棋。
如果当前的棋格的行号和列号为(i,j),则在同一行中其中两个棋格的行号和列号为(i,(j+1)%3)和(i,(j+2)%3),在同一列中其中两个棋格的行号和列号为((i+1)%3,j)和((i+2)%3,j),在的、主对角线上的其他两个棋格的行号和列号为((i+1)%3, (j+1)%3)和((i+2)%3,(j+2)%3),在付对角线上的其他两个棋格的行号和列号为((i-1+3)%3, (j-1+3)%3)和((i-2+3)%3, (j-2+3)%3).
2.3编码实现
#include #include #include typedef enum {
WIN,LOSE,TIE,UNEND
/*状态:WIN(胜),LOSE(负),TIE
(平),UNEND(还没结束)*/ }StatusType; typedef enum {
HUMAN,COMPUTER
/*选手:HUMAN(真人),COMPUTER(计
算机)*/ }piayertype; typedef struct {
int row; int col;
/*行号*/ /*列号*/
/*选手player当前棋局状态*/
/*位置*/
/*标准输入输出头文件*/ /*标准函数库头文件*/ /*时间头文件*/
}PositionType;
StatusType ChessStatus(PlayerType, player); PositionType SelectByComputer(void); PositionType SelectByHuman(void); void Display(void); char chess[3][3]={ };
int main(void) {
PositionType grid; char isFirst; do {
printf("是否先走(Y/N)?");
/*计算机选手选择的走法*/ /*真人选手选择的走法*/ /*显示棋局*/ /*棋盘*/
{' ',' ',' '}, {' ',' ',' '}, {' ',' ',' '}
/*主函数*/ /*选手选择的棋格*/ /*真人选手是否先走*/
/*输入提示*/
/*逃过当前行的其他字符*/ /*真人选手先走*/ /*真人选手选择的走法*/ /*真人选手的棋子为O*/ /*显示棋局*/
while(getchar()!='\n');
}while (isFirst!='Y'&&isFirst!='y'&& isFirst!='N'&& isFirst!='n'); if (isFirst=='Y'||isFirst=='y') { } while (1) {
grid=SelectByComputer();
/*计算机选手选择的走法*/ /*计算机选手的棋子为+*/ /*显示棋局*/
printf("计算机选手走的棋格是:%d,%d\n",grid.row,grid.col); chess[grid.row][grid.col]='+' ; Display(); { }
else if (ChessStatus(COMPUTER)==LOSE) {printf("真人选手胜,计算机也不过如此!\n"); break; }
else if(ChessStatus(COMPUTER)==TIE) { }
grid=SelectByHuman(); Display(); {
printf("真人选手胜,计算机也不过如此!\n"); break;
grid=SelectByHuman(); Display();
chess[grid.row][grid.col]='O';
if(ChessStatus(COMPUTER)==WIN)
printf("计算机胜,真人选手还需努力!\n"); break;
/*棋已结束*/
/*棋已结束*/
printf("下和了!\n"); break;
/*棋已结束*/
/*真人选手选择的走法*/ /*计算机选手的棋子为O*/ /*显示棋局*/
chess[grid.row][grid.col]='O';
if(ChessStatus(HUMAN)==WIN)
/*棋已结束*/
}
}
else if(ChessStatus(HUMAN)==LOSE) {
printf("计算机胜,真人选手还需努力!\n"); break;
/*棋已结束*/
}
else if(ChessStatus(HUMAN)==TIE) { }
/*调用库函数system(),输出系统提/*返回值0,返回操作系统*/
printf("下和了!\n"); break;
/*棋已结束*/
system("PAUSE"); return 0;
示信息*/
StatusType ChessStatus(PlayerType,player) /*选手player当前棋局状态*/ {
if (player==HUMAN) {
if(chess[0][0]=='O' && chess[0][1]=='O' && chess[0][2]=='O' ||
chess[1][0]=='O' && chess[1][1]=='O' && chess[1][2]=='O' || chess[2][0]=='O' && chess[2][1]=='O' && chess[2][2]=='O' || chess[0][0]=='O' && chess[1][0]=='O' && chess[2][0]=='O' || chess[0][1]=='O' && chess[1][1]=='O' && chess[2][1]=='O' || chess[0][2]=='O' && chess[1][2]=='O' && chess[2][2]=='O' || chess[0][0]=='O' && chess[1][1]=='O' && chess[2][2]=='O' ||
/*第1行*/ /*第2行*/ /*第3行*/ /*第1列*/ /*第2列*/ /*第3列*/ /*主对象线*/
chess[0][2]=='O' && chess[1][1]=='O' && chess[2][0]=='O'
/*副对象线*/
手胜*/
else if(chess[0][0]=='+' && chess[0][1]=='+' && chess[0][2]=='+' ||
chess[1][0]=='+' && chess[1][1]=='+' && chess[1][2]=='+' ||
/*第1行*/ /*第2行*/ /*第3行*/
chess[0][0]=='+' && chess[1][0]=='+' && chess[2][0]=='+' || chess[0][1]=='+' && chess[1][1]=='+' && chess[2][1]=='+' || chess[0][2]=='+' && chess[1][2]=='+' && chess[2][2]=='+' || chess[0][0]=='+' && chess[1][1]=='+' && chess[2][2]=='+' || chess[0][2]=='+' && chess[1][1]=='+' && chess[2][0]=='+' )return LOSE;
/*副
/*第1列*/ /*第2列*/ /*第3列*/ /*主对象线*/
chess[2][0]=='+' && chess[2][1]=='+' && chess[2][2]=='+' ||
对象线*/
/*真人选
手负*/
else if(chess[0][0] !=' '&& chess[0][1]!=' '&& chess[0][2]!=' '&& /*第1
chess[1][0] !=' '&& chess[1][1]!=' '&& chess[1][2]!=' '&& chess[2][0] !=' '&& chess[2][1]!=' '&& chess[2][2]!=' '&& chess[0][0] !=' '&& chess[1][0]!=' '&& chess[2][0]!=' '&& chess[0][1] !=' '&& chess[1][1]!=' '&& chess[2][1]!=' '&& chess[0][2] !=' '&& chess[1][2]!=' '&& chess[2][2]!=' '&& chess[0][0] !=' '&& chess[1][1]!=' '&& chess[2][2]!=' '&& chess[0][1] !=' '&& chess[1][1]!=' '&& chess[2][0]!=' '
15
行*/
/*第2/*第3/*第1/*第2/*第3/*主
行*/ 行*/ 列*/ 列*/ 列*/ 对象线*/
/*副对象线*/
}
/*棋未下
else return UNEND;
完*/
else {
/*计算机
选手*/
if (chess[0][0]=='+' && chess[0][1]=='+' && chess[0][2]=='+'||
chess[1][0]=='+' && chess[1][1]=='+' && chess[1][2]=='+' || chess[2][0]=='+' && chess[2][1]=='+' && chess[2][2]=='+' || chess[0][0]=='+' && chess[1][0]=='+' && chess[2][0]=='+' || chess[0][1]=='+' && chess[1][1]=='+' && chess[2][1]=='+' || chess[0][2]=='+' && chess[1][2]=='+' && chess[2][2]=='+' || chess[0][0]=='+' && chess[1][1]=='+' && chess[2][2]=='+' || chess[0][2]=='+' && chess[1][1]=='+' && chess[2][0]=='+' ) return WIN;
/*副
/*第1行*/ /*第2行*/ /*第3行*/ /*第1列*/ /*第2列*/ /*第3列*/ /*主对象线*/
对象线*/
/*计算机
选手胜*/
else if(chess[0][0]=='O' && chess[0][1]=='O' && chess[0][2]=='O' ||/*第1行*/ /*第2行*/ /*第3行*/ /*第1列*/ /*第2列*/
16
chess[1][0]=='O' && chess[1][1]=='O' && chess[1][2]=='O' || chess[2][0]=='O' && chess[2][1]=='O' && chess[2][2]=='O' || chess[0][0]=='O' && chess[1][0]=='O' && chess[2][0]=='O' || chess[0][1]=='O' && chess[1][1]=='O' && chess[2][1]=='O' || chess[0][2]=='O' && chess[1][2]=='O' && chess[2][2]=='O' ||
}
/*主对象线*/ }
/*计
chess[0][2]=='O' && chess[1][1]=='O' && chess[2][0]=='O'
)return LOSE;
/*副
chess[0][0]=='O' && chess[1][1]=='O' && chess[2][2]=='O' ||
对象线*/
/*计算机
选手负*/
else if(chess[0][0]!=' ' && chess[0][1]!=' ' && chess[0][2]!=' ' &&
chess[1][0]!=' ' && chess[1][1]!=' ' && chess[1][2]!=' ' && chess[2][0]!=' ' && chess[2][1]!=' ' && chess[2][2]!=' ' && chess[0][0]!=' ' && chess[1][0]!=' ' && chess[2][0]!=' ' && chess[0][1]!=' ' && chess[1][1]!=' ' && chess[2][1]!=' ' && chess[0][2]!=' ' && chess[1][2]!=' ' && chess[2][2]!=' ' && chess[0][0]!=' ' && chess[1][1]!=' ' && chess[2][2]!=' ' && chess[0][2]!=' ' && chess[1][1]!=' ' && chess[2][0]!=' ' )return TIE;
/*副
/*第1行*/ /*第2行*/ /*第3行*/ /*第1列*/ /*第2列*/ /*第3列*/ /*主对象线*/
对象线*/
/*和棋*/ /*棋未下
else return UNEND;
完*/
PositionType SelectByComputer(void) 算机选手选择的走法*/ {
int score[3][3]={0}; int i,j,n=0,pos; int max=0;
17
/*棋盘各/*临时变/*最高分
格的分值*/ 量*/
max*/ */ */ */
)
18
int count=0;
/*得最高/*得最高
分的棋格个数*/
PositionType grid; for(i=0;i
for(j=0;j
if(chess[i][j] !=' ')
score[i][j]=0;
/*当前格
分的随机的一个棋格*/
有棋子,得0分*/
else if (chess[i][(j+1)%3]== '+' && chess[i][(j+2)%3]=='+' || /*行
chess[(i+1)%3][j]== '+' && chess[(i+2)%3][j]=='+' || i==j &&
/*主对角
线*/
chess[(i+1)%3][(j+1)%3]=='+' &&chess[(i+2)%3][(j+2)%3]=='+' || i+j== 2 &&
/*副对角
线*/
chess[(i+1)%3][(j-1+3)%3]=='+' &&chess[(i+2)%3][(j-2+3)%3]=='+' )
score[i][j]=6;
/*行,列或
对角线有两个+,得6分*/
else if (chess[i][(j+1)%3]== 'O' && chess[i][(j+2)%3]=='O' || /*行
chess[(i+1)%3][j]== 'O' && chess[(i+2)%3][j]=='O' || i==j &&
/*列
/*主对角
线*/
chess[(i+1)%3][(j+1)%3]=='O' && chess[(i+2)%3][(j+2)%3]=='O' || i+j== 2 &&
/*副对角
线*/
chess[(i+1)%3][(j-1+3)%3]=='O' && chess[(i+2)%3][(j-2+3)%3]=='O'
score[i][j]=5; /*行,列 ,
或对角线有两个o,得5分*/
else if (chess[i][(j+1)%3]== '+' && chess[i][(j+2)%3]==' ' || */ */ */ || */ */ */ */
i==j &&
19
/*行 */
chess[i][(j+1)%3]== ' ' && chess[i][(j+2)%3]=='+' || chess[(i+1)%3][j]== '+' && chess[(i+2)%3][j]==' ' || chess[(i+1)%3][j]== ' ' && chess[(i+2)%3][j]=='+' || i==j &&
/*行/*列/*列
/*主对角
线*/
chess[(i+1)%3][(j+1)%3]=='+' && chess[(i+2)%3][(j+2)%3]==' ' || i==j &&
/*主对角
线*/
chess[(i+1)%3][(j+1)%3]==' ' && chess[(i+2)%3][(j+2)%3]=='+' || i+j== 2 &&
/*副对角
线*/
chess[(i+1)%3][(j-1+3)%3]=='+' && chess[(i+2)%3][(j-2+3)%3]==' ' i+j== 2 &&
/*副对角
线*/
chess[(i+1)%3][(j-1+3)%3]==' ' && chess[(i+2)%3][(j-2+3)%3]=='+' )
score[i][j]=4;
/*行,列或
对角线其他格有一个+和一个没有棋了,得4分*/
else if (chess[i][(j+1)%3]== ' ' && chess[i][(j+2)%3]=='O'|| /*行
chess[i][(j+1)%3]== 'O' && chess[i][(j+2)%3]==' ' || chess[(i+1)%3][j]== ' ' && chess[(i+2)%3][j]=='O' || chess[(i+1)%3][j]== 'O' && chess[(i+2)%3][j]==' ' ||
/*行 /*列/*列
/*主对角
线*/
|| */
i==j &&
/*主对角
线*/
chess[(i+1)%3][(j+1)%3]=='O' && chess[(i+2)%3][(j+2)%3]==' ' || i+j== 2 &&
/*副对角
线*/
chess[(i+1)%3][(j-1+3)%3]==' '&& chess[(i+2)%3][(j-2+3)%3]=='O' i+j== 2 &&
/*副对角
线*/
chess[(i+1)%3][(j-1+3)%3]=='O' && chess[(i+2)%3][(j-2+3)%3]==' ' )
score[i][j]=3;
/*行,列或
对角线其他格有一个O和一个没有棋了,得3分*/
else if (chess[i][(j+1)%3]== ' ' && chess[i][(j+2)%3]==' '|| /*行
chess[(i+1)%3][j]== ' ' && chess[(i+2)%3][j]==' ' || /*行 */
i==j && 线*/ */
chess[(i+1)%3][j]== '+' && chess[(i+2)%3][j]=='O'||
/*列*/
20
/*主对角
chess[(i+1)%3][(j+1)%3]==' ' && chess[(i+2)%3][(j+2)%3]==' i+j== 2 &&
/*副'&&
'|| 对角线*/
chess[(i+1)%3][(j-1+3)%3]=='
)
score[i][j]=2;
/*行,
chess[(i+2)%3][(j-2+3)%3]==' '
列或对角线没有棋子,得2分*/
else if (chess [i][(j+1)%3]=='+'&&chess[i][(j+2)%3]=='O' ||
/*行 */
chess[i][(j+1)%3]== 'O' && chess[i][(j+2)%3]=='+' || /*行
chess[(i+1)%3][j]=='O' && chess[(i+2)%3][j]=='+' ||
}
for (i=0;i
for (i=0;i
srand(time (NULL));
21
}
i==j && /*主对角
&&
线*/
chess[(i+1)%3][(j+1)%3]=='+' i==j &&
chess[(i+2)%3][(j+2)%3]=='O'||
/*主对角
&&
/*副对角
线*/
chess[(i+1)%3][(j i+j== 2 &&
+1)%3]=='O'
chess[(i+2)%3][(j+2)%3]=='+'|| 线*/
chess[(i+1)%3][(j-1+3)%3]=='+'&& i+j==2
score[i][j]=1;
&&
chess[(i+1)%3][(j-1+3)%3]=='+'&&
/*行,列或
chess[(i+2)%3][(j-2+3)%3]=='O' || chess[(i+2)%3][(j-2+3)%3]=='+') 对角线有一个+和一个o,得1分*/
/*行 */ /*列*/
for (j=0;j
if (score [i][j]>max) max=score[i][j];
/*score[i][j]当前新最高分*/
/*行 */ /*列*/
/*对
for (j=0;j
/*设
if (score [i][j]==max) count++;
分值为高最分的棋格进行计数*/
置随机数种子*/ pos=rand()%count; 0~count-1的随机数*/
for (i=0;i
for (j=0;j
if (score [i][j]==max)
{ if (n==pos)
到最高分序号为pos的棋格*/
{ grid.row=i; 号*/ grid.col=j;
号*/
return grid;
值最高的棋格*/
} n++;
最高的棋局进行计数*/
}
}
}
}
PositionType SelectByHuman (void) 人选手选择的走法*/ {
PositionType grid; 手选择的棋格*/ do { printf("输入要走的棋格行号和列号:"); 入提示*/
scanf ("%d,%d",&grid.row,&grid.col);
22
/*得到
/*行 */ /*列*/
/*找
/*行
/*列
/*返回分
/*对分值
/*真
/*真人选
/*输
/*输
入行列号*/
}while (grid.row=3 || 号超过的范围*/
grid.col=3 ||
/*列/*棋
号超过的范围*/
chess[grid.row][grid.col] !=' ');
格上已放有的棋子*/ return grid; }
void Display (void) 示棋局*/ { }
printf ("*---*---*---*\n");
/*显/*显/*显/*显/*显/*显/*显
示表格线*/
printf("| %C | %C | %C |\n",chess[0][0],chess[0][1],chess[0][2]); printf ("*---*---*---*\n");
示第1行*/ 示表格线*/
printf("| %C | %C | %C |\n",chess[1][0],chess[1][1],chess[1][2]); printf ("*---*---*---*\n");
示第2行*/ 示表格线*/
printf("| %C | %C | %C |\n",chess[2][0],chess[2][1],chess[2][2]); printf ("*---*---*---*\n\n");
示第3行*/ 示表格线*/
/*显/*返回真
人选手选择的棋格*/
/*行
23
闰1闰main闰闰
(2)StatuType ChessStatus
24
否
否
(3)PositionType SelectByComputer
(4)PositionType SelectByHuman
(5)void Display
2.4运行结果
3员工工资管理系统(学生学籍管理系统、班级成绩管理系统)
3.1需求与总体设计
需求描述:设计一个利用文件处理方式,实现对学生学籍进行登记、修改、删除、查找、统计等操作。学生学籍管理系统的功能要求如下:
①系统以菜单方式工作。
②登记学生的学籍信息(包括:学号,姓名,性别,年龄,籍贯,系别,专业,班级);
③修改已知学号的学生信息; ④删除已知学号的学生信息; ⑤查找已知学号的学生信息;
⑥可以按学号,或是按专业输出学生学籍信息表。
⑦要求本系统采用结构体和链表等数据结构。
总体设计:设计一个利用文件处理方式实现对学生学籍的管理,具有增加数据,更新数据,查询数据,删除数据,列表显示数据的功能。定义一些结构体,确立几个函数,分别用来处理增加数据,删除数据,查询数据,删除数据,列表显示数据,然后利用main函数分别对各个子函数的利用,以达到实现用户所需的要求。
数据结构:本系统查用的数据结构是结构体,结构体可以同时存储不同的数据类型,并并且相同结构的结构体变量是可以相互赋值的。结构体声明的时候本身不占用任何内存,只有当使用已定义的结构体类型定义结构体变量时,计算机才会分配内存空间,所以用结构体便于数据的传输和保存。
对于学生信息资定义一个全局变量: typedef struct{
int status; /* 数据状态,0为正常,1为删除*/ char schoolnum[16]; /*学生学号*/ char name[16]; /*学生姓名*/
char sex[8]; /*学生性别*/ int age; /*学生年龄*/ char city[16]; /*学生籍贯*/ char college[16]; /*学生院系*/ char major[16]; /*学生专业*/ char classnum[16]; /*学生班级*/
}StudentType;
3.2详细设计
描述系统包含的主函数和子函数; 解释各个功能模块的软件功能;
画系统的总体流程图,某种查询、插入、删除程序实现的子函数流程图,要求采用标准流程图图符至少画两个流程图。 (1)AddData( )函数
函数原型:void AddData(void)
函数功能:输入一个或多个学生学籍信息,并将输入的学生信息存入到数据文件中
(2)UpdateData( )函数
函数原型:void UpdateData(void) 函数功能:更新已存在的学生信息 (3) DeleteData( )函数 函数原型:void DeleteData(void)
函数功能:对某位学生作删除标志,只做逻辑删除 (4)SearchData( )函数
函数原型:void SearchData(void)
函数功能:按照指定条件查询未作删除标记的学生信息 (5)ListData( )函数
函数原型:void ListData(void)
函数功能:列示显示所有未作删除标记的学生信息
3.3编码实现
只能使用C语言,源程序编写格式要按照缩进方式,源程序要有详细的注释,使程序容易阅读。
源程序编写格式的规范和注释体现程序员的素质,必须从本课程设计开始培养。
#include #include #include #include typedef struct{
void AddData(void) {
int status;/* 数据状态,0为正常,1为删除*/ char schoolnum[16]; char name[16]; char sex[8]; int age; char city[16]; char college[16]; char major[16]; char classnum[16];
}StudentType;
FILE *fp;
StudentType student; char tag; char buf[16]; student.status=0; printf("\n添加学生\n");
if((fp=fopen("student.dat","rb+"))==NULL){ }
if((fp=fopen("student.dat","wb+"))==NULL){ }
printf("打开文件student.dat失败!\n"); system("PAUSE"); return;
for(;;) {
tag=getchar(); while(getchar()!='\n')
;
tag=tolower(tag); if(tag!='y'&&tag!='n') {
printf("输入非法,重新输入(y/n):");
do{
printf("学生学号:"); gets(student.schoolnum); printf("学生姓名:"); gets(student.name); printf("学生性别:"); gets(student.sex); printf("学生年龄:"); gets(buf);
student.age=atoi(buf); // 字符串转换为整数 printf("学生籍贯:"); gets(student.city); printf("学生院系:"); gets(student.college); printf("学生专业:"); gets(student.major); printf("学生班级:"); gets(student.classnum);
fseek(fp,0,SEEK_END); //移动文件指针到最后
fwrite(&student,sizeof(StudentType),1,fp);//写一个学生
printf("继续添加吗(y/n):");
}
}
else { }
break;
}while(tag=='y'); fclose(fp);
void UpdateData(void) {
rewind(fp); for(;;) {
if(fread(&student,sizeof(StudentType),1,fp)>0) {
FILE * fp;
StudentType student; char schoolnum[16]; char buf[16];
printf("输入要修改的学生的学号:"); gets(schoolnum); }
if((fp=fopen("student.dat","wb+"))==NULL){ }
printf("打开文件student.dat失败!\n"); system("PAUSE"); return;
if((fp=fopen("student.dat","rb+"))==NULL){
}
}
break; // 找到学号而退出
if(feof(fp))
break;
if(!feof(fp)){ // 判断是否到文件末尾
student.age,student.city,student.college,student.major,student.classnum);
printf("输入更改后数据:\n"); printf("学生学号:"); gets(student.schoolnum); printf("学生姓名:"); gets(student.name); printf("学生性别:"); gets(student.sex); printf("学生年龄:"); gets(buf);
student.age=atoi(buf); // 字符串转换为整数 printf("学生籍贯:"); gets(student.city); printf("学生院系:"); gets(student.college); printf("学生专业:"); gets(student.major); printf("学生班级:"); gets(student.classnum);
// 文件指针从当前位置往前移动一个学生,再重新写
printf("%-12s%-9s%-6s%-6s%-12s%-15s%-10s%-5s\n","学号","姓名","性别","printf("%-12s%-9s%-6s%-6d%-12s%-15s%-10s%-5s\n",
student.schoolnum,student.name,student.sex,
年龄","籍贯","系别","专业","班级");
}
}
fwrite(&student,sizeof(StudentType),1,fp);
else{
printf("无此学号学生!\n"); clearerr(fp);
}
fclose(fp);
void DeleteData(void) {
for(;;) {
if(fread(&student,sizeof(StudentType),1,fp)>0) {
FILE * fp;
StudentType student; char schoolnum[16]; char c;
printf("输入要删除的学生的学号:"); gets(schoolnum);
if((fp=fopen("student.dat","rb+"))==NULL){ }
rewind(fp);
if((fp=fopen("student.dat","wb+"))==NULL){ }
printf("打开文件student.dat失败!\n"); system("PAUSE"); return;
}
}
}
break; // 找到学号而退出
if(feof(fp))
break;
if(!feof(fp)){ // 判断是否到文件末尾
student.age,student.city,student.college,student.major,student.classnum); } else{
printf("无此学号学生!\n"); clearerr(fp);
printf("%-12s%-9s%-6s%-6s%-12s%-15s%-10s%-5s\n","学号","姓名","性别","printf("%-12s%-9s%-6s%-6d%-12s%-15s%-10s%-5s\n",
student.schoolnum,student.name,student.sex,
年龄","籍贯","系别","专业","班级");
printf("是否删除此学生(y/n)?"); c=getchar();
while(getchar()!='\n')
;
c=tolower(c);
// 磁盘上的文件没有删掉,只是把标记标为1 if(c=='y'){ }
student.status=1;
fseek(fp,-(sizeof(StudentType)),SEEK_CUR); fwrite(&student,sizeof(StudentType),1,fp);
} fclose(fp);
void SearchData(void) {
if(!feof(fp)){ // 判断是否到文件末尾
FILE * fp;
StudentType student; char schoolnum[16];
printf("输入要查找的学生的学号:"); gets(schoolnum);
if((fp=fopen("student.dat","rb+"))==NULL){ }
rewind(fp); for(;;) { }
if(fread(&student,sizeof(StudentType),1,fp)>0) { }
if(feof(fp))
break;
if(strcmp(student.schoolnum,schoolnum)==0&&student.status==0)
break; // 找到学号而退出
if((fp=fopen("student.dat","wb+"))==NULL){ }
printf("打开文件student.dat失败!\n"); system("PAUSE"); return;
printf("%-12s%-9s%-6s%-6s%-12s%-15s%-10s%-5s\n","学号","姓名","性别","printf("%-12s%-9s%-6s%-6d%-12s%-15s%-10s%-5s\n",
student.schoolnum,student.name,student.sex,
年龄","籍贯","系别","专业","班级");
}
} else{
printf("无此学号学生!\n"); clearerr(fp);
} fclose(fp);
void ListData(void) {
rewind(fp); //文件指针移到头
fread(&student,sizeof(StudentType),1,fp); while(!feof(fp)) // 判断文件到末尾 {
printf("%-12s%-9s%-6s%-6d%-12s%-15s%-10s%-5s\n",student.schoolnum,student.
FILE * fp;
StudentType student;
printf("%-12s%-9s%-6s%-6s%-12s%-15s%-10s%-5s\n","学号","姓名","性别","年龄
if((fp=fopen("student.dat","rb+"))==NULL){ }
if((fp=fopen("student.dat","wb+"))==NULL){ }
printf("打开文件student.dat失败!\n"); system("PAUSE"); return;
","籍贯","系别","专业","班级");
if(student.status==0){
name,student.sex,
student.age,student.city,student.college,student.major,student.classnum);
}
}
fread(&student,sizeof(StudentType),1,fp);
//clearerr(fp); fclose(fp);
int main(void) {
while(select'6'){ }
switch(select){ case '1':AddData();
break; break; break;
char select; do{
printf("请选择:\n");
printf("1.增加数据 2.修改数据 3.查询数据 4.删除数据 5.显示数据 6.退出select=getchar(); while(getchar()!='\n')
;
\n");
system("cls"); // 清屏 printf("输入1~6\n");
printf("1.增加数据 2.修改数据 3.查询数据 4.删除数据 5.显示数据 6.退select=getchar(); while(getchar()!='\n')
;
出\n");
case '2':UpdateData(); case '3':SearchData(); case '4':DeleteData();
}
}
break;
case '5':ListData();
}while(select!='6'); return 0;
3.4运行结果
总结
经过一个学期对《C语言与程序设计》这门课程的学习,同学们都认为真正的学到了有用知识,可能有一些人学的不够理想,但无论如何,这些知识都为我们的下一步学习打下了坚实的基础。做这么一个课程设计,一方面是为了检查我们一个学期来我们学习的成果,另一方面也是为了让我们进一步的掌握和运用它,同时也让我们认清自己的不足之处和薄弱环节,加以弥补和加强。
第一个程序是一个万年历程序,可以查询某年某月某日到公元1年1月1日中任意一天是星期几,只要在运行程序时按照要求输入年份程序就会把这一年的所有天是星期几显示在屏幕上。这个程序花费了几天时间,用了一天的时间去思索和了解程序,又用了三天去设计程序以及调试程序,而在调试程序的过程中,经常会出现一些不如意的地方,例如在写 DateToNum函数时,我把“+=”这个复合的赋值运算符写成了“=+”,程序在全部组建时并没有显示错误与警告,但程序的执行结果不正确。经过一番检查,我任然没有发现错误在那里。没有办法之下,我只好请教老师帮忙修改程序。通过老师的指导,我才发现原来是把“+=”写成了“=+”,虽然没有语法错误,然而存在逻辑错误。当然程序还存在一些其他错误,所以程序不断被修改。这样经过一次又一次的修改之后,程序执行后终于能够得到正确结果,而且程序更显得人性化。
第二个程序是井子棋游戏。说实话我在考虑井子棋游戏的整体设计时,并没有想到要用结
构体和枚举类型。因为在学习《C语言与程序设计》这本书的第九章(结构与联合)和第十一章(复杂类型的指针)时 ,我并没有学好,所以不了解结构体和枚举类型的适用范围以及优点。还是通过阅读《C语言程序设计实验与课程设计报告》时,发现原来枚举类型适合用于某些变量,它们的取值被界定在一个有限的范围内这种情况下,然而系统需要对一些类型不同但又相互关联的数据进行处理,定义结构体类型则更合适。
第三个程序是学生学籍管理系统。此程序涉及到FILE指针、标准流式文件、打开文件的函数、关闭文件的函数、文件的直接输入输出函数等,这些知识点都是我不熟悉的,为了能够完成这个程序,我又把相关知识再次复习了一遍。 通过这一次程序的设计,让我深深的感受到编程的艰难与乐趣。
(要求:一级标题,黑体,三号,居中;二级标题,黑体,小三号;三级标题,黑体,四号;正文,宋体,小四号,1.25倍行距)
课程设计成绩评定表