Untitled
unknown
plain_text
2 years ago
20 kB
11
Indexable
#include <iostream> #include <vector> #include <cmath> #include <string> #include <cstdlib> #include <stdexcept> #include <set> #include <random> using namespace std; class Map; class Team; class Obstacle; class Team; class InvalidInputException : public runtime_error { public: InvalidInputException(const string& message) : runtime_error(message) {} }; class OccupiedCellException : public runtime_error { public: OccupiedCellException(const string& message) : runtime_error(message) {} }; class OutOfBoundsException : public runtime_error { public: OutOfBoundsException(const string& message) : runtime_error(message) {} }; set<int> generateUniqueRandomNumbers(int min, int max, int count) { std::random_device rd; // 用於獲得種子 std::mt19937 gen(rd()); // 標準 mersenne_twister_engine std::uniform_int_distribution<> distrib(min, max); std::set<int> uniqueNumbers; while (uniqueNumbers.size() < count) { uniqueNumbers.insert(distrib(gen)); } return uniqueNumbers; } class character { protected: //名字、血量、攻擊、防禦、速度 char symbol; string name; int origin_healthPoints; int current_healthPoints; //int healthPoints; int attackPoints; int defensePoints; int speedPoints; int x; // 角色在方格地圖上的x、y座標 int y; vector<size_t> canAttackIndex; public: //Constructor character() : symbol('N'), name("None"), origin_healthPoints(0),current_healthPoints(0), attackPoints(0), defensePoints(0), speedPoints(0), x(0), y(0) {} character(const char charSymbol, const string& charName, int origin_HP, int current_HP, int charAttack,int charDefense, int charSpeed, int x, int y) : symbol(charSymbol), name(charName), origin_healthPoints(origin_HP),current_healthPoints(current_HP),attackPoints(charAttack), defensePoints(charDefense), speedPoints(charSpeed), x(x), y(y) {} //取得基本資料函數 char getSymbol() const { return symbol; } string getName() const { return name; } int get_current_HP() const { return current_healthPoints; } int get_origin_HP() const { return origin_healthPoints; } int getAttackPoints() const { return attackPoints; } int getDefensePoints() const { return defensePoints; } int getSpeedPoints() const { return speedPoints; } int getX() const { return x; } int getY() const { return y; } // 顯示基本資料 void displayInfo(const vector<character*>& team, int index); // 傷害 void takeDamage(Map& chessBoard, int damage, int index, Team& temp); // 攻擊 void attack(int index, Team& temp, Map& chessBoard); // 移動角色 void move(Map& chessBoard, Team& otherTeam); // 確認是否在攻擊範圍內 bool checkCharacter(character& character) const; void checkObstacle(vector<Obstacle>& allObstacles ,Map& chessBoard); void obstacleHeal(int amount); void obstaclePlus(int amount); // 發送可供attack的對象的prompt void chooseToAttack(const vector<character*>& team); }; class Wizard : public character { private: public: Wizard(int x, int y): character('W', "Wizard", 80, 80, 25, 5, 8, x, y) {} }; class Knight : public character { private: public: Knight(int x, int y): character('K', "Knight", 100, 100, 15, 3, 5, x, y){} }; class Archer : public character { private: public: Archer(int x, int y): character('A', "Archer", 50,50, 40, 1, 7, x, y){} }; class Tank : public character { private: public: Tank(int x, int y): character('T', "Tank", 300 ,300, 5, 10, 10, x, y){} }; class Map { private: int rows; // 地圖的行數 int cols; // 地圖的列數 vector<vector<char> > map; // 地圖的表示 public: Map() {} Map(int rows, int cols) : rows(rows), cols(cols), map(rows, vector<char>(cols, '.')) {} void draw() const; void cleanCharacter(character& character); void cleanObstacle(Obstacle& obstacle); void placeCharacter(const character* character); void placeObstacle(const Obstacle& obstacle ) ; bool isCellOccupied(int x, int y) const { return (map[x][y] != '.'); } }; class Obstacle{ private: char symbol; string name; int x; int y; public: Obstacle(const char symbol ,const string& name, int X , int Y) : symbol(symbol), name(name), x(X), y(Y) {}; char getSymbol() const { return symbol; } int getX() const {return x; } int getY() const {return y; } void applyEffect(character& someone,Map& chessBoard); }; class Team{ private: vector<character*> members; bool teamMark; public: Team(){ teamMark = false; }; ~Team(){ for (character* member : members) { delete member; } } // 獲得隊伍的大小 size_t getSize() const { return members.size(); } character& operator[](size_t index) const { if (index < members.size()) { return *members[index]; } else { //越界處理,待修 return *members[0]; } } // 提供 const vector<character*> 的方法 const vector<character*>& getMembers() const { return members; } void setTeamMark(){teamMark = true; return;} void addClassWizard(int x, int y) { character* newWizard = new Wizard(x, y); // 假設 Wizard 類別有符合的建構函式 members.push_back(newWizard); } void addClassArcher(int x, int y){ character* newArcher = new Archer(x, y); members.push_back(newArcher); } void addClassTank(int x, int y){ character* newTank = new Tank(x, y); members.push_back(newTank); } void addClassKnight(int x, int y){ character* newKnight = new Knight(x, y); members.push_back(newKnight); } // 確認是否為第一隊 bool getteamMark(){return teamMark;} bool allMembersDead() const{ for (const character* member : members) { if (member->get_current_HP() > 0) { return false; // 如果有任何一個成員血量不為 0,返回 false } } return true; } }; // 地圖函數 void Map::cleanCharacter(character& character){ int row = character.getY(); int col = character.getX(); // 檢查座標是否合法 if (row >= 0 && row < rows && col >= 0 && col < cols) { map[row][col] = '.'; } } void Map::cleanObstacle(Obstacle& obstacle){ int row = obstacle.getY(); int col = obstacle.getX(); // 檢查座標是否合法 if (row >= 0 && row < rows && col >= 0 && col < cols) { map[row][col] = '.'; } } void Map::placeCharacter(const character* character) { int row = character->getY(); int col = character->getX(); // 檢查座標是否合法 if (row >= 0 && row < rows && col >= 0 && col < cols) { map[row][col] = character->getSymbol(); } } void Map::placeObstacle(const Obstacle& obstacle){ int row = obstacle.getY(); int col = obstacle.getX(); // 檢查座標是否合法 if (row >= 0 && row < rows && col >= 0 && col < cols) { map[row][col] = obstacle.getSymbol(); } } void Map::draw() const{ for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { cout << map[i][j] << ' '; } cout << endl; } } //character函數 void character::displayInfo(const vector<character*>& team, int index){ cout << "member_number " << index << ','<<"Name: " << name << endl; cout << "HP: " << current_healthPoints << "/" << origin_healthPoints << endl; cout << "Attack: " << attackPoints << endl; cout << "Defence: " << defensePoints << endl; } void character::move(Map& chessBoard, Team& otherTeam) { const int MAX_DIMENSION = 15; const int MAX_MOVE_SUM = 5; bool moveCompleted = false; while (!moveCompleted) { try { string input; cout << "Your Move (attack or move): "; cin >> input; chessBoard.cleanCharacter(*this); if(input == "attack") { int attackIndex; cout << "Enter attack index: "; cin >> attackIndex; attack(attackIndex, otherTeam, chessBoard); chessBoard.placeCharacter(this); moveCompleted = true; } else if(input == "move") { int moveX = 0, moveY = 0; cout << "Enter move coordinates (x y): "; cin >> moveX >> moveY; if (abs(moveX) + abs(moveY) > MAX_MOVE_SUM) { throw OutOfBoundsException("Move exceeds maximum allowed distance of 5."); } int targetX = x + moveX; int targetY = y + moveY; if (targetX < 0 || targetX >= MAX_DIMENSION || targetY < 0 || targetY >= MAX_DIMENSION) { throw OutOfBoundsException("Target position is out of bounds."); } if (chessBoard.isCellOccupied(targetX, targetY)) { throw OccupiedCellException("Cell is occupied!"); } x = targetX; y = targetY; chessBoard.placeCharacter(this); cout << "New position: " << x << " " << y << endl; moveCompleted = true; } else { throw InvalidInputException("Invalid action input!"); } } catch (const InvalidInputException& e) { cout << "Error: " << e.what() << " Please try again." << endl; } catch (const OccupiedCellException& e) { cout << "Error: " << e.what() << " Please try again." << endl; } catch (const OutOfBoundsException& e) { cout << "Error: " << e.what() << " Please try again." << endl; } } } // 確認傳入之角色是否於九宮格內 bool character::checkCharacter(character& character) const{ if(abs(x - character.getX()) == 1 && abs(y - character.getY()) == 0 || abs(y - character.getY()) == 1 && abs(x - character.getX()) == 0 || (abs(x - character.getX()) == 1 && abs(y - character.getY()) == 1)){ return true; } return false; } void character::chooseToAttack(const vector<character*>& team){ vector<size_t> tempAttackIndex; for(size_t i = 0; i < team.size(); i++){ if(checkCharacter(*(team[i])) == true){ if(team[i]->get_current_HP() == 0){ continue; } else{ tempAttackIndex.push_back(i); } } } // 如果此vector為空(沒人可以打) if(tempAttackIndex.empty() == true){ return; } else{ cout << "You can attack: "; canAttackIndex = tempAttackIndex; for(size_t i = 0; i < tempAttackIndex.size(); i++){ cout << tempAttackIndex[i] << ',' << team[tempAttackIndex[i]]->getName() << " "; } cout << '\n'; return; } } void character::attack(int index, Team& temp, Map& chessBoard){ temp[index].takeDamage(chessBoard, attackPoints, index, temp); } void character::takeDamage(Map& chessBoard, int damage, int index, Team& temp) { current_healthPoints -= damage; if (current_healthPoints <= 0) { current_healthPoints = 0; chessBoard.cleanCharacter(*this); cout << index << ',' << name << " is DEAD! " << endl; } else { cout << index << ',' << name << " received damage points: " << damage << " Current Health Point: " << current_healthPoints << endl; } } void character::obstacleHeal(int amount) { int old_healthPoints = current_healthPoints; int new_healthPoints = current_healthPoints + amount; // 确保生命值不超過最大值 current_healthPoints = min(new_healthPoints,origin_healthPoints); cout << name << " restored health points: " << current_healthPoints-old_healthPoints << " Current Health Point:" << current_healthPoints << endl; } void character::obstaclePlus(int amount) { this->attackPoints += amount; cout << name << " gain an power up, increase " << amount << " attack points, Current attack points is:" << attackPoints << endl; } void character::checkObstacle(vector<Obstacle>& allObstacles , Map& chessBoard){ for (auto& obstacle : allObstacles) { int obstacleX = obstacle.getX(); int obstacleY = obstacle.getY(); // 檢查障礙物是否在九宮格 if (x >= obstacleX - 1 && x <= obstacleX + 1 && y >= obstacleY - 1 && y <= obstacleY + 1){ // 如果找到,調用障礙物的 applyEffect 方法 obstacle.applyEffect(*this,chessBoard); } } } //Obstacle函數 void Obstacle::applyEffect(character& someone, Map& chessBoard){ if (name == "supplement") { // 回血 int healAmount = 30; someone.obstacleHeal(healAmount); chessBoard.cleanObstacle(*this); } if(name == "plus"){ //攻擊力加成 int plusAmount = 20; someone.obstaclePlus(plusAmount); chessBoard.cleanObstacle(*this); } } //global function class InvalidCharacterException : public runtime_error { public: InvalidCharacterException(const string& message) : runtime_error(message) {} }; class InvalidQuantityException : public runtime_error { public: InvalidQuantityException(const string& message) : runtime_error(message) {} }; class InvalidLocationException : public runtime_error { public: InvalidLocationException(const string& message) : runtime_error(message) {} }; void addToTeam(Team& temp, int& teamCnt) { while (temp.getSize() < 3) { string characterName; int quantity = 0; int x, y; int space = 3 - temp.getSize(); if (teamCnt == 0) { cout << "Which character do you want to add in team1? ( Wizard, Knight, Archer, Tank )" << endl; } else if (teamCnt == 1) { cout << "Which character do you want to add in team2? ( Wizard, Knight, Archer, Tank )" << endl; } bool validInput = false; while (!validInput) { try { cin >> characterName; if (characterName != "Wizard" && characterName != "Knight" && characterName != "Archer" && characterName != "Tank") { throw InvalidCharacterException("Invalid character type."); } cout << "You can at most add " << space << " characters." << endl; cout << "Quantity: "; cin >> quantity; if (quantity < 1 || quantity > space) { throw InvalidQuantityException("Invalid quantity. It must be between 1 and " + to_string(space) + "."); } for (int i = 0; i < quantity; i++) { cout << "Location: "; cin >> x >> y; if (x < 0 || y < 0 ) { // 或者添加更多座標的檢查條件 throw InvalidLocationException("Invalid location coordinates."); } if (characterName == "Wizard") { temp.addClassWizard(x, y); } else if (characterName == "Knight") { temp.addClassKnight(x, y); } else if (characterName == "Archer") { temp.addClassArcher(x, y); } else if (characterName == "Tank") { temp.addClassTank(x, y); } } validInput = true; // 若無異常發生,則輸入有效 } catch (const runtime_error& e) { cout << "Error: " << e.what() << " Please try again." << endl; // 重置輸入狀態 cin.clear(); cin.ignore(numeric_limits<streamsize>::max(), '\n'); } } } teamCnt++; } int main() { // 初始化地圖 Map chessBoard(15, 15); int teamCnt = 0; set<int> randomNumbers = generateUniqueRandomNumbers(2, 10, 4); vector<int> randomNumbersVec(randomNumbers.begin(), randomNumbers.end()); // 分配到具體變量 int random_x1 = randomNumbersVec[0]; int random_y1 = randomNumbersVec[1]; int random_x2 = randomNumbersVec[2]; int random_y2 = randomNumbersVec[3]; vector<Obstacle> All_obstacles = { Obstacle('+',"supplement",random_x1, random_y1), Obstacle('*',"plus",random_x2 , random_y2), }; // 丟入Team中之vector<character*> members Team team1; team1.setTeamMark(); addToTeam(team1, teamCnt); // 丟入Team中之vector<character*> members Team team2; cout << "You cannot use team1's members' locations!!!!!!!" << endl; addToTeam(team2, teamCnt); // 放置隊伍進地圖 for(size_t i = 0; i < team1.getSize(); i++) { chessBoard.placeCharacter(&team1[i]); } for(size_t i = 0; i < team2.getSize(); i++){ chessBoard.placeCharacter(&team2[i]); } //放置道具進地圖 for (const auto& Obstacle : All_obstacles ) { chessBoard.placeObstacle(Obstacle); } //遊戲剛開始時地圖 cout << "Initial Chess Board:" << endl; chessBoard.draw(); // Team loop while(!team1.allMembersDead() && !team2.allMembersDead()) { string check; for(size_t i = 0 ; i < team1.getSize(); i++) { if(team1[i].get_current_HP() == 0) {continue;} else{ cout << "Your team : Team1" << endl; // 顯示角色基本資料 team1[i].displayInfo(team1.getMembers(), i); // 顯示可攻擊誰 team1[i].chooseToAttack(team2.getMembers()); // 移動角色 team1[i].move(chessBoard, team2); //檢查周圍的 Obstacle team1[i].checkObstacle(All_obstacles ,chessBoard) ; cout << "\n\n\n\n\n\n\n\n\n\n"; cout << "Chess Board after moving player:" << endl; chessBoard.draw(); } } for(size_t i = 0 ; i < team2.getSize(); i++) { if(team2[i].get_current_HP() == 0){ continue; } else{ cout << "Your team : Team2" << endl; // 顯示角色基本資料 team2[i].displayInfo(team1.getMembers(), i); // 可攻擊誰 如果有敵方的人在周圍即可選擇 team2[i].chooseToAttack(team1.getMembers()); // 移動角色 team2[i].move(chessBoard, team1); //toContinue(); team2[i].checkObstacle(All_obstacles,chessBoard) ; cout << "\n\n\n\n\n\n\n\n\n\n"; cout << "Chess Board after moving player:" << endl; chessBoard.draw(); } } } return 0; }
Editor is loading...
Leave a Comment