Cannot Access Class Functions and Variables

Started by
12 comments, last by Steve Elliott 16 years, 5 months ago
Refering to your first source posted:

A quick fix would be to send the obBoard as an argument to the getmove function

bool csInput::getmove(csBoard &obBoard){        // problem lines	iMovepiece = obBoard.iBoard[iSqr];	if (bPlaygame)		obBoard.update(iMovepiece, iMovefrom, iMoveto);	return(bPlaygame);}


in input.h:
...public:	csInput();	~csInput();	bool getmove(csBoard &obBoard);	void draw();...


and in main:
...do {	obBoard.draw();	obInput.draw();	bPlaygame = obInput.getmove(obBoard);}while(bPlaygame);...


Or you could "fix" it the crude way:
in input.h add this at the top:
#ifndef INPUT_H#define INPUT_H#include "board.h"extern csBoard obBoard;...

and in main, declare the obBoard object at file scope:
#include "board.h"#include "input.h"bool bPlaygame = true;csBoard obBoard;int main(){...


There is also a third way you could go abaout it:
give the csInput class constructor a csBoard argument, and store it as a pointer or reference in the csInput class

...#include "board.h"class csInput {	int iMove, iMovepiece, iMovefrom, iMoveto;	int iSqr, iConvertcol, iConvertrow;	char cCol, cRow;	bool bError, bPlaygame;	csBoard &obBoard;	public:		csInput(csBoard &myBoard);		~csInput();		bool getmove();		void draw();};// the csInput constructor definition:csInput::csInput(csBoard &myBoard)   : obBoard(myBoard){...}// and a small change in main:int main(){	csBoard obBoard;	csInput obInput(obBoard);...


The first or last solutions are the cleaner ones IMO.
Advertisement
Thanks guys. :-D

Can't help but think there's a better way of designing my classes - but that's ok for now.
Quote:Original post by Steve Elliott
Thanks guys. :-D

Can't help but think there's a better way of designing my classes - but that's ok for now.


Of course there is. :)

Updating the board is not logically a part of the process of getting input, so don't put that code there. The logical way to do things is to return the input from a function that "gets the input", and pass it along (as an argument) to the board. You can handle "is the game still going on?" by asking, not telling - there's no particularly good reason to communicate that state through a global. Now, between "input" and "board", which "knows" whether it's possible to keep playing? I would argue that the board would know, in general. So it makes sense to return that information from the update function.

Actually, it looks like the reason you want the Input class to "talk to" the board is to read its raw data, in order to figure out what piece is being moved - and then to tell the board that same information when you call update(). That's missing the point. Don't ask objects what they aren't specifically designed to tell you, and don't tell them things they know.

In fact, you probably don't need an input class at all. The board should be responsible for figuring out whether a particular move is legal, because it's the board which has the necessary information. Just get the input, and send it along. Design the input spec such that you don't need to know anything about the game logic - the board will check, and report whether the move was actually made, or was illegal.

It seems like you have some other fundamental misunderstandings, though - in particular, your classes look like they contain redundant data. The usual rules about scope apply: use a local when you can, and a class member when you have to (i.e. when it's actually logically "part of the object").

Consider dropping the Hungarian notation, too. It's actually seducing you into choosing worse "non-Hungarian-notation parts" of the variable names here. The positions on a Board aren't Boards; if you were to just write Board instead of csBoard and iBoard (not to mention pBoard and obBoard), this would stand out as kinda wrong - which it is.

// Splitting into separate files left as an exercise, of course. ;)// I am using old-style comments to represent the bits you need to fill in,// and regular ones to explain what is going on here.enum { ILLEGAL_MOVE, GAME_STILL_GOING, YOU_WIN, YOU_LOSE, DRAW } GameStatus;class Board {	// Don't make the data public! That's why we have this kind of	// organization in the first place; so we can *control* how 'cells'	// are modified.	int cells[64];	public:	// I assume the pointer pointed at the cells; that's totally redundant	// anyway - C++ lets you use the name of an array as if it were a	// pointer to the beginning element.	Board();	// From what is shown, it is extremely unlikely that you need a	// destructor at all.	GameStatus update(int from, int to);	void draw();};GameStatus Board::update(int from, int to) {	// Of course, "the complexity has to go somewhere":	// we need to put the code here that determines whether the move	// is legal, and what piece is being moved. But since 'cells' is	// OUR data, we are perfectly positioned to do so.	if (/* move is not legal - maybe split into another function */) {		return ILLEGAL_MOVE;	}	/* make the move */	/* return one of the other values accordingly */}void Board::draw() {	/* As before. */}#include <iostream>using namespace std;int main() {	Board board;	bool playing = true;	do {		board.draw();		int from = /* ask for input here */;		int to = /* ask for input here */;		switch (board.update(from, to)) {			case ILLEGAL_MOVE: /* complain */; break;			case GAME_STILL_GOING: break; /* nothing to do */			case YOU_WIN: /* report victory */; playing = false; break;			case YOU_LOSE: /* report defeat */; playing = false; break;			case DRAW: /* report stalemate */; playing = false; break;		}	} while (playing);}


Yes, It's Really That Easy(TM).
Nicely done. Thanks Zahlman, I guess I was over complicating it.

This topic is closed to new replies.

Advertisement