Untitled
unknown
plain_text
2 years ago
20 kB
14
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