《C++游戏编程入门》第4章 标准模板库: Hangman
4.1 标准模板库
Standard Template Library,提供算法、容器和迭代器等。
4.2 vector
动态数组。
优势:
- 根据需要动态增长。
- 和STL算法使用,获得查找排序等功能。
缺点:
- 额外内存开销。
- 增长时可能性能损失。
- 某些游戏控制台系统无法使用向量。
04.heros_inventory2.cpp
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
vector<string> inventory; // 声明
// 添加元素
inventory.push_back("sword");
inventory.push_back("armor");
inventory.push_back("shield");
cout << "You have " << inventory.size() << " items.\n"; // 向量大小
cout << "\nYour items:\n";
for (unsigned int i = 0; i < inventory.size(); ++i)
{
cout << inventory[i] << endl; // 向量索引
}
cout << "\nYou trade your sword for a battle axe.";
inventory[0] = "battle axe"; // 向量元素赋值
cout << "\nYour items:\n";
for (unsigned int i = 0; i < inventory.size(); ++i)
{
cout << inventory[i] << endl;
}
cout << "\nThe item name '" << inventory[0] << "' has ";
cout << inventory[0].size() << " letters in it.\n";
cout << "\nYour shield is destroyed in a fierce battle.";
inventory.pop_back(); // 移除最后一个元素
cout << "\nYour items:\n";
for (unsigned int i = 0; i < inventory.size(); ++i)
{
cout << inventory[i] << endl;
}
cout << "\nYou were robbed of all of your possessions by a thief.";
inventory.clear(); // 移除所有元素
if (inventory.empty()) // 判断是否为空
{
cout << "\nYou have nothing.\n";
}
else
{
cout << "\nYou have at least one item.\n";
}
return 0;
}
4.3 使用迭代器
迭代器标识容器中某个特定元素的值,引用元素。
04.heros_inventory3.cpp
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
vector<string> inventory;
inventory.push_back("sword");
inventory.push_back("armor");
inventory.push_back("shield");
vector<string>::iterator myIterator; // 迭代器声明
vector<string>::const_iterator iter; // 常量迭代器,不能修改相应元素
cout << "Your items:\n";
for (iter = inventory.cbegin(); iter != inventory.cend(); ++iter)
{
cout << *iter << endl;
}
cout << "\nYou trade your sword for a battle axe.";
myIterator = inventory.begin();
*myIterator = "battle axe";
cout << "\nYour items:\n"; // 循环访问向量
// 第一个元素,最后一个元素之后,更新
for (iter = inventory.begin(); iter != inventory.end(); ++iter)
{
cout << *iter << endl; // 解引用
}
cout << "\nThe item name '" << *myIterator << "' has ";
cout << (*myIterator).size() << " letters in it.\n";
cout << "\nThe item name '" << *myIterator << "' has ";
cout << myIterator->size() << " letters in it.\n";
cout << "\nYou recover a crossbow from a slain enemy.";
inventory.insert(inventory.begin(), "crossbow"); // 插入元素
cout << "\nYour items:\n";
for (iter = inventory.begin(); iter != inventory.end(); ++iter)
{
cout << *iter << endl;
}
cout << "\nYour armor is destroyed in a fierce battle.";
inventory.erase((inventory.begin() + 2)); // 移除元素
cout << "\nYour items:\n";
for (iter = inventory.begin(); iter != inventory.end(); ++iter)
{
cout << *iter << endl;
}
return 0;
}
4.4 使用算法
泛型,同样算法用于不同容器类型的元素。
04.high_scores.cpp
#include <iostream>
#include <vector>
#include <algorithm>
#include <ctime>
#include <cstdlib>
using namespace std;
int main()
{
vector<int>::const_iterator iter;
cout << "Creating a list of scores.";
vector<int> scores;
scores.push_back(1500);
scores.push_back(3500);
scores.push_back(7500);
cout << "\nHigh Scores:\n";
for (iter = scores.begin(); iter != scores.end(); ++iter)
{
cout << *iter << endl;
}
cout << "\nFinding a score.";
int score;
cout << "\nEnter a score to find: ";
cin >> score;
iter = find(scores.begin(), scores.end(), score); // 查找
if (iter != scores.end())
{
cout << "Score found.\n";
}
else
{
cout << "Score not found.\n";
}
cout << "\nRandomizing scores.";
srand(static_cast<unsigned int>(time(0)));
random_shuffle(scores.begin(), scores.end()); // 随机重排
cout << "\nHigh Scores:\n";
for (iter = scores.begin(); iter != scores.end(); ++iter)
{
cout << *iter << endl;
}
cout << "\nSorting scores.";
sort(scores.begin(), scores.end()); // 排序
cout << "\nHigh Scores:\n";
for (iter = scores.begin(); iter != scores.end(); ++iter)
{
cout << *iter << endl;
}
string word = "High Scores";
random_shuffle(word.begin(), word.end());
for (auto it = word.cbegin(); it != word.cend(); ++it)
cout << *it << endl;
return 0;
}
4.5 理解向量性能
向量添加新元素超过当前大小时,重新分配内存,可能全部元素重新复制,导致性能损失。
capacity()向量容量,预先多分配空间。
reserve()扩充容量。
push_back()或pop_back(),尾部添加或移除元素效率高。
insert()或erase(),中间添加或移除元素效率底。
4.6 其他STL容器
顺序型容器:依次检索元素值。
关联型容器:基于键值检索元素值。
deque、list、map、multimap、multiset、priority_queue、queue、set、stack、vector
4.7 Hangman简介
04.hangman.cpp
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <ctime>
#include <cctype>
using namespace std;
int main()
{
// 常量、变量初始化
const int MAX_WRONG = 8; // maximum number of incorrect guesses allowed
vector<string> words; // collection of possible words to guess
words.push_back("GUESS");
words.push_back("HANGMAN");
words.push_back("DIFFICULT");
srand(static_cast<unsigned int>(time(0)));
random_shuffle(words.begin(), words.end());
const string THE_WORD = words[0]; // word to guess
int wrong = 0; // number of incorrect guesses
string soFar(THE_WORD.size(), '-'); // word guessed so far
string used = ""; // letters already guessed
cout << "Welcome to Hangman. Good luck!\n";
// main loop
while ((wrong < MAX_WRONG) && (soFar != THE_WORD))
{
cout << "\n\nYou have " << (MAX_WRONG - wrong);
cout << " incorrect guesses left.\n";
cout << "\nYou've used the following letters:\n"
<< used << endl;
cout << "\nSo far, the word is:\n"
<< soFar << endl;
char guess;
cout << "\n\nEnter your guess: ";
cin >> guess;
guess = toupper(guess); // make uppercase since secret word in uppercase
while (used.find(guess) != string::npos)
{
cout << "\nYou've already guessed " << guess << endl;
cout << "Enter your guess: ";
cin >> guess;
guess = toupper(guess);
}
used += guess;
if (THE_WORD.find(guess) != string::npos)
{
cout << "That's right! " << guess << " is in the word.\n";
// update soFar to include newly guessed letter
for (unsigned int i = 0; i < THE_WORD.length(); ++i)
{
if (THE_WORD[i] == guess)
{
soFar[i] = guess;
}
}
}
else
{
cout << "Sorry, " << guess << " isn't in the word.\n";
++wrong;
}
}
// shut down
if (wrong == MAX_WRONG)
cout << "\nYou've been hanged!";
else
cout << "\nYou guessed it!";
cout << "\nThe word was " << THE_WORD << endl;
return 0;
}