Extreme Newbie here - hello world :)

Started by
65 comments, last by moaq 14 years, 10 months ago
Quote:is that just a way to write a member function for that class outside of the actual function code?
Outside of the class declaration? Yes. show() is a member function of Dot, so you must define it as Dot::show(). By the way, :: is called the scope resolution operator. You've already seen it in use elsewhere. std::cout, for example.

Quote:to keep things more organized?
I'm not sure what you are referring to here. If you mean if the function definitions outside the class declaration is an organization issue, then yes.

Quote:so show() is just a public function of the dot class?
It's a member function. Whether it is public depends on the class declaration, where you would indicate the access specifier.
Advertisement
Quote:Original post by oler1s
Quote:is that just a way to write a member function for that class outside of the actual function code?
Outside of the class declaration? Yes. show() is a member function of Dot, so you must define it as Dot::show(). By the way, :: is called the scope resolution operator. You've already seen it in use elsewhere. std::cout, for example.

Quote:to keep things more organized?
I'm not sure what you are referring to here. If you mean if the function definitions outside the class declaration is an organization issue, then yes.

Quote:so show() is just a public function of the dot class?
It's a member function. Whether it is public depends on the class declaration, where you would indicate the access specifier.




thanks that did clear it up :) I had the right idea, just wasn't sure.
Ok I am ready to ask my next question which has to do with loading data from a text file.. first, I'll post the code for the entire 'Maze' game I created while messing around with arrays.

#include <iostream>const int tileWide = 23;const int tileHigh = 10;bool gameOver = false;void printBoard(int[tileHigh][tileWide]);void locateOne(int& , int& , int[tileHigh][tileWide]);void move(const char direction, int[tileHigh][tileWide]);int iaBoard[tileHigh][tileWide] = {	{1,2,2,2,2,2,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},	{0,2,0,2,0,0,0,2,0,2,0,2,2,2,2,2,0,2,2,2,2,2,0},	{0,0,0,0,0,2,0,2,0,2,0,0,0,0,0,0,0,0,2,0,0,2,0},	{2,0,2,2,2,2,0,2,0,2,0,2,0,2,0,2,2,0,2,2,0,2,0},	{0,0,0,0,2,2,0,2,0,0,0,0,0,2,0,0,0,0,0,2,0,0,0},	{0,2,2,0,2,2,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,2,2},	{0,0,2,0,2,0,0,2,0,2,0,2,0,0,0,0,0,2,0,2,0,0,0},	{2,0,0,2,2,2,0,2,0,2,0,0,2,2,2,0,0,0,0,2,0,2,0},	{2,0,2,0,0,0,0,2,0,2,2,2,2,0,2,0,0,2,0,2,0,2,0},	{2,0,0,0,0,0,0,2,0,0,0,0,0,0,2,0,0,2,0,2,2,0,0}	};int main(){    	do{	system("cls");	std::cout << "find your way to the bottom right corner.... ";    printBoard(iaBoard);	std::cout << "enter a direction (w = up, s = down, a = left, d = right):";    char cNextMove;	if(iaBoard[tileHigh - 1][tileWide - 1] == 1)	{	  gameOver = true;	} else {	std::cin >> cNextMove;	}	move(cNextMove,iaBoard);	} while(!gameOver);	std::cout << std::endl << " You made did it! you made it to the corner ! \n ";    system("pause");	std::cout << "sorry you can't restart this game :) \n" << std::endl;	return 0;}void printBoard(int iaBoard[tileHigh][tileWide]){	std::cout << " \n\n ";	for(int i=0;i<tileHigh;++i){		std::cout << "\t";		for(int j=0;j<tileWide;++j){			std::cout << iaBoard[j];		}		std::cout << std::endl;	}}void locateOne(int& irRow, int& irCol, int iaBoard[tileHigh][tileWide]){  for(int iRow = 0;iRow < tileHigh ;++iRow)  {	for(int iCol = 0;iCol < tileWide ;++iCol)	{		if(iaBoard[iRow][iCol] == 1)		{		 irRow = iRow;		 irCol = iCol;		}	}  }}void move(const char direction, int iaBoard[tileHigh][tileWide]){ int iRowOne = 0; int iColOne = 0; locateOne(iRowOne, iColOne, iaBoard); int iOldRow = iRowOne; int iOldCol = iColOne;  switch(direction)  {   case 'w':   {    --iRowOne;	break;   }   case 's':   {    ++iRowOne;	break;   }   case 'a':   {    --iColOne;	break;   }   case 'd':   {    ++iColOne;	break;   }  } if (iRowOne >= 0 && iRowOne < tileHigh && iColOne >= 0 && iColOne < tileWide)  {	 if(iaBoard[iRowOne][iColOne] != 2)	 {      iaBoard[iRowOne][iColOne] = 1;      iaBoard[iOldRow][iOldCol] = 0;	 } }}


