Generic Game Functions?

I'm working on a bunch of random functions that I figure will be useful for console games. I was wondering if anyone had other ideas?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/* Standard Game Header */
#pragma once
#ifndef _STDGAME_H
#define _STDGAME_H

#pragma warning (push)
#pragma warning (disable: 4244)

#include <iostream>
#include <sstream>
#include <string>
#include <time.h>
#include <math.h>
#include <vector>


namespace stdgame {

  template<typename t> inline std::string toString(const t &val1);
  template<typename t> inline void swap(t &val1, t &val2);
  template<typename t> inline t max(const t &val1, const t &val2);
  template<typename t> inline t min(const t &val1, const t &val2);

  inline void randomize();
  inline int randomNumber(int);
  bool chance(float);

  std::vector<std::string> parse(std::string, std::string);
  void print(std::string);
}


/* Attempts to covert (val1) into a string data type */
template<typename t> inline std::string stdgame::toString(const t &val1) {
  std::stringstream ss;
  ss << val1;
  return ss.str();
}

/* Attempts to swap two variables */
template<typename t> inline void stdgame::swap(t &val1, t &val2) {
  t _tmpVal;
  _tmpVal = val1;
  val1 = val2;
  val2 = _tmpVal;
}

/* Returns the larger of two values; returns the first value if they are equal */
template<typename t> inline t stdgame::max(const t &val1, const t &val2) {
  return (val1 >= val2) ? val1 : val2;
}

/* Returns the smaller of two values; returns the first value if they are equal */
template<typename t> inline t stdgame::min(const t &val1, const t &val2) {
  return (val1 <= val2) ? val1 : val2;
}

/* Generates new random seed */
inline void stdgame::randomize() { srand(time(0)); }

/* Return a random integer between 0 and (range - 1) */
inline int stdgame::randomNumber(int range) {
  int r = rand();
  r = (r % abs(range));
  return r;
}

/* Returns true if a chance for a certain percentage (percent) occurs */
bool stdgame::chance(float percent) {
  if (percent <= 0.0) return false;
  if (percent >= 100.0) return true;
  float r = (static_cast<float>(rand()) / static_cast<float>(RAND_MAX)) * 100;
  if (r <= percent) return true;
  return false;
}

/* Parse a string (strLn) into a vector broken up by the string (strDiv) */
std::vector<std::string> stdgame::parse(std::string strLn, std::string strDiv) {
	
  std::vector<std::string> v;
  int pos = 0;
  int newPos = 1;

  while (newPos != std::string::npos) {

    newPos = strLn.find(strDiv, pos);
			
    //If a divider was not found, or if we are at the end of file,
    //this is our last vector value
    if (newPos == std::string::npos) {
      v.push_back(strLn.substr(pos));
      return v;
    }

    //If we are here, we found a divider
    v.push_back(strLn.substr(pos, newPos-pos));
			
    //Reset the starting position equal to the next position after divider
    pos = newPos + 1;

  }
  return v;
}

/* Simple console output print function */
void stdgame::print(std::string str) {
  std::cout << str << std::endl;
}

#pragma warning (pop)
#endif 
Those are good to implement as a training, but are superceded by standard library and boost (almost-standard-library). Here is direct (and usually more powerful) analogues:

stdgame::toStringboost::lexical_cast 

stdgame::swapstd::swap Also you might want ot modify your swap to work with move.

stdgame::max / stdgame::minstd::max / std::min

stdgame::randomize / stdgame::randomNumber: C random is terrible and modulus operator introduces additional bias. Use mt19937 and uniform_int_distribution. Idea to have an easy-to-use function for integer generation is good (and possibly we will have it in C++17).

stdgame::chance: Pretty large bias, low precision. Use bernoulli_distribution

stdgame::parseboost::tokenizer
Thanks for the tips about Boost. I figured these functions existed somewhere out there in the universe. With that said, some of the fun in this is just figuring stuff out myself. (I program for fun as a hobbyist).

