大家好,欢迎来到IT知识分享网。
Guess-the-word—Chinese-Version
背景
莫妮卡想要和我一起玩“上吊小人儿”(猜单词),但是我还是个中学生啊……
可在github上下载完整代码,词库,教程等
点我跳转
为什么我要写这个程序
当然是因为MAS(Monika After story)中Monika提出了的新游戏——上吊小人儿——过于困难啦~
基本操作
1.编译运行,输入要猜的残缺单词,未知部分用*表示。
例如,app**
2.按下回车。
3.接下来输入你已经猜过但是猜错了的字母,中间不需要打空格,回车结束。如果还没有猜错了的字母的话就直接一个回车
例如你猜了但是猜错了的字母有b,c,d
那么你就输入bcd和一个回车
4.接下来程序就会给你所有可能性以及其中出现每个字母的次数,方便你选择接下来要猜什么。
技巧
先输入常用的字母如e,t,a
如果没有足够多的元音说明可能还有(aoeiu)
元音的后面及其可能接着n、r
Code
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cstring> 5 #include<string> 6 #include<cmath> 7 #include<map> 8 #include<set> 9 #include<queue> 10 #include<vector> 11 #include<fstream> 12 #define IL inline 13 #define re register 14 #define LL long long 15 using namespace std; 16 17 bool in(char ch) 18 { 19 if (ch <= 'z' && ch >= 'a') return 1; 20 if (ch <= 'Z' && ch >= 'A') return 1; 21 return 0; 22 } 23 24 bool exclude(string a, string b, string c)//a中没有b中的任何字母,a中没有c中不同位置的任何字母 25 { 26 for (unsigned i = 0; i < a.size(); i++) 27 for (unsigned j = 0; j < b.size(); j++) 28 if (a[i] == b[j]) { 29 //cout<<"当前单词为"<<a<<",重复字母为"<<a[i]<<endl; 30 return 0;//猜错的字母不可能有 31 } 32 33 map<char, int>lib; 34 for (unsigned int i = 0; i < c.size(); i++) if (c[i] != '*') lib[c[i]]++; 35 for (unsigned int i = 0; i < a.size(); i++) if (c[i] == '*' && lib.find(a[i]) != lib.end()) return 0; 36 37 return 1; 38 } 39 40 vector<string>word; 41 42 string t; 43 int main() 44 { 45 ifstream fin("word.txt"); 46 ofstream fout("word.his", ios::app); 47 ifstream his("word.his"); 48 49 if (his.peek() == EOF) cout << "没有查询历史\n"; 50 else while (his.peek() != EOF) his >> t, word.push_back(t); 51 52 cout << "读取数据库...\n"; 53 while (fin.peek() != EOF) { 54 string w; 55 getline(fin, t); 56 int post = 0; 57 while (!in(t[post]) && post < t.size()) post++; 58 while (in(t[post]) && post < t.size()) w.push_back((t[post] < 'a') ? (t[post] - 'A' + 'a') : t[post]), post++; 59 word.push_back(w); 60 } 61 cout << "读取完毕!\n"; 62 while (true) { 63 string q, o; 64 cout << "输入你想补全的残缺的单词,未知部分用*代替。\n"; 65 cin >> q; 66 getchar();//读取刚刚剩下的一个空格 67 cout << "输入已经猜错了的字母,没有的话直接按下回车键\n"; 68 getline(cin, o); 69 bool succ = 0; 70 int total = 0; 71 map<string, int>lib; 72 int count[27]; 73 memset(count, 0, sizeof(count)); 74 for (unsigned int i = 0; i < word.size(); i++) 75 { 76 if (lib.find(word[i]) == lib.end()) 77 if (q.size() == word[i].size() && exclude(word[i], o, q)) 78 { 79 bool flag = 1; 80 for (unsigned int j = 0; j < q.size(); j++) 81 { 82 if (q[j] != '*' && q[j] != word[i][j]) { 83 flag = 0; 84 break; 85 } 86 } 87 if (flag) { 88 succ = 1; 89 lib[word[i]]++; 90 cout << ++total << "\t" << word[i] << endl; 91 for (unsigned int j = 0; j < word[i].size(); j++) count[((word[i][j] < 'a') ? word[i][j] - 'A' + 'a' : word[i][j]) - 'a']++; 92 } 93 } 94 } 95 if (!succ) { 96 cout << "单词没有找到啊~你知道答案么?(yes/no)"; 97 string know; cin >> know; 98 if (know == "y" || know == "yes") { 99 cout << "请输入答案:"; 100 string ans; 101 cin >> ans; 102 cout << "好哒,它已经被保存了\n"; 103 fout << ans << endl; 104 } 105 } 106 else { 107 cout << "共计" << total << "个符合条件的单词\n"; 108 int max = -1; 109 count[max] = -1; 110 for (int i = 0; i < 26; i++) { 111 cout << (char)(i + 'a') << " " << count[i] << endl; 112 if (count[max] < count[i] && q.find(i + 'a') == q.npos) max = i; 113 } 114 cout << "建议猜测 " << (char)(max + 'a') << " 出现了 " << count[max] << "次"; 115 } 116 cout << endl << endl << endl; 117 } 118 return 0; 119 }
基本算法
读取word.txt,进行无关字符的过滤,选取其有效部分加入vector<string>word中。读取时如果是大写字母则将其转化为小写
同理读取历史
输入要猜的单词以及猜错了的字母
遍历word,按照一下顺序进行排除:
- 这个单词本轮中没有出现过(如果没有则将其加入lib)
- 长度相同
- exclude()检测这次扫的单词中没有猜错的单词,且其没有被猜到的单词位置上不能有猜对了的单词(否则应该已经被猜出来而不是还是未知的)
- 除了*以外,相同位置上字母相同
- 如果没有找到这个单词的话,询问要不要加入到错词本中
- 如果找到了,输入所有结果和总数以及字母频率分析
特点
- 词库不需要清洗
- 你可以疯狂向词库末尾添加单词,而不需要在意它会输出多余相同的单词(因为lib会自动过滤)
- 会向您推荐最佳的下一步应该猜的单词
- 查不到的话可以记录下来,下次就可以查
词库来源
感谢mahavivo的词库
本文使用的便是其其中的COCA_with_translation.txt,有20111个单词
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/32006.html