the concept is simple.. there is a multi-dimensional array of numbers, 0's and 2's and a 1, you control the one starting in the top left and have to make it to the bottom right spot. you cannot move through 2's, only 0's.

you can download the executable at http://www.27software.net/Maze.zip

My question is about the array itself, for learning purposes I would like to be able to load the array (the level) in from a text file. The way I visualize this happening is in the text file there is something like this:

map.txt
tilesWide = 20;tilesHigh = 20;1 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 2 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 02 2 0 2 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 00 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 2 2 2 0 2 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 2 0 2 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 2 0 2 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 2 0 2 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0


from there, somehow get the 2 variables from tilesWide, and tilesHigh
and put them into the 2 const variables from the Maze code:
const int tileWide = ?
const int tileHigh = ?

then somehow sort the numbers delimited by the spaces / new lines into a multi dimensional array.

am I close? is it a lot of work to do that?

[Edited by - AstralAaroN on May 30, 2009 9:19:08 AM]
Quote:Original post by AstralAaroN
My question is about the array itself, for learning purposes I would like to be able to load the array (the level) in from a text file. The way I visualize this happening is in the text file there is something like this:

map.txt
*** Source Snippet Removed ***

from there, somehow get the 2 variables from tilesWide, and tilesHigh
and put them into the 2 const variables from the Maze code:
const int tileWide = ?
const int tileHigh = ?

then somehow sort the numbers delimited by the spaces / new lines into a multi dimensional array.

am I close? is it a lot of work to do that?


There is not much work, but you do have to use more sophisticated tools.

You don't need to indicate the width and height within the file. That can be figured out on the fly. We'll just put the grid of numbers into the file.

You can't just use a 'const' variable to size an array. The array's size has to be known at the time you compile the program.

However, there are better storage solutions than arrays. In our case, we will use the standard library class std::vector.

We'll use a vector that holds ints (spelled std::vector<int>) for each "row" of the maze, and then the maze is a vector that holds rows. (Can you guess how that's spelled? Actually, there's a slight trick here - you can't put the two >'s next to each other; you need a space in between. Oops, was that a hint?)

Getting numbers delineated by spaces is easy: we just use the operator>> of the stream to read into a variable of type int. (The fact that there is such a thing as an operator>> has something to do with the "trick" mentioned in the previous paragraph.) This operator does different things depending on the type of the variable that you're reading into. For ints, it expects a number in human readable format (i.e. the file contains a sequence of characters picked from '0' through '9').

To assemble a vector of ints, we'll repeatedly read in an int from the stream, and then append the read-in value to the vector. To append, we use the .push_back() function of the stream.

Similarly, to assemble the entire map, we'll repeatedly create rows using the above technique, and .push_back() them onto the map vector.

How do we know when we reach the end of a line? The operator>> won't tell us - it skips past all leading whitespace before attempting to read in a value. (Because of this, we don't need to do anything special to ignore the spaces themselves.) That means if we just keep reading ints in a loop, we'll read the entire file. (Actually, if there's any non-number in the file data, things will get messed up at that point; but we'll worry about error handling later.)

