题意:
1. 猜单词游戏, 输入一个 puzzle 和 guess, 判断 guess 是否在限定次数(7次)内猜中 puzzle 中的所在字符.
2. guess 中每一个猜错的字符, 只计算一次; 即若猜了 a, 不中, 则下次再猜 a , 仍不中, 但不会递增 stroke.
3. 若错误次数超过限定次数, 则输出 lose, 若在限定次数内猜完 puzzle, 则输出 win. 若 guess 中的字符已遍历完, 既未猜完 puzzle, 也未到达限定次数, 则输出 chickened out.
思路:
取 guess 中每个字符, 判断此字符是否在 puzzle 中, 若在, 则把 puzzle 中相同字符全部删掉; 若不在, 则判断此字符是否以前猜过, 若未猜过, 则递增 stroke, 并把错误字符添加到 wrongAnswer 中; 若已猜过, 则不作处理.
要点:
1. C++ 字符串中查找指定字符, 使用以下代码
wrongAnswer.find(guesses[i]) == string::npos
2. C++ 字符串删除指定字符, 使用以下代码
string::iterator new_end = remove_if(puzzle.begin(), puzzle.end(),
bind2nd(equal_to<char>(), guesses[i]));
puzzle.erase(new_end, puzzle.end());
3. STL 容器(包含 string) 都可以使用 empty() 函数来判断其是否为空.
代码:
# include <iostream>
# include <string>
# include <cstdio>
# include <cstdlib>
# include <algorithm>
# include <functional>
using namespace std;
// 以下这两种写法是有区别的, cin 对于回车换行的处理太诡异了
// 所以保险时可用 getline 读进来一个字符串, 再转成 int, 至少不会出错
// cin >> round >> blank;
// cin >> round;
// cin >> blank;
int main(int argc, char const *argv[])
{
#ifndef ONLINE_JUDGE
freopen ("489_i.txt", "r", stdin);
freopen ("489_o.txt", "w", stdout);
#endif
const int MAX_STROKES = 7;
int round;
string puzzle;
string guesses;
while (cin >> round >> puzzle >> guesses && round != -1) {
string wrongAnswer = "";
int strokes = 0;
cout << "Round " << round << endl;
for (int i=0; i<guesses.length(); i++) {
if (puzzle.find(guesses[i]) == string::npos) {
// 没有猜中, 则每个猜错的只计算一次 stroke
if (wrongAnswer.find(guesses[i]) == string::npos) {
++strokes;
if (strokes == MAX_STROKES) {
cout << "You lose." << endl;
break;
}
wrongAnswer.push_back(guesses[i]);
}
} else {
// 在 puzzle 中删除猜中了的 guesses[i]
string::iterator new_end = remove_if(puzzle.begin(), puzzle.end(),
bind2nd(equal_to<char>(),
guesses[i]));
puzzle.erase(new_end, puzzle.end());
if (puzzle.empty()) {
cout << "You win." << endl;
break;
}
}
}
if (!puzzle.empty() && strokes != MAX_STROKES) {
cout << "You chickened out." << endl;
}
}
return 0;
}
环境: C++ 4.5.3 - GNU C++ Compiler with options: -lm -lcrypt -O2 -pipe -DONLINE_JUDGE