// Warscape
// (c) 2017 by, Handge
#include <iostream>
#include <string>
#include <cstdlib>
#include <algorithm>
#include <ctime>
#include <tuple>
using namespace std;
// Clears the screen
void clear() {
cout << string(50, '\n');
}
// Draw the ascii art
void draw(string type) {
if (type == "Lion") {
cout << R"(
======================================================================
,w.
,YWMMw ,M ,
_.---.._ __..---._.'MMMMMw,wMWmW,
_.-"" """ YP"WMMMMMMMMMb,
.-' __.' .' MMMMW^WMMMM;
_, .'.-'"; `, /` .--"" :MMM[==MWMW^;
,mM^" ,-'.' / ; ; / , MMMMb_wMW" @\
,MM:. .'.-' .' ; `\ ; `, MMMMMMMW `"=./`-,
WMMm__,-'.' / _.\ F"""-+,, ;_,_.dMMMMMMMM[,_ / `=_}
"^MP__.-' ,-' _.--"" `-, ; \ ; ;MMMMMMMMMMW^``; __|
/ .' ; ; ) )`{ \ `"^W^`, \ :
/ .' / ( .' / Ww._ `. `"
/ Y, `, `-,=,_{ ; MMMP`""-, `-._.-,
(--, ) `,_ / `) \/"") ^" `-, -;"\:
`""" `""" `"' `---"
======================================================================
)" << endl;
} else if (type == "Boar") {
cout << R"(
============================================
_,-""""-..__
|`,-'_. ` ` `` `--'""".
; ,' | `` ` ` ` ``` `.
,-' ..-' ` ` `` ` `` ` ` |==.
,' ^ ` ` `` ` ` `. ; \
`}_,-^- _ . ` \ ` ` __ ` ; #
`"---"' `-`. ` \---""`.`. `;
\` ; ; `. `,
||`; / / | |
//_;` ,_;' ,_;"
============================================
)" << endl;
} else if (type == "Spider") {
cout << R"(
================================
/\ .-"""-. /\
//\/ ,,, \//\
|/\| ,;;;;;, |/\|
//\\;-"""-;///\
// \/ . \/ \
(| ,-_| \ | / |_-, |)
//`__\.-.-./__`\
// /.-(() ())-.\ \
(\ |) '---' (| /)
` (| |) `
\) (/
================================
)" << endl;
} else if (type == "Wolf") {
cout << R"(
=====================================
, ,
|\---/|
/ , , |
__.-'| / \ /
__ ___.-' ._O|
.-' ' : _/
/ , . . |
: ; : : _/
| | .' __: /
| : /'----'| \ |
\ |\ | | /| |
'.'| / || \ |
| /|.' '.l \_
|| || '-'
'-''-'
=====================================
)" << endl;
} else if (type == "Elephant") {
cout << R"(
=====================================================
___.-~"~-._ __....__
.' ` \ ~"~ ``-.
/` _ ) `\ `\
/` a) / | `\
:` / | \
<`-._|` .-. ( / . `;\
`-. `--'_.'-.;\___/' . . | \
_ /:--` | / / .' \
("\ /`/ | ' ' / :`;
`\'\_/`/ .\ /`~`=-.: / ``
`._.' /`\ | `\ /(
/ /\ | `Y / \
J / Y | | /`\ \
/ | | | | | | |
"---" /___| /___| /__|
=====================================================
)" << endl;
} else if (type == "Slime") {
cout << R"(
==================================
, - ~ ~ ~ - ,
, ' ' ,
, ! ! ,
, ,
, @@ @@ ,
, ! @@ @@ ,
, ! ,
, ,
, ! ,
, ! , '
' - , _ _ _ , '
==================================
)" << endl;
}
}
// Displays the abilities
pair<string, int> getability(string pclass, int mana, int inte, int level) {
string input;
string ability;
int cost;
cout << "Choose an ability" << endl;
if (pclass == "Champion") { // Champion Section
cost = inte*(level);
cout << "[1] Cleaving Strike [" << cost << " mana]" << endl;
cout << "[2] Melting Thrust [" << cost << " mana]" << endl;
cout << "[3] Critical Bash [" << cost << " mana]" << endl;
cost = inte*(level+1);
cout << "[4] Purify [" << cost << " mana]" << endl;
cost = inte*(level);
cin >> input;
if (input == "1") {
ability = "cleaving strike";
if (mana >= cost) {
mana = mana - cost;
return {ability, mana};
} else {
ability = "none";
return {ability, mana};
}
} else if (input == "2") {
ability = "melting thrust";
if (mana >= cost) {
mana = mana - cost;
return {ability, mana};
} else {
ability = "none";
return {ability, mana};
}
} else if (input == "3") {
ability = "critical bash";
if (mana >= cost) {
mana = mana - cost;
return {ability, mana};
} else {
ability = "none";
return {ability, mana};
}
} else if (input == "4") {
ability = "purify";
if (mana >= cost) {
cost = inte*(level+1);
mana = mana - cost;
return {ability, mana};
} else {
ability = "none";
return {ability, mana};
}
} else {
ability = "none";
return {ability, mana};
}
} else if (pclass == "Necromancer") { // Necromancer Section
cost = inte*(level);
cout << "[1] Shadow Strike [" << cost << " mana]" << endl;
cout << "[2] Cripple [" << cost << " mana]" << endl;
cout << "[3] Mutilate [" << cost << " mana]" << endl;
cost = inte*(level+2);
cout << "[4] Life Tap [" << cost << " mana]" << endl;
cost = inte*(level);
cin >> input;
if (input == "1") {
ability = "shadow strike";
if (mana >= cost) {
mana = mana - cost;
return {ability, mana};
} else {
ability = "none";
return {ability, mana};
}
} else if (input == "2") {
ability = "cripple";
if (mana >= cost) {
mana = mana - cost;
return {ability, mana};
} else {
ability = "none";
return {ability, mana};
}
} else if (input == "3") {
ability = "mutilate";
if (mana >= cost) {
mana = mana - cost;
return {ability, mana};
} else {
ability = "none";
return {ability, mana};
}
} else if (input == "4") {
ability = "life tap";
if (mana >= cost) {
cost = inte*(level+2);
mana = mana - cost;
return {ability, mana};
} else {
ability = "none";
return {ability, mana};
}
} else {
ability = "none";
return {ability, mana};
}
} else if (pclass == "Assassin") { // Assassin Section
cost = inte*(level);
cout << "[1] Back Stab [" << cost << " mana]" << endl;
cout << "[2] Headcrack [" << cost << " mana]" << endl;
cout << "[3] Poison [" << cost << " mana]" << endl;
cost = inte*10;
cout << "[4] Assassinate [" << cost << " mana]" << endl;
cost = inte*(level);
cin >> input;
if (input == "1") {
ability = "back stab";
if (mana >= cost) {
mana = mana - cost;
return {ability, mana};
} else {
ability = "none";
return {ability, mana};
}
} else if (input == "2") {
ability = "headcrack";
if (mana >= cost) {
mana = mana - cost;
return {ability, mana};
} else {
ability = "none";
return {ability, mana};
}
} else if (input == "3") {
ability = "poison";
if (mana >= cost) {
mana = mana - cost;
return {ability, mana};
} else {
ability = "none";
return {ability, mana};
}
} else if (input == "4") {
ability = "assassinate";
if (mana >= cost) {
cost = inte*10;
mana = mana - cost;
return {ability, mana};
} else {
ability = "none";
return {ability, mana};
}
} else {
ability = "none";
return {ability, mana};
}
}else if (pclass == "Cleric") { // Cleric Section
cost = inte*(level);
cout << "[1] Smite [" << cost << " mana]" << endl;
cout << "[2] Enflame [" << cost << " mana]" << endl;
cout << "[3] Atonement [" << cost << " mana]" << endl;
cout << "[4] Flash Heal [" << cost << " mana]" << endl;
cin >> input;
if (input == "1") {
ability = "smite";
if (mana >= cost) {
mana = mana - cost;
return {ability, mana};
} else {
ability = "none";
return {ability, mana};
}
} else if (input == "2") {
ability = "enflame";
if (mana >= cost) {
mana = mana - cost;
return {ability, mana};
} else {
ability = "none";
return {ability, mana};
}
} else if (input == "3") {
ability = "atonement";
if (mana >= cost) {
mana = mana - cost;
return {ability, mana};
} else {
ability = "none";
return {ability, mana};
}
} else if (input == "4") {
ability = "flash heal";
if (mana >= cost) {
mana = mana - cost;
return {ability, mana};
} else {
ability = "none";
return {ability, mana};
}
} else {
ability = "none";
return {ability, mana};
}
} else {
ability = "none";
return {ability, mana};
}
}
int main()
{
srand((unsigned)time(0));
// Strings
string code; // Game save code
string name; // Player name
string etype; // Enemy Type (spider, giant)
string pclass; // Player class
string action; // Player ability / action
// Dungeons
string status = "arena"; // Status if in Dungeon or just Arena
int ckills; // Current amount of kills in Dungeon
int rkills; // Required amount of kills to complete a Dungeon
// Armor / Weapons
int bhp = 0; // Bonus hp
double bphp = 0; // Bonus precantage hp
double goldb = 0; // Bonus Gold
int slimychestplate = 0; // Slimy Chestplate (TRUE or FALSE)
int slimyhelmet = 0; // Slimy Helmet (TRUE or FALSE)
int oozinglegplates = 0; // Oozing Legplates
int oozingboots = 0; // Oozing Boots
string head = "Open"; // Whats on the head
string chest = "Open"; // Whats on the chest
string legs = "Open"; // Whats on the legs
string feet = "Open"; // Whats on the feet
// Player Variables
int piclass = 0;
int level = 1; // Level
int xp = 0; // Current XP
int rxp; // Reward XP
int xpb = 50; // Increases each level, adds to max hp to increase it
int xpl = 25; // XP Required till next level
int stre = 5; // Strength
int inte = 5; // Intelligence
int dext = 5; // Dexterity
int skill = 0; // Skillpoint points (used to increase Strength, Intelligence, Dexterity)
int dmg; // Damage
int hp = stre * 20; // Current hp
int mhp = stre * 20; // Max hp
int shp = stre * 20; // hp used to set enemy hp
int mana = inte * 10; // Mana
int mmana = inte * 10; // Max Mana
// Inventory / Shop
int hpotion = 1; // Healing Potions
int price; // Price of item(s)
// Resources
int gold = 25; // Gold
int rgold; // Reward Gold
// Saving / Loading Strings
int x = 0;
int y = 0;
string sslimychestplate = std::to_string(slimychestplate);
string sslimyhelmet = std::to_string(slimyhelmet);
string soozinglegplates = std::to_string(oozinglegplates);
string soozingboots = std::to_string(oozingboots);
string spiclass = std::to_string(piclass);
string slevel = std::to_string(level);
string sxp = std::to_string(xp);
string sxpb = std::to_string(xpb);
string sxpl = std::to_string(xpl);
string sstre = std::to_string(stre);
string sinte = std::to_string(inte);
string sdext = std::to_string(dext);
string shpotion = std::to_string(hpotion);
string sgold = std::to_string(gold);
string sskill = std::to_string(skill);
// Questhall
int quest = 0; // The quest
int questr = 0; // The quest requirements (6 boars slain)
int questc = 0; // The current position on the requirements (3/6 boars slain)
int questreward = 0; // The quest's reward
string questmob; // Enemy that must be slain to complete the quest
string questdisplay; // Displays the quest
int qxpr; // Quest xp reward
int qgoldr; // Quest gold reward
// Monster Variables
int elevel; // Enemy level
int ehp; // Enemy hp
int mehp; // Max Enemy hp
int edmg; // Enemy dmg
string eability; // Enemy Ability
// Other Variables
int random; // Random Integer #1
int random2; // Random Integer #2
// Weapons
// Inputs
string input; // Standard Input
// Setup
neworload:
clear();
cout << "Hello there please choose an option" << endl;
cout << "1- New Game" << endl;
cout << "2- Load Game" << endl;
cin >> input;
if (input == "1") {
goto setup;
} else if (input == "2") {
goto loadgame;
} else {
goto neworload;
}
setup:
clear();
cout << "Hello there, what is your name?" << endl;
cin >> input;
name = input;
cout << "Ahh, is it " << input << "? [y/n]" << endl;
cin >> input;
if (input == "n") {
clear();
goto setup;
}
// Class Setup
csetup:
cout << endl;
cout << "Choose your Class" << endl;
cout << "=================" << endl;
cout << "[1] Champion" << endl;
cout << "[2] Necromancer" << endl;
cout << "[3] Assassin" << endl;
cout << "[4] Cleric" << endl;
cin >> input;
if (input == "1") {
pclass = "Champion";
piclass = 1;
} else if (input == "2") {
pclass = "Necromancer";
piclass = 2;
} else if (input == "3") {
pclass = "Assassin";
piclass = 3;
} else if (input == "4") {
pclass = "Cleric";
piclass =4;
}
goto menue;
// Main Menue
menue:
clear();
if (pclass == "Assassin") {
goldb = 1.25;
} else {
goldb = 1;
}
cout << R"(
___ ___ _____ _ _ _ _
| \/ || ___| \ | | | | |
| . . || |__ | \| | | | |
| |\/| || __|| . ` | | | |
| | | || |___| |\ | |_| |
\_| |_/\____/\_| \_/\___/
)" << endl;
cout << pclass << " " << name << endl;
cout << "[1] Traveller's Encounter" << endl;
cout << "[2] Inventory" << endl;
cout << "[3] Rest (Returns you to full health/mana)" << endl;
cout << "[4] Assign Skillpoints [" << skill << " available]" << endl;
cout << "[5] Shop" << endl;
cout << "[6] Questhall" << endl;
cout << "[7] Dungeons" << endl;
cout << "[98] Save Game" << endl;
cout << "[99] Exit" << endl;
cin >> input;
if (input == "1") {
goto sarena;
} else if (input == "99") {
goto leave;
} else if (input == "2") {
goto inventory;
} else if (input == "3") {
mhp = stre * 20;
mmana = inte * 10;
hp = mhp;
hp = hp * (bphp+1);
hp = hp + bhp;
mana = mmana;
goto menue;
} else if (input == "4") {
goto askill;
} else if (input == "5") {
goto shop;
} else if (input == "6") {
goto questhall;
} else if (input == "7") {
goto dungeonmenue;
} else if (input == "98") {
goto savegame;
}
goto menue;
// Setting Up Enemys
sarena:
mmana = inte * 10;
shp = stre * 20;
mhp = stre * 20;
random = rand()%5+1;
switch (random) {
case 1:
etype = "Lion";
random2 = rand()%2+1;
eability = "gnaw";
if (random2 == 1) {
ehp = shp + rand()%(level*5);
} else {
ehp = shp - rand()%(level*5);
}
mehp = ehp;
break;
case 2:
etype = "Boar";
random2 = rand()%2+1;
eability = "goar";
if (random2 == 1) {
ehp = shp + rand()%(level*3);
} else {
ehp = shp - rand()%(level*3);
}
mehp = ehp;
break;
case 3:
etype = "Spider";
random2 = rand()%2+1;
eability = "webspin";
elevel = rand()%(level+3)+1;
if (random2 == 1) {
ehp = shp + rand()%(level*2);
} else {
ehp = shp - rand()%(level*2);
}
mehp = ehp;
break;
case 4:
etype = "Wolf";
random2 = rand()%2+1;
eability = "growl";
elevel = rand()%(level+3)+1;
if (random2 == 1) {
ehp = shp + rand()%(level*4);
} else {
ehp = shp - rand()%(level*4);
}
mehp = ehp;
break;
case 5:
etype = "Elephant";
random2 = rand()%2+1;
eability = "stomp";
if (random2 == 1) {
ehp = shp + rand()%(level*6);
} else {
ehp = shp - rand()%(level*3);
}
mehp = ehp;
break;
}
elevel = rand()%(level+3)+1;
if ((elevel < (level-3)) || (elevel > (level+3))) {
elevel = level;
}
goto aarena;
// Arena Main
aarena:
clear();
draw(etype);
cout << "[" << etype << " " << elevel << "] >>> " << ehp << "/" << mehp << endl;
cout << "[" << name << " " << level << "] >>> " << hp << "/" << mhp << endl;
cout << "-Mana- >>> " << mana << "/" << mmana << endl;
cout << "[1] Attack" << endl;
cout << "[2] Do ability" << endl;
cout << "[3] Inventory" << endl;
cout << "[99] Flee" << endl;
cin >> input;
if (input == "1") {
dmg = (stre+inte) + rand()%(dext*2);
ehp = ehp - dmg;
// If enemy ehp < 0 then
if (ehp <= 0) {
clear();
cout << "[*] You killed the " << etype << endl;
cout << "Type [1] to continue" << endl;
cin >> input;
goto rarena;
}
random2 = rand()%2+1;
edmg = dmg;
// Setting up enemy damage
if (random2 == 1) {
edmg = edmg + rand()%(dext*2);
} else {
edmg = edmg - rand()%(dext*2);
}
hp = hp - edmg;
// If player hp < 0 then
if (hp <= 0) {
clear();
cout << "[*] You Died" << endl;
cout << "Type [1] to continue" << endl;
cin >> input;
if (status != "arena") {
status = "arena";
}
goto menue;
}
goto aarena;
} else if (input == "99") {
goto menue;
} else if (input == "2") {
goto darena;
} else if (input == "3") {
goto iarena;
} else {
goto aarena;
}
// Using items from Inventory
iarena:
clear();
cout << "Inventory" << endl;
cout << "[1] Health Potion, " << hpotion << " (Heals you to max health)" << endl;
cout << "[99] Exit" << endl;
cin >> input;
if (input == "1") {
if (hpotion > 0) {
hpotion = hpotion - 1;
hp = mhp;
}
} else if (input == "99") {
goto aarena;
}
goto iarena;
// Picking spells and doing damage
darena:
clear();
tie(action, mana) = getability(pclass, mana, inte, level);
// Champion spells
if (action == "cleaving strike") {
dmg = (stre+inte+dext) + rand()%(dext*2);
} else if (action == "melting thrust") {
dmg = (stre+inte+dext) + rand()%(stre*2);
} else if (action == "critical bash") {
dmg = (stre+inte+dext) + rand()%(inte*2);
} else if (action == "purify") {
hp = hp + inte*(level)+(rand()%inte);
if (hp > mhp) {
hp = mhp;
}
goto aarena;
} else if (action == "none") {
goto aarena;
} else if (action == "shadow strike") {
dmg = (stre+inte+dext) + rand()%(dext*2);
} else if (action == "cripple") {
dmg = (stre+inte+dext) + rand()%(stre*2);
} else if (action == "mutilate") {
dmg = (stre+inte+dext) + rand()%(inte*2);
} else if (action == "life tap") {
dmg = (stre+inte) + rand()%(inte);
hp = hp + dmg;
if (hp > mhp) {
hp = mhp;
}
ehp = ehp - dmg;
// If enemy ehp < 0 then
if (ehp <= 0) {
clear();
cout << "[*] You killed the " << etype << endl;
cout << "Type [1] to continue" << endl;
cin >> input;
goto rarena;
}
goto aarena;
} else if (action == "back stab") {
dmg = (stre+inte+dext) + rand()%(dext*2);
} else if (action == "headcrack") {
dmg = (stre+inte+dext) + rand()%(stre*2);
} else if (action == "poison") {
dmg = (stre+inte+dext) + rand()%(inte*2);
} else if (action == "assassinate") {
dmg = (stre+inte+dext) + rand()%((inte+stre)*3);
ehp = ehp - dmg;
// If enemy ehp < 0 then
if (ehp <= 0) {
clear();
cout << "[*] You killed the " << etype << endl;
cout << "Type [1] to continue" << endl;
cin >> input;
goto rarena;
}
goto aarena;
} else if (action == "smite") {
dmg = (stre+inte+dext) + rand()%(dext);
} else if (action == "enflame") {
dmg = (stre+inte+dext) + rand()%(stre);
} else if (action == "atonement") {
dmg = (stre+inte+dext) + rand()%(inte);
} else if (action == "flash heal") {
hp = hp + ((stre * level) + (rand()%(inte*2)));
if (hp > mhp) {
hp = mhp;
}
goto aarena;
}
// Doing the damage (Enemy)
ehp = ehp - dmg;
// If enemy ehp < 0 then
if (ehp <= 0) {
clear();
cout << "[*] You killed the " << etype << endl;
cout << "Type [1] to continue" << endl;
cin >> input;
goto rarena;
}
random2 = rand()%2+1;
dmg = (stre+inte) + rand()%(dext*2);
edmg = dmg;
// Setting up enemy damage
if (random2 == 1) {
edmg = edmg + rand()%(dext*2);
} else {
edmg = edmg - rand()%(dext*2);
}
hp = hp - edmg;
// If player hp < 0 then
if (hp <= 0) {
clear();
cout << "[*] You Died" << endl;
cout << "Type [1] to continue" << endl;
cin >> input;
if (status != "arena") {
status = "arena";
}
goto menue;
}
goto aarena;
// Here you get arena awards
rarena:
clear();
rxp = rand()%(level*2)+5;
rgold = rand()%(level*5);
rgold = rgold * goldb;
cout << R"(
*******************************************************************************
| | | |
_________|________________.=""_;=.______________|_____________________|_______
| | ,-"_,="" `"=.| |
|___________________|__"=._o`"-._ `"=.______________|___________________
| `"=._o`"=._ _`"=._ |
_________|_____________________:=._o "=._."_.-="'"=.__________________|_______
| | __.--" , ; `"=._o." ,-"""-._ ". |
|___________________|_._" ,. .` ` `` , `"-._"-._ ". '__|___________________
| |o`"=._` , "` `; .". , "-._"-._; ; |
_________|___________| ;`-.o`"=._; ." ` '`."\` . "-._ /_______________|_______
| | |o; `"-.o`"=._`` '` " ,__.--o; |
|___________________|_| ; (#) `-.o `"=.`_.--"_o.-; ;___|___________________
____/______/______/___|o;._ " `".o|o_.--" ;o;____/______/______/____
/______/______/______/_"=._o--._ ; | ; ; ;/______/______/______/_
____/______/______/______/__"=._o--._ ;o|o; _._;o;____/______/______/____
/______/______/______/______/____"=._o._; | ;_.--"o.--"_/______/______/______/_
____/______/______/______/______/_____"=.o|o_.--""___/______/______/______/____
/______/______/______/______/______/______/______/______/______/______/______/_
*******************************************************************************
)" << endl; // That chest looks amazing
if (status == "oozeworks") {
goto oozeworksr;
} else {
goto rrarena;
}
rrarena:
cout << "You recieved " << rxp << " xp" << endl;
cout << "You recieved " << rgold << " gold" << endl;
xp = xp + rxp;
gold = gold + rgold;
if (xp >= xpl) {
level = level + 1;
xpl = xpl + xpb;
xpb = xpb + 50;
skill = skill + 5;
cout << "You have leveled up to level " << level << endl;
}
cout << "Type [1] to continue to the menue" << endl;
if (etype == questmob) {
questc = questc + 1;
}
cin >> input;
goto menue;
// Inventory
inventory:
clear();
cout << R"(
___
)_( _
| | [_ ]
.-'-'-. _ .-'. '-.
/-::_..-\ _[_]_ /:;/ _.-'\
)_ _( /_ _\ [-] |:._ .-|
|;:: | )_``'_( .-'-'-. (-) |:._ |
|;:: | |;: | :-...-: .-'-'-. |:._ |
|;:: | |;: | |;: | |-...-| |:._ |
|;::-.._| |;:.._| |;:.._| |;:.._| |:._ |
`-.._..-' `-...-' `-...-' `-...-' `-.____.-'
)" << endl;
levelalert:
if (xp >= xpl) {
level = level + 1;
xpl = xpl + xpb;
xpb = xpb + 50;
skill = skill + 5;
goto levelalert;
} else {
goto inventory2;
}
inventory2:
cout << "[Level] >>> " << level << endl;
cout << "[XP] >>> " << xp << "/" << xpl << endl;
cout << "[Gold] >>> " << gold << endl;
cout << "[Healing Potions] >>> " << hpotion << endl;
cout << "==================================" << endl;
cout << "Head- " << head << endl;
cout << "Chest- " << chest << endl;
cout << "Legs- " << legs << endl;
cout << "Feet- " << feet << endl;
cout << "==================================" << endl;
cout << "1- Armory" << endl;
cout << "99- Exit" << endl;
cin >> input;
if (input == "99") {
goto menue;
} else if (input == "1") {
goto armory;
}
goto inventory;
armory:
clear();
cout << R"(
, A {}
/ \, | , .--.
| =|= > /.--.\
\ /` | ` |====|
` | |`::`|
| .-;`\..../`;_.-^-._
/\/ / |...::..|` : `|
|:'\ | /'''::''| .:. |
\ /\;-,/\ :: |..:::::..|
|\ <` > >._::_.| ':::::' |
| `""` / ^^ | ':' |
)" << endl;
cout << "1- Slimy Chestplate >>> [10% HP Increase] ";
if (slimychestplate == 1) {
cout << ">>> [Owned] ";
if (chest == "slimychestplate") {
cout << ">>> [Equiped]" << endl;
} else {
cout << endl;
}
} else {
cout << endl;
}
cout << "2- Slimy Helmet >>> [5% HP Increase] ";
if (slimyhelmet == 1) {
cout << ">>> [Owned] ";
if (head == "slimyhelmet") {
cout << ">>> [Equiped]" << endl;
} else {
cout << endl;
}
} else {
cout << endl;
}
cout << "3- Oozing Legplates >>> [15% HP Increase] ";
if (oozinglegplates == 1) {
cout << ">>> [Owned] ";
if (legs == "oozinglegplates") {
cout << ">>> [Equiped]" << endl;
} else {
cout << endl;
}
} else {
cout << endl;
}
cout << "4- Oozing Boots >>> [10% HP Increase] ";
if (oozingboots == 1) {
cout << ">>> [Owned] ";
if (feet == "oozingboots") {
cout << ">>> [Equiped]" << endl;
} else {
cout << endl;
}
} else {
cout << endl;
}
cout << "99- Back" << endl;
cin >> input;
if (input == "99") {
goto armor2;
} else if (input == "1") {
if (chest == "slimychestplate") {
chest = "Open";
goto armory;
} else if (slimychestplate == 1) {
chest = "slimychestplate";
goto armory;
} else {
goto armory;
}
} else if (input == "2") {
if (head == "slimyhelmet") {
head = "Open";
goto armory;
} else if (slimyhelmet == 1) {
head = "slimyhelmet";
goto armory;
} else {
goto armory;
}
} else if (input == "3") {
if (legs == "oozinglegplates") {
legs = "Open";
goto armory;
} else if (oozinglegplates == 1) {
legs = "oozinglegplates";
goto armory;
} else {
goto armory;
}
} else if (input == "4") {
if (feet == "oozingboots") {
feet = "Open";
goto armory;
} else if (oozingboots == 1) {
feet = "oozingboots";
goto armory;
} else {
goto armory;
}
}
armor2:
bhp = 0;
bphp = 0;
// Head
if (head == "slimyhelmet") {
bphp = bphp + .10;
}
// Chest
if (chest == "slimychestplate") {
bphp = bphp + .05;
}
// Legs
if (legs == "oozinglegplates") {
bphp = bphp + .15;
}
// Feet
if (feet == "oozingboots") {
bphp = bphp + .10;
}
goto inventory;
askill:
clear();
cout << R"(
.__=\__ .__==__,
jf' ~~=\, _=/~' `\,
._jZ' `\q, /=~ `\__
j5(/ `\./ V\,
.Z))' _____ | .____, \)/\
j5(K=~~ ~~~~\=_, | _/=~~~~' `~~+K\,
.Z)\/ `~=L | _=/~ t\ZL
j5(_/.__/===========\__ ~q |j/ .__============___/\J(N,
4L#XXXL_________________XGm, \P .mXL_________________JXXXW8L
~~~~~~~~~~~~~~~~~~~~~~~~~YKWmmWmmW@~~~~~~~~~~~~~~~~~~~~~~~~~~
)" << endl; // Bedtime stories?
cout << "Available Skillpoints [" << skill << "]" << endl;
cout << "1- Strength [" << stre << "]" << endl;
cout << "2- Intelligence [" << inte << "]" << endl;
cout << "3- Dexterity [" << dext << "]" << endl;
cout << "99- Exit" << endl;
cin >> input;
if (skill > 0) {
if (input == "1") {
stre = stre + 1;
skill = skill - 1;
} else if (input == "2") {
inte = inte + 1;
skill = skill - 1;
} else if (input == "3") {
dext = dext + 1;
skill = skill - 1;
} else if (input == "99") {
goto menue;
}
} else {
goto menue;
}
goto askill;
shop:
clear();
cout << R"(
____
_ |---|| _
||__________|---||___________||
/_ _ _ _ _ _ |:._|'_ _ _ _ _ _ _\`.
/_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _\:`.
/_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _\::`.
/:.___________________________________\:::`-._
_.-'_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _`::::::`-.._
_.-' _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ `:::::::::`-._
,'_:._________________________________________________`:_.::::-';`
`.'/ || |:::::`.'/::::::::`.'/::::::::`.'/::::::|.`.'/.| :|
|| || |::::::||::::::::::||::::::::::||:::::::|..||..| ||
|| || | __ || :: ___ || :: __ || :: |..||;|| ||
|| || | |::| || :: |:::| || :: |::| || :: |.|||:||_____||__
|| || | |::| || :: |:::| || :: |::| || :: |.|||:||_|_|_||,(
||_.|| | |::| || :: |:::| || :: |::| || :: |.'||..| _||,|
.-'::_.:'.:-.--.-::--.-:.--:-::--.--.--.-::--.--.-:.-::,'.--.'_|| |
);||_|__||_|__|_||__|_||::|_||__|__|__|_||__|__|_|;-'|__|_(,' || '-
|||| || |. . . ||. . . . . ||. . . . . ||. . . .|::||;''|| ||:'
||||.; _|._._._||._._._._._||._._._._._||._._._.|:'||,, ||,,
''''' ''- ''- ''- ''' '''
)" << endl;
price = level*5;
cout << "[Gold] >>> " << gold << endl;
cout << "1- Health Potion (" << price << " gold)" << endl;
cout << "99- Exit" << endl;
cin >> input;
if (input == "1") {
price = level*5;
if (gold >= price) {
hpotion = hpotion + 1;
gold = gold - price;
goto shop;
} else {
goto menue;
}
} else if (input == "99") {
goto menue;
}
goto shop;
// Receive / "Turn" in quests
questhall:
clear();
cout << R"(
_______________
()==( (@==()
'______________'|
| |
| |
__)_____________|
()==( (@==()
'--------------'
)" << endl;
cout << "Current Quest >>> ";
if (quest == 0) {
quest = rand()%5+1;
switch (quest) {
case 1:
questc = 0;
questr = 6;
questmob = "Boar";
questreward = rand()%4+1;
questdisplay = "Slay Boars";
break;
case 2:
questc = 0;
questr = 6;
questmob = "Lion";
questreward = rand()%4+1;
questdisplay = "Slay Lions";
break;
case 3:
questc = 0;
questr = 6;
questmob = "Elephant";
questreward = rand()%4+1;
questdisplay = "Slay Elephants";
break;
case 4:
questc = 0;
questr = 6;
questmob = "Wolf";
questreward = rand()%4+1;
questdisplay = "Slay Wolves";
break;
case 5:
questc = 0;
questr = 6;
questmob = "Spider";
questreward = rand()%4+1;
questdisplay = "Slay Spiders";
break;
}
}
cout << questdisplay << " [" << questc << "/" << questr << "]" << endl;
cout << "Reward >>> ";
switch (questreward) {
case 1:
qgoldr = rand()%(level*10)+(level*10);
cout << qgoldr << " Gold" << endl;
break;
case 2:
qxpr = rand()%(level*5)+(level*5);
cout << qxpr << " XP" << endl;
break;
case 3:
cout << "Slimy Chestplate >>> [10% HP Increase]" << endl;
break;
case 4:
cout << "Slimy Helmet >>> [5% HP Increase]" << endl;
break;
}
if (questc >= questr) {
quest = 0;
switch (questreward) {
case 1:
gold = gold + qgoldr;
goto questhall;
break;
case 2:
xp = xp + qxpr;
goto questhall;
break;
case 3:
slimychestplate = 1;
goto questhall;
break;
case 4:
slimyhelmet = 1;
goto questhall;
break;
}
}
cout << "99- Exit" << endl;
cin >> input;
goto menue;
dungeonmenue:
clear();
cout << R"(
_________________________________________________________
| , |
| .-'````````'. '(` .-'```````'-. |
| .` | `. `)' .` | `. |
| / | () \ U / | () \ |
| | | ; | o T o | | ; | |
| | | ; | . | . | | ; | |
| | | ; | . | . | | ; | |
| | | ; | .|. | | ; | |
| | |____;_________| | | |____;_________| |
| | / __ ; - | ! | / `'() _ - | |
| | / __ () -| - | / __-- - | |
| | / __-- _ | _- _ - | / __--_ | |
|__|/__________________|___________|/__________________|__|
/ _ - lc \
/ -_- _ - _- _--- -_- -_ \
)" << endl;
cout << "Available Dungeons" << endl;
cout << "[1] Oozing Oozeworks >>> [150 Gold, Oozing Gear]" << endl;
cout << "[99] Return to Menue" << endl;
cin >> input;
if (input == "99") {
goto menue;
} else if (input == "1") {
if (gold >= 150) {
status = "oozeworks";
gold = gold - 150;
ckills = 0;
rkills = 6;
goto oozeworks;
} else {
goto menue;
}
}
goto dungeonmenue;
oozeworks:
clear();
cout << R"(
_____ _ _____ _
| _ | (_) | _ | | |
| | | | ___ _____ _ __ __ _ | | | | ___ ______ _____ _ __| | _____
| | | |/ _ \_ / | '_ \ / _` | | | | |/ _ \_ /\ \ /\ / / _ \| '__| |/ / __|
\ \_/ / (_) / /| | | | | (_| | \ \_/ / (_) / / \ V V / (_) | | | <\__ \
\___/ \___/___|_|_| |_|\__, | \___/ \___/___| \_/\_/ \___/|_| |_|\_\___/
__/ |
|___/
)" << endl;
if (ckills >= rkills) {
goto oozeworksc;
}
cout << "[1] Continue [" << ckills << "/" << rkills << " slimes killed]" << endl;
cout << "[2] Adrenalin (Heals all missing hp/mana)" << endl;
cout << "[99] Exit" << endl;
cin >> input;
if (input == "1") {
mmana = inte * 10;
shp = stre * 20;
mhp = stre * 20;
etype = "Slime";
random2 = rand()%2+1;
eability = "ooze";
if (random2 == 1) {
ehp = shp + rand()%(level*8);
} else {
ehp = shp + rand()%(level*6);
}
mehp = ehp;
elevel = rand()%(level+3)+1;
if ((elevel < (level-3)) || (elevel > (level+3))) {
elevel = level;
}
goto aarena;
} else if (input == "99") {
goto menue;
} else if (input == "2") {
mhp = stre * 20;
mmana = inte * 10;
hp = mhp;
hp = hp * (bphp+1);
hp = hp + bhp;
mana = mmana;
}
goto oozeworks;
oozeworksc:
status = "arena";
cout << "You have completed the Oozing Oozworks" << endl;
rxp = rand()%(level*6)+5;
rgold = rand()%(level*9);
cout << "You recieved " << rxp << " xp" << endl;
cout << "You recieved " << rgold << " gold" << endl;
xp = xp + rxp;
gold = gold + rgold;
random = rand()%2+1;
switch (random) {
case 1:
cout << "New legplates unlocked! >>> [Oozing Legplates, increases hp by 15%]" << endl;
oozinglegplates = 1;
break;
case 2:
cout << "New boots unclocked! >>> [Oozing Boots, increases hp by 10%]" << endl;
oozingboots = 1;
break;
}
cout << "Type [1] to return to the menue" << endl;
cin >> input;
goto menue;
oozeworksr:
ckills = ckills + 1;
rxp = rand()%(level*4)+5;
rgold = rand()%(level*7);
rgold = rgold * goldb;
cout << "You recieved " << rxp << " xp" << endl;
cout << "You recieved " << rgold << " gold" << endl;
xp = xp + rxp;
gold = gold + rgold;
if (xp >= xpl) {
level = level + 1;
xpl = xpl + xpb;
xpb = xpb + 50;
skill = skill + 5;
cout << "You have leveled up to level " << level << endl;
}
cout << "Type [1] to continue your adventure" << endl;
cin >> input;
goto oozeworks;
savegame:
clear();
// Saving / Loading Strings
sslimychestplate = std::to_string(slimychestplate);
sslimyhelmet = std::to_string(slimyhelmet);
soozinglegplates = std::to_string(oozinglegplates);
soozingboots = std::to_string(oozingboots);
spiclass = std::to_string(piclass);
slevel = std::to_string(level);
sxp = std::to_string(xp);
sxpb = std::to_string(xpb);
sxpl = std::to_string(xpl);
sstre = std::to_string(stre);
sinte = std::to_string(inte);
sdext = std::to_string(dext);
shpotion = std::to_string(hpotion);
sgold = std::to_string(gold);
sskill = std::to_string(skill);
code = "";
code = code + sgold + ":" + sstre + ":" + sinte + ":" + sdext + ":" + sskill + ":" + sxp + ":" + sxpl + ":" + sxpb + ":" + slevel + ":";
code = code + shpotion + ":";
code = code + spiclass + sslimyhelmet + sslimychestplate + soozinglegplates + soozingboots;
cout << code << endl;
cout << "Type [1] to return to the menue" << endl;
cin >> input;
goto menue;
// Loading the game code they input
loadgame:
clear();
sslimychestplate = "";
sslimyhelmet = "";
soozinglegplates = "";
soozingboots = "";
spiclass = "";
slevel = "";
sxp = "";
sxpb = "";
sxpl = "";
sstre = "";
sinte = "";
sdext = "";
shpotion = "";
sgold = "";
sskill = "";
cout << "Please input your game code EXACTLY (if you don't this may corrupt your game save)" << endl;
cin >> input;
code = input;
goto compile;
cout << code << endl;
// Loading Game Save FILE
compile:
x = 0;
goldr:
cout << sgold << endl;
if (code[x] == ':') { // If the character is a pipe
x=x+1; // Go to next variable
goto strer;
} else {
sgold = sgold + code[x]; // If not add the variables
x=x+1; // Go to next charcter
goto goldr;
}
strer:
if (code[x] == ':') { // If the character is a pipe
x=x+1; // Go to next variable
goto inter;
} else {
sstre = sstre + code[x]; // If not add the variables
x=x+1; // Go to next charcter
goto strer;
}
inter:
if (code[x] == ':') { // If the character is a pipe
x=x+1; // Go to next variable
goto dextr;
} else {
sinte = sinte + code[x]; // If not add the variables
x=x+1; // Go to next charcter
goto inter;
}
dextr:
if (code[x] == ':') { // If the character is a pipe
x=x+1; // Go to next variable
goto skillr;
} else {
sdext = sdext + code[x]; // If not add the variables
x=x+1; // Go to next charcter
goto dextr;
}
skillr:
if (code[x] == ':') { // If the character is a pipe
x=x+1; // Go to next variable
goto xpr;
} else {
sskill = sskill + code[x]; // If not add the variables
x=x+1; // Go to next charcter
goto skillr;
}
xpr:
if (code[x] == ':') { // If the character is a pipe
x=x+1; // Go to next variable
goto xplr;
} else {
sxp += code[x]; // If not add the variables
x=x+1; // Go to next charcter
goto xpr;
}
xplr:
if (code[x] == ':') { // If the character is a pipe
x=x+1; // Go to next variable
goto xpbr;
} else {
sxpl = sxpl + code[x]; // If not add the variables
x=x+1; // Go to next charcter
goto xplr;
}
xpbr:
if (code[x] == ':') { // If the character is a pipe
x=x+1; // Go to next variable
goto levelr;
} else {
sxpb = sxpb + code[x]; // If not add the variables
x=x+1; // Go to next charcter
goto xpbr;
}
levelr:
if (code[x] == ':') { // If the character is a pipe
x=x+1; // Go to next variable
goto hpotionr;
} else {
slevel = slevel + code[x]; // If not add the variables
x=x+1; // Go to next charcter
goto levelr;
}
hpotionr:
if (code[x] == ':') { // If the character is a pipe
x=x+1; // Go to next variable
goto items;
} else {
shpotion = shpotion + code[x]; // If not add the variables
x=x+1; // Go to next charcter
goto hpotionr;
}
items:
spiclass += code[x];
x=x+1;
sslimyhelmet += code[x];
x=x+1;
sslimychestplate += code[x];
x=x+1;
soozinglegplates += code[x];
x=x+1;
soozingboots += code[x];
goto settingvaribles;
settingvaribles:
gold = atoi(sgold.c_str()); // Gold
stre = atoi(sstre.c_str()); // Strength
inte = atoi(sinte.c_str()); // Intelligence
dext = atoi(sdext.c_str()); // Dexterity
skill = atoi(sskill.c_str()); // Skillpoints
xp = atoi(sxp.c_str()); // Xp
xpl = atoi(sxpl.c_str()); // Xp till level
xpb = atoi(sxpb.c_str()); // Increases xpl
level = atoi(slevel.c_str()); // Level
hpotion = atoi(shpotion.c_str()); // HP potions
piclass = atoi(spiclass.c_str()); // Class
slimyhelmet = atoi(sslimyhelmet.c_str()); // Slimy Helmet
slimychestplate = atoi(sslimychestplate.c_str()); // Slimy Chestplate
oozinglegplates = atoi(soozinglegplates.c_str()); // Oozing Legplates
oozingboots = atoi(soozingboots.c_str()); // Oozing Boots
if (piclass == 1) {
pclass = "Champion";
} else if (piclass == 2) {
pclass = "Necromancer";
} else if (piclass == 3) {
pclass = "Assassin";
} else if (piclass == 4) {
pclass = "Cleric";
}
/*
gold = arr[1];
stre = arr[2];
inte = arr[3];
dext = arr[4];
skill = arr[5];
xp = arr[6];
xpl = arr[7];
xpb = arr[8];
level = arr[9];
hpotion = arr[10];
piclass = arr[11];
slimyhelmet = arr[12];
slimychestplate = arr[13];
oozinglegplates = arr[14];
oozingboots = arr[15];
*/
goto compilend;
compilend:
clear();
loadingload:
cout << R"(
db .d88b. .d8b. d8888b. d888888b d8b db d888b
88 .8P Y8. d8' `8b 88 `8D `88' 888o 88 88' Y8b
88 88 88 88ooo88 88 88 88 88V8o 88 88
88 88 88 88~~~88 88 88 88 88 V8o88 88 ooo
88booo. `8b d8' 88 88 88 .8D .88. 88 V888 88. ~8~
Y88888P `Y88P' YP YP Y8888D' Y888888P VP V8P Y888P
)" << endl;
y = 0;
loadingload2:
if (y < 101) {
y = y + 1;
goto loadingload2;
}
clear();
cout << "-------~ Process Complete ~-------" << endl;
cout << "Please re-input your name" << endl;
cin >> input;
name = input;
goto menue;
leave:
clear();
cout << "See you later!" << endl;
return 0;
}
#1 楼
首先,让我与其他人一起指出您所做的甜美ASCII艺术。这肯定是比大多数文本游戏都更好的文本游戏的开始。我首先定义一些结构来保存有关游戏中特定事物的数据。举几个例子:
struct Ability {
std::string name;
int level_adder;
int cost(int level, int inte) {
return (level + level_adder) * inte;
}
bool can_afford(int level, int inte, int manna) {
return cost(level, inte) <= manna;
}
void show(int level, int inte) {
std::cout << name << "[" << cost() << " manna]\n";
}
};
class PlayerClass {
std::string name;
std::vector<Ability> abilities;
size_t ability_count() { return abilities.size(); }
void show(int level, int inte) {
for (int i=0; i<abilities.size(); i++)
std::cout << "[" << i << "] ";
abilities[i].show(level, inte);
}
Ability const &operator[](size_t index) const {
return abilities.at(index);
}
};
使用这些,我们可以为Player类定义所有数据,如下所示:
PlayerClass Champion{
"Champion",
{ "Cleaving Strike", 0},
{ "Melting Thrust", 0},
{"Critical Bash", 0},
{"Purify", 1}
};
PlayerClass Necromancer{
"Necromancer",
{ "Shadow Strike", 0},
{ "cripple", 0},
{ "Mutilate", 0},
{ "Life Tap", 2}
};
...等等,以供其他玩家使用。仅举一个例子,这使得将来添加更多玩家类变得更加容易-例如,我可以坐下来决定要添加一个“小偷”类:
PlayerClass Thief {
"Thief",
{ "Pick Pocket", 0},
{ "Grab Purse", 0},
{ "Rob Business", 1},
{ "Rob Bank", 4}
};
...并且游戏的其余大部分内容都可以与此新玩家类一起使用,而无需进行任何修改。同样地,我可以通过简单地决定使用该能力的名称和相对成本来向现有的玩家类别中添加新的能力-我不必修改所有与能力相关的逻辑就可以将新添加的能力考虑在内。
然后我们可以定义一个播放器来保存(例如)对
PlayerClass
对象的引用:class Player {
PlayerClass &pclass;
// ...
};
返回(可能是指向或引用的)Ability对象,看起来像这样:
player.pclass.show();
cin >> input;
// This logic isn't complete--we need to add a call to `can_afford` to see
// whether the player can afford to use an ability.
if (input > player.pclass.ability_count()
ability = None;
else {
ability = player.pclass[input];
player.manna -= ability.cost();
}
请注意,这如何消除了代码中的大量重复,对于每个玩家等级的每种能力,基本上重复相同的逻辑。
防止错误
我还考虑在显示该能力之前,检查玩家是否有能力使用特定能力能力。这样,他们仅从可以使用的能力中进行选择,而不是试图选择实际上无法承受的能力,然后为时已晚,发现他们做出了错误的选择,并且什么也没有发生。
命名
您使用的某些名称会缩短到无法确定其含义的程度。仅举几个例子,
getability
和inte
-我将它们缩写为一点,以便阅读代码的人可以轻松理解它们的真实含义。评论
\ $ \ begingroup \ $
有趣的是,您的播放器不是其播放器类的实例:-)
\ $ \ endgroup \ $
– einpoklum
17年8月5日在19:39
\ $ \ begingroup \ $
@einpoklum:有点-并倾向于暗示我使用的名字仍然不是很理想...
\ $ \ endgroup \ $
–杰里·科芬(Jerry Coffin)
17年8月5日在19:48
\ $ \ begingroup \ $
好吧,您不能称其为“ PlayerClassButNotInInCppSense” ...
\ $ \ endgroup \ $
– einpoklum
17年8月5日在21:00
\ $ \ begingroup \ $
如果您正在寻找RPG意义上的“职业”的替代品,则有时会首选“职业”或“职业”。
\ $ \ endgroup \ $
–法老王
17年8月6日在2:41
#2 楼
关于此代码,有好消息也有坏消息。坏消息是它不是很好的代码。好消息是,对其进行很大的改进将不会太困难,而且ASCII艺术很棒!以下是一些可以帮助您改进代码的观察结果。不要滥用
using namespace std
在每个程序的顶部放置
using namespace std
是一个坏习惯,您最好避免。 考虑将I / O与算法分离
现在,一切都在main中完成。更好的做法是将事物分成功能。特别是,我建议将输入/输出例程分成单独的函数。现在,控制流程很难遵循,也很难说出代码中正在发生什么。
避免使用
goto
goto
语句的泛滥通常是不良设计的标志。最好是完全消除它们-它使代码更易于遵循且不易出错。在此代码中,很可能可以使用状态机和switch
语句来代替,这将使代码更易于遵循,并且更不容易出错。使用对象
因为您是用C ++编写的,所以使用对象很有意义。例如,您可能具有一个
Player
类,该类包含当前仅用注释标记为“玩家变量”的所有变量,以及一个游戏状态类,以简化加载和保存游戏状态的过程。考虑使用更好的随机数生成器
您当前正在使用
random = rand()%5+1;
这种方法存在一个问题:随机数生成器的低位不是特别随机,因此
random
也不是。在我的机器上,有一个相对于0的轻微但可测量的偏差。如果编译器和库支持,更好的解决方案是使用C ++ 11`std :: uniform_int_distribution。它看起来很复杂,但实际上非常易于使用。class Die {
public:
Die(int min, int max) : min{min}, max{max} {}
Die(int max=6) : min{1}, max{max} {}
int operator()() {
std::uniform_int_distribution<> dist(min,max);
return dist(eng);
}
private:
int min;
int max;
static std::mt19937 eng;
};
std::mt19937 Die::eng{std::random_device{}()};
如本例中所示,当您想要从1到6的某个数字时,可以这样称呼它:
int main() {
Die die{6}; // create conventional 6-sided die
for (int i=20; i; --i) {
std::cout << die();
}
}
消除“魔术数字”
整个代码中都有一些数字,例如
5
和6
在其中具有特定含义他们的特定背景。通过使用命名常量,程序变得更易于阅读和维护。对于常量仅对特定对象有意义的情况,请考虑将该常量作为对象的一部分。忽略
return 0
当C或C ++程序到达
main
的末尾,编译器将自动生成返回0的代码,因此无需将return 0;
显式放在main
的末尾。 评论
\ $ \ begingroup \ $
出于应有的尊重-我认为谈论return 0浪费了建议空间。这和这和其他方式真的无关紧要,对任何事物的设计都没有影响。建议您只删除较长(且有用)答案中的该部分。
\ $ \ endgroup \ $
– einpoklum
17年8月5日在19:36
\ $ \ begingroup \ $
我修剪了。
\ $ \ endgroup \ $
–爱德华
17年8月5日在21:43
\ $ \ begingroup \ $
关于个人编码风格,但我学会了写return EXIT_SUCCESS;而且通常还是在C或C ++中声明为return int的任何其他函数都需要return语句,并且幻数是错误的样式。
\ $ \ endgroup \ $
–戴维斯洛
17年8月7日在8:31
\ $ \ begingroup \ $
从int到布尔的隐式转换使i;条件语句中的有效表达式,但这是C ++的常规做法吗?我想我!= 0或我> 0更好。
\ $ \ endgroup \ $
–person27
17年8月7日在20:13
\ $ \ begingroup \ $
@ Anon234_4521:是的,这是常见的做法,我想您会发现,在大多数体系结构和编译器中,如果将其写成i!= 0,它将产生相同的代码。
\ $ \ endgroup \ $
–爱德华
17年8月7日在21:02
#3 楼
控制流我想赞同并充实一点爱德华关于删除
goto
语句的建议。这里更好的方法是某种状态机。您具有某种游戏状态,可以跟踪您所处的模式,例如是否选择一种能力,四处移动,开始相遇等等。屏幕适合当前状态。 (例如,在陆路模式下的地图,在战斗模式下的怪物的ASCII艺术,如果您要向巫师或《创世纪》致敬,可能是盒装的第一人称地牢?)显示的选项取决于游戏模式,什么能力您拥有的物品,以及其他合适的物品(例如,您的库存中可能有哪些物品,或者您拥有多少能量或冷却时间)。选择任何选项即可更新游戏状态。例如,赢得战斗可能会使您进入战利品屏幕。程序逻辑就是这样的循环:
while ( !state.hasQuit() ) {
state.displayScreen();
state.getActionAndUpdate();
}
比起一堆
goto
语句更简单,更容易理解!然后
displayScreen()
可以说,清除屏幕,打印状态栏,打印ASCII艺术作品,查找角色具有的能力,打印这些能力,并给您提供菜单提示。如果状态变大而且体积又大了,您将不再希望将整个游戏状态保持在单个“上帝对象”中,而所有东西都需要混在一起。玩家统计数据可能会进入一个对象,世界地图可能位于另一个对象中,而敌方统计则可能进入另一个对象。分开的子系统是有意义的。但是这种循环是一种很好的简单模式,用于跟踪您当前所处的游戏模式并采取适当的操作。
使用OO清理代码
一种变体是使最后一行类似于
state = state->getNewState()
,其中state
是一个指针,其类型是所有状态的基类。这样,您就可以将游戏模式的抽象概念分解为具体实例,例如陆上模式或战斗模式。这些可以是子类,其成员函数实现该模式的正确行为。这样,每个成员函数都将比包含每个模式的所有代码路径的一个大函数更短,更清晰。您可以通过返回对另一个状态对象的引用来选择它们,而不涉及if
,switch
或goto
。如果只有有限数量的静态游戏模式,则可以为每个状态对象创建一个对象。返回
const
对它们的引用。每种模式的特定代码都将驻留在一个派生类的成员函数中。如果您需要创建新的状态对象(例如为每次战斗存储不同的信息),则需要使用像
std::unique_ptr
这样的智能指针。这将为您完成所有的内存管理,否则,这是最棘手的事情之一。如果您还有其余的符合某些测试模式的代码部分,则可以选择一个对于许多情况,每种情况都有不同的代码分支,经典的解决方案是为每种可能的情况定义一个带有常量的
enum
,然后编写switch
语句。如果您忘记或输错了其中一种情况,您的编译器甚至可能会发出警告。避免全局变量
这会使您的程序很难调试,因为任何部分代码可能已经更改了它们。更好的解决方案是让玩家状态在内部存储诸如您拥有多少个健康药水之类的东西。然后,只有使用一个的代码才减少计数,只有检查库存的代码才查找并显示它。
您还希望将数字数据存储为数字,而不是存储为反复转换回数字的字符串。
使用数据结构
通常,我会建议将特殊情况移入数据结构,而不是代码分支。杰里·科芬(Jerry Coffin)提出了有关如何提高玩家能力的好的建议。但是,例如,您惊人的ASCII艺术和其他怪物数据可以作为值存储在哈希表中(STL中为
std::unordered_map
)与您用来选择它们作为键的名称。这将具有几个优点。最重要的一点是,如果添加另一个怪物,则只需要将其条目添加到表中的一个位置即可。将每个新技能和每个新怪物作为特例处理在处理它们的每段代码中进行特殊处理都成为一个真正的噩梦:您必须检查自己是否记得所有地方,并始终如一地对其进行处理。如果将所有数据放在一个地方,而在另一个地方可以处理任何数据的地方编写代码,则添加内容变得非常容易。
一些技术知识
在这种情况下,您可以考虑将ASCII艺术作品存储为行向量。 (由于二维数组可能意味着一些不同的东西,因此,一个很好的明确名称是矩形数组。)这将使例如在盒子中显示怪物的图片并在其周围包裹一个信息转储成为可能。 ,或在图片的左侧或右侧显示其统计信息,或在帧上覆盖“ -999 HP”之类的标题。
我想重复并强调将数据与显示代码分开的建议。您需要与游戏数据正交的代码。您不应该为每种怪物重写显示代码,因为这使它永远成为噩梦。不要重复自己!这样一来,您还可以对数据做更多的事情,或者对任意新数据运行代码。
如果您将art数组设置为宽字符,请使用
std::wcout
,您可以使用Unicode艺术,而不仅仅是ASCII艺术。您可能不一定想要。您的艺术很壮观。您正在回想起的经典游戏使用的现在是Unicode的盒形绘图和几何形状字符。但是选项在那里。请注意,Windows在#ifdef
块内需要一些非标准的初始化代码才能使其正常工作,但是我可以共享它。即使在今天,在许多系统上,您也可以插入ANSI color代码(16种颜色,前景和背景,以及一些特殊功能,如粗体和下划线,例如在8位晚期或16位早期,并且完全类似于telnet上的经典Unix终端)或xterm颜色(超过200种)。再没有比这更真实的复古了。 Linux控制台本地支持这些代码,我认为OSX终端也支持。
#4 楼
您可能需要从单独的文本文件中加载ascii艺术作品,以便您可以在不影响功能代码的情况下进行编辑。评论
\ $ \ begingroup \ $
这似乎更像是评论,但我也注意到您没有足够的声誉来发表评论。还是+1。
\ $ \ endgroup \ $
–奥斯卡·斯科格(Oskar Skog)
17年8月7日在20:02
#5 楼
用简短函数和简单函数分开代码您当前的函数太长了:例如,
main()
有1282行。这远远超过了可接受的范围。虽然确切的最大行数是主观的,但是有一些好的经验法则。例如,此问题提到100到200行作为上限。理想情况下,每个函数都应该做一件事并且做好事-这就是所谓的SRP(单一职责原则)。
在许多程序中,
main()
在某种程度上是一个例外,因为它通常同时进行两种初始化(通过调用init()
或类似功能)和主循环。尽管如此,主循环仍应主要包括对其他功能和/或状态机逻辑的调用。我相信其他答案会提供更多有关结构化的细节。#6 楼
在所有答案中,我最强调的一件事是使用对象。这已经得到了回答,但是我想再次强调它。如果仅了解这一点,那么这比其余答案的总和还有价值。您似乎在思考过程和算法。如果您使用C,这很好,但是如果您想要使用C ++,请学习在对象中进行思考。对象具有明确的责任,您可以盲目地信任它们(只要它们的单元测试有效),而您无需知道它们如何工作。对象作为自治实体工作。我建议您完全不使用任何函数,最好仅在需要扩展标准库类型(如std :: vector)的功能时使用。
最后,您的主程序应该看起来像这样:
int main() {
Game game;
game.run();
return 0;
}
Game类(或者您想调用它)然后创建其他类,这些类又可以在某种层次结构中创建更多类。这样的类的方法调用其他类的方法,其作用仅仅是使子对象协同工作。在大多数基本类的方法中,实际算法尽可能短。
任何内容(例如ASCII艺术,RPG字符类名称,场所名称等)都不应包含在代码本身中。
关注可读性的概念。您的代码应具有非常清晰的轮廓。如果一个陌生人想找到一些特定的功能,那么应该在哪里寻找就可以了。现在,必须浏览一个大文件。如果您有几个带有头文件和源文件的类,那么一个人就会知道在哪里查找。
评论
\ $ \ begingroup \ $
OOP是其中一种方法,但不是所有方法中的唯一方法,也不一定是最好的方法。 C ++是一种多范式语言。
\ $ \ endgroup \ $
–kfx
17年8月8日在9:52
\ $ \ begingroup \ $
@kfx我会说使用其他方法的情况相对较少。基本上,当涉及解决一些数学上非常模型化的问题的实际算法时。无论如何,事情是,初学者应该学习一种在他遇到的大多数情况下将是最好的方法,即OOP。我们可以争论在哪种情况下其他方法更好,但是如果我们有初学者...那么,我们手头的实际情况当然可以用OOP最好地解决。
\ $ \ endgroup \ $
–方位角
17年8月8日在15:00
评论
一些非常令人印象深刻的ascii艺术。Thx,也称为“使用命名空间std”的问题,直到完成一半时才知道是不好的,目前我仍在从事该项目。
您能否谈谈为什么要用C ++而不是某种脚本语言来实现此目的?
好吧,我之所以用C ++这样做是因为:a-我真正了解的唯一一种语言。 b-我认为C ++非常好用且简单,我现在真的不想学习另一种语言。
我非常怀疑他做过ascii艺术,因为此页面上有一些带有不同名称的附件... ascii.co.uk/art