But there's another trick we can pull here: we can read the file a line at a time, and then read ints out of the read-in line. To do this, we'll need a container for the text data that makes up each line, a way to read a line at a time from the file, and a way to treat the line of text like a stream (so that we can read ints out of it).

The natural choice for the text container is std::string, of course. We don't want to use operator>> to read into it (because that will stop at the next whitespace; i.e. it will only read one "word"). Instead, we will use the function std::getline. (Note that there is a member function of input stream objects named "getline"; but we don't want that one - we want the free function named "getline", which takes an input stream as a parameter.)

To treat the string like a stream, we wrap it up using yet another standard library tool: std::stringstream. This is pretty much exactly what it sounds like. :)



Putting all of that together, we get:

#include <vector> // for std::vector#include <string> // for std::string#include <iostream> // for std::getline#include <fstream> // for std::ifstream etc.#include <sstream> // for std::stringstream// I'm going to use a 'typedef' to give a name to the data type that we're// reading into.typedef std::vector<std::vector<int> > map_type;// Now "map_type" means a vector of (vector of int)s. Did you figure out the// "spelling", by the way? Complicated, isn't it? That's why we use the // typedef: so we only have to write out that icky thing once.// And now we'll make a loading function.map_type loadMap(const std::string& fileName) {  map_type result;  // You should be familiar with this file opening code by now, I hope...  std::ifstream input(fileName.c_str());  // We repeately read lines of the file in an outer loop.  // Notice that the read operation itself is used for the loop condition.  // This is the normal way to do these loops in C++.  std::string line;  while (std::getline(input, line)) {    // Now we make a stringstream that wraps the current line...    std::stringstream ss(line);    // and read ints from it, in an inner loop:    std::vector<int> row;    int value;    while (ss >> value) { // again, we use the read operation to control the loop.      row.push_back(value);    }    // Now that we have an assembled row, it can be appended to the map.    result.push_back(row);  }  return result;}


To use the map, we can index into it just like with an array: the operator[] for a vector will return a reference to the corresponding element; so indexing once into a map gives us a row vector, and indexing again (i.e., into the row vector) gives us an int.

To check the size of the vector, use its .size() member function. Beware! The way the code is written, we've allowed each row of the map to have its own length. Think carefully about what will happen if we don't make all the rows the same length in the file data.
Why wont anyone suggest CodeBlocks?
It is a very good, OPEN SOURCE IDE as well.
Zahlman thank you, your post is awesome.
I have been a little busy with things. I am going to refresh my memory on what I learned previously and then I am going to study your post and learn what you are talking about.

thanks again!
Hi I got really busy the past few days and the C++ marathon was on hold but is restarting right now :)

Before I got busy, I was learning all kinds of concepts and trying to understand them. This post is mainly about classes. I created this little game "Coin Toss Casino" and tried to make use of classes. Curious to have someone look through what I've done and point out anything I am doing right, or wrong.

am I using member functions effectively?

here's the code:

