In: Computer Science
First, we think about how we want to save the warriors. We start by creating a Warrior struct. This has the name, strength and the constructor for Warrior. Now we would like to have an array for adding all these warriors. We use a vector of Warriors to do this. Now over here I have also used an unordered_map to keep track of the index a warrior is saved in the array. Why? because in the battle commands we are given just the names of the warriors so to find these warriors in our array we would have to search it linearly. This is O(n) search. Using unordered_map we can do it in O(1) although we are using a little bit more space.
Next, we start by reading the file. We read the file line by line and tokenize each line. After tokenizing we check which command was given and the corresponding function is called.
The create_warrior function creates a new warrior, pushes it into our warrior vector and saves in which index the warrior is stored in the unordered_map. Note that we are using pass by reference to pass our vector in so changes made in the function to vector would reflect in our original vector in the main function.
Next, in the start_battle function, we get the indices of the warriors from the unordered_map then get the corresponding strength of these warriors from our array. We then apply the various conditional statements to check who wins and update their strengths accordingly.
Finally, in the get_status function, we simply iterate over our warrior's vector and print out the names and strengths of the warriors.
Source Code and screenshots given below:
Source code:
#include <iostream>
#include <cstring>
#include <fstream>
#include <string>
#include <vector>
#include <unordered_map>
using namespace std;
// Struct of warrior
struct Warrior {
string name;
int strength;
// Constructor
Warrior(string n, int s) {
name = n;
strength = s;
}
};
// Function that tokenizes the given string and returns it as a
vector
// Example: line = "Warrior Arthur 15"
// Return vector<string> = {"Warrior", "Arthur", "15"}
vector<string> tokenize_str(string line) {
vector<string> v;
string temp = "";
for (int i = 0; i < line.size(); i++) {
if (line[i] != ' ') {
temp +=
line[i];
} else {
v.push_back(temp);
temp = "";
}
}
v.push_back(temp);
return v;
}
// Function which creates a new warrior and pushes it into our
warrior vector
// It also saves the index of the array in which the warrior has
been added in the unordered_map
// This way we don't have to search for warriors during the battle
command
void create_warrior(string name, string s, vector<Warrior>
&warriors, unordered_map<string, int> &index) {
// Converts string to int
int strength = stoi(s);
Warrior new_warrior = Warrior(name, strength);
index[name] = warriors.size();
warriors.push_back(new_warrior);
return;
}
// Battle function
void start_battle(string name1, string name2, vector<Warrior>
&warriors, unordered_map<string, int> &index) {
// Get index of warriors in the vector using the
unordered_map
int i = index[name1];
int j = index[name2];
// Get the strengths of these warriors
int s1 = warriors[i].strength;
int s2 = warriors[j].strength;
cout << name1 << " battles " <<
name2 << endl;
if (s1 == 0 && s2 == 0) {
cout << "Oh, NO! They're both
dead! Yuck!" << endl;
} else if (s2 == 0) {
cout << "He's dead, "
<< name1 << endl;
} else if (s1 == 0) {
cout << "He's dead, "
<< name2 << endl;
} else if (s1 > s2) {
cout << name1 << "
defeats " << name2 << endl;
warriors[i].strength -= s2;
warriors[j].strength = 0;
} else if (s2 > s1) {
cout << name2 << "
defeats " << name1 << endl;
warriors[j].strength -= s1;
warriors[i].strength = 0;
} else {
cout << "Mutual Annihilation:
" << name1 << " and " << name2 << " die at
each other's hands" << endl;
warriors[i].strength = 0;
warriors[j].strength = 0;
}
}
// Status function
// Prints the status using the warriors vector
void get_status(vector<Warrior> &warriors) {
int num_warriors = warriors.size();
cout << "There are: " << num_warriors
<< " warriors" << endl;
for (int i = 0; i < num_warriors; i++) {
cout << "Warrior: " <<
warriors[i].name << ", strength: " <<
warriors[i].strength << endl;
}
return;
}
int main() {
// A vector which stores all our warriors
vector<Warrior> warriors;
// an unordered map to store the index in which the
warrior is saved in the vector
// This always us to get the warrior in O(1) time
during battle
// You have the option of not using this but then you
would have to search the warrior vector every time
// in the battle function
unordered_map<string, int> index;
// Open the warriors file
ifstream myFile;
myFile.open("warriors.txt");
// Check if file has been opened properly
if (!myFile) {
cerr << "Unable to open
file";
// Exit the program if file did not
open successfully
exit(1);
}
// If file opened successfully
// Variable which stores each line in the warriors.txt
file
string line;
// Read the file till we reach the end
while(getline(myFile,line)) {
// Tokenize the line
vector<string> tokens =
tokenize_str(line);
// The first word is the
command
string command = tokens[0];
// Check what the command is and
execute the corresponding function
if (command == "Warrior") {
create_warrior(tokens[1], tokens[2], warriors, index);
} else if (command == "Battle")
{
start_battle(tokens[1], tokens[2], warriors, index);
} else {
get_status(warriors);
}
}
return 0;
}