/* Improved Treasure Hunt game */

#include <lvp\gui_top.h>
#include <lvp\matrix.h>
#include <lvp\string.h>
#include <lvp\bool.h>
#include <lvp\random.h>

//--------------------------------------------------------------------------------
class ButtonClass {
public:
	ButtonClass(String Text, int X1,int Y1, int X2, int Y2);
	/*	Post: A button created with upper-left corner at X1,Y1 and 
	lower-right corner at X2,Y2 with Text centered in box           */
	void Paint();
	bool IsHit(int x, int y);
	/*	Post: true returned if and only if (x,y) is on the button */
private:
	int MyX1, MyY1, MyX2, MyY2;
	String MyText;
};
//--------------------------------------------------------------------------------
ButtonClass::ButtonClass(String Text, int X1, int Y1, int X2, int Y2)
	: MyText(Text), MyX1(X1), MyY1(Y1), MyX2(X2), MyY2(Y2)
/*	Post: Button created with upper-left corner at X1, Y1 and 
	lower	right corner at X2,Y2 with Text centered in box */
{
}
//--------------------------------------------------------------------------------
void ButtonClass::Paint()
{
	SetColor(BLACK);
	Rectangle(MyX1, MyY1, MyX2, MyY2);
	gotoxy((MyX1+MyX2)/2, 5+(MyY1+MyY2)/2);
	DrawCenteredText(MyText);
}
//--------------------------------------------------------------------------------
bool ButtonClass::IsHit(int x, int y)
/*	Post: true returned if and only if point (x, y) is on the button */
{
	return (x >= MyX1 && x <= MyX2 && y >= MyY1 && y <= MyY2);
}
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
class GridClass {
public:
	GridClass();
	void Paint();
	void MouseClick(int x, int y);
	void InitGrid();
private:
	const int GridDimension;    // # of Rows/columns in grid
	// Constants for board; must all differ
	const int Empty, EmptyPicked, Treasure, TreasurePicked;
	matrix<int> Board;    // Uses above constants
	int TreasureRow, TreasureCol;
	bool GameOver;
	int NumClicks;
	int BoxSize;       // Pixels per box
	int LeftMargin;    // Pixels from left
	int TopMargin;    // Pixels from top
	void XYToRowCol(int x, int y, int &Row, int &Col);
	void MarkBox(int Row, int Col, int BoxContents);
	ButtonClass QuitButton;
};
//--------------------------------------------------------------------------------
GridClass::GridClass()
	: GridDimension(5),
	Empty(0), EmptyPicked(-1), Treasure(1), TreasurePicked(2),
	Board(GridDimension,GridDimension,0),
	NumClicks(0), GameOver(false),
	BoxSize(GetMaxY()/2/GridDimension),    // Fill half of y-dimension
	LeftMargin((GetMaxX()-BoxSize*GridDimension)/2),
	TopMargin(GetMaxY()/4),
	QuitButton("I give up!",10,10,100,40)
{
	randomize();
	TreasureRow = random(GridDimension);
	TreasureCol = random(GridDimension);
	Board[TreasureRow][TreasureCol] = Treasure;
}

//--------------------------------------------------------------------------------
void GridClass::InitGrid()
/*	Post: Grid initialized for a new game */
{
	NumClicks = 0;
	GameOver = false;
	for (int Row=0; Row < GridDimension; Row++)
		for (int Col=0; Col < GridDimension; Col++)
			Board[Row][Col] = Empty;
	TreasureRow = random(GridDimension);
	TreasureCol = random(GridDimension);
	Board[TreasureRow][TreasureCol] = Treasure;
}
//--------------------------------------------------------------------------------
void GridClass::XYToRowCol(int x, int y, int &Row, int &Col)
/*	Post: Row and Column corresponding to x, y returned, 
	or -1 for if x, y is not on the board                                    */
{
	int DistFromLeft = x - LeftMargin;
	Col = (DistFromLeft+BoxSize)/BoxSize -1;
	int DistFromTop = y - TopMargin;
	Row = (DistFromTop+BoxSize)/BoxSize -1;
	if (Col < 0 || Col >= GridDimension ||
 	    Row < 0 || Row >= GridDimension) {
		Row = -1;
		Col = -1;
	}
}
//--------------------------------------------------------------------------------
void GridClass::MarkBox(int Row, int Col, int BoxContents)
/*	Post: Row, Col box in appropriate color */
{
	SetColor(BLACK);    // For outline
	SetFillColor(WHITE);
	if (BoxContents==EmptyPicked)
		SetFillColor(GRAY);
	else if (BoxContents==TreasurePicked)
		SetFillColor(RED);
	FilledRectangle(Col*BoxSize+LeftMargin, Row*BoxSize+TopMargin,
	(Col+1)*BoxSize+LeftMargin, 
	(Row+1)*BoxSize+TopMargin);
}
//--------------------------------------------------------------------------------
void GridClass::MouseClick(int x, int y)
{
	int Row, Col;
	if (QuitButton.IsHit(x,y)) {
		GameOver = true;
		Board[TreasureRow][TreasureCol] = TreasurePicked;
		Paint();    // To show the treasure square
		MessageBox("Come back again!", "Quit button clicked");
		PostQuitMessage(0);
	}	
	else {
		XYToRowCol(x, y, Row, Col);
		if (Row != -1 && Col != -1 && Board[Row][Col] != EmptyPicked) {
			if (Board[Row][Col] == Empty)
	   			Board[Row][Col] = EmptyPicked;
			else if (Board[Row][Col] == Treasure) {
				Board[Row][Col] = TreasurePicked;
				GameOver = true;
				Paint();    // To show treasure square
				if (MessageBoxYN("Play again?", "Game over")==1)
					InitGrid();
				else
					PostQuitMessage(0);
			}
			NumClicks++;
		}
		else
			MessageBeep(-1);
	}
}
//--------------------------------------------------------------------------------
void GridClass::Paint()
{
	QuitButton.Paint();
	SetColor(BLACK);

	int Row, Col;
	// Draw lines
	for (Col = 0; Col <= GridDimension; Col++)
		Line(LeftMargin+Col*BoxSize, TopMargin,
		LeftMargin+Col*BoxSize, 
		TopMargin+GridDimension*BoxSize);
	for (Row = 0; Row <= GridDimension; Row++)
		Line(LeftMargin, TopMargin+Row*BoxSize,
		LeftMargin+GridDimension*BoxSize, 
		TopMargin+Row*BoxSize);
	// Color in boxes
	for (Row=0; Row < GridDimension; Row++)
		for (Col=0; Col < GridDimension; Col++)
			MarkBox(Row,Col,Board[Row][Col]);
	// Display results
	if (GameOver==true) {
		gotoxy(20,GetMaxY()-60);
		DrawText("Game over!  Score = ");
		DrawText(NumClicks);
	}
}

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
class GuiClass {
public:
	GuiClass();
	void GuiMouseClick(int x, int y);    //Action if mouse click
	void GuiPaint();    // Repaint the entire window
	String Title();    // Title to display
private:
	GridClass Game;
};
//--------------------------------------------------------------------------------
GuiClass::GuiClass()
{
}
//--------------------------------------------------------------------------------
String GuiClass::Title()
{
	return ("Treasure hunt!");
}
//--------------------------------------------------------------------------------
void GuiClass::GuiMouseClick(int x, int y)
{
	Game.MouseClick(x, y);
}
//--------------------------------------------------------------------------------
void GuiClass::GuiPaint()
{
	Game.Paint();
}
//--------------------------------------------------------------------------------
#include <lvp\gui_bot.h>



