之前帮别人写的一个简单的报告,无偿分享给大家~代码在后面,有一些图片出于懒惰没有上传。比较简单,喜欢的话关注我~,请勿商用~
1 系统功能模块结构图
该程序主要思路:
头文件设计,存储结构设计,函数设计;
函数包括:
显示主菜单,功能选择函数
文件读入写入函数,两个txt文件,四个函数
进行游戏设计两个函数
单词的增删改设置1一个函数
对于记录的排序设置一个排序方式函数
2 数据结构设计及用法说明
利用结构体和数组进行存储
应用函数的实参形参实现各个函数的信息一致
typedef struct HISTORY
{
char name[32];
int count;
int len;
}JL;
以下是在M函数中定义的局部变量,主要是结构体数组和字符数组以及整型统计
JL LS[128];
char words[128][2][32];
int SUM1=R1(LS);//计数——历史信息
int SUM2 = R2(words);//计数——单词信息
3 程序结构(画流程图)
该图为函数M()的流程图,该函数是菜单作用,循环调出功能。
该图是主函数
对单词功能菜单实现的源代码以及分析:
int W(char words[128][2][32], int SUM2)//对单词增删改,返回的是单词的总共数量
{
int I;char en[32], ch[32];
printf("\t\t 单词管理\n");
printf("\t\t 1.增加单词\n");
printf("\t\t 2.删除单词\n");
printf("\t\t 3.更改单词\n");
printf("\t\t 4.退出管理\n");
printf("\t\t请输入相应功能前的数字进行操作:\n");
scanf("%d", &I);
switch (I)//switch结构调用功能
{
case 1:
printf("请输入单词的英文和中文\n");
scanf("%s %s", words[SUM2][1], words[SUM2][0]);
return SUM2+1;
case 2:
printf("请输入要删除单词的中文\n");
scanf("%s", ch);
for (int i = 0; i < SUM2; i++)
{
if (strcmp(ch, words[i][0]) == 0)//寻找相同的单词
{
for (int j = i; j < SUM2 - 1; j++)//用strcpy函数将后面的单词移动上前,达成删除功能
{
strcpy(words[j][0], words[j + 1][0]);
strcpy(words[j][1], words[j + 1][1]);
}
printf("删除成功!\n");
return SUM2-1;
}
}
printf("没有找到该单词!\n");
return SUM2;//如果没有这个单词,就不改变SUM2
case 3:
printf("请输入单词的英文和中文\n");
scanf("%s %s", en, ch);
for (int i = 0; i < SUM2; i++)
{
if (strcmp(ch, words[i][0]) == 0)
{
strcpy(words[i][1], en);//用strcpy功能更改单词
}
}
break;
case 4:
return SUM2;
default:
break;
}
return SUM2;
}
4各模块的功能
函数 | 形参 | 功能介绍和返回值 |
void H; | () | 欢迎界面 无返回值 |
void M; | () | 功能选择 无返回值 |
int R1; | (JL LS[128]) | 读取history.txt文件 返回历史信息的条数 |
Int R2; | (char words[128][2][32]) | 读取words.txt文件 返回单词的条数 |
int G1; | (char words[128][2][32], int SUM2,JL LS[128],int SUM1) | 开始游戏 返回历史记录的长度 |
JL G2; | (JL ret,char word_ch[32], char word_en[32]) | 进行猜单词 返回一个历史记录 |
int W; | char words[128][2][32], int SUM2) | 单词管理菜单 返回值0 |
int callback; | (const void* a, const void* b) | 排序回调函数 返回值0或1 |
void save1; | (JL LS[128], int SUM1) | 保存历史记录 无返回值 |
void save2; | (char words[128][2][32], in()t SUM2) | 存储单词 无返回值 |
int main; | () | 主函数 返回值0 |
5 试验结果
设计过程中出现的问题和解决方法:
1 函数的逻辑结构问题
解决方法:分析关联,明确调用关系
2 部分代码语法不清晰
解决方法:查询书籍和互联网,询问老师同学
以下是玩家尝试游戏的输入输出样例:
输入:1
输入玩家姓名
输入:alice
谜底:白
单词首字母:w
你还有3次机会,请输入完整单词
输入:write
w-ite
你还有2次机会,请输入完整单词
输入:white
谜底:心
单词首字母:h
你还有3次机会,请输入完整单词
输入:heart
谜底:父亲
单词首字母:f
你还有3次机会,请输入完整单词
输入:father
谜底:一个
单词首字母:a
你还有3次机会,请输入完整单词
输入:an
游戏结束!
6 调试与测试
调试方法:
1输入简单样例测试
2根据编译器提示改错
3使用编译器debug
程序运行结果截图及文字分析:
1 程序运行测试步骤如下:
- 创建txt文件words.txt
按英文 中文格式创建
- 创建txt文件history.txt
空白文件
- 输入内容,尝试玩家猜单词输入
- 查看历史记录
- 进行单词的增删改
- 关闭系统
- 查看两个txt文件现状
2 程序运行结果截图如下:
=================================
1.开始游戏
2.单词管理
3.历史记录
4.退出系统
=================================
请输入相应功能前的数字进行操作:
3
以下是前三名玩家的最优历史记录
玩家姓名tim 猜单词次数1 猜单词长度4
玩家姓名alice 猜单词次数5 猜单词长度18
请按任意键继续. . .
7 总结
设计的收获和体会:
通过一学期系统的学习,综合运用了课内外的C语言知识,独立完成了这个具有多种功能,较为完善的猜单词系统。
该系统综合运用了结构体,指针,函数,文件读写等知识,,以较精炼的语言实现了数据的文件流,格式输入输出,结构体存储,,简易计算和查找,筛选数据,排序等功能。
在编写代码的过程中,曾多次出现例如知识点盲区,出现明显的BUG,逻辑结构运用混乱等问题,通过询问老师以及前辈,互联网自学等方式解决了问题,提升了自我。完成该项实验,对于基础的C语言语法有了更深刻的理解,提高了自学能力和耐心,对此有了很大的收获。
历经数日,终于做出了系统的雏形,有着小小的成就感。但我也认识到做一个完善系统的不易。在编写的过程中,有不少的的设想,因为能力不足没有实现。距离真正的系统开发,我们还有很多可以学习的地方。
千里之行,积于跬步。希望能在未来学习的过程中,能融会贯通,力争以后能有更好的编写代码的能力,把程序做得更好。
参考文献
https://www.csdn.net/?spm=1001.2101.3001.4476
附录
#define _CRT_SECURE_NO_DEPRECATE
#define _CRT_SECURE_NO_WARNINGS
#include<math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct HISTORY
{
char name[32];
int count;
int len;
}JL;
void H();//欢迎界面
void M(); //功能选择
int R1(JL LS[128]);//读取history.txt文件,返回历史信息的条数
int R2(char words[128][2][32]);//读取words.txt文件,返回单词的条数
int G1(char words[128][2][32], int SUM2,JL LS[128],int SUM1);//开始游戏,返回历史记录的长度
JL G2(JL ret,char word_ch[32], char word_en[32]);//一次游戏 返回一个历史记录
int W(char words[128][2][32], int SUM2);//单词管理菜单
int callback(const void* a, const void* b);//排序回调函数
void save1(JL LS[128], int SUM1);//保存历史记录
void save2(char words[128][2][32], int SUM2);//存储单词
int main()
{
H();
M();
return 0;
}
void H()//欢迎界面
{
printf("欢迎进入猜单词系统!\n\n");
printf("\t\t |--------------------------|\n");
printf("\t\t |------- 猜单词系统 -------|\n");
printf("\t\t |--------------------------|\n");
printf("\n");
return;
}
void M() //功能选择
{
JL LS[128];
char words[128][2][32];
int SUM1=R1(LS);//计数——历史信息
int SUM2 = R2(words);//计数——单词信息
while (1)
{
printf("\t\t=================================\n");
printf("\t\t 1.开始游戏\n");
printf("\t\t 2.单词管理\n");
printf("\t\t 3.历史记录\n");
printf("\t\t 4.退出系统\n");
printf("\t\t=================================\n");
printf("\t\t请输入相应功能前的数字进行操作:\n");
int I;
scanf("%d", &I);
switch (I)
{
case 1:
SUM1 =G1(words,SUM2,LS,SUM1);
save1(LS, SUM1);
break;
case 2:
SUM2= W(words, SUM2);
save2(words, SUM2);
break;
case 3:
qsort(LS,SUM1, sizeof(JL), callback);
printf("以下是前三名玩家的最优历史记录\n");
for (int i=0;i<3&&i<SUM1;i++)
{
printf("玩家姓名%s 猜单词次数%d 猜单词长度%d\r\n", LS[i].name, LS[i].count, LS[i].len);
}
system("pause");
break;
case 4:
printf("\t\t欢迎下次使用!\n");
exit(0);
default:
break;
}
}
}
int R1(JL LS[128])//读取history.txt文件,返回历史信息的条数
{
FILE* fp;
int SUM= 0;
fp = fopen("history.txt", "r");
while (fscanf(fp, "%s %d %d",LS[SUM].name,&LS[SUM].count,&LS[SUM].len) != EOF)//
{
SUM++;
}
fclose(fp);
return SUM;
}
int R2(char words[128][2][32])//读取words.txt文件
{
FILE* fp;
int SUM= 0;
fp = fopen("words.txt", "r");
while (fscanf(fp, "%s %s", words[SUM][1], words[SUM][0]) != EOF)//前一个存英文,后一个存中文
{
SUM++;//每读一条计数增加
}
fclose(fp);
return SUM;//返回单词的条数
}
void save1(JL LS[128], int SUM1)//保存历史记录
{
FILE* fp;
fp = fopen("history.txt", "w");
for (int i = 0; i <SUM1; i++)
{
fprintf(fp, "%s %d %d\n", LS[i].name, LS[i].count, LS[i].len);
}
fclose(fp);
}
void save2(char words[128][2][32], int SUM2)//存储单词
{
FILE* fp;
fp = fopen("words.txt", "w");
for (int i = 0; i < SUM2; i++)
{
fprintf(fp, "%s %s\n",
words[i][1], words[i][0]);
}
fclose(fp);
}
int G1(char words[128][2][32], int SUM2,JL LS[128],int SUM1)//开始游戏,返回历史记录的长度
{
JL h;
h.count = 0;
h.len=0;
printf("输入玩家姓名\n");
scanf("%s", h.name);
int prelen=h.len,I=4;//设置有4次机会
while(I--)
{
int r = rand();
r %= SUM2;
h= G2(h,words[r][0], words[r][1]);
if(h.len==prelen)break;
prelen=h.len;
}
printf("游戏结束!\n");
system("pause");
for (int i = 0; i < SUM1; i++)
{
if (strcmp(h.name, LS[i].name) == 0)//已经有这个名字
{
if (h.count / h.len < LS[i].count / LS[i].len)
{
LS[i] = h;
return SUM1;
}
}
}
LS[SUM1] = h;//从来没有
return SUM1+1;
}
JL G2(JL ret,char word1[32], char word2[32])//一次游戏 返回一个历史记录
{
char A[32];
int count=0;
printf("谜底:%s\n", word1);
printf("单词首字母:%c\n",word2[0]);
while (count <3)
{
printf("你还有%d次机会,请输入完整单词\n",3-count);
count++;
scanf("%s",A);
for (int i= 0; i < (int)strlen(word2); i++)
{
if (A[i] != word2[i])
{
A[i] = '-';
}
}
A[strlen(word2)] = '\0';
if (strcmp(A, word2) == 0)
{
ret.count+=count;
ret.len+=strlen(word2);
return ret;
}
else
{
printf("%s\r\n", A);
}
}
count=0xfffff;//没有猜中
return ret;
}
int W(char words[128][2][32], int SUM2)//对单词增删改,返回的是单词的总共数量
{
int I;char en[32], ch[32];
printf("\t\t 单词管理\n");
printf("\t\t 1.增加单词\n");
printf("\t\t 2.删除单词\n");
printf("\t\t 3.更改单词\n");
printf("\t\t 4.退出管理\n");
printf("\t\t请输入相应功能前的数字进行操作:\n");
scanf("%d", &I);
switch (I)//switch结构调用功能
{
case 1:
printf("请输入单词的英文和中文\n");
scanf("%s %s", words[SUM2][1], words[SUM2][0]);
return SUM2+1;
case 2:
printf("请输入要删除单词的中文\n");
scanf("%s", ch);
for (int i = 0; i < SUM2; i++)
{
if (strcmp(ch, words[i][0]) == 0)//寻找相同的单词
{
for (int j = i; j < SUM2 - 1; j++)//用strcpy函数将后面的单词移动上前,达成删除功能
{
strcpy(words[j][0], words[j + 1][0]);
strcpy(words[j][1], words[j + 1][1]);
}
printf("删除成功!\n");
return SUM2-1;
}
}
printf("没有找到该单词!\n");
return SUM2;//如果没有这个单词,就不改变SUM2
case 3:
printf("请输入单词的英文和中文\n");
scanf("%s %s", en, ch);
for (int i = 0; i < SUM2; i++)
{
if (strcmp(ch, words[i][0]) == 0)
{
strcpy(words[i][1], en);//用strcpy功能更改单词
}
}
break;
case 4:
return SUM2;
default:
break;
}
return SUM2;
}
int callback(const void* a, const void* b)//排序回调函数
{
JL* x = (JL*)a;
JL* y = (JL*)b;
if (x->count / x->len < y->count / y->len) return 1;
else if (x->count / x->len == y->count / y->len) return 0;
else return 1;
}