#include <iostream>#include <ctime>#include <string>//streak, a game that generates 1 of 2 numbers and lets a player bet on the result// the longer your streak is the more points you receive.void playGame();bool gameOver = false;class Player{public:  Player() : money(200), streak(0), total(0), name("Player") {}  long long money;       int streak;  int total;  std::string name;};Player One;  //declair a playerclass Machine{ public:  void generate(int bet, int guess)  {      time_t t;      time(&t);      srand(t);      int res = (rand() % 2);      outCome(bet,guess,res);  }  void takeBet(int bet, int guess)  {    One.total;// = One to;    generate(bet, guess);  }  void outCome(int bet, int guess, int iRand)  {       if(iRand == guess)       {        int prize;         std::cout << "The Number IS !: " << iRand << std::endl;         One.streak = (One.streak + 1);                 if (One.streak == 0 || One.streak == 1)         {          prize = bet;          int payBack = (bet + bet);          std::cout << One.name << "WINS! "<< bet << "+" << bet << "= $" << payBack << " New streak: " << One.streak << std::endl;         } else {          prize = (bet * One.streak);          std::cout << One.name << "WINS! "<< bet << "x" << One.streak << "=$" << prize << " New streak: " << One.streak << std::endl;         }        //add to players money        One.money = (One.money + prize);        } else {        //player loses        int iHadMoney = One.money;         One.money = (One.money - bet);         std::cout << One.name <<  " LOSER! " << iHadMoney << "-" << bet << "=" << One.money << " New streak: 0 \n";         One.streak = 0;       }  } };Machine CoinToss; //declair a coin tosserint main(){playGame();return 0;}void playGame(){//game loop    do{std::cout << "Coin Toss Casino, 0 = heads, 1 = tails \n\n";//display player statsstd::cout << One.name << " $" << One.money << std::endl;// player makes betint playerBet;int playerChoice;std::cout << One.name << " Make your bet!: ";std::cin >> playerBet;std::cout << "\n What's your choice?: ";std::cin >> playerChoice;CoinToss.takeBet(playerBet, playerChoice);if(One.money <= 0){gameOver = true;}system("pause");system("cls");}while(!gameOver);std::cout << "\n Game Over \n";system("pause");}



Game info:
player starts with 200 dollars, you make a bet then the coin is flipped.
when you win it doubles your money, if you get on a streak it will start multiplying your bet by how high of a streak of right calls you are on.

that's the game.

you can download it here if you want to try it:
http://27software.net/cpp/CoinTossCasino.zip


I had a few specific questions I am sure will pop back into my mind once I get back into it tomorrow morning. Overall I just want to hear if I am using classes correctly or not.

thanks
About your posts:
You should form new threads when you have a new line of questions. You're just tacking on and on to this thread like this is your personal help thread. Hopefully, a mod will split off this portion of the thread and give it a decent thread title ("Extreme newbie" is not a good thread title).

Looking at your code, I noticed right away the inconsistent indentation and spacing. It's annoying at the least, and problem causing over the longer run. The latter half of your code has absolutely no indentation. Your tab key break or something? Indentation overall is wonky, with some indentation at 2 spaces, some at 4, some at 5, etc. Keep it consistent. I use something called UniversalIndentGui to fix poorly indented source files. Get a program to help you indent if you need it. But keep sloppy code formatting in check. It's for your own benefit too.

Your program works. And so the syntax is correct. As to whether your use of classes was effective, the answer is no. The problem lies with your coupling the design to a very specific configuration. Let me give you a different example so you can understand the kind of fault your program shows.

int add5and7() { return 5 + 7;}
What's wrong here, from a design perspective? This function is extremely limited, that's what. This add function is only useful for adding 5 and 7. Great help this function is. Why not make this function take two arguments, x and y, and add those instead? It's definitely more useful to be get the sum of any two integers, right? But let's not even stop there. Why just two numbers? What if we wanted a third number? Or a fourth? So we design our function to be able to take an arbitrary number of integers and return the sum. But why integers only? Why not have some arbitrary number of something, like floats and doubles, as well as integers, and design our function to handle each appropriately? You'll end up eventually reaching the design of std::accumulate.

The reason I gave you this example is because you need to think about how usable your design is. How well does it express your logic and how usable is it in code? The generalized accumulate is far more usable than the rather useless adding 5 and 7 function. Similarly, consider your design, and how coupled it is to a specific configuration.

For example, you have bool gameOver = false. Let's assume you are representing an arcade in your code. Many machines, many players. is gameOver true or false? It depends on the machine, the type of game, the players involved, and so on, right? So having gameOver as some global variable is a bad idea. Someone needs to be in charge of determining whether the game is over or not (who?).

There isn't anything faultable in your design of the class Player. Although, hold back on the global variables. Player one shouldn't be hanging about in global space (does everyone need to know about this one specific player? or do they just need to know about the concept of a player?).

