有没有办法在循环中的条件至少满足一次时运行语句?



我目前在空闲时间玩游戏,目前正在开发一个刽子手游戏。但是,我偶然发现了一个问题,我认为如果有一种方法可以运行语句,如果循环中的条件至少满足一次,并且如果条件甚至一次都不满足,它就可以解决它,它会做另一件事。可以做到吗?有人有什么想法吗? 我赞赏任何建议。

我尝试做这样的事情:

for (){
if (string [i] == letter that the player inputed){
// replace underscores with the letter guessed
// and also turn a bool statement true
}
else {
// turn the bool statement false
}
}
if (!bool variable){
// print that the letter guessed was not in the answer
// and substract one from the number of guesses available
}

但是我注意到它不起作用,因为循环将运行,如果它检查的最后一个字母不在答案中,则布尔值将变为假,从而打印该字母不在答案中并从分数中减去一个。(这也是我第一次在这里发帖,我不知道这是否是我应该写代码的方式,所以如果我做得不正确,我事先道歉( `

你应该从不同的角度来解决这个问题:

for( ... ) {
if( your condition is met ) {
do_whatever_you_have_to();
break;   // <<--- exit the loop, so it's done only once
}
}

如果比较失败,您不必关闭标志guessed

string s;
bool guessed = false;
char inputted_letter; // comes from somewhere
for (size_t i = 0; i < s.size(); ++i) {
if (s[i] == inputted_letter) {
// replace underscores with the letter guessed
guessed = true;
}
}
if (!guessed) {
// print that the letter guessed was not in the answer
// and substract one from the number of guesses available
}

您不必在循环中设置false

bool has_found = false;
for (auto& c : word_to_guess)
{
if (input_letter == c) {
// replace _ by current letter...
has_found = true;
}
}
if (!has_found){
// print that the letter guessed was not in the answer
// and substract one from the number of guesses available
}

但我建议你的循环一次只做一件事:

bool contains(const std::string& word_to_guess, char input_letter)
{
return std::any_of(word_to_guess.begin(),
word_to_guess.end(),
[&](char c){ return input_letter == c; })
/*
for (auto& c : word_to_guess)
{
if (input_letter == c) {
return true;
}
}
return false;
*/
}

if (contains(word_to_guess, input_letter)
{
// show current letter...
for (std::size_t i = 0; i != hangman_word.size(); ++i) {
if (word_to_guess[i] == input_letter) {
hangman_word[i] = word_to_guess[i];
}
}
} else {
// print that the letter guessed was not in the answer
// and substract one from the number of guesses available
}

你能按照你的要求去做吗? 可能,但是你说你正在制作游戏 Hangman 在C++,我认为你用错误的方法去做这件事,因此,选择或实现错误的算法。您正在尝试遍历后端长度可能不同的两个字符串,如果操作不正确可能会导致问题,往往难以跟踪,特别是如果它们的比较决定了循环条件、退出或返回语句。

我已经实现了我的"刽子手"版本,现在尽管格式不是最漂亮的,但关卡词典也不是从大量随机单词中生成的。我在代码的注释中表达了这一点,这些通常会从文本文件中读入并保存到这些结构中。为了简单起见,我直接在代码中使用随机单词初始化它们。

看看我做了什么:


#include <string>
#include <iostream>
#include <vector>
#include <map>
#include <random>    
class Game;
int main() {
using namespace util;
try {
Game game("Hangman");
game.start();
} catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
} 
class Game {
private:
std::string title_;
bool is_running_{ false };
std::string answer_;
std::string guessed_;
std::map<unsigned, std::vector<std::string>> dictionary_; // unsigned represents difficulty level of word
unsigned choosen_difficulty_;
std::string guessed_characters_{"n"};
public:
Game(const std::string& title) : title_{ title }, choosen_difficulty_{ 0 } {
initialize();
start_over();
}
void start() {
is_running_ = true;
// the player has as many attempts as twice the length of hidden answer's word length. 
int number_tries = answer_.size() * 2;
while (is_running_ || number_tries > 0) {
displayGuessedWord();
displayGuessedCharacters();
// ask the player to guess a character;
char guess;
// get a character and make sure it is a valid alphabet character
do {
std::cout << "Guess a character ";
std::cin >> guess;
// Note: I'm using ascii characters in this case 
// but for demonstration purposes only!
if ((guess < 'a' && guess > 'z') ||
(guess < 'A' && guess > 'Z')) {
std::cout << "invalid entry ";
}
} while ( (guess < 'a' && guess > 'z') ||
(guess < 'A' && guess > 'Z') );
// test character and update guessed word and number of tries.
test_character(guess);
update_guessed_characters(guess);
number_tries--;
// failed condition
if (number_tries <= 0 && guessed_ != answer_) {
std::cout << "nGame Over!n";              
is_running_ = try_again(number_tries);
// winning condition
} else if (number_tries > 0 && guessed_ == answer_) {
std::cout << "nCongratulations!n";
is_running_ = try_again(number_tries);
}
if (!is_running_) break;                
}
}
private:
void displayGuessedWord() {
std::cout << 'n' << guessed_ << 'n';
}
void displayGuessedCharacters() {
std::cout << guessed_characters_ << 'n';
}
void initialize() {
// Normally this would be read in from a file upon game initialization
// but for demonstration purpose, I'll generate a few small vectors of strings
// and associate them to their difficulty level
// levels are based on 3 factors, the length of the word, the repetitive occurance 
// of common characters, and the amount of less commonly used characters.
std::vector<std::string> level_1{ "ate", "cat", "dog", "coat", "coal", "does" };
std::vector<std::string> level_2{ "able", "believe", "balloon", "better", "funny", "happy" };
std::vector<std::string> level_3{ "ability", "carpenter", "dogmatic", "hilarious", "generosity", "hostility" };
// ... etc. I'll use just these here for simplicty where each vector has six entries, however,
// with random number generators, this can be done generically for any size 
// or number of elements in each of the different vectors.
// create generate the map:
dictionary_[1] = level_1;
dictionary_[2] = level_2;
dictionary_[3] = level_3;
}
std::string getWordFromDictionary(unsigned difficulty, std::map<unsigned, std::vector<std::string>>& dict) {
auto level = dict[difficulty]; // extract the vector based on difficulty level
auto size = level.size();      // get the size of that vector
std::random_device dev;        // create a random device                     
std::mt19937 rng(dev());       // create a pseudo random generator
// create a uniform int distribution type with the range from 0 to size-1
std::uniform_int_distribution<std::mt19937::result_type> dist(0, size - 1);
return level[dist(rng)]; // return a random string from this level.
}
void start_over() {
system("cls"); // Note: I'm running visual studio on Windows!
std::cout << "Welcome to " << title_ << 'n';
// We can use a random generator to pick a word from the given difficulty
// but first we need to get user input for the chosen level.
do {
std::cout << "Choose your difficulty [1-3]n";
std::cin >> choosen_difficulty_;
if (choosen_difficulty_ < 1 || choosen_difficulty_ > 3) {
std::cout << "Invalid entry:n";
}
} while (choosen_difficulty_ < 1 || choosen_difficulty_ > 3);
answer_ = getWordFromDictionary(choosen_difficulty_, dictionary_);
// clear and resize guessed word to be that of answer_ and add bunch of hypens.
guessed_.clear();
guessed_.resize(answer_.size(), '-');
// also reset the guessed_characters
guessed_characters_ = std::string("n");
}
bool try_again(int& tries) {
std::cout << "Would you like to try again?n";
char c;
std::cin >> c;
if (c == 'y' || c == 'Y') {
start_over();
// don't forget to update this so that the loop can repeat
tries = answer_.size() * 2;
return true;
}
else {
std::cout << "Thank you for playing " << title_ << 'n';
return false;
}
}
void test_character(const char c) {
// here is where you would use the standard library for taking the character
// passed into this function, updating the guessed_characters
// get all indexes
std::vector<unsigned> locations;
for (unsigned i = 0; i < answer_.size(); i++)
if (answer_[i] == c)
locations.push_back(i);
// now update the guessed word
if ( locations.size() > 0 )
for (size_t n = 0; n < locations.size(); n++)
guessed_[locations[n]] = c;
}
void update_guessed_characters(const char c) {
guessed_characters_.insert(0, &c); // just push to the front
}
};

如果你注意到我是如何构建上面的游戏类的;我正在使用 while 和 do-while 循环与 for 循环和 if 语句以及单个布尔标志结合使用来确定游戏的状态。游戏状态也是从更新到猜到的角色和猜到的单词来确定的。然后我将其与答案进行比较。根据某些条件,循环将继续从用户那里寻求输入或退出。

我不保证这段代码是 100% 没有错误的,因为我没有做任何严格的测试或检查极端情况或特殊情况,但代码已经运行没有错误,我已经测试了所有主要的游戏状态情况。它似乎工作正常。

我知道如果我选择使用一些标准库函数来处理字符串,可能会有很多改进和简化,但我想说明在制作具有状态及其过渡的游戏的设计或思考过程中涉及的各个步骤。我也可以将游戏类声明放入它自己的头文件中,并在 cpp 文件中实现,但我将其保留为 main 中显示的单个类.cpp以便于复制、粘贴和编译。

在这个特定的游戏中,我没有使用开关和案例语句,我只是坚持使用一些 while 和 do-while 循环,一些 for 循环和 if 语句,因为只有几个游戏状态和过渡需要担心。此实现还演示了所涉及的算法,并展示了它们如何相互连接。我希望这有助于您更好地了解设计过程。

在制作具有不同状态且有点复杂的游戏时,您应该首先制作状态表,并在编写任何代码之前列出其所有转换。然后,您应该列出开始,继续,获胜,失败和退出状态或案例。然后,您需要根据其所需条件制定如何从一种状态过渡到另一种状态。从长远来看,这将对您有所帮助!

正确布置游戏状态及其过渡后,您就可以开始为这些状态制作所需的函数并开始将它们连接在一起。之后,您将编写函数的内部或它们将执行的操作的实现。

最后,在你完成之后,你想做一些调试和单元和案例测试,如果一切看起来都很好,那么改进你当前的算法或选择更好的算法以获得峰值或最有效的性能是安全的。

最新更新