猜单词--莫妮卡的新游戏

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 << "没有查询历史
";
 50     else while (his.peek() != EOF) his >> t, word.push_back(t);
 51 
 52     cout << "读取数据库...
";
 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 << "读取完毕!
";
 62     while (true) {
 63         string q, o;
 64         cout << "输入你想补全的残缺的单词,未知部分用*代替。
";
 65         cin >> q;
 66         getchar();//读取刚刚剩下的一个空格 
 67         cout << "输入已经猜错了的字母,没有的话直接按下回车键
";
 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 << "	" << 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 << "好哒,它已经被保存了
";
103                 fout << ans << endl;
104             }
105         }
106         else {
107             cout << "共计" << total << "个符合条件的单词
";
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,按照一下顺序进行排除:

  1. 这个单词本轮中没有出现过(如果没有则将其加入lib)
  2. 长度相同
  3. exclude()检测这次扫的单词中没有猜错的单词,且其没有被猜到的单词位置上不能有猜对了的单词(否则应该已经被猜出来而不是还是未知的)
  4. 除了*以外,相同位置上字母相同
  5. 如果没有找到这个单词的话,询问要不要加入到错词本中
  6. 如果找到了,输入所有结果和总数以及字母频率分析

特点

  • 词库不需要清洗
  • 你可以疯狂向词库末尾添加单词,而不需要在意它会输出多余相同的单词(因为lib会自动过滤)
  • 会向您推荐最佳的下一步应该猜的单词
  • 查不到的话可以记录下来,下次就可以查

词库来源

感谢词库

本文使用的便是其其中的COCA_with_translation.txt,有20111个单词

原文地址:https://www.cnblogs.com/send-off-a-friend/p/13463414.html