猜單詞--莫妮卡的新游戲


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,按照一下順序進行排除:

  1. 這個單詞本輪中沒有出現過(如果沒有則將其加入lib)
  2. 長度相同
  3. exclude()檢測這次掃的單詞中沒有猜錯的單詞,且其沒有被猜到的單詞位置上不能有猜對了的單詞(否則應該已經被猜出來而不是還是未知的)
  4. 除了*以外,相同位置上字母相同
  5. 如果沒有找到這個單詞的話,詢問要不要加入到錯詞本中
  6. 如果找到了,輸入所有結果和總數以及字母頻率分析

特點

  • 詞庫不需要清洗
  • 你可以瘋狂向詞庫末尾添加單詞,而不需要在意它會輸出多余相同的單詞(因為lib會自動過濾)
  • 會向您推薦最佳的下一步應該猜的單詞
  • 查不到的話可以記錄下來,下次就可以查

詞庫來源

感謝mahavivo詞庫

本文使用的便是其其中的COCA_with_translation.txt,有20111個單詞

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM