Templates? - Repetitious Coding for a Board Game

Started by
7 comments, last by Antheus 16 years, 10 months ago
Hello pros of gamedev, I'm making a board game called Omok (yes, the game in MapleStory). It's like a connect 5 game played with Go pieces. What I need help on is to eliminate the repetitive coding. The game has 225 game squares. Starting with the basics, every time I click on one, I need to write a snippet of code which to checks to see if there's already a piece played in that game square. For these 3-4 lines of code, however, I would have to copy and paste them 225 times and rename the bool variable names 225 times. I bet there's another way to do the same thing but with much less coding, but I don't know what it is. My friend said I might need a template to do this, but he's not sure. So what kind of coding is necessary to omit the repetitious coding? Edit: Oops, sorry for not including more info. I am developing this game using C++ on VS 2005 with .NET on a Microsoft Forms Application.
Advertisement
Oh wow... Yeah definitely don't store it as 225 different variables. I'm not sure if you've learned about arrays yet, but if I understand what you're doing right, what you want to do is create an array of bool's. Then you can loop through the check just create a function which takes the index and performs the check.

This would be the easiest way to implement it.
One solution is an array; however, we're using C++ so we'll use std::vector. Basically this is just a container; we are going to use it to hold the 255 bool values we need to represent our board. Here is some code you can run to see how it all works - it's not 100% "pristine" C++ but you should get the idea :)

#include <iostream>#include <vector>// This is our class that is going to handle our game board// We use a std::vector to hold our array and handle indexing ourselves using WhichIndexIsThisclass GameBoard{public:	// The constructor creates a container with 255 false entries in it	GameBoard() :  theBoard_(255, false) {}	// Attempt to place a piece, returns false is the location is already filled	// True otherwise	bool PlacePiece(int x, int y)	{		if(IsSlotFilled(x, y))			return false;		theBoard_[WhichIndexIsThis(x, y)] = true;		return true;	}private:	// Query function to check the container of locations	bool IsSlotFilled(int x, int y)	{		return theBoard_[WhichIndexIsThis(x, y)];	}	// Turns an x, y location into an index in our container 	int WhichIndexIsThis(int x, int y)	{		return 15*x + y;	}	// A container for our board	// False means that square is empty, true means it has a piece played        // One thing to bear in mind is vector<bool> has some "interesting" qualities, but it serves our purpose here	std::vector<bool> theBoard_;};int main(){	// Create our game board	GameBoard theGameBoard;	// An ever lasting loop we are going to use until we explicitly break out of it	for(;;)	{		// In practice you'd throw some error checking in here		int x, y;		std::cout << "Enter an x location (0-14): ";		std::cin >> x;		if(x < 0 || x > 14)			break;		// Error check here too!		std::cout << "Enter a y location (0-14): ";		std::cin >> y;		if(y < 0 || y > 14)			break;		// Check to see if we can place a piece		bool result = theGameBoard.PlacePiece(x, y);		// This resultant code you might want to have made part of GameBoard class, up to you		if(result)			std::cout << "Piece placed at " << x << ", " << y;		else			std::cout << "Location " << x << ", " << y << " already full, try again!";		// Flush for the new loop		std::cout << std::endl;	}	// All done	system("pause");	return 0;}


Boost probably has an array alternative (probably called something imaginative like boost::array). However, the code above should give you your first steps towards using the C++ libraries container classes.

Hope this helps,

Jim.
Be careful with vectors of bool as they are not supported by all compliers in the same way. There's more info here http://www.gotw.ca/publications/N1211.pdf, and probably if you search around a bit. If you do have problems just use a vector of chars or ints and then cast to bool.

I'm writing a book about How To Make An RPG, check it out! | Blog

Quote:Original post by Balaam
Be careful with vectors of bool as they are not supported by all compliers in the same way. There's more info here http://www.gotw.ca/publications/N1211.pdf, and probably if you search around a bit. If you do have problems just use a vector of chars or ints and then cast to bool.


A much better solution would be to use an enum:

enum BoardSquareState{  NoPiecePlayed,  BlackPiecePlayed,  WhitePiecePlayed};std::vector<BoardSquareState> Board(225);

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

Yup, in my defence I did put in a comment about vector<bool> having some interesting properties - but given this was a basic introduction to a container class I thought it unlikely it would be a big issue at this time - this code was purely intended as a first glance at containers (without having to worry about the pitfalls of proxy classes).

In a larger program I assumed that in fact it would be a vector<int>, or even a vector<shared_ptr<Player> > - although an enum would be good too, I just never use enums enough.

Jim.
1) Omok is Pente in the US. I love this game. Although a pente board is normally the same size a go board (19x19) - but that doesn't matter.

2) I'm assume your 225 squares are in a grid of 9x10 or 10x9?

If so then you would want to do something like this: (I'm assuming the enum option used previously)

using std::vector;typedef vector<vector<BoardSquareState> > OmokBoard;void InitializeOmokBoard(OmokBoard board){  board.clear();  board.resize(10);  for(i=0; i<10; ++i)    {    board.clear();    board.resize(9, NoPiecePlayed);    }}


of course, in your case that would probably be a member function instead of a function which takes an OmokBoard parameter, but you should get the idea.
Quote:Original post by Xai
1) Omok is Pente in the US. I love this game. Although a pente board is normally the same size a go board (19x19) - but that doesn't matter.

2) I'm assume your 225 squares are in a grid of 9x10 or 10x9?

If so then you would want to do something like this: (I'm assuming the enum option used previously)

*** Source Snippet Removed ***

of course, in your case that would probably be a member function instead of a function which takes an OmokBoard parameter, but you should get the idea.


First of all, your code doesn't work. Secondly, it's terribly inefficient.

Both of these problems have the same cause: you pass the board parameter by value. This means that the InitializeOmokBoard function will have a copy of the original board vector. In other words, every time the function is called, the memory of the original vector is copied over into a new variable, and then destroyed again as soon as the function exits. The function will accomplish no meaningful work, and wastes resources doing it.

At the very least, the board parameter should be passed by reference, i.e. OmokBoard& board. However, this is C++, so we may as well use the language properly:

enum OmokPiece{  NoPiece,  BlackPiece,  WhitePiece};class OmokBoard{// Constructorpublic:  OmokBoard() : Board(225)  {  }// Access to the boardpublic:  bool IsSquareOpen(unsigned square) const  {     return (Board[square] == NoPiece);  }  void PlaySquare(unsigned square, OmokPiece piece)  {     assert(IsSquareOpen(square)); // Shouldn't play on top of a used square!     Board[square] = piece;  }// Internal storageprotected:  std::vector<OmokPiece> Board;};



Obviously, this can be changed to use the vector-of-vectors approach easily enough. Even better, since the concept of the game board is now encapsulated in a class, the internal representation can be changed in any way we want without breaking other code, because the interface (the IsSquareOpen and PlaySquare functions) will always stay the same.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

Quote:Original post by Xai
2) I'm assume your 225 squares are in a grid of 9x10 or 10x9?


9x10 is 90 squares, no matter how you orient them.

The board in question is 15 x 15.

http://users.abac.com/MeriBird/Omok/rules.html

This topic is closed to new replies.

Advertisement