I made some additions to my header file. Would like some constructive criticism on ways to improve or fixing bad form/structure/etc... (besides not putting definitions in headers... did that here cause it's easier to paste in as one code block).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
/* Standard Game Header */
#pragma once
#ifndef _STDGAME_H
#define _STDGAME_H

#pragma warning (push)
#pragma warning (disable: 4244)
#pragma warning (disable: 4018)

#include <iostream>
#include <sstream>
#include <string>
#include <time.h>
#include <math.h>
#include <vector>
#include <sys/stat.h>
#include <fstream>


namespace stdgame {

	//Templates
	template<typename t> inline std::string toString(const t &val1);
	template<typename t> inline void swap(t &val1, t &val2);
	template<typename t> inline t max(const t &val1, const t &val2);
	template<typename t> inline t min(const t &val1, const t &val2);
	template<typename t> inline void print(const t &val);

	//Numbers
	inline void randomize();
	inline int randomNumber(const int&);
	bool chance(const float&);
	inline bool isEven(const int&);
	inline bool isOdd(const int&);

	//File Handling (Small files - reads in and edits through vector)
	inline bool fileExists(const std::string& fileName);
	class file {
	private:
		std::string _fname;
		std::vector<std::string> _fvector;
	public:
		~file() { close(); }
		bool create(const std::string& fileName);
		bool open(const std::string& fileName);
		std::string read(const int& line);
		void write(const int& line, const std::string& str);
		void insert(const int& line, const std::string& str);
		void add(const std::string& str);
		inline void close();
		inline int size();
	};
	std::vector<std::string> parse(const std::string&, const std::string&);
}

//TEMPLATES **************************************************

/* Attempts to covert (val) into a string data type */
template<typename t> inline std::string stdgame::toString(const t &val) {
	std::stringstream ss;
	ss << val;
	return ss.str();
}

/* Attempts to swap two variables */
template<typename t> inline void stdgame::swap(t &val1, t &val2) {
	t _tmpVal;
	_tmpVal = val1;
	val1 = val2;
	val2 = _tmpVal;
}

/* Returns the larger of two values; returns the first value if they are equal */
template<typename t> inline t stdgame::max(const t &val1, const t &val2) {
	return (val1 >= val2) ? val1 : val2;
}

/* Returns the smaller of two values; returns the first value if they are equal */
template<typename t> inline t stdgame::min(const t &val1, const t &val2) {
	return (val1 <= val2) ? val1 : val2;
}

/* Simple console output print function */
template<typename t> inline void stdgame::print(const t &val) {
	std::cout << toString(val) << std::endl;
}

//NUMBERS **************************************************

/* Generates new random seed */
inline void stdgame::randomize() { srand(time(0)); }

/* Returns a random integer between 0 and (range - 1) */
inline int stdgame::randomNumber(const int& range) {
	int r = rand();
	r = (r % abs(range));
	return r;
}

/* Returns true if a chance for a certain percentage (percent) occurs */
bool stdgame::chance(const float& percent) {
	if (percent <= 0.0) return false;
	if (percent >= 100.0) return true;
	float r = (static_cast<float>(rand()) / static_cast<float>(RAND_MAX)) * 100;
	if (r <= percent) return true;
	return false;
}

/* Returns true if an integer (val) is even */
inline bool stdgame::isEven(const int& val) { return (val % 2 == 0); }

/* Inverse of previous function; returns true if odd number */
inline bool stdgame::isOdd(const int& val) { return (val % 2 == 1); }

//FILE HANDLING **************************************************

/* Returns true if the file exists */
inline bool stdgame::fileExists(const std::string& fileName) {
	struct stat buffer;
	return (stat(fileName.c_str(), &buffer) == 0);
}

/* Creates a new file; will not overwrite an existing one */
bool stdgame::file::create(const std::string& fileName) {
	close();
	if (fileExists(fileName)) return false;
	std::fstream _f;
	_f.open(fileName, std::fstream::out);
	_f.close();
	_fname = fileName;
	_fvector.clear();
	return true;
}

/* Opens a file and reads the data into a vector (returns false if fails) */
bool stdgame::file::open(const std::string& fileName) {
	close();
	if (!fileExists(fileName)) return false;
	std::ifstream _f;
	_f.open(fileName);
	if (!_f) {
		_f.close();
		return false;
	}
	_fname = fileName;
	_fvector.clear();
	std::string tmp;
	while (!_f.eof()) {
		std::getline(_f, tmp);
		_fvector.push_back(tmp);
	}
	_f.close();
	return true;
}

/* Returns a specific text line from the contents of the file stored in the vector */
std::string stdgame::file::read(const int& line) {
	if (_fname == "" || _fvector.size() == 0) return "";
	if (line < 0 || line >= _fvector.size()) return "";
	return _fvector[line];
}

/* Writes data at a specific line (overwrites existing); if line doesn't exist, creates it */
void stdgame::file::write(const int& line, const std::string& str) {
	if (_fname == "" || line < 0) return;
	while (line >= _fvector.size()) {
		_fvector.resize(_fvector.size() + 1);	
	}
	_fvector[line] = str;
}

/* Inserts data at a specific line; passes to write() if out of bounds */
void stdgame::file::insert(const int& line, const std::string& str) {
	if (_fname == "" || line < 0) return;
	if (line >= _fvector.size()) {
		write(line, str);
	} else {
		_fvector.insert(_fvector.begin() + line, str);
	}
}

/* Adds data to the end of the file */
void stdgame::file::add(const std::string& str) {
	if (_fname == "") return;
	_fvector.push_back(str);
}

/* Writes vector back to file; clears file data*/
void stdgame::file::close() {
	if (_fname == "") return;
	std::ofstream _f(_fname, std::fstream::out | std::fstream::trunc);
	for (int i = 0; i < _fvector.size(); i++) {
		_f << _fvector[i];
		if (i != (_fvector.size()-1)) _f << std::endl;
	}
	_f.close();
	_fname = "";
	_fvector.clear();
}

/* Returns the number of lines in the file (vector size) */
inline int stdgame::file::size() { return _fvector.size(); }

/* Parse a string (strLn) into a vector broken up by the string (strDiv) */
std::vector<std::string> stdgame::parse(const std::string& strLn, const std::string& strDiv) {
	
	std::vector<std::string> v;
	int pos = 0;
	int newPos = 1;

	while (newPos != std::string::npos) {

			newPos = strLn.find(strDiv, pos);
			
			//If a divider was not found, or if we are at the end of file,
			//this is our last vector value
			if (newPos == std::string::npos) {
				v.push_back(strLn.substr(pos));
				return v;
			}

			//If we are here, we found a divider
			v.push_back(strLn.substr(pos, newPos-pos));
			
			//Reset the starting position equal to the next position after divider
			pos = newPos + 1;

		}
		return v;
}

#pragma warning (pop)
#endif
Last edited on
1
2
3
4
	while (!_f.eof()) {
		std::getline(_f, tmp);
		_fvector.push_back(tmp);
	}
Reads one extra (empty) string in most cases
Do not loop on eof. It is almost always wrong. Loop on input operations:
1
2
3
while (std::getline(_f, tmp)) {
    fvector.push_back(tmp);
}
http://stackoverflow.com/a/8734207
Thanks, I'll change that in my code.
Topic archived. No new replies allowed.