我正在尝试用C ++编写一个简单的Hangman游戏。游戏大多数工作,但有时当我调试它时,我得到异常std :: length_error。通常在用户输入选择之后。由于Stack Overflow说我的大多数帖子都是代码,所以我在这里编写了相关的代码。但如果需要,我会提供其余的。主要代码,变量和函数声明:
#include "stdafx.h"
#include <iostream>
#include <string>
#include <ctime>
#include <stdlib.h>
using namespace std;
void game(int choice);
void check(char letter, string word);
bool check_win(string word);
char guessed[30];
int guessCount = 0, tries = 0;
int main()
{
int choice, sentinel;
cout << "Welcome to Phobez's Hangman game!" << endl;
cout << "=================================" << endl;
cout << "Guess a word which is represented by a row of dashes, representing each letter of the word." << endl;
cout << "Pick a Topic" << endl;
cout << "1. Animals\n2. Colours\n3. Days of the Week\n4. Months\n5. Body Parts\n6. Numbers" << endl;
cout << "Choice: ";
cin >> choice;
game(choice);
system("pause");
return 0;
}
然后game()函数负责设置和运行游戏的大部分内容:
void game(int choice) {
string word;
const int MAX_TRIES = 6;
char letter;
string animal[] = { "cat", "dog", "horse", "elephant", "duck", "turtle", "bird", "crab", "spider", "bear", "pig", "penguin", "mouse", "rabbit", "lion", "monkey", "bull"};
string colour[] = { "black", "white", "red", "yellow", "purple", "green", "blue" };
string day[] = { "monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday" };
string month[] = { "january", "february", "may", "march", "april", "june", "july", "august", "september", "october", "november", "december" };
string bodPart[] = { "head", "shoulder", "knee", "forehead", "eyebrow", "ear", "eye", "nose", "chest", "mouth", "arm", "stomach", "hand", "leg", "foot", "toe" };
string nums[] = { "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "zero" };
srand(time(0));
switch (choice) {
case 1:
word = animal[(rand() % 17) - 1];
break;
case 2:
word = colour[(rand() % 7) - 1];
break;
case 3:
word = day[(rand() % 7) - 1];
break;
case 4:
word = month[(rand() % 12) - 1];
break;
case 5:
word = bodPart[(rand() % 16) - 1];
break;
case 6:
word = nums[(rand() % 10) - 1];
break;
default:
word = animal[(rand() % 18) - 1];
}
do {
cout << "Word: ";
for (int i = 0; i < strlen(word.c_str()); i++) {
bool isPrinted = 0;
for (int j = 0; j < strlen(word.c_str()); j++) {
if (word[i] == guessed[j]) {
cout << word[i];
isPrinted = 1;
break;
}
}
if (isPrinted) {
continue;
}
else {
cout << "_";
}
}
cout << endl;
cout << "Misses: " << tries << endl;
cout << "Guess: ";
cin >> letter;
check(letter, word);
if (check_win(word)) {
cout << word << endl;
cout << "You won!" << endl;
break;
}
else {
continue;
}
} while (tries < MAX_TRIES);
if (tries >= MAX_TRIES) {
cout << "You lost!" << endl;
}
}
我已经尝试搜索Google和Stack Overflow以获取有关此问题的帮助,但我找不到可以向我解释我的代码有什么问题。
错误有时会弹出。大部分时间都有效。我认为这是我的开关案例中的错误(随机整数生成器限制),但我尝试将它们更改几次,但没有区别。有人可以帮忙吗?这是我面临的唯一错误。提前谢谢!
答案 0 :(得分:0)
在if (word[i] == guessed[j])
j
索引可能超出范围,因为它的上限为j < strlen(word.c_str());
而不是guessed
长度。同样值得将guessed
类型更改为::std::string
。因此,循环条件需要更改为
for
(
::std::string::size_type guessed_symbol_index = 0;
guessed.length() != guessed_symbol_index;
++guessed_symbol_index
)
...
if (word[i] == guessed[guessed_symbol_index]) {
所有切换案例都填充了可能导致越界访问的行,例如animal[(rand() % 17) - 1];
如果rand
返回17.此外,您可能会意外地设置错误的数组大小(使用魔术数字很糟糕) 。您应该将这些数组重新定义为
::std::array<::std::string, 7> day = { "monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday" };
然后正确提取长度:
day[static_cast<::std::size_t>(rand()) % day.size()];
答案 1 :(得分:0)
使用调试器它会更快。但这里有演绎方式:
max_size
string
或vector
等vector
对象的实现定义长度限制时,会引发 std::length_error
。 (请注意,这不是超出范围的问题,而是存储对象所需大小的问题)。
您不使用word
,而您唯一的字符串是word
。 RAND_MAX
可能超出存储限制的唯一位置是您对其进行分配时。但是限制是如此之大,以至于数组中的小字无法触发。
因此,这意味着您的数组访问权限不会访问您认为它访问的元素。因此下标必定存在问题。
此处我们登陆rand()
,返回0到rand()
之间的值。使用模数,您可以确保上限正常。但是如果-1
返回0怎么办?然后,您可以访问元素animal[]
,这是未定义的行为以及意外崩溃的根本原因。
如何解决?
更改下标表达式。例如,在rand() % 17
中,您有17个元素,索引从0到16.因此,如果您将下标更改为 <string> animal{ "cat", "dog", "horse", "elephant", "duck", "turtle", "bird", "crab", "spider", "bear", "pig", "penguin", "mouse", "rabbit", "lion", "monkey", "bull"};
...
word = animal[ rand()%animal.size() ]; // asuming that the vector is not empty :-)
,您将得到0到16之间的数字,保证在预期的范围内。
您也可以使用向量而不是数组,这可以避免手动计算其中的元素:
strlen(word.c_str())
P.S:word.size()
可以替换为{{1}}