Your class Machine gets it wrong though. Your machine is a very specific kind of game, a cointoss machine. I'm not faulting you on this point, but just to note, it looks like you wanted to create a separation of the concept of a machine and a specific type of game in a machine. Your design currently couples the idea of a machine, to the idea of a cointoss game.

The real problem though, is that your machine refers to Player one. Whoa, wait a minute. Why does this general idea of a machine depend on a specific Player? You see, your machine and the player are really one giant blob divided up by syntax. For example, in the member function outCome, the machine doesn't notify the player that he has won. Instead, it directly modifies One.streak. First, a machine's kind of useless if it only functions with one very specific player. Why bother having a class if it can be used in only one specific configuration? If your machine needs to work with a player, it should be informed about the player currently using the machine.

Furthermore, a machine is not in control of the player. It should not be modifying his playing streak directly. It should not be taking his money directly. Let me give you an example. Let's say you went to the arcade and walked up to a game cabinet. On the screen, it displays, "insert coin". When you are ready to play, does the cabinet have robot arms that grab you, probe your pockets for change, and take what is needed? No. It waits. You decide if you want to add money. You give out money. The cabinet takes in money. And then the game starts. You can put money in a machine. A machine can accept it. Similarly, a machine can deposit money in a tray, you can grab it. But the transfer of money requires a pair of actions. Something a machine must do, and something the player must do. Your design is very coupled. You have a player, but the machine is in complete control of the player. Why bother keeping them separate?

I realize your program was for learning purposes only. But you did want feedback, so here it is. I hope you realize the issues discussed have nothing to do with syntax, and everything to do with design, which can be done with pen and paper.
Quote:Original post by oler1s
About your posts:
You should form new threads when you have a new line of questions. You're just tacking on and on to this thread like this is your personal help thread. Hopefully, a mod will split off this portion of the thread and give it a decent thread title ("Extreme newbie" is not a good thread title).


o1er1s I disagree with starting a new topic for every question I have, what sense does that make? other forums I've used for programming prefer things be kept in 1 thread to not spam the forum. I don't see your logic here.

It was the first time I used classes, obviously I am a little confused about them...

In your post it seems like you are offended by me, just pass my thread up next time. no need for negativity, just relax.

Overall your post was slightly informational, thanks.
Quote:o1er1s I disagree with starting a new topic for every question I have, what sense does that make?
It's like forming paragraphs. There's a central theme to your questions. So your form a new topic, describe the theme with a good title, and then post away. It's beneficial to the community because one can search the forums and come across your thread. But more importantly, it gets you answers faster. Ultimately, you rely on people coming across your thread and taking the time to answer it. Right now, your thread title doesn't describe your question, the first post question is completely different from the lastest question, and the previous posts are not relevant to what you discussed.

of course, you don't need to care. You can continue posting in this thread. But, you'll get fewer and fewer responses. You want help, but you take steps that undermine that goal. I'm pointing that out, and of course, you can dismiss my advice, but you're the one who suffers...

Quote:It was the first time I used classes, obviously I am a little confused about them...
Sure. Getting a good design isn't something you do right off the bat.

Quote:In your post it seems like you are offended by me, just pass my thread up next time. no need for negativity, just relax.
I'm not at all offended by you. I hope you aren't confusing my criticism of your code with a perceived negativity towards you.

I took some time to type up that post. It is discouraging to take the time to carefully give feedback and then be accused of negativity. Overall, your response seems to be rather dismissive of what I said. I'm not looking for thanks. I'm looking for some intellectual acknowledgement and response or flow of ideas, that suggest its worth giving you this feedback. I'm sure others have the same mindset.

So if you feel the urge to respond defensively, I suggest you don't. You'll derail your own thread and fight a losing battle. Just don't be so quick to accuse others of being negative, and do address the points I raised (or mull over them silently). So, moving on...

This topic is closed to new replies.

Advertisement