CFGReader

         Console display board(perfect)

A. Nth Edition
These classes are all base classes for console displays and on this edition I finished a board class.
In this edition I modified my dictionary so that it will save all words into a file named "dictionary.txt" and
restore them before next running. But I warn you not to try to open the file "dictionary.txt"!! If you think my
dictionary missed some words, then you can add them in file "readme.txt" which is located under same directory.
However, if you feel you don't like the words in my dictionary, you can replace the "dictionary.txt".
Do you want to know how I implement my dictionary? I used each node to represent a letter and there are two
advantage than a binary-search-tree: 
1. Space-saving: for example, the words "an" and "and" will be treated as two string and will store in two nodes.
However, in my dictionary, there are total four three nodes.
2. Fast-searching: BST will use string comparison every time when comparing. However, my dictionary will simply 
compare letters for every node.
B.The problem
How to display in console without using iostream class?
Do you like to play cross-word game, like scribble? Or card game, like rummy? Then this is the game!
C.The idea of program
¡¡
These classes are for our comp354 project which is going to make a little game like cross word.

Game Rules:

 

All the game rules are as is, unless a rule is changeable in the game option screen. For example the default size of the game board is 15 x 15, but it is changeable. Furthermore, all the original Scrabble rules apply, only certain functionalities from Rummy are added onto our game. The game and rules are not set in stone, they are simply a framework for us to start building our game. Any suggestions, changes and modifications to the game are welcomed.

 

 

//General Rules

¨¤ 2 ¨C 4 players. (Only humans, no A.I.)

¨¤ Game ends after a predetermined number of turns (hands played) or after a total score is reached.

¨¤ A player can hold a maximum of 7 letters and 7 cards.

¨¤ A player is randomly selected to start.

¨¤ According to the selected player to start, the rest of the rotation is clockwise.

¨¤ Board size 15 x 15.

¨¤ Starting cell H8.

¨¤ 100 Tiles or letters in the selection bag.

¨¤ One complete deck of cards is used.

¨¤ Players start with a hand of 7 letters and 7 Cards.

 

 

//At End of Every Turn

¨¤ At the end of every turn a player has to discard at least 1 letter and can discard up to 7 letters.

¨¤ At the end of every turn if a player has less then 7 cards, the player does not have to discard any cards. However, if the player has 7 cards then at the end of the turn the player is obligated to discard 1 card.

 

 

//Discarding Cards

¨¤Discarded letters are added back into the bag. More then likely the bag will be randomly sorted before giving letters to players.

¨¤ Discarded cards will be placed at the bottom of the pack. Since, players will only be getting one card at a time the cards will not have to be randomly sorted.

 

 

//At the Beginning of Every Turn

¨¤ At the beginning of every turn, the player picks up the number of letters missing for a total of 7 letters.

¨¤ At the beginning of every turn, the player gets 1 card.

 

 

//Scoring Points

¨¤ As in scrabble points are scored as follows,

Every letter has a pre-assigned value. Furthermore, the words formed can benefit from double letter, triple letter, double word and triple word cells.

 

Also, players can use a suite or group from their cards as a joker. The joker can be used to represent any desired card. For example, King + King + King = ¡®A¡¯ Thus the player would score 10 + 10 + 10 + The value of A = 30 + 2 = 32. Hence the player would get 32 points for the ¡®A¡¯. After the player¡¯s turn is over the cell on the board with the ¡®A¡¯ would return back to the original value of ¡®A¡¯ = 2. Thus, only the player using the Joker would benefit from using the Joker. The Joker can be used to represent any letter from ¡®A¡¯ to ¡®Z¡¯. A minimum of 3 cards is needed to make a suite or a group, thus the player can benefit from a maximum of two Jokers at once. The player can use the two Jokers together to represent 2 consecutive letters or be used on the same word. If a players manages to use 7 cards together to form a Joker then the player gets another bonus of 50 points, this is like a bingo for scrabble (Forming a 7 letter word).

 

 

 

Game Options:

 

Many of the following options can be configured by the user or assigned a random value (Fun Factor),

 

¨¤ The size of the board can be changed. (Default 15 x 15)

 

¨¤ The value of each letter can be changed.

 

¨¤ The quantity of each letter can be changed.

 

¨¤ The number of deck of cards can be changed (Minimum 1 deck of cards.)

 

¨¤ The cells that contain double letter, triple letter, double word and triple word can be changed.

 

¨¤ Some cells can be assigned as ¡®dead cells¡¯ hence no letter nor joker can be played on that cell.

 

 

Points:

 

English language editions of the game contain 100 letter tiles, in the following distribution: 2 "blank" tiles (scoring 0 points), 9 As (1 point), 2 Bs (3), 2 Cs (3), 4 Ds (2), 12 Es (1), 2 Fs (4), 3 Gs (2), 2 Hs (4), 9 Is (1), 1 J (8), 1 K (5), 4 Ls (1), 2 Ms (3), 6 Ns (1), 8 Os (1), 2 Ps (3), 1 Q (10), 6 Rs (1), 4 Ss (1), 6 Ts (1), 4 Us (1), 2 Vs (4), 2 Ws (4), 1 X (8), 2 Ys (4), and 1 Z (10).

 

 

Rummy

 Sample Game: The sample game only demonstrates what is happening with the hand of one player.

 

(Start)

Player 1:

1 2       3       4       5       6       7

------------------------------------------------------------------------------------------------------

Letters       A       D       T       S       C       S       W

Cards         3       4       5       3       2       Ace   King

 

¨¤ Forms the word ¡®What¡¯: ¡®W¡¯ +  ¡®Joker (Ace, 2, 3, 4, 5)¡¯ +  ¡®A¡¯ +  ¡®T¡¯

¨¤ Total Points = W = 4 +  H = 4 + 1 + 2 + 3 + 4 + 5 +  A =  1 + T = 1 = 25

 

Discard      ¨¤ Letters: S, D

         ¨¤ Cards: (Maximum 1, Minimum = 0) No Cards.

 

(2nd Turn)          * = new letter or card

Player 1:

1 2       3       4       5       6       7

------------------------------------------------------------------------------------------------------

Letters       *F      *P      *F      *Y     C       S       *V

Cards         3       King  *Queen

 

Discard      ¨¤ Letters: P, F, Y

         ¨¤ Cards: ------

 

(3rd Turn)          * = new letter or card

Player 1:

1 2       3       4       5       6       7

------------------------------------------------------------------------------------------------------

Letters       *S      *S      F       *T      C       S       V

Cards         3       King  Queen        *7

 

Discard      ¨¤ Letters: S, F

         ¨¤ Cards: ------

 

 

The game continues ¡­¡­¡­. 20 or so turns later

 

(20th Turn)       * = new letter or card

Player 1:

1 2       3       4       5       6       7

------------------------------------------------------------------------------------------------------

Letters       A       R       F       B       C       V       *V

Cards         3       King  Queen        7       Ace   9       *5

 

Discard      ¨¤ Letters: R, C

         ¨¤ Cards: (Has to discard one card) 9

 

(21st Turn)       * = new letter or card

Player 1:

1 2       3       4       5       6       7

------------------------------------------------------------------------------------------------------

Letters       A       *B      F       T       *S      V       *V

Cards         3       King  Queen        7       Ace   *Jack 5

 

¨¤ Forms the word ¡®fast¡¯: ¡®F¡¯ +  ¡®A¡¯ +  ¡®S¡¯ +  ¡®T¡¯

¨¤ Total Points = F = 4 +  A = 1 +  S =  1 + T = 1 = 7

 

Discard      ¨¤ Letters: V

         ¨¤ Cards: (Has to discard one card) 5

 

Etc¡­. Etc¡­.

¡¡
D.The major functions
E.Further improvement
F.File listing
1. tile.h
2. tile.cpp
3. tiles.h
4. tiles.cpp
5. token.h
6. token.cpp
7. tokens.h
8. tokens.cpp
9. RoverType.h
10. board.h
11. board.cpp
12. cell.h
13. cell.cpp
14. block.h
15. block.cpp
16. bag.h
17. bag.cpp
18. deck.h
19. deck.cpp
20. rack.h
21. rack.cpp
22. background.h
23. background.cpp
24. dictionary.h
25. dictionary.cpp
26. frame.h
27. frame.cpp
28. message.h
29. message.cpp
30. menu.h
31. menu.cpp
32. listener.h
33. listener.cpp
34. control.h
35. control.cpp
36. rummy.h
37. rummy.cpp
38. player.h
39. player.cpp
40. logo.h
41. logo.cpp
42. scoreboard.h
43. scoreboard.cpp
44. main.cpp (main)

¡¡

file name: tile.h

#ifndef TILE_H
#define TILE_H

#include "RoverType.h"

class CTile
{
protected:
	char ch;
	WORD ftColor;
	WORD bkColor;
public:
	void display(int x, int y);
	void setFontColor(WORD theColor){ftColor=theColor;}
	void setBKGroundColor(WORD theColor){ bkColor=theColor;}
	void setValue(char myCh) { ch=myCh;}
	char getValue(){ return ch;}
	CTile(char myCh=DefaultCharacter);
};

#endif
¡¡

file name: tile.cpp

#include "Tile.h"

HANDLE hOutPut=0;

CTile::CTile(char myCh)
{
	ftColor=DefaultFontColor;
	bkColor=DefaultBKGroundColor;
	setValue(myCh);
	if (hOutPut==0)
	{
		hOutPut=GetStdHandle(STD_OUTPUT_HANDLE);
	}
}

void CTile::display(int x, int y)
{
	COORD coord;
	coord.X=x;
	coord.Y=y;
	FillConsoleOutputAttribute(hOutPut, ftColor|bkColor, 1, coord, NULL);
	FillConsoleOutputCharacter(hOutPut, ch, 1, coord, NULL);
}



file name: tiles.h
#ifndef TILES_H
#define TILES_H

#include "tile.h"

class CTiles
{
private:
	CTile* tiles;
	int len;
	WORD ftColor;
	WORD bkColor;
	bool isVertical;
	void initialize();	
public:
	CTiles(const char* str);
	CTiles();
	virtual	~CTiles();
	void clear();
	void setDirection(bool beVertical){ isVertical=beVertical;}
	CTile& operator[](int index){return tiles[index];}
	void setFontColor(WORD theColor){ftColor=theColor;}
	void setBKGroundColor(WORD theColor){bkColor=theColor;}
	int getLength(){return len;}
	void display(int x, int y);
	void setValue(const char* str);
	void setLength(int size);
	void setNumber(int num);
	int getNumber();
};

#endif
¡¡
file name: tiles.cpp
#include "tiles.h"


int CTiles::getNumber()
{
	int total=0;
	int index=0, temp;
	while (index<len)
	{
		temp=tiles[index].getValue();
		if (temp>'9'||temp<'0')
		{
			break;
		}
		total=total*10+temp-'0';
		index++;
	}
	return total;
}



CTiles::CTiles()
{
	initialize();
}

void CTiles::initialize()
{
	len=0;
	tiles=NULL;
	isVertical=false;
	ftColor=DefaultFontColor;
	bkColor=DefaultBKGroundColor;
}

void CTiles::setNumber(int num)
{
	char buffer[10];
	itoa(num, buffer, 10);
	setValue(buffer);
}


CTiles::~CTiles()
{
	delete[]tiles;
}

void CTiles::setValue(const char* str)
{	
	//len=;
	setLength(strlen(str));
	for (int i=0; i<len; i++)
	{
		tiles[i].setValue(str[i]);
	}
}

void CTiles::clear()
{
	for (int i=0; i<len; i++)
	{
		tiles[i].setValue(0);
	}
}

CTiles::CTiles(const char* str)
{
	initialize();
	setValue(str);
}


void CTiles::display(int x, int y)
{
	for (int i=0; i<len; i++)
	{
		tiles[i].setFontColor(ftColor);
		tiles[i].setBKGroundColor(bkColor);
		if (!isVertical)
		{
			tiles[i].display(x+i, y);
		}
		else
		{
			tiles[i].display(x, y+i);
		}
	}
}

void CTiles::setLength(int size)
{
	if (len!=size)
	{
		len=size;
		delete[]tiles;
		tiles=new CTile[len] ;
	}
}
file name: token.h
#ifndef TOKEN_H
#define TOKEN_H

#include "block.h"


class CToken : public CBlock
{
protected:

public:	
	CToken(int num);
	CToken(char ch=DefaultCharacter);
	CToken& operator=(const CToken& theToken);
	int getNumber();
	void setNumber(int num);	
	void setSuit(int theSuit);
	int getSuit();
};

class CCardBack: public CToken
{
public:
	CCardBack();
};

#endif
¡¡
file name: token.cpp
#include "token.h"
#include "tile.h"

CToken& CToken::operator =(const CToken& theToken)
{	
	for (int i=0; i<3; i++)
	{
		for (int j=0; j<3; j++)
		{
			block[i][j].setValue(theToken.block[i][j].getValue());
		}
	}
	return *this;
}

void CToken::setSuit(int theSuit)
{
	block[0][0].setValue(theSuit);
	block[2][2].setValue(theSuit);
}

CToken::CToken(char ch):CBlock(3)
{
	block[1][1].setValue(ch);	
}

int CToken::getNumber()
{
	if (block[1][0].getValue()!=0)
	{
		return (block[1][0].getValue()-'0')*10+block[1][1].getValue()-'0';
	}
	if (block[1][1].getValue()>'9')
	{
		switch(block[1][1].getValue())
		{
			case 'J': return 11;
			case 'Q': return 12;
			case 'K': return 13;
			case 'A': return 14;
		}
	}
	return block[1][1].getValue()-'0';
}

void CToken::setNumber(int num)
{
	//in no condition, this would happen
	block[1][0].setValue(0);
	block[1][1].setValue(0);
	block[1][2].setValue(0);
	if (num>999)
	{
		return ;
	}
	if (num>99)
	{
		block[1][0].setValue(num/100+'0');
		block[1][1].setValue((num%100)/10+'0');
		block[1][2].setValue((num%100)%10 + '0');
	}
	else
	{
		if (num>9)
		{
			block[1][0].setValue(num/10+'0');
			block[1][1].setValue(num%10+'0');
		}
		else
		{
			block[1][1].setValue(num+'0');
		}
	}
}

CToken::CToken(int num)
{
	initialize();
	setNumber(num);
}

int CToken::getSuit()
{
	return block[0][0].getValue();
}

CCardBack::CCardBack()
{
	block[0][0].setValue(Club);
	block[0][2].setValue(Diamond);
	block[2][0].setValue(Heart);
	block[2][2].setValue(Spade);
	for (int i=0; i<3; i++)
	{
		for (int j=0; j<3; j++)
		{
			block[i][j].setBKGroundColor(DefaultCardBackBKGroundColor);
			block[i][j].setFontColor(DefaultCardBackFontColor);
		}
	}
}
file name: tokens.h
#ifndef TOKENS_H
#define TOKENS_H

#include "token.h"


class CTokens
{
protected:
	CToken* tokens;
	int len;
	int pos;
	WORD ftColor;
	WORD bkColor;
	WORD frColor;
	bool isVertical;//default is false
	void initialize();	
	bool pushToken(const CToken& token);
	bool popToken(CToken& token);
public:
	CTokens(int theLen=DefaultTokenLength);
	CTokens(const char* str);
	CToken& operator[](unsigned short index){ return tokens[index];}
	void setDirection(bool beVertical){isVertical=beVertical;}
	void setLength(int size);
	void setValue(const char* str);
	void setFontColor(WORD theColor);
	void setBKGroundColor(WORD theColor);
	void setFrameColor(WORD theColor);
	virtual ~CTokens();
	void display(int x, int y);
	//initialize the position of starting stack pos
	void setStackPos(int startPos=0){ pos=startPos;}
	void shuffle();
};

#endif
¡¡
¡¡
file name: tokens.cpp
#include "tokens.h"


void CTokens::shuffle()
{
	int j;
	for (int num=0; num<10; num++)//shuffle number
	{
		for (int i=0; i<len-1; i++)
		{
			/*
			int j=0;
			while (j<=i)
			{
				j=rand()%len;
			}
			*/
			j=rand()%len;
			CToken temp;
			temp=tokens[i];
			tokens[i]=tokens[j];
			tokens[j]=temp;
		}
	}
}

CTokens::CTokens(int theLen)
{
	initialize();
	setLength(theLen);
}

CTokens::CTokens(const char* str)
{
	initialize();
	setValue(str);
}

bool CTokens::popToken(CToken& token)
{
	if (pos!=0)
	{
		token= tokens[--pos];
		return true;
	}
	else
	{
		return false;
	}
}

bool CTokens::pushToken(const CToken& token)
{
	if (pos+1<len)
	{
		tokens[pos++]=token;
		return true;
	}
	else
	{
		return false;
	}
}

void CTokens::initialize()
{
	len=0;
	tokens=NULL;
	isVertical=false;
	ftColor=DefaultFontColor;
	bkColor=DefaultBKGroundColor;
	frColor=DefaultFrameColor;
	pos=0;
}

void CTokens::setBKGroundColor(WORD theColor)
{
	for (int i=0; i<len; i++)
	{
		tokens[i].setBKGroundColor(theColor);
	}
}

void CTokens::setFontColor(WORD theColor)
{
	for (int i=0; i<len; i++)
	{
		tokens[i].setFontColor(theColor);
	}
}

void CTokens::setFrameColor(WORD theColor)
{
	for (int i=0; i<len; i++)
	{
		tokens[i].setFrameColor(theColor);
	}
}

void CTokens::setLength(int size)
{
	if (len!=size)
	{
		delete []tokens;
		len=size;
		tokens=new CToken[len];
	}
}


void CTokens::setValue(const char* str)
{
	setLength(strlen(str));
	for (int i=0; i<len; i++)
	{
		tokens[i].setValue(str[i]);
	}
}

void CTokens::display(int x, int y)
{
	for (int i=0; i<len; i++)
	{
		if (!isVertical)
		{
			if (x>DefaultScreenWidth-5)
			{
				y+=4;
				x=0;
			}
			tokens[i].display(x, y);
			x+=4;
		}
		else
		{
			if (y>DefaultScreenHeight-5)
			{
				x+=4;
				y=0;
			}
			tokens[i].display(x, y);
			y+=4;
		}
	}
}

CTokens::~CTokens()
{
	delete [] tokens;	
}
file name: RoverType.h
#include <windows.h>

/*****************************nick****************************/

extern HANDLE hOutPut;


//the font color
#define  FTBLUE        FOREGROUND_BLUE 
#define	 FTGREEN       FOREGROUND_GREEN 
#define	 FTRED         FOREGROUND_RED 
#define	 FTPURPLE      FOREGROUND_BLUE|FOREGROUND_RED
#define	 FTGREY        FOREGROUND_BLUE|FOREGROUND_GREEN
#define	 FTBROWN	   FOREGROUND_RED|FOREGROUND_GREEN
#define	 FTWHITE       FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_RED
#define	 FTINTENSITY   FOREGROUND_INTENSITY

//the background color
#define	 BKBLUE        BACKGROUND_BLUE 
#define  BKGREEN       BACKGROUND_GREEN 
#define	 BKRED         BACKGROUND_RED 
#define	 BKPURPLE      BACKGROUND_BLUE|BACKGROUND_RED
#define	 BKGREY        BACKGROUND_BLUE|BACKGROUND_GREEN
#define	 BKBROWN	   BACKGROUND_RED|BACKGROUND_GREEN
#define	 BKWHITE       BACKGROUND_BLUE|BACKGROUND_GREEN|BACKGROUND_RED
#define	 BKINTENSITY   BACKGROUND_INTENSITY

#define DefaultFontColor           FTRED
#define DefaultBKGroundColor       BKWHITE
#define DefaultFrameColor          BKGREY
#define DefaultIndexFontColor      FTWHITE
#define DefaultIndexBKGroundColor  BKBLUE
#define DefaultIndexFrameColor     BKBLUE
#define DefaultHighLightFont	   FTINTENSITY

//board
#define DefaultBoardSize		   15
#define MaxBoardSize			   20
#define DefaultBoard_x             2
#define DefaultBoard_y             2

#define DefaultCharacter           0
#define DefaultTokenLength         7
#define MinimumLengthOfWord		   2
#define MaxInputBufferLength	   20

//background
#define DefaultScreenBKColor    BKGREEN
#define DefaultScreenFTColor    FTWHITE

#define DefaultScreenWidth        120
#define DefaultScreenHeight       70 //70

//inputArea
#define DefaultInputArea_x        4   //60
#define DefaultInputArea_y        37   //30
#define DefaultInputAreaHeight    5
#define DefaultInputAreaWidth     10
#define DefaultInputAreaBKColor   BKBLUE 
#define DefaultInputAreaFTColor   FTWHITE


#define LetterCount               26
#define MaxLengthOfWord			  20
#define DefaultInputPositionRow   30
#define DefaultInputPositionCol   30

//rack
#define DefaultSelectedBKGColor   BKINTENSITY
#define DefaultSelectedFontColor  FTBROWN

#define DefaultLetterRack_x             40
#define DefaultLetterRack_y             11
#define DefaultCardRack_x               40
#define DefaultCardRack_y               15


//card back color
#define DefaultCardBackBKGroundColor BKBROWN
#define DefaultCardBackFontColor     FTBLUE

//bag
#define BagTokenNumber    0
#define BagTokenPoints    1
#define DefaultNumberOfToken   100
//#define DefaultBlankTokenValue  255
//#define DefaultBlandTokenIndex  26

//coord of bag
#define DefaultBag_x      50    //60
#define DefaultBag_y      21    //25

//deck
#define DefaultPlayedDeck_x   45
#define DefaultPlayedDeck_y   21
#define DefaultPlayingDeck_x  40
#define DefaultPlayingDeck_y  21

/*
enum Suit
{Club=5, Diamond=4, Heart=3, Spade=6};
*/
#define Club           5
#define Diamond        4
#define Heart          3
#define Spade          6

//menu index
//Menu starts from 1 	
#define  WAITINGMENUCHOICE  0						
#define 	PICKCARD        1 
#define 	SELECTCARD     2
#define		SELECTLETTER   3 
#define 	TRADE		    4     
#define 	DISCARD         5  
#define 	FORMWORD	    6  
#define 	CANCEL		    7   
#define 	ENDROUND	   8 
#define 	QUIT		    9     

//message						
#define   INPUTPLACEWORDINFO  10
#define   INVALIDCARDSTRADING 11
#define   INPUTEXCHANGELETTER 12
#define  CANNOTEXCHANGELETTER 13
#define  INPUTDIRECTION       14
#define  INPUTROW             15
#define  INPUTCOL	           16
#define  INVALIDINDEXENTERED   17
#define  INVALIDWORDFORMED     18
#define  UNABLEPLACEWORD       19
#define  PLAYERALREADYPICKED   20
#define  PLAYERALREADYFORMED   21
#define  PLAYERALREADYTRADED   22
#define  INVALIDDICTIONARYFILENAME  23
#define  TRYUSEDEFAULTFILENAME  24
#define  INVALIDROWCOLNUMBER    25
#define  INPUTFIRSTPLAYERNAME   26
#define  INPUTSECONDPLAYERNAME  27
#define  PRESSANYKEYTOSTART     28
#define  JUSTASECOND            29

//logo 
#define DefaultLogo_x   15
#define DefaultLogo_y   10


//menu
#define  DefaultMenu_x  0
#define  DefaultMenu_y  MaxHeightScreen-20
#define DefaultMenuFontColor       FTGREY
#define DefaultMenuBKGroundColor   BKWHITE
#define DefaultMenuSelectedBKGroundColor BKRED

//frame
#define DefaultFrameBKColor    BKBLUE
#define DefaultFrameFTColor     FTPURPLE
#define DefaultFrameChar       '*'

//end of game winner's name
#define DefaultWinnerNameX    10
#define DefaultWinnerNameY    3

#define DefaultYouWinX        5
#define DefaultYouWinY        25

/****************************nick*****************************/

//***********************David Start***********************
#define MaxLengthScreen  80    //80//160
#define MaxHeightScreen  60    //40//81

#define CountOfButtons   18
#define MenuSpace         4

#define DefaultSystemMessageLength  50   //36   

#define DefaultEchoLength		20    //14
#define DefaultEchoX			41    //58
#define DefaultEchoY			32   //30

#define DefaultWordLength		10   //10
#define DefaultWordX			56   //58
#define DefaultWordY			29   //32

#define DefaultStringLength		20   //14
#define DefaultStringX			56   //58
#define DefaultStringY			26   //30

#define DefaultFrameHight			1

//***********************David End*************************

//***********************Charles Start*********************
#define DefaultScoreBoard_X   48    //40
#define DefaultScoreBoard_Y    4
#define DefaultScoreBoardWidth 10
#define DefaultSelectedPlayerBKColor FTGREY

//#define PlayerMaxWidth 10
//#define PlayerMaxLength 6
//#define BackgroundArea "          "
//#define FrameArea "                       "

//***********************Charles End***********************

file name: board.h
#ifndef BOARD_H
#define BOARD_H

#include "cell.h"

class CBoard
{
private:
	int curRow, curCol;
	int headRow, headCol;
	int exchRow, exchCol;
	bool isVer;
	bool isFirst;
	char buffer[MaxBoardSize];
	bool doFindStr(int& exchangedIndex);
	void setStartPoint();
	void getFirstStr(int& exchangedIndex);

	int findHead(int startRow, int startCol, bool isVertical);
	int score;
protected:
	CCell** board;
	int boardWidth;
	void initialize(int size);
public:
	CBoard(int size=DefaultBoardSize);
	void setSize(int size);
	void display(int x, int y);
	char getValue(int r, int c);
	void setValue(int r, int c, char ch);
	void setValue(char** matrix);
	bool placeWord(int r, int c, const char* str, bool isVertical, int index);
	void update(bool rollBack=false);
	void show();
	char* getNextStr(int& exchangedIndex);
	char* verifyStr(int& exchangedIndex);
};

#endif
¡¡
file name: board.cpp
#include "board.h"

void CBoard::initialize(int size)
{
	boardWidth=0;
	board=NULL;
	isFirst=true;
	setSize(size);
	for (int i=0; i<=size; i++)
	{
		for (int j=0; j<=size; j++)
		{
			if (i==0||j==0)
			{
				board[i][j].setBKGAll(DefaultIndexFontColor, DefaultIndexBKGroundColor);
								
				if (i!=0)
				{
					board[i][j].setNumber(i-1, false);
				}
				if (j!=0)
				{
					board[i][j].setNumber(j-1, true);
				}
			}
		}
	}
}

void CBoard::setValue(char** matrix)
{
	for (int i=1; i<=boardWidth; i++)
	{
		for (int j=1; j<=boardWidth; j++)
		{
			board[i][j].setValue(matrix[i-1][j-1]);
		}
	}
}

void CBoard::setSize(int size)
{
	if (boardWidth!=size)
	{
		if (board!=NULL)
		{
			for (int i=0; i<=boardWidth; i++)
			{
				delete []board[i];			
			}
		}
		delete[] board;
		boardWidth=size;
		board=new CCell*[size+1];
		for (int i=0; i<=size; i++)
		{			
			board[i]=new CCell[size+1];
		}		
	}
}
		
void CBoard::show()
{
	display(DefaultBoard_x, DefaultBoard_y);
}

CBoard::CBoard(int size)
{
	initialize(size);	
}

void CBoard::setValue(int r, int c, char ch)
{
	board[r+1][c+1].setValue(ch);
}

char CBoard::getValue(int r, int c)
{
	return board[r+1][c+1].getValue();
}

void CBoard::display(int x, int y)
{	
	for (int i=0; i<=boardWidth; i++)
	{
		for (int j=0; j<=boardWidth; j++)
		{
			board[i][j].display(x+2*j, y+i*2);
		}

	}
}

void CBoard::update(bool rollBack)
{
	int row=curRow, col=curCol;
	while (board[row][col].getValue()!=0)
	{
		if (rollBack)
		{
			if (!board[row][col].getStatus())
			{				
				board[row][col].setValue(DefaultCharacter);
			}
		}	
		board[row][col].setFontColor(DefaultFontColor);
		board[row][col].setStatus(true);//anyway, it must be true
		if (isVer)
		{
			row++;
		}
		else
		{
			col++;
		}
		if (row>boardWidth||col>boardWidth)
		{
			break;
		}
	}
}

void CBoard::setStartPoint()
{
	headRow=curRow;
	headCol=curCol;
	if (isVer)
	{
		headRow=findHead(headRow, headCol, isVer);
	}
	else
	{
		headCol=findHead(headRow, headCol, isVer);
	}	
}

char* CBoard::verifyStr(int& exchangedIndex)
{
	setStartPoint();
	getFirstStr(exchangedIndex);
	isFirst=true;//set back!!!
	return buffer;
}


void CBoard::getFirstStr(int& exchangedIndex)
{
	int row=headRow, col=headCol, pos=0;
	char chr;
	while ((chr=board[row][col].getValue())!=0) 
	{
		//buffer[pos]=board[row][col].getValue();
		buffer[pos]=chr;
		if (exchRow==row&&exchCol==col)
		{
			exchangedIndex=pos;
		}
		pos++;
		if (isVer)
		{
			row++;
		}
		else
		{
			col++;
		}
		if (row==boardWidth||col==boardWidth)
		{
			break;
		}
	}
	/*
	//this is means that it is only a single char word
	//try to search if it is possible to have other word
	if (pos==1)
	{
		pos=0;
		if (isVer)
		{
			col=findHead(row, col, !isVer);
			do//the boardWidth is one more than the real size 
			{
				buffer[pos]=board[row][col].getValue();
				if (row==exchRow&&col==exchCol)
				{
					exchangedIndex=pos;
				}
				col++;
				pos++;
				if (col>boardWidth)
				{
					break;
				}
			} while (board[row][col].getValue()!=0);
			headRow++;
			//buffer[pos]='\0';
		}
		else
		{
			row=findHead(row, col, !isVer);
			do
			{
				buffer[pos]=board[row][col].getValue();
				if (row==exchRow&&col==exchCol)
				{
					//find the index of exchanged letter
					exchangedIndex=pos;
				}
				row++;
				pos++;
				if (row>boardWidth)
				{
					break;
				}
			}while (board[row][col].getValue()!=0);
			//buffer[pos]='\0';
			headCol++;
		
		}

	}
	*/

	buffer[pos]='\0';
}

char* CBoard::getNextStr(int& exchangedIndex)
{	
	if (isFirst)
	{
		setStartPoint();
		isFirst=false;
		getFirstStr(exchangedIndex);
		return buffer;//the original one will always return
	}
	if (doFindStr(exchangedIndex))
	{
		return buffer;
	}
	else
	{
		return NULL;
	}
}

bool CBoard::doFindStr(int& exchangedIndex)
{
	int row=headRow, col=headCol, pos=0;
	exchangedIndex=-1;
	if (headRow>boardWidth||headCol>boardWidth)
	{
		return false;
	}
	if (board[row][col].getValue()==0)
	{
		return false;
	}
	if (isVer)
	{
		//skip the old word placed by others
		if (board[row][col].getStatus())
		{
			headRow++;
			return doFindStr(exchangedIndex);
		}
		col=findHead(row, col, !isVer);//the crossing direction
		do//the boardWidth is one more than the real size 
		{
			buffer[pos]=board[row][col].getValue();
			if (row==exchRow&&col==exchCol)
			{
				exchangedIndex=pos;
			}
			col++;
			pos++;
			if (col>boardWidth)
			{
				break;
			}
		} while (board[row][col].getValue()!=0);
		buffer[pos]='\0';
		headRow++;
		if (pos>MinimumLengthOfWord)
		{
			return true;
		}
		else
		{				
			return doFindStr(exchangedIndex);
		}
	}
	else
	{
		if (board[row][col].getStatus())
		{
			headCol++;
			return doFindStr(exchangedIndex);
		}
		row=findHead(row, col, !isVer);
		do
		{
			buffer[pos]=board[row][col].getValue();
			if (row==exchRow&&col==exchCol)
			{
				//find the index of exchanged letter
				exchangedIndex=pos;
			}
			row++;
			pos++;
			if (row>boardWidth)
			{
				break;
			}
		}while (board[row][col].getValue()!=0);
		buffer[pos]='\0';
		headCol++;
		if (pos>=MinimumLengthOfWord)
		{
			return true;
		}
		else
		{			
			return doFindStr(exchangedIndex);
		}
	}
}

//to do
int CBoard::findHead(int startRow, int startCol, bool isVertical)
{
	if (isVertical)
	{
		while (startRow>=0) //because the coord is starting from 1
		{
			if (board[startRow][startCol].getValue()==0)
			{
				break;
			}
			startRow--;
		}
		return startRow+1;
	}
	else
	{
		while (startCol>=0)
		{
			if (board[startRow][startCol].getValue()==0)
			{
				break;
			}
			startCol--;
		}
		return startCol+1;
	} 
}



bool CBoard::placeWord(int r, int c, const char* str, bool isVertical, int index)
{
	int row=r+1, col=c+1, pos=0;
	curRow=row;
	curCol=col;
	isVer=isVertical;
	if (index!=-1)//do have a special exchanged letter!
	{
		exchRow=curRow;
		exchCol=curCol;
		isVertical?exchRow+=index:exchCol+=index;//the coord of exchanged letter
	}
	else
	{
		exchRow=exchCol=-1;//this ensures no coord will match
	}
	while (str[pos]!='\0')
	{
		if (board[row][col].getValue()==0)
		{
			board[row][col].setValue(str[pos]);
			board[row][col].setFontColor(DefaultHighLightFont);
			board[row][col].setStatus(false);
			pos++;
		}
		else
		{
			//the starting position cannot be occupied
			if (pos==0)
			{
				return false;
			}
			if (pos<=index)//if index==-1 never execute here
			{
				//update new exchanged letter coord
				isVertical?exchRow++:exchCol++;
			}
		}
		if (isVertical)
		{
			row++;
		}
		else
		{
			col++;
		}
		if (row>boardWidth||col>boardWidth)//the bound is boardWidth
		{			
			return str[pos]=='\0';
		}
	}
	return true;
}


		



file name: cell.h
#ifndef CELL_H
#define CELL_H

#include "block.h"

//this class is specially used by CBoard
class CCell: public CBlock
{
protected:
	bool isOld;
public:
	CCell();
	void setStatus(bool beOld);
	bool getStatus();
	void setNumber(int num, bool atBottom);//special for index bar
	void setBKGAll(WORD theFont, WORD theBKG);
};

#endif
¡¡
file name: cell.cpp
#include "cell.h"

CCell::CCell():CBlock(1)
{
	isOld=true;
}

void CCell::setStatus(bool beOld)
{
	isOld=beOld;
}

bool CCell::getStatus()
{
	return isOld;
}

void CCell::setNumber(int num, bool atBottom)
{
	int row=0, col=1;
	if (atBottom)
	{
		row=1;
		col=0;
	}
	if (num>9)
	{
		block[row][0].setValue(num/10+'0');
		block[row][1].setValue(num%10+'0');
	}
	else
	{
		block[row][col].setValue(num+'0');
	}
}

void CCell::setBKGAll(WORD theFont, WORD theBKG)
{
	for (int i=0; i<2; i++)
	{
		for (int j=0; j<2; j++)
		{
			block[i][j].setBKGroundColor(theBKG);
			block[i][j].setFontColor(theFont);
		}
	}
}
¡¡
file name: block.h
#ifndef BLOCK_H
#define BLOCK_H

#include "tile.h"

class CBlock
{
protected:
	CTile** block;
	int width;
	void initialize();
public:
	CBlock(int size=1);
	void setLength(int size);
	void setValue(char myCh);
	char getValue();
	void setFrameColor(WORD theColor);
	void setFontColor(WORD theColor);
	void setBKGroundColor(WORD theColor);
	void display(int x, int y);
};

#endif
¡¡
¡¡
file name: block.cpp
#include "block.h"

CBlock::CBlock(int size)
{
	initialize();
	setLength(size);
}

void CBlock::initialize()
{
	block=NULL;
	width=0;
}

void CBlock::setLength(int size)
{
	width=size;
	block=new CTile*[size+1];
	for (int i=0; i<=size; i++)
	{
		block[i]=new CTile[size+1];
		for (int j=0; j<=size; j++)
		{
			if (i==size||j==size)
			{
				block[i][j].setBKGroundColor(DefaultFrameColor);
			}
		}
	}
}

void CBlock::setValue(char myCh)
{
	block[(width-1)/2][(width-1)/2].setValue(myCh);
}

void CBlock::setBKGroundColor(WORD theColor)
{
	for (int i=0; i<width; i++)
	{
		for (int j=0; j<width; j++)
		{
			block[i][j].setBKGroundColor(theColor);
		}
	}
}

void CBlock::setFontColor(WORD theColor)
{
	for (int i=0; i<width; i++)
	{
		for (int j=0; j<width; j++)
		{
			block[i][j].setFontColor(theColor);
		}
	}
}

void CBlock::setFrameColor(WORD theColor)
{
	for (int i=0; i<=width; i++)
	{
		for (int j=0; j<=width; j++)
		{
			if (i==width||j==width)
			{
				block[i][j].setBKGroundColor(theColor);
			}
		}
	}
}

char CBlock::getValue()
{
	return block[(width-1)/2][(width-1)/2].getValue();
}

void CBlock::display(int x, int y)
{
	for (int i=0; i<=width; i++)
	{
		for (int j=0; j<=width; j++)
		{
			block[i][j].display(x+j, y+i);
		}
	}
}
file name: bag.h
#ifndef BAG_H
#define BAG_H

#include "RoverType.h"
#include "tokens.h"

class CBag: public CTokens
{
private:
	static int tokenData[26][2];
	int tokenLeft;
	CToken bag;
public:
	CBag();
	int getTokenPoint(char ch);
	//int getBlankNumber();
	//void setBlankNumber(int newNum);	
	int getTokenNumber(char ch);
	void setTokenPoint(char ch, int newPoint);
	void setTokenNumber(char ch, int newNumber);	
	void show();//only show the number of left tokens
	bool removeLetter(CToken& result);
	bool removeLetter(char ch, CToken& result);
	bool addLetter(const CToken& target);
};

#endif
file name: bag.cpp
#include "bag.h"

/*
 2 "blank" tiles (scoring 0 points), 9 As (1 point), 2 Bs (3), 2 Cs (3), 4 Ds (2), 
 12 Es (1), 2 Fs (4), 3 Gs (2), 2 Hs (4), 9 Is (1), 1 J (8), 1 K (5), 4 Ls (1), 
 2 Ms (3), 6 Ns (1), 8 Os (1), 2 Ps (3), 1 Q (10), 6 Rs (1), 4 Ss (1), 6 Ts (1),
 4 Us (1), 2 Vs (4), 2 Ws (4), 1 X (8), 2 Ys (4), and 1 Z (10).

  */

int CBag::tokenData[26][2]=
{
	{9,  1}, // As (1 point),
	{2,  3},// Bs (3),
	{2,  3},// Cs (3), 
	{4,  2},// Ds (2), 
	{12, 1},//Es (1),
	{2,  4},// Fs (4),
	{3,  2},//Gs (2), 
	{2,  4},//Hs (4),
	{9,  1},// Is (1), 
	{1,  8},// J (8), 
	{1,  5},// K (5), 
	{5,  1},// Ls (1),
	{2,  3},// Ms (3),
	{6,  1},//Ns (1), 
	{8,  1},// Os (1),
	{2,  3},// Ps (3), 
	{1,  9},// Q (10),
	{6,  1},// Rs (1),
	{4,  1},// Ss (1), 
	{6,  1},// Ts (1),
	{5,  1},// Us (1),
	{2,  4},// Vs (4),
	{2,  4},// Ws (4),
	{1,  8},// X (8),
	{2,  4},// Ys (4), and 
	{1,  9}// Z (10).
//	{2,   0}//blank token valued 255
};


bool CBag::removeLetter(char ch, CToken& result)
{
	for (int i=CTokens::pos-1; i>=0; i--)
	{
		if (CTokens::tokens[i].getValue()==ch)
		{
			//swap, this is INEFFICIENT!
			result=CTokens::tokens[i];
			CTokens::tokens[i]=CTokens::tokens[CTokens::pos-1];
			CTokens::tokens[CTokens::pos-1]=result;
			return removeLetter(result);
		}
	}
	return false;
}


bool CBag::removeLetter(CToken& result)
{
	if (tokenLeft==0)
	{
		return false;
	}
	result=tokens[--tokenLeft];
	return true;
}

bool CBag::addLetter(const CToken& target)
{
	if (tokenLeft==DefaultNumberOfToken)
	{
		return false;
	}
	tokens[tokenLeft++]=target;
	return true;
}



CBag::CBag():CTokens(DefaultNumberOfToken)
{
	bag.setNumber(DefaultNumberOfToken);
	tokenLeft=DefaultNumberOfToken;
	int index=0;
	for (int i=0; i<26; i++)
	{
		int j=0;
		while (j<tokenData[i][BagTokenNumber])
		{
			/*
			if (i!=26)
			{
				tokens[index].setValue(i+'A');
			}
			else
			{
				tokens[index].setValue((char)DefaultBlankTokenValue);
			}
			*/
			tokens[index].setValue(i+'A');
			j++;//always
			index++;
		}
	}
	shuffle();
	CTokens::pos=DefaultNumberOfToken;
}

void CBag::show()
{
	bag.setNumber(tokenLeft);
	bag.display(DefaultBag_x, DefaultBag_y);
}

int CBag::getTokenNumber(char ch)
{
	return tokenData[ch-'A'][BagTokenNumber];
}

/*
int CBag::getBlankNumber()
{
	return tokenData[DefaultBlandTokenIndex][BagTokenNumber];
}

void CBag::setBlankNumber(int newNum)
{
	tokenLeft+= newNum-tokenData[DefaultBlandTokenIndex][BagTokenNumber];
	//????
	tokenData[DefaultBlandTokenIndex][BagTokenNumber]=newNum;
}
*/

void CBag::setTokenNumber(char ch, int newNum)
{
	tokenLeft+=newNum-tokenData[ch-'A'][BagTokenNumber];
	tokenData[ch-'A'][BagTokenNumber]=newNum;
}

void CBag::setTokenPoint(char ch, int newPoint)
{
	tokenData[ch-'A'][BagTokenPoints]=newPoint;
}

int CBag::getTokenPoint(char ch)
{
	return tokenData[ch-'A'][BagTokenPoints];
}






file name: deck.h
#ifndef DECK_H
#define DECK_H	

#include "tokens.h"

class CDeck: public CTokens
{
protected:
	CCardBack deckBack;
	bool faceDown;
	int x, y;
public:
	CDeck(bool isEmpty=false);
	void setCoord(int newX, int newY);
	void showHand();
    int  numOfCards();
	bool addCard(const CToken& card);
	bool removeCard(CToken& token);	
	void setFace(bool faceDown=true);
	void display(int x, int y);
	void show();
};

#endif

file name: rack.h
#ifndef CRACK_H
#define CRACK_H
#include "tokens.h"
#include "rummy.h"
//#include "control.h"

class CControl;

class CRack: public CTokens
{
	friend class CControl;
protected:
	char buffer[9];
	CToken cardBuf[7];
	char exchanged;	
	static CRummy rummy;
	CToken empty;
    int selected[7];
	int selectedCount;
	int x,y;
	int exchangedIndex;
	int points;
	bool canRollBack;
public:
	CRack();
	bool selectToken(int index, bool isLetter=true);//success return true
	void addToken(const CToken& token);
	//void showRack(int x,int y);
	void addExchanged(char exch);
	void updateRack(bool rollBack=false);
	bool canAdd() { return selectedCount>0;}
	char* exportWord();
	bool verifyCards();
	void setCoord(int theX, int theY){ x=theX; y=theY;}
	void removeToken(int index, CToken& result);
	void show();
};

#endif
file name: rack.cpp
#include "rack.h"


CRummy CRack::rummy;

CRack::CRack():CTokens(7)
{
	selectedCount=7;//means empty at beginning
	for (int i=0; i<7; i++)
	{
		selected[i]=i;
	}
	exchangedIndex=-1;//means no exchanged!!!
	x=y=points=0;
	canRollBack=true;
}


bool CRack::selectToken(int index, bool isLetter)
{
	if (selectedCount==7)
	{
		return false;
	}
	for (int i=0; i<selectedCount; i++)
	{
		if (index==selected[i])
		{
			return false;//means repeat selecting
		}
	}
	selected[selectedCount]=index;
	if (isLetter)
	{
		buffer[selectedCount]=tokens[index].getValue();	
	}
	else
	{
		cardBuf[selectedCount]=tokens[index];
	}
	tokens[index].setBKGroundColor(DefaultSelectedBKGColor);	
	tokens[index].setFontColor(DefaultSelectedFontColor);
	selectedCount++;
	show();
	return true;
}

//this is rackCard method
bool CRack::verifyCards()
{
	if (selectedCount==0)
	{
		return false;
	}
	return rummy.verify(cardBuf, selectedCount, points);
}

void CRack::addToken(const CToken& newToken)
{
	if (selectedCount>0)
	{
		tokens[selected[--selectedCount]]=newToken;
	}
}


void CRack::addExchanged(char ch)
{
	exchanged=ch;
	exchangedIndex=selectedCount;
}


void CRack::show()
{
	display(x,y);
}


void CRack::removeToken(int index, CToken& result)
{
	result=tokens[index];
	tokens[index]=empty;
}

char* CRack::exportWord()
{
	//insert the exchanged letter
	if (exchangedIndex!=-1)
	{
		for (int i=selectedCount; i>exchangedIndex; i--)
		{
			buffer[i]=buffer[i-1];
		}
		buffer[exchangedIndex]=exchanged; //insert the char
		buffer[selectedCount+1]='\0';
	}
	else
	{
		buffer[selectedCount]='\0';
	}
	return buffer;
}

void CRack::updateRack(bool rollBack)
{
	if(rollBack)
	{
		if (canRollBack)
		{
			for(int i=0; i<selectedCount;i++)
			{
				tokens[selected[i]].setBKGroundColor(DefaultBKGroundColor);
				tokens[selected[i]].setFontColor(DefaultFontColor);			
			}
			selectedCount=0;
			//exchangedIndex=-1;
		}
	}
	else
	{
		for(int i=0; i<selectedCount;i++)
		{
			tokens[selected[i]].setBKGroundColor(DefaultBKGroundColor);
			tokens[selected[i]].setFontColor(DefaultFontColor);	
			tokens[selected[i]]=empty;			
		}        
		//exchangedIndex=-1;//should I do at this moment?
	}
	exchangedIndex=-1;
	points=0;
	show();
}
file name: background.h
//background
#ifndef BACKGROUND_H
#define BACKGROUND_H

#include "RoverType.h"

class CBackGround
{
protected:
	int width, height;
	int row, col;
	WORD ftColor;
	WORD bkColor;
public:
	CBackGround(int theRow=0, int theCol=0, int
		theHeight=DefaultScreenHeight, int theWidth=DefaultScreenWidth);
	void setFontColor(WORD theFTColor){ ftColor=theFTColor;}
	void setBKGroundColor(WORD theBKColor){bkColor=theBKColor;}
	void show();
};

class CInputArea: public CBackGround
{
public:
	CInputArea();
};

#endif
¡¡
¡¡
file name: background.cpp
#include "background.h"



CBackGround::CBackGround(int theRow, int theCol, int theHeight, int theWidth)
{
	COORD coord;
	bkColor=DefaultScreenBKColor;
	ftColor=DefaultScreenFTColor;
	width=theWidth;
	height=theHeight;
	row=theRow;
	col=theCol;
	if (hOutPut==0)
	{
		hOutPut=GetStdHandle(STD_OUTPUT_HANDLE);
		SetConsoleTitle("WordRover");
		CONSOLE_CURSOR_INFO cursorInfo;
		cursorInfo.bVisible=false;
		cursorInfo.dwSize=50;
		SetConsoleCursorInfo(hOutPut, &cursorInfo);
		coord.X = DefaultInputPositionCol;
		coord.Y = DefaultInputPositionRow;
		SetConsoleCursorPosition(hOutPut, coord);
	}
	show();
	//SetConsoleTextAttribute(hOutPut, bkColor|ftColor);
}


void CBackGround::show()
{
	char ch=0;
	COORD coord;
	for (int r=row; r<row+height; r++)
	{
		for (int c=col; c<col+width; c++)
		{	
			coord.X=c;
			coord.Y=r;
			FillConsoleOutputAttribute(hOutPut, ftColor|bkColor, 1, coord, NULL);
			FillConsoleOutputCharacter(hOutPut, ch, 1, coord, NULL);
		}
	}
}

CInputArea::CInputArea():CBackGround(DefaultInputArea_y, DefaultInputArea_x,
		DefaultInputAreaHeight, DefaultInputAreaWidth)
{
	COORD coord;
	coord.X = DefaultInputArea_x;
	coord.Y = DefaultInputArea_y;
	bkColor=DefaultInputAreaBKColor;
	ftColor=DefaultInputAreaFTColor;
	CONSOLE_CURSOR_INFO cursorInfo;
	cursorInfo.bVisible=true;
	cursorInfo.dwSize=50;
	SetConsoleCursorInfo(hOutPut, &cursorInfo);
//	coord.X = DefaultInputPositionCol;
//	coord.Y = DefaultInputPositionRow;
	SetConsoleCursorPosition(hOutPut, coord);
	show();
}
file name: dictionary.h
#ifndef DICTIONARY_H
#define DICTIONARY_H

#include "RoverType.h"


struct Letter
{
	char ch;
	Letter* next;
	Letter* son;
	bool end;
};

class CDictionary
{
private:
	Letter* root[52];
	Letter* current;
	Letter* findBrother(Letter* brother, char ch);
	Letter* createLetter(char ch);
	Letter* addSon(char ch);
	int indexOf(char ch);
	bool caseSensitive;
	void change2Capital(char* target, char* source);
	void deleteWord(Letter* node);
public:
	bool addWord(char* str);
	bool findWord(char* str);
	bool readFile(const char* fileName);
	void saveFile(const char* fileName);
	void setCaseSensitive(bool isCaseSensitive);
	CDictionary(bool isCaseSensitive=true);
	~CDictionary();
};

#endif
¡¡
¡¡
file name: dictionary.cpp
#include <stdio.h>
#include "dictionary.h"

const int MinimumLengthOfStr=2;
extern char* defaultInputFileName;

void CDictionary::change2Capital(char* target, char* source)
{
	char* tgt=target, *src=source;
	do
	{
		*tgt=toupper(*src);
		tgt++;
		src++;
	}while (*src!='\0');
	*tgt='\0';
}

void writeWord(Letter* node, char* str, int level, FILE* stream)
{
	if (node==NULL)
	{
		return;
	}
	
	str[level]=node->ch;
	if (node->end)
	{
		str[level+1]='\0';
		fputs(str, stream);
		fputc(',', stream);
	}
	//depth-first-search!!???
	Letter*son=node->son;
	writeWord(son, str, level+1, stream);

	Letter*brother=node->next;
	writeWord(brother, str, level, stream);
}


void CDictionary::saveFile(const char* fileName)
{
	void writeWord(Letter* node, char* str, int level, FILE* stream);

	char buffer[MaxLengthOfWord];
	Letter* node;
	int level=0;
	FILE* stream;
	stream=fopen(fileName, "w");
	if (stream==NULL)
	{
		return ;
	}
	for (int i=0; i<LetterCount+LetterCount; i++)
	{
		node=root[i];
		writeWord(node, buffer, level, stream);
		fputs("\n", stream);

	}
	fclose(stream);
}

bool CDictionary::readFile(const char* fileName)
{
	char buffer[MaxLengthOfWord];
	char*ptr=buffer;
	char ch;
	int counter=0;
	FILE* stream;
	stream=fopen(fileName, "r");
	if (stream==NULL)
	{
		return false;
	}
	while (!feof(stream))
	{
		ch=fgetc(stream);
		if (isalpha(ch)&&ptr!=buffer+MaxLengthOfWord-1)
		{
			if (!caseSensitive)
			{
				*ptr=toupper(ch);
			}
			else
			{
				*ptr=ch;
			}
			ptr++;
		}
		else
		{
			*ptr='\0';
			if (ptr!=buffer)
			{
				if (strlen(buffer)>=MinimumLengthOfStr)
				{
					addWord(buffer);					
				}
				ptr=buffer;
			
			}
			//else remain the same ptr.
		}
	}
	fclose(stream);
	return true;
}


bool CDictionary::findWord(char* str)
{
	char* ptr=str;
	char buffer[MaxLengthOfWord];
	if (str==NULL)
	{
		return false;
	}

	if (!caseSensitive)
	{		
		ptr=buffer;
		change2Capital(buffer, str);
	}
	Letter* hold;
	int index;
	//not empty string
	if (ptr!=NULL)
	{
		index = indexOf(*ptr);
		if (index==-1)
		{
			return false;
		}
		current=root[index];		
		ptr++;

		if (current->son==NULL)
		{
			//if string is a one-letter string
			if (*ptr=='\0')
			{
				//and there is a one-letter word in dictionary
				return current->end;
			}
			else
			{
				return false;
			}
		}
		hold=current;//
		current=current->son;
		
		while (*ptr!='\0')
		{				
			current=findBrother(current, *ptr);
			if (current==NULL)
			{
				return false;
			}
			if (current->ch==*ptr)
			{
				hold=current;
				current=current->son;
			}
			else
			{
				//not found
				return false;
			}
			ptr++;
		} 
		return hold->end;
	}
	//in my dictionary there is no empty string word
	return false;
}
	

Letter* CDictionary::createLetter(char ch)
{
	Letter* ptr=new Letter;
	if (ptr==NULL)
	{
		printf("no memory available any more!\n");
		exit(1);
	}
	ptr->ch=ch;
	ptr->end=false;
	ptr->next=NULL;
	ptr->son=NULL;
	return ptr;
}

//ch is not '\0'
Letter* CDictionary::findBrother(Letter* brother, char ch)
{
	Letter* hold=brother;
	if (brother==NULL)
	{
		return NULL;
	}
	while (hold->next!=NULL)
	{
		if (hold->ch==ch)
		{
			break;
		}
		hold=hold->next;
	}
	return hold;
}

Letter* CDictionary::addSon(char ch)
{
	//the word ends
	if (ch=='\0')
	{
		current->end=true;		
	}
	else
	{
		//need a new son
		if (current->son==NULL)
		{
			current->son=createLetter(ch);
			current=current->son;
		}
		else
		{
			//current->son is not NULL!!!
			current=findBrother(current->son, ch);
			//check if the current is the node
			if (current->ch!=ch)
			{
				current->next=createLetter(ch);	
				current=current->next;//add brother
			}	
			//else return current;!!!
		}
	}
	return current;
}


//add word actually add letter by letter till NULL, nonsense!
bool CDictionary::addWord(char* str)
{
	char* ptr=str;
	int index;
	if (*ptr!='\0')
	{
		index=indexOf(*ptr);
		if (index==-1)
		{
			return false;
		}
		current=root[index];		
		do
		{
			ptr++;
			current=addSon(*ptr);			
		} while (*ptr!='\0');
		return true;
	}
	return false;
}

CDictionary::CDictionary(bool isCaseSensitive)
{
	caseSensitive=isCaseSensitive;

	for (int i=0; i<LetterCount; i++)
	{
		root[i]=new Letter;
		root[i]->ch='A'+i;
		root[i]->next=NULL;
		root[i]->son=NULL;
		root[i]->end=false;
	}
	if (caseSensitive)
	{
		for (i=0; i<LetterCount; i++)
		{
			root[i+LetterCount]=new Letter;
			root[i+LetterCount]->ch='a'+i;
			root[i+LetterCount]->next=NULL;
			root[i+LetterCount]->son=NULL;
		}
	}
	readFile(defaultInputFileName);
}

int CDictionary::indexOf(char ch)
{
	if (ch-'A'>=0&&ch-'Z'<=0)
	{
		return ch-'A';
	}
	if (ch-'a'>=0&&ch-'z'<=0)
	{
		return ch-'a'+LetterCount;
	}
	return -1;
}

void CDictionary::deleteWord(Letter* node)
{
	if (node!=NULL)
	{
		Letter*brother=node->next;
		Letter*son=node->son;
		delete node;
		deleteWord(brother);
		deleteWord(son);
	}
}


CDictionary::~CDictionary()
{
	saveFile(defaultInputFileName);
	for (int i=0; i<LetterCount+LetterCount; i++)
	{		
		deleteWord(root[i]);
	}
}



¡¡
file name: frame.h
#ifndef FRAME_H
#define FRAME_H

#include "RoverType.h"
#include "tile.h"

class CFrame
{
private:
	int x,y;
	int width, height;
	CTile pixel;
	CTile inside;
	char ch;
	WORD ftColor;
	WORD bkColor;
public:
	void setFrame(int x, int y, int height, int width);
	void show();
	void setChar(char chr){ ch=chr;}
	void setFTColor(WORD theColor){ftColor=theColor; }
	void setBKColor(WORD theColor){bkColor=theColor;}
};
#endif
¡¡
¡¡
¡¡
file name: frame.cpp
#include "frame.h"

//the height and width are the one of region, not that of frame
void CFrame::setFrame(int theX, int theY, int theHeight, int theWidth)
{
	ch=DefaultFrameChar;
	//change to that of frame
	////must at least 1!!!
	if (theX*theY==0||theX+theWidth+2>DefaultScreenWidth||theY+theHeight+2>DefaultScreenHeight)
	{
		return;
	}
	x=theX-1;
	y=theY-1;
	height=theHeight+2;
	width=theWidth+2;
	pixel.setValue(ch);
	pixel.setBKGroundColor(DefaultFrameBKColor);
	pixel.setFontColor(DefaultFrameFTColor);
	inside.setValue(0);
	inside.setBKGroundColor(DefaultScreenBKColor);
}


void CFrame::show()
{
	for (int r=0; r<height; r++)
	{
		for (int c=0; c<width; c++)
		{
			if (r==0||r==height-1||c==0||c==width-1)
			{
				pixel.display(x+c, y+r);
			}
			else
			{
				inside.display(x+c, y+r);
			}
		}
	}
	/*
	for (int i=0; i<height; i++)
	{
		pixel.display(x, y+i);
		pixel.display(x+width-1, y+i);
	}
	for (i=0; i<width; i++)
	{
		pixel.display(x+i, y);
		pixel.display(x+i, y+height-1);
	}
	*/
}
¡¡
file name: message.h
#include "RoverType.h"
#include "tiles.h"
#include "frame.h"

const int MsgStrCount=30;

class CMessage: public CTiles
{
private:
	CTiles tiles[MsgStrCount];
	CTile echo[DefaultEchoLength];
	CTile word[DefaultWordLength];
	CTiles string;

	int currentEcho;
	int currentWord;

	CFrame frameSystemMessage;
	CFrame frameEcho;
	CFrame frameWord;
	//CFrame frameString;
	void initialize();
public:
	CMessage();	
	void setCursor(int x=DefaultEchoX, int y=DefaultEchoY);
	void showMessage(int msgID);//the id should be define in rovertype.h
	void clearAll();
	void showInt(int num);
	void showChar(char ch);
	void clearEcho();
	void showWord(char ch);
	void clearWord();
	//void showString(char *);
	//void clearString();
	void show();
	void clear(int x, int y, int len);
	

};


/*

*/

¡¡
¡¡
file name: message.cpp
#include "message.h"
//#include "background.h"

//CInputArea  D;


char* msgStr[MsgStrCount]=
{
	"CHOOSE FROM MENU BY PRESSING 1-9",
	"PICK A CARD",
	"ENTER THE CARD INDEX TO BE SELECTED",
	"ENTER THE LETTER INDEX TO BE SELECTED",
	"TRADE		  ",
	"DISCARD       ",
	"FORMWORD	  ",
	"CANCEL		  ",
	"ENDROUND	  ",
	"QUIT		  ",
	"INPUTPLACEWORDINFO ",
	"INVALIDCARDSTRADING",
	"EXCHANGE FOR WHICH LETTER?",
	"CANNOT EXCHANGE FOR THE LETTER",
	"ENTER THE DIRECTION <H/V> TO PLACE THE WORD",
	"ENTER THE ROW NUMBER TO PLACE THE WORD",
	"ENTER THE COLUMN NUMBER TO PLACE THE WORD",
	"INDEX ENTERED IS INVALID",
	"WORD FORMED IS INVALID",
	"UNABLE TO PLACE THE WORD",
	"PLAYER ALREADY PICKED A CARD",
	"PLAYER ALREADY FORMED A WORD",
	"PLAYER ALREADY TRADED",
	"INVALIDDICTIONARYFILENAME",
	"TRYUSEDEFAULTFILENAME",
	"INVALID ROW/COLUMN NUMBER",
	"ENTER FIRST PLAYER'S NAME",
	"ENTER SECOND PLAYER'S NAME",
	"PRESS ANY KEY TO START", 
	"JUST A SECOND! LET'S GO!"
};


void CMessage::setCursor(int x, int y)
{
	COORD coord;
	frameEcho.show();
	coord.X=x;
	coord.Y=y;
	CONSOLE_CURSOR_INFO cursorInfo;
	cursorInfo.bVisible=true;
	cursorInfo.dwSize=50;
	SetConsoleCursorInfo(hOutPut, &cursorInfo);
	SetConsoleCursorPosition(hOutPut, coord);
}

void CMessage::initialize()
{
	currentEcho=currentWord=0;
	frameSystemMessage.setFrame(DefaultInputArea_x, DefaultInputArea_y,DefaultFrameHight, 
		DefaultSystemMessageLength);
	frameEcho.setFrame(DefaultEchoX, DefaultEchoY,DefaultFrameHight, DefaultEchoLength);
	frameWord.setFrame(DefaultWordX, DefaultWordY,DefaultFrameHight, DefaultWordLength);
	//frameString.setFrame(DefaultStringX, DefaultStringY,DefaultFrameHight, 
	//	DefaultStringLength);
}

void CMessage::show()
{
	frameSystemMessage.show();
	frameWord.show();
	frameEcho.show();
	setCursor();
	clearEcho();
	//frameString.show();
}

CMessage::CMessage()
{
	for (int i=0; i<MsgStrCount; i++)
	{
		tiles[i].setValue(msgStr[i]);
	}
	initialize();
	show();
//	this->frameSystemMessage.setFrame(DefaultInputArea_x, DefaultInputArea_y,DefaultFrameHight, DefaultSystemMessageLength);
//	this->frameSystemMessage.show();
//	this->frameEcho.setFrame(DefaultInputArea_x, DefaultInputArea_y+3,DefaultFrameHight, DefaultSystemMessageLength);
//	this->frameEcho.setFrame(DefaultEchoX, DefaultEchoY,DefaultFrameHight, DefaultEchoLength);
//	this->frameEcho.show();
//	this->frameWord.setFrame(DefaultWordX, DefaultWordY,DefaultFrameHight, DefaultWordLength);
//	this->frameWord.show();
//	this->frameString.setFrame(DefaultStringX, DefaultStringY,DefaultFrameHight, DefaultStringLength);
//	this->frameString.show();
}

void CMessage::showMessage(int msgID)
{
	this->clear(DefaultInputArea_x, DefaultInputArea_y, DefaultSystemMessageLength);
	tiles[msgID].display(DefaultInputArea_x, DefaultInputArea_y);
}

void CMessage::clear(int x, int y, int len)
{
	CTiles whiteTiles;
	whiteTiles.setLength(len);
	whiteTiles.display(x, y);
}

void CMessage::showChar(char ch)
{
	if (currentEcho+1==DefaultEchoLength)
	{
		clearEcho();
		currentEcho=0;
	}
	echo[currentEcho].setValue(ch);
	echo[currentEcho].display(DefaultEchoX+currentEcho, DefaultEchoY);
	currentEcho++;
}

void CMessage::showInt(int anInt)
{
	char buffer[6];
	int len;
	itoa(anInt, buffer, 10);
	len=strlen(buffer);
	if (currentEcho + len+1>DefaultEchoLength)
	{
		clearEcho();
		currentEcho = 0;
	}
	for (int i=0; i<len; i++)
	{
		echo[currentEcho].setValue(buffer[i]);
		echo[currentEcho].display(DefaultEchoX+currentEcho, DefaultEchoY);
		currentEcho++;
	}

	
	//echo[this->currentEcho].setValue(char(anInt));
	//this->echo[this->currentEcho].display(DefaultEchoX+this->currentEcho, DefaultEchoY);
}

void CMessage::clearEcho()
{
	this->clear(DefaultEchoX, DefaultEchoY, DefaultEchoLength);
	currentEcho=0;
}

void CMessage::showWord(char anChar)
{
	//this->currentWord = ( this->currentWord + 1) % DefaultWordLength;
	word[this->currentWord].setValue(anChar);
	word[this->currentWord].display(DefaultWordX+currentWord, DefaultWordY);
	currentWord++;
}

void CMessage::clearWord()
{
	this->clear(DefaultWordX, DefaultWordY, DefaultWordLength);
}

/*
void CMessage::showString(char* str)
{
	clear(DefaultStringX, DefaultStringY, DefaultStringLength);
	string.setValue(str);
	string.display(DefaultStringX, DefaultStringY);
}

void CMessage::clearString()
{
	clear(DefaultStringX, DefaultStringY, DefaultStringLength);
}
*/
void CMessage::clearAll()
{
	currentEcho=currentWord=0;
	clearEcho();
	clearWord();
//	clearString();
}


file name: menu.h
#ifndef MENU_H
#define MENU_H

#include "tiles.h"

class CMenu
{
private:
	CTiles buttons[CountOfButtons];
	int selected;
public:
	//constructor
	CMenu();
//iButton--the index of button, theColor--the color value
	bool setFontColor(int iButton, WORD theColor);
//iButton--the index of button, theColor--the color value
	bool setBKGroundColor(int iButton, WORD theColor);
	void displayH(int x=0, int y=MaxHeightScreen-2);
	void displayV(int x=MaxLengthScreen-15, int y=MaxHeightScreen-9);
	void setSelected(int index);
	void show();
};

#endif

/*
private:
	CTile* tiles;
	int len;
	WORD ftColor;
	WORD bkColor;
	bool isVertical;
	void initialize();	
public:
	CTiles(const char* str);
	CTiles();
	~CTiles();
	void setDirection(bool beVertical){ isVertical=beVertical;}
	CTile& operator[](int index){return tiles[index];}
	void setFontColor(WORD theColor){ftColor=theColor;}
	void setBKGroundColor(WORD theColor){bkColor=theColor;}
	int getLength(){return len;}
	void display(int x, int y);
	void setValue(const char* str);
//	void setValue(const char* str) const;
	void setLength(int size);
*/
¡¡
file name: menu.cpp
#include "Menu.h"

const char * ButtonName[CountOfButtons] = { "1", "Pick Card    ", 
											"2", "Select Card  ",
					                        "3", "Select Letter",
											"4", "Trade        ",
											"5", "Discard      ",
											"6", "Form Word    ",
											"7", "Cancel       ",
											"8", "End  Round   ",
											"9", "Quit         "};


CMenu::CMenu()
{
	for (int i=0; i<CountOfButtons; i++)
	{
		this->buttons[i].setValue(ButtonName[i]);
		this->buttons[i].setBKGroundColor(DefaultMenuBKGroundColor);
		if (i%2 == 0)
		{
			this->buttons[i].setFontColor(FTRED);
		}
		else
		{
			this->buttons[i].setFontColor(DefaultMenuFontColor);
		}
	}
	selected=-1;
}

void CMenu::setSelected(int index)
{
	if (selected!=index&&index!=-1)
	{
		//restore first
		if (selected!=-1)
		{
			setBKGroundColor(selected, DefaultMenuBKGroundColor);
		}
		setBKGroundColor(index, DefaultMenuSelectedBKGroundColor);
		selected=index;
		show();
	}
}


void CMenu::show()
{
	displayH(DefaultMenu_x, DefaultMenu_y);
}

//iButton--the index of button, theColor--the color value
bool CMenu::setFontColor(int iButton, WORD theColor)
{
	this->buttons[iButton*2+1].setFontColor(theColor);
	return true;
}
	
//iButton--the index of button, theColor--the color value
bool CMenu::setBKGroundColor(int iButton, WORD theColor)
{
	this->buttons[iButton*2+1].setBKGroundColor(theColor);
	return true;
}

void CMenu::displayH(int x, int y)
{
	for (int i=0; i<CountOfButtons; i++)
	{
		this->buttons[i].display(x, y);

		if ( i==7 )
			y++, x=0;
		
		if (i%2==1 && i!=0 && i!=7)
			x += strlen(ButtonName[i]) + MenuSpace;
		else
			x++;
	}
}

void CMenu::displayV(int x, int y)
{
	int xb=x;
	for (int i=0; i<CountOfButtons; i++)
	{
		this->buttons[i].display(x, y);
		if ( i%2 == 1 )
			y+=2, x=xb;
		else 
			x++;
	}
}
file name: listener.h
#ifndef   LISTENER_H
#define   LISTENER_H

#include "RoverType.h"

class CListener
{
protected:
	static HANDLE hOut;
	static char buffer[MaxInputBufferLength];
	void initialize();
public:
	CListener();
	int listenMenu();
	int listenInt();
	int listenIndex();
	char listenChar();
	char* listenStr();//must ended by entering return
};

#endif

¡¡
file name: listener.cpp
#include "listener.h"

const int MaxIntLen=3;

HANDLE CListener::hOut=NULL;
char CListener::buffer[MaxInputBufferLength];

CListener::CListener()
{
	initialize();
}

void CListener::initialize()
{
	hOut=GetStdHandle(STD_INPUT_HANDLE);
	
}

int CListener::listenMenu()
{
	DWORD temp;
	SetConsoleMode(hOut, 0);
	ReadConsole(hOut, buffer, 1, &temp, NULL);
	return buffer[0]-'0';
}

char CListener::listenChar()
{
	DWORD temp;
	SetConsoleMode(hOut, 0);
	ReadConsole(hOut, buffer, 1, &temp, NULL);
	if (buffer[0]>='a'&&buffer[0]<='z')
	{
		return buffer[0];
	}
	else
	{
		if (buffer[0]>='A'&&buffer[0]<='Z')
		{
			return buffer[0];
		}
		else
		{
			return '\0';
		}
	}
}

int CListener::listenIndex()
{
	return listenMenu();
}

//better name
int CListener::listenInt()
{	
	DWORD temp;
	int result=0;
	SetConsoleMode(hOut, ENABLE_LINE_INPUT);
	ReadConsole(hOut, buffer, MaxIntLen, &temp, NULL);

	for (int i=0; i<temp; i++)
	{
		if (buffer[i]>'9'||buffer[i]<'0')
		{
			break;//error!!
		}
		result=result*10 + buffer[i]-'0';
	}
	return result;
}

char* CListener::listenStr()
{
	DWORD temp;
	SetConsoleMode(hOut, ENABLE_LINE_INPUT);
	ReadConsole(hOut, buffer, MaxInputBufferLength, &temp, NULL);
	buffer[temp-1]='\0';
	return buffer;
}

file name: control.h
#ifndef  CONTROL_H
#define  CONTROL_H
#include "roverType.h"
#include "listener.h"
#include "player.h"
#include "message.h"
#include "bag.h"
#include "deck.h"
#include "board.h"
#include "menu.h"
#include "dictionary.h"
#include "scoreboard.h"
#include "logo.h"
#include "background.h"


class CControl
{
private:
	char playerName[2][DefaultScoreBoardWidth+1];
	char* fileName;
	CScoreBoard scoreBoard;
	CBackGround backGround;
	CLogo logo;
	CListener listener;
	CPlayer player[2];
	CMessage message;
	CMenu  menu;
	CBag bag;
	int turn;
	void initPlayGame();
	void initStartGame();
	void initEndGame();
	int doFormWord();
	int doSelectCard();
	int doSelectLetter();
	int doTrade();
	int doPickCard();
	int doDiscard();
	int doEndRound();
	int doCancel();
	void fillUpRack();
	int listenMenu();
	int listenInt();
	char listenChar();
	int listenIndex();
	void showMessage(int msgID);
	void nextTurn();
	void calculateScore();
	void getPlayerName(int index);
	void refresh();
public:
	void setInputFile(char* inputFileName);
	void startLogo();
	void startGame();
	void playGame();
	void endGame();
	void show();
	CControl();
};


#endif
¡¡
file name: control.cpp
#include "control.h"
#include "scoreboard.h"

CDeck playingDeck, playedDeck(true);
CScoreBoard scoreBoard;
CBoard board;
CDictionary dictionary(false);
char* defaultInputFileName="dictionary.txt";


void CControl::playGame()
{
	//bool quit=false;
	int choice;
	initPlayGame();
	choice=listenMenu();
	while (true)
	{
		switch (choice)
		{
		case SELECTCARD:
			choice =doSelectCard();			
			break;
		case SELECTLETTER:
			choice=doSelectLetter();
			break;
		case TRADE:
			if (!player[turn].traded&&!player[turn].formed)
			{				
				choice =doTrade();
			}
			else
			{
				showMessage(PLAYERALREADYTRADED);
				choice=CANCEL;
			}
			break;
		case PICKCARD:
			if (!player[turn].picked)
			{
				choice=doPickCard();
			}
			else
			{
				showMessage(PLAYERALREADYPICKED);
				choice=CANCEL;
			}
			break;
		case FORMWORD:
			if (!player[turn].formed)
			{
				choice=doFormWord();
			}
			else
			{
				showMessage(PLAYERALREADYFORMED);
				choice=CANCEL;
			}
			break;
		case QUIT:
			return;
			break;
		case ENDROUND:
			choice=doEndRound();
			break;
		case CANCEL:
			choice =doCancel();
			break;
		case DISCARD:
			choice =doDiscard();
			break;
		default:
			choice=listenMenu();
			break;
		}
	}
}

void CControl::endGame()
{
	backGround.show();
	if (scoreBoard.getTotalScore(0)>scoreBoard.getTotalScore(1))
	{
		logo.showString(playerName[0], DefaultWinnerNameX, DefaultWinnerNameY);
		logo.showString("YOU WIN", DefaultYouWinX, DefaultYouWinY);
	}
	else
	{
		if (scoreBoard.getTotalScore(0)<scoreBoard.getTotalScore(1))
		{
			logo.showString(playerName[1], DefaultWinnerNameX, DefaultWinnerNameY);
			logo.showString("YOU WIN", DefaultYouWinX, DefaultYouWinY);
		}
		else
		{
			logo.showString("GOODBYE", DefaultYouWinX, DefaultYouWinY);
		}
	}
	Sleep(3000);
}

void CControl::calculateScore()
{
	int points=0, index=0, score=0;
	char* ptr;
	int pos=0;
	//index=player[turn].rackLetter.exchangedIndex;
	points=player[turn].rackCard.points;
	message.clearEcho();
	while ((ptr=board.getNextStr(index))!=NULL)
	{
		if (!dictionary.findWord(ptr))
		{
			continue;
		}
		pos=0;		
		
		while (ptr[pos]!='\0')
		{
			message.showChar(ptr[pos]);
			if (pos!=index)
			{
				score+=bag.getTokenPoint(ptr[pos]);
			}
			else
			{
				score+=bag.getTokenPoint(ptr[pos])+points;
			}
			pos++;
		}	
		message.showChar(',');
	}
	//here to set score to score board
	//this is for debug only

	scoreBoard.setPlayerScore(score);
	scoreBoard.show();
	//refresh();
	//this is for debug only
	
}

void CControl::refresh()
{
	backGround.show();
	show();
}

int CControl::doDiscard()
{
	CToken temp;
	//show prompt message, this is no cancel operation
	if (player[turn].rackCard.selectedCount>0)
	{
		for (int i=0; i<player[turn].rackCard.selectedCount; i++)
		{
			temp=player[turn].rackCard.tokens[player[turn].rackCard.selected[i]];
			playedDeck.addCard(temp);
		}		
		player[turn].rackCard.updateRack();
		player[turn].rackCard.canRollBack=false;
		playedDeck.show();
		player[turn].rackCard.show();
	}
	if (player[turn].rackLetter.selectedCount>0)
	{
		for (int i=0; i<player[turn].rackLetter.selectedCount; i++)
		{
			temp=player[turn].rackLetter.tokens[player[turn].rackLetter.selected[i]];
			bag.addLetter(temp.getValue());
		}
		bag.shuffle();
		bag.show();
		player[turn].rackLetter.updateRack();
		player[turn].rackLetter.canRollBack=false;
		player[turn].rackLetter.show();
	}
	message.clearWord();
	return listenMenu();
}


int CControl::doCancel()
{	
	player[turn].rackCard.updateRack(true);
	player[turn].rackLetter.updateRack(true);
	player[turn].traded=false;
	player[turn].formed=false;
	player[turn].show();
	board.update(true);
	message.clearAll();
	
	//board.show();
	return listenMenu();
}

int CControl::doEndRound()
{
	showMessage(ENDROUND);
	board.update();

	player[turn].rackLetter.updateRack();
	player[turn].rackCard.updateRack();
	fillUpRack();
	//player[turn].show();
	
	//set scoreboard to show current player
	nextTurn();
	
	//update all view to show
	//fillUpRack();
	player[turn].traded=false;
	player[turn].formed=false;
	player[turn].picked=false;
	player[turn].rackCard.canRollBack=true;
	//player[turn].rackCard.points=0;
	player[turn].rackLetter.canRollBack=true;
	scoreBoard.switchCurrentPlayer();
	message.clearAll();
	show();
	return listenMenu();
}

void CControl::nextTurn()
{
	turn=(turn+1)%2;//next player
}


int CControl::doFormWord()
{
	int row=-1, col=-1;
	int index;
	char dir;
	showMessage(FORMWORD);
	char* ptr;
	ptr=player[turn].rackLetter.exportWord();
	//this should be done after the word is placed on the board
	/*
	if (!dictionary.findWord(ptr))
	{
		showMessage(INVALIDWORDFORMED);
		return CANCEL;
	}
	*/

	//showMessage(INPUTPLACEWORDINFO);
	showMessage(INPUTROW);
	row=listenInt();
	if (row>=DefaultBoardSize-1||row<0)
	{
		showMessage(INVALIDROWCOLNUMBER);
		return CANCEL;		
	}
	
	
	showMessage(INPUTCOL);
	col=listenInt();
	if (col>=DefaultBoardSize-1||col<0)
	{
		showMessage(INVALIDROWCOLNUMBER);
		return CANCEL;		
	}
	showMessage(INPUTDIRECTION);
	dir=listenChar();

	//points=player[turn].rackCard.points;

	index=player[turn].rackLetter.exchangedIndex;

	//have no verification here now, but need future
	if (board.placeWord(row, col, ptr, dir=='V'||dir=='v', index))
	{
		int temp;
	
		ptr=board.verifyStr(temp);
		if (!dictionary.findWord(ptr))
		{
			showMessage(INVALIDWORDFORMED);
			return CANCEL;
		}

		calculateScore();
		board.update();
		board.show();
	
		player[turn].rackLetter.canRollBack=false;
		player[turn].rackCard.canRollBack=false;
		player[turn].rackLetter.updateRack();		
		player[turn].rackLetter.show();	
		for (int i=0; i<player[turn].rackCard.selectedCount; i++)
		{
			CToken temp;
			player[turn].rackCard.removeToken(player[turn].rackCard.selected[i], temp);
			playedDeck.addCard(temp);
		}
		playedDeck.show();
		player[turn].rackCard.updateRack();
		player[turn].rackCard.show();
		player[turn].formed=true;
		message.clearWord();
	}
	else
	{
		showMessage(UNABLEPLACEWORD);
		//board.update(true);
		return CANCEL;
		//board.update(true);
		//board.show();
	}
	return listenMenu();
}





//I want a simple solution: you can only pick card if your last selected card
//has been discarded
int CControl::doPickCard()
{
	CToken target, source;
	int& count=player[turn].rackCard.selectedCount;
	int index=player[turn].rackCard.selected[count-1];

	if (count>0)
	{
		target=player[turn].rackCard.tokens[index];
		if (target.getValue()==0)//empty space
		{
			if (playedDeck.removeCard(source))
			{
				//remove from selected count and update displaying
				player[turn].rackCard.tokens[index]=source;
				count--;
				/*
				if (player[turn].rackCard.tokens[
					player[turn].rackCard.selected[player[turn].rackCard.selectedCount-1]]
				player[turn].rackCard.tokens[
					player[turn].rackCard.selected[--player[turn].rackCard.selectedCount]]=temp;
					*/

				playedDeck.display(DefaultPlayedDeck_x, DefaultPlayedDeck_y);
				player[turn].rackCard.show();
				player[turn].picked=true;//no cancel
			}
		}
	}
	return listenMenu();	
}

int CControl::doSelectLetter()
{
	int choice;
	showMessage(SELECTLETTER);
	choice=listenIndex();
	//message.showInt(choice);

	if (choice<=7&&choice>=1) 
	{
		if (player[turn].selectLetter(choice-1))
		{
			message.showWord(player[turn].rackLetter.tokens[choice-1].getValue());
		}
	}
	else
	{
		showMessage(INVALIDINDEXENTERED);
		return doSelectLetter();
	}
	/*
	newAction=listenMenu();
	switch(newAction)
	{
	case SELECTLETTER:
		return doSelectLetter();
		break;
	case CANCEL:
		player[turn].updateLetters(true);
		break;
	case DISCARD:
		//add some prompted warning message in future.
		for (i=0; i<player[turn].rackLetter.selectedCount; i++)
		{
			CToken temp;
			player[turn].rackLetter.removeToken(player[turn].rackLetter.selected[i], temp);
			bag.addLetter(temp);
		}
		player[turn].rackLetter.updateRack();//no turning back!!!
		bag.show();
		//maybe deck need refresh for displaying
		return ENDROUND;//this is considered to be end of round 
		break;
	default:
		return newAction;
	}
	*/
	return listenMenu();
}

int CControl::doSelectCard()
{	
	int choice;
	showMessage(SELECTCARD);
	choice=listenIndex();
	//message.showInt(choice);

	if (choice<=7&&choice>=1) 
	{
		player[turn].selectCard(choice-1);
	}
	else
	{
		showMessage(INVALIDINDEXENTERED);//prompt user to re-enter choice
		return doSelectCard();
	}

	return listenMenu();
}

int CControl::doTrade()
{
	//int points;
	showMessage(TRADE);

	if (!player[turn].verifyCards())
	{
		showMessage(INVALIDCARDSTRADING);//warn user to reselect cards
		player[turn].updateCards(true);
		return listenMenu();//rollback
	}
	else
	{
		CToken temp;
		char ch;
		showMessage(INPUTEXCHANGELETTER);
		ch=listenChar();
		ch=toupper(ch);
		if (!isalpha(ch))
		{
			player[turn].updateCards(true);
			return listenMenu();
		}
		//need some verifications here!!!!
		if (bag.removeLetter(ch, temp))
		{
			player[turn].addExchanged(ch);
			message.showWord(ch);
			player[turn].traded=true;
		}
		else
		{
			showMessage(CANNOTEXCHANGELETTER);//warn user to reselect cards
			player[turn].updateCards(true);				
		}			
	}
	return listenMenu();
}


void CControl::showMessage(int msgID)
{
	message.showMessage(msgID);
}

int CControl::listenMenu()
{
	int result=-1;
	while (result<1||result>9)
	{
		showMessage(WAITINGMENUCHOICE);
		result= listener.listenMenu();
	}
	menu.setSelected(result-1);
	return result;
}

void CControl::show()
{
	player[turn].show();
	playingDeck.show();
	playedDeck.show();
	board.show();
	bag.show();
	menu.show();
	message.show();
	scoreBoard.show();
	//scoreboard.show(); //this is for Charles
}

void CControl::fillUpRack()
{
	CToken temp;
	for (int i=0; i<player[turn].rackCard.selectedCount; i++)
	{
		temp=player[turn].rackCard.tokens[player[turn].rackCard.selected[i]];
		if (temp.getValue()!=0)
		{
			playedDeck.addCard(temp);
		}
		if (playingDeck.removeCard(temp))
		{
			player[turn].rackCard.tokens[player[turn].rackCard.selected[i]]=temp;
		}
	}
	//player[turn].rackCard.updateRack();
	player[turn].rackCard.selectedCount=0;
	player[turn].rackCard.show();
	playingDeck.show();
	playedDeck.show();
	for (i=0; i<player[turn].rackLetter.selectedCount; i++)
	{
		temp=player[turn].rackLetter.tokens[player[turn].rackLetter.selected[i]];
		//for the initialization
		if (temp.getValue()!=0)
		{
			bag.addLetter(temp);		
		}
	}
	bag.shuffle();
	for (i=0; i<player[turn].rackLetter.selectedCount; i++)
	{
		if (bag.removeLetter(temp))
		{
			player[turn].rackLetter.tokens[player[turn].rackLetter.selected[i]]=temp;
		}
	}

	//player[turn].rackLetter.updateRack();
	player[turn].rackLetter.selectedCount=0;
	bag.show();
	player[turn].rackLetter.show();
}

void CControl::initPlayGame()
{
	backGround.show();
	if (!dictionary.readFile(fileName))
	{
		showMessage(INVALIDDICTIONARYFILENAME);
		showMessage(TRYUSEDEFAULTFILENAME);
		fileName=defaultInputFileName;
		if (!dictionary.readFile(fileName))
		{
			showMessage(INVALIDDICTIONARYFILENAME);
			exit(INVALIDDICTIONARYFILENAME);
		}
	}
	bag.shuffle();
	playingDeck.shuffle();
	//dictionary.readFile(defaultInputFileName);
	turn=0;
	playingDeck.setFace(true);
	playingDeck.setCoord(DefaultPlayingDeck_x, DefaultPlayingDeck_y);
	playedDeck.setFace(false);
	playedDeck.setCoord(DefaultPlayedDeck_x, DefaultPlayedDeck_y);
	fillUpRack();
	player[turn].traded=false;
	player[turn].formed=false;
	player[turn].picked=false;
	nextTurn();
	fillUpRack();
	player[turn].traded=false;
	player[turn].formed=false;
	player[turn].picked=false;
	nextTurn();
	menu.setSelected(-1);
	show();
}

void CControl::setInputFile(char* inputFileName)
{
	if (inputFileName!=NULL)
	{
		fileName=inputFileName;
	}
}

CControl::CControl()
{
	fileName=defaultInputFileName;
	backGround.show();
}

void CControl::getPlayerName(int index)
{
	char buffer[DefaultScoreBoardWidth];
	int pos=0;
	if (index==0)
	{
		showMessage(INPUTFIRSTPLAYERNAME);
	}
	else
	{
		showMessage(INPUTSECONDPLAYERNAME);
	}
	//message
	message.clearEcho();
	message.setCursor();
	//message.s
	while ((buffer[pos]=listener.listenChar())!='\0')
	{
		message.showChar(buffer[pos]);
		pos++;
		if (pos==DefaultScoreBoardWidth-1)
		{
			break;
		}
	}
	buffer[pos]='\0';


	//ptr=listener.listenStr();
/*
	if (strlen(ptr)>DefaultScoreBoardWidth)
	{
		ptr[DefaultScoreBoardWidth-1]='\0';
	}
	*/
	if (pos==0)
	{
		getPlayerName(index);
	}
	//message.showString(ptr);

	strcpy(playerName[index], buffer);
	
}

void CControl::startGame()
{
	backGround.show();
	getPlayerName(0);
	getPlayerName(1);
	scoreBoard.setPlayerName(playerName[0], playerName[1]);
	//debug
	//scoreBoard.show();
	showMessage(JUSTASECOND);
	//listenChar();
	Sleep(1000);
}


void CControl::startLogo()
{
	backGround.show();
	logo.show();
	Sleep(3000);
}

int CControl::listenInt()
{
	int result;
	result=listener.listenInt();
	message.showInt(result);
	message.showChar(',');
	return result;
}

char CControl::listenChar()
{
	char ch;
	ch=listener.listenChar();
	message.showChar(ch);
	message.showChar(',');
	return ch;
}

int CControl::listenIndex()
{
	int result=listener.listenIndex();
	message.showInt(result);
	message.showChar(',');
	return result;
}



¡¡
¡¡
file name: rummy.h
#ifndef RUMMY_H
#define RUMMY_H

#include "token.h"

class CRummy
{
private:
	int array[7];
	int pos;
	bool sameSuit, isSequence, isGroup;
	void addOne(CToken* tokens, int index);
public:
	bool verify(CToken* tokens, int len, int& points);
	CRummy();
};

#endif
¡¡
¡¡
file name: rummy.cpp
#include "rummy.h"

bool CRummy::verify(CToken* tokens, int len, int& points)
{
	sameSuit=isSequence=isGroup=true;
	points=0;

	int theSuit, theBase, theNext;
	pos=0;
	for (int i=0; i<len; i++)
	{
		addOne(tokens, i);
	}
	theSuit=tokens[array[0]].getSuit();
	theBase=tokens[array[0]].getNumber();
	points=theBase;//sum points
	for (i=1; i<len; i++)
	{
		if (tokens[array[i]].getSuit()!=theSuit)
		{
			sameSuit=false;
		}
		theNext=tokens[array[i]].getNumber();
		points+=theNext;//sum points
		if (theNext-theBase!=0)
		{
			isGroup=false;
		}
		if (theNext-theBase!=-1)
		{
			isSequence=false;
		}
		theBase=theNext;
	}
	return sameSuit||isSequence||isGroup;
}
	

CRummy::CRummy()
{
	pos=0;
}

void CRummy::addOne(CToken* tokens, int index)
{
	int i=0;
	if (pos==0)
	{
		array[0]=index;
		pos++;
		return;
	}
	//insertion sorting	
	while (i<pos)
	{
		if (tokens[index].getNumber()>tokens[array[i]].getNumber())
		{
			break;
		}
		i++;	
	}
	
	for (int j=pos; j>i; j--)
	{
		array[j]=array[j-1];
	}
	array[i]=index;
	pos++;
}
file name: player.h
#ifndef CPLAYER_H
#define CPLAYER_H

#include "rovertype.h"
#include "rack.h"
//#include "control.h"

//to do:
//I need charles's CScoreBoard to put an instance inside Player
//so that all set, get method is implemented by CScoreBoard

class CControl;

class CPlayer
{
	friend class CControl;
private:
	char* name;
	CRack rackLetter;
	CRack rackCard;
	int currentScore;
	int totalScore;
	int index;
	bool traded;
	bool formed;
	bool picked;
public:
	CPlayer();
	~CPlayer();
	void setName(const char* theName);
	const char* getName();
	int getCurrentScore();
	void setCurrentScore(int score);
	//int getTotalScore();
	void setTotalScore(int score);
	int getIndex(void);
	void setIndex(int theIndex);
	bool selectCard(int index);
	bool selectLetter(int index);
	void addCard(const CToken & newCard );
	void addLetter(const CToken& newLetter);
	char* exportWord();
	bool verifyCards();
	void show();
	void discardCard(int index, CToken& result);
	void discardLetter(int index, CToken& result);
	bool canAddCard();
	bool canAddLetter();
	void updateCards(bool rollBack=false);
	void updateLetters(bool rollBack=false);
	void addExchanged(char ch);
};

#endif
¡¡
file name: player.cpp
#include "player.h"


CPlayer::CPlayer()
{
	name=NULL;
	index=-1;
	rackLetter.setCoord(DefaultLetterRack_x, DefaultLetterRack_y);
	rackCard.setCoord(DefaultCardRack_x, DefaultCardRack_y);
	show();
}

void CPlayer::show()
{
	rackLetter.show();
	rackCard.show();
	//to do:
	//here to call scoreboard set current player method
}

void CPlayer::discardCard(int index, CToken& result)
{
	rackCard.removeToken(index, result);
}

void CPlayer::discardLetter(int index, CToken& result)
{
	rackLetter.removeToken(index, result);
}


CPlayer::~CPlayer()
{
	if (name!=NULL)
	{
		delete[]name;
	}
}

void CPlayer::setName(const char* theName)
{
	if (name!=NULL)
	{
		delete[]name;
	}
	name=new char[strlen(theName)+1];
	strcpy(name, theName);
}


const char* CPlayer::getName()
{
	return name;
}

void CPlayer::setCurrentScore(int score)
{
	currentScore=score;
}

int CPlayer::getCurrentScore()
{
	return currentScore;
}

void CPlayer::setTotalScore(int score)
{
	totalScore=score;
}

/*
int CPlayer::getTotalScore()
{
	return scoreBoard.getTotalScore(turn);
}
*/
int CPlayer::getIndex()
{
	return index;
}

bool CPlayer::selectCard(int index)
{
	return rackCard.selectToken(index, false);
}

bool CPlayer::selectLetter(int index)
{
	return rackLetter.selectToken(index);
}

void CPlayer::addCard(const CToken& newToken)
{
	rackCard.addToken(newToken);
	rackCard.show();
}
  
void CPlayer::addLetter(const CToken& newToken)
{
	rackLetter.addToken(newToken);
	rackLetter.show();
}

char* CPlayer::exportWord()
{
	return rackLetter.exportWord();
}
  
bool CPlayer::verifyCards()
{
	return rackCard.verifyCards();
}

bool CPlayer::canAddCard()
{
	return rackCard.canAdd();
}

bool CPlayer::canAddLetter()
{
	return rackLetter.canAdd();
}


void CPlayer::updateCards(bool rollBack)
{
	rackCard.updateRack(rollBack);
}

void CPlayer::updateLetters(bool rollBack)
{
	rackLetter.updateRack(rollBack);
}

void CPlayer::addExchanged(char ch)
{
	rackLetter.addExchanged(ch);
}



file name: logo.h
#ifndef LOGO_H
#define LOGO_H

#include "rovertype.h"
#include "tiles.h"

const int PatternSize=10;
const int RoverWordCount=9;

class CLogo
{
private:
	CTiles rover[26][PatternSize];
	void initialize();
	void showWord(int index, int x, int y);
public:
	CLogo();
	void showString(const char* str, int x, int y);
	void show();
};

#endif
¡¡
¡¡
¡¡
file name: logo.cpp
#include "logo.h"


char roverLetters[RoverWordCount]={'W','O','R','D','R','O','V','E','R'};


char patterns[26][PatternSize][PatternSize]=
{
	{
		{0,0,0,0,1,1,0,0,0,0},
		{0,0,0,0,1,1,0,0,0,0},
		{0,0,0,1,1,1,1,0,0,0},
		{0,0,0,1,0,0,1,0,0,0},
		{0,0,1,1,0,0,1,1,0,0},
		{0,0,1,1,0,0,1,1,0,0},
		{0,1,1,1,1,1,1,1,1,0},
		{0,1,0,0,0,0,0,0,1,0},    //A
		{1,1,0,0,0,0,0,0,1,1},
		{1,0,0,0,0,0,0,0,0,1}
	},

	{
		{0,1,1,1,1,1,1,1,0,0},
		{1,1,1,1,1,1,1,1,1,0},
		{1,1,0,0,0,0,0,1,1,0},
		{1,1,0,0,0,0,0,1,0,0},
		{1,1,1,1,1,1,1,1,0,0},
		{1,1,1,1,1,1,1,0,0,0},
		{1,1,0,0,0,0,0,1,0,0},
		{1,1,0,0,0,0,0,0,1,0},    //B
		{1,1,1,1,1,1,1,1,1,0},
		{1,1,1,1,1,1,1,1,0,0}
	},
	{
		{0,0,1,1,1,1,1,1,0,0},
		{0,1,1,1,1,1,1,1,1,1},
		{1,1,0,0,0,0,0,0,0,1},
		{1,1,0,0,0,0,0,0,0,0},
		{1,1,0,0,0,0,0,0,0,0},
		{1,1,0,0,0,0,0,0,0,0},
		{1,1,0,0,0,0,0,0,0,0},
		{1,1,0,0,0,0,0,0,0,1},    //C
		{0,1,1,1,1,1,1,1,1,0},
		{0,0,1,1,1,1,1,1,0,0}
	},
	{
		{0,1,1,1,1,1,1,0,0,0},
		{0,1,1,1,1,1,1,1,0,0},
		{0,1,1,0,0,0,0,1,1,0},
		{0,1,1,0,0,0,0,0,1,0},
		{0,1,1,0,0,0,0,0,1,1},   //D
		{0,1,1,0,0,0,0,0,1,1},
		{0,1,1,0,0,0,0,0,1,1},
		{0,1,1,0,0,0,0,1,1,0},
		{0,1,1,1,1,1,1,1,1,0},
		{0,1,1,1,1,1,1,0,0,0}
	},
	{
		{1,1,1,1,1,1,1,1,1,0},
		{1,1,1,1,1,1,1,1,1,0},
		{1,1,0,0,0,0,0,0,0,0},
		{1,1,0,0,0,0,0,0,0,0},
		{1,1,1,1,1,1,1,1,0,0},   //E
		{1,1,1,1,1,1,1,1,0,0},
		{1,1,0,0,0,0,0,0,0,0},
		{1,1,0,0,0,0,0,0,0,0},
		{1,1,1,1,1,1,1,1,1,0},
		{1,1,1,1,1,1,1,1,1,0}
	},
	{		
		{1,1,1,1,1,1,1,1,1,0},
		{1,1,1,1,1,1,1,1,1,1},
		{1,1,0,0,0,0,0,0,0,0},
		{1,1,0,0,0,0,0,0,0,0},
		{1,1,0,0,0,0,0,0,0,0},
		{1,1,1,1,1,1,1,1,0,0},
		{1,1,1,1,1,1,1,1,0,0},
		{1,1,0,0,0,0,0,0,0,0},    //F
		{1,1,0,0,0,0,0,0,0,0},
		{1,0,0,0,0,0,0,0,0,0}
	},
	{
		{0,0,0,1,1,1,1,1,0,0},
		{0,1,1,1,1,1,1,1,1,0},
		{1,1,0,0,0,0,0,0,1,1},
		{1,1,0,0,0,0,0,0,0,0},
		{1,1,0,0,0,0,0,0,0,0},
		{1,1,0,0,0,0,1,1,1,1},
		{1,1,0,0,0,0,1,1,1,1},
		{1,1,1,0,0,0,0,0,1,0},    //G
		{0,1,1,1,1,1,1,1,1,1},
		{0,0,1,1,1,1,1,1,1,1}
	},
	{
		{1,1,0,0,0,0,0,0,1,1},
		{1,1,0,0,0,0,0,0,1,1},
		{1,1,0,0,0,0,0,0,1,1},
		{1,1,0,0,0,0,0,0,1,1},
		{1,1,1,1,1,1,1,1,1,1},
		{1,1,1,1,1,1,1,1,1,1},
		{1,1,0,0,0,0,0,0,1,1},
		{1,1,0,0,0,0,0,0,1,1},    //H
		{1,1,0,0,0,0,0,0,1,1},
		{1,1,0,0,0,0,0,0,1,1}
	},
	{
		{0,0,0,1,1,1,1,0,0,0},
		{0,0,0,1,1,1,1,0,0,0},
		{0,0,0,0,1,1,0,0,0,0},
		{0,0,0,0,1,1,0,0,0,0},
		{0,0,0,0,1,1,0,0,0,0},
		{0,0,0,0,1,1,0,0,0,0},
		{0,0,0,0,1,1,0,0,0,0},
		{0,0,0,0,1,1,0,0,0,0},    //I
		{0,0,1,1,1,1,1,1,0,0},
		{0,0,1,1,1,1,1,1,0,0}
	},
	{
		{0,0,0,1,1,1,1,0,0,0},
		{0,0,0,0,0,1,1,0,0,0},
		{0,0,0,0,0,1,1,0,0,0},
		{0,0,0,0,0,1,1,0,0,0},
		{0,0,0,0,0,1,1,0,0,0},
		{0,0,0,0,0,1,1,0,0,0},
		{0,0,0,0,0,1,1,0,0,0},
		{0,1,0,0,0,1,1,0,0,0},    //J
		{0,1,1,1,1,1,1,0,0,0},
		{0,1,1,1,1,1,1,0,0,0}
	},
	{
		{0,1,1,0,0,0,0,1,0,0},
		{0,1,1,0,0,0,1,0,0,0},
		{0,1,1,0,0,1,0,0,0,0},
		{0,1,1,0,1,0,0,0,0,0},
		{0,1,1,1,1,0,0,0,0,0},
		{0,1,1,1,1,0,0,0,0,0},
		{0,1,1,0,1,1,0,0,0,0},
		{0,1,1,0,0,1,1,0,0,0},    //K
		{0,1,1,0,0,0,1,1,0,0},
		{0,1,1,0,0,0,0,1,1,0}
	},
	{
		{0,1,1,0,0,0,0,0,0,0},
		{0,1,1,0,0,0,0,0,0,0},
		{0,1,1,0,0,0,0,0,0,0},
		{0,1,1,0,0,0,0,0,0,0},
		{0,1,1,0,0,0,0,0,0,0},
		{0,1,1,0,0,0,0,0,0,0},
		{0,1,1,0,0,0,0,0,0,0},
		{0,1,1,0,0,0,0,0,0,0},    //L
		{0,1,1,1,1,1,1,1,1,0},
		{0,1,1,1,1,1,1,1,1,0}
	},
	{
		{1,1,0,0,0,0,0,0,1,1},
		{1,1,1,0,0,0,0,1,1,1},
		{1,1,1,1,0,0,1,1,1,1},
		{1,1,0,1,1,1,1,0,1,1},
		{1,1,0,0,1,1,0,0,1,1},
		{1,1,0,0,0,1,0,0,1,1},
		{1,1,0,0,0,0,0,0,1,1},
		{1,1,0,0,0,0,0,0,1,1},    //M
		{1,1,0,0,0,0,0,0,1,1},
		{1,1,0,0,0,0,0,0,1,1}
	},
	{
		{1,1,0,0,0,0,0,0,1,1},
		{1,1,1,0,0,0,0,0,1,1},
		{1,1,1,1,0,0,0,0,1,1},
		{1,1,0,1,1,0,0,0,1,1},
		{1,1,0,0,1,1,0,0,1,1},
		{1,1,0,0,0,1,1,0,1,1},
		{1,1,0,0,0,0,1,1,1,1},
		{1,1,0,0,0,0,0,1,1,1},    //N
		{1,1,0,0,0,0,0,0,1,1},
		{1,1,0,0,0,0,0,0,1,1}
	},
	{
		{0,0,0,0,1,1,0,0,0,0},
		{0,0,1,1,1,1,1,1,0,0},
		{0,1,1,0,0,0,0,1,1,0},
		{0,1,0,0,0,0,0,0,1,0},
		{1,1,0,0,0,0,0,0,1,1},
		{1,1,0,0,0,0,0,0,1,1},
		{0,1,0,0,0,0,0,0,1,0},   //O
		{0,0,1,0,0,0,0,1,1,0},
		{0,0,1,1,1,1,1,1,0,0},
		{0,0,0,0,1,1,0,0,0,0}
	},
	{
		{0,1,1,1,1,1,1,1,0,0},
		{0,1,1,1,1,1,1,1,1,0},
		{0,1,1,0,0,0,0,0,1,1},
		{0,1,1,0,0,0,0,0,1,1},
		{0,1,1,0,0,0,0,0,1,1},
		{0,1,1,1,1,1,1,1,1,0},
		{0,1,1,1,1,1,1,1,1,0},
		{0,1,1,0,0,0,0,0,0,0},    //P
		{0,1,1,0,0,0,0,0,0,0},
		{0,1,1,0,0,0,0,0,0,0}
	},
	{
		{0,0,1,1,1,1,1,1,0,0},
		{0,1,1,1,1,1,1,1,1,0},
		{1,1,0,0,0,0,0,0,1,0},
		{1,0,0,0,0,0,0,0,1,1},
		{1,0,0,0,0,0,0,0,1,1},
		{1,0,0,0,0,0,0,0,1,1},
		{1,1,0,0,0,1,1,0,1,1},
		{0,1,0,0,0,1,1,1,1,0},    //Q
		{0,1,1,1,1,1,1,1,1,1},
		{0,0,1,1,1,1,1,1,1,1}
	},
	{
		{0,0,1,1,1,1,1,1,0,0},
		{0,1,1,1,1,1,1,1,1,0},
		{0,1,1,0,0,0,0,0,1,0},
		{0,1,1,0,0,0,0,1,1,0},
		{0,1,1,0,1,1,1,0,0,0},
		{0,1,1,0,1,1,0,0,0,0},
		{0,1,1,0,0,0,1,0,0,0},
		{0,1,1,0,0,0,0,1,0,0},    //R
		{0,1,1,0,0,0,0,0,1,0},
		{0,1,1,0,0,0,0,0,0,1}
	},	
	{
		{0,0,0,1,1,1,1,1,0,0},
		{0,1,1,1,1,1,1,1,1,0},
		{1,1,0,0,0,0,0,0,0,0},
		{1,1,0,0,0,0,0,0,0,0},
		{1,1,0,0,0,0,0,0,0,0},
		{0,0,1,1,1,1,1,1,0,0},
		{0,0,0,0,0,0,0,0,1,0},
		{0,0,0,0,0,0,0,0,1,1},    //S
		{1,1,0,0,0,0,0,0,1,1},
		{0,1,1,1,1,1,1,1,1,0}
	},

	{
		{1,1,1,1,1,1,1,1,1,1},
		{1,1,1,1,1,1,1,1,1,1},
		{0,0,0,0,1,1,0,0,0,0},
		{0,0,0,0,1,1,0,0,0,0},
		{0,0,0,0,1,1,0,0,0,0},
		{0,0,0,0,1,1,0,0,0,0},
		{0,0,0,0,1,1,0,0,0,0},
		{0,0,0,0,1,1,0,0,0,0},    //T
		{0,0,0,0,1,1,0,0,0,0},
		{0,0,0,1,1,1,1,0,0,0}
	},
	{
		{1,1,0,0,0,0,0,0,1,1},
		{1,1,0,0,0,0,0,0,1,1},
		{1,1,0,0,0,0,0,0,1,1},
		{1,1,0,0,0,0,0,0,1,1},
		{1,1,0,0,0,0,0,0,1,1},
		{1,1,0,0,0,0,0,0,1,1},
		{1,1,0,0,0,0,0,0,1,1},
		{1,1,0,0,0,0,0,0,1,1},    //U
		{0,1,1,1,1,1,1,1,1,1},
		{0,1,1,1,1,1,1,1,1,0}

	},

	{
		{1,0,0,0,0,0,0,0,0,1},
		{1,0,0,0,0,0,0,0,0,1},
		{1,0,0,0,0,0,0,0,0,1},
		{1,1,0,0,0,0,0,0,1,1},
		{1,1,0,0,0,0,0,0,1,1},
		{1,1,0,0,0,0,0,0,1,1},
		{0,1,1,0,0,0,0,1,1,0}, //V
		{0,0,1,1,0,0,1,1,0,0},
		{0,0,0,1,1,1,1,0,0,0},
		{0,0,0,0,1,1,0,0,0,0}
	},
	{		
		{0,0,0,0,0,0,0,0,0,0},
		{1,0,0,0,0,0,0,0,0,1},
		{1,1,0,0,0,0,0,0,1,1},
		{1,1,0,0,0,0,0,0,1,1},
		{1,1,0,0,0,0,0,0,1,1},
		{1,1,0,0,1,1,0,0,1,1},
		{0,1,0,0,1,1,0,0,1,0},
		{0,1,0,1,0,0,1,0,1,0},  //W
		{0,1,1,1,0,0,1,1,1,0},
		{0,0,1,0,0,0,0,1,0,0}
	},

	{
		{1,1,0,0,0,0,0,0,0,1},
		{1,1,0,0,0,0,0,0,1,0},
		{0,0,1,0,0,0,0,1,0,0},
		{0,0,0,1,0,0,1,0,0,0},
		{0,0,0,0,1,1,0,0,0,0},
		{0,0,0,0,1,1,0,0,0,0},
		{0,0,0,1,0,0,1,0,0,0},
		{0,0,1,0,0,0,0,1,0,0},    //X
		{1,1,0,0,0,0,0,0,1,1},
		{1,1,0,0,0,0,0,0,1,1}
	},
	{
		{1,1,0,0,0,0,0,0,1,1},
		{1,1,0,0,0,0,0,0,1,1},
		{1,1,0,0,0,0,0,0,1,1},
		{0,1,1,0,0,0,0,1,1,0},
		{0,0,1,1,1,1,1,1,0,0},
		{0,0,0,0,1,1,0,0,0,0},
		{0,0,0,0,1,1,0,0,0,0},
		{0,0,0,0,1,1,0,0,0,0},    //Y
		{0,0,0,0,1,1,0,0,0,0},
		{0,0,0,0,1,1,0,0,0,0}
	},
	{
		{0,1,1,1,1,1,1,1,1,1},
		{0,1,1,1,1,1,1,1,1,1},
		{0,1,0,0,0,0,0,1,0,0},
		{0,0,0,0,0,0,1,0,0,0},
		{0,0,0,0,0,1,0,0,0,0},
		{0,0,0,0,1,0,0,0,0,0},
		{0,0,0,1,0,0,0,0,0,0},
		{0,0,1,0,0,0,0,0,0,1},    //Z
		{0,1,1,1,1,1,1,1,1,1},
		{1,1,1,1,1,1,1,1,1,1}
	}

};


void CLogo::initialize()
{
	for (int i=0; i<26; i++)
	{
		for (int r=0; r<PatternSize; r++)
		{
			rover[i][r].setLength(PatternSize);
			for (int c=0; c<PatternSize; c++)
			{
				rover[i][r][c].setValue(patterns[i][r][c]==1?char('A'+i):0);
			}
		}
	}
}

CLogo::CLogo()
{
	initialize();
}
				
void CLogo::show()
{
	for (int i=0; i<RoverWordCount; i++)
	{
		if (i<4)
		{
			showWord(roverLetters[i]-'A', DefaultLogo_x+ i*(PatternSize+2), DefaultLogo_y);
		}
		else
		{
			showWord(roverLetters[i]-'A', DefaultLogo_x+(i-4)*(PatternSize+2)-PatternSize/2, 
				DefaultLogo_y+PatternSize+1);
		}		
	}
}

void CLogo::showWord(int index, int x, int y)
{
	for (int i=0; i<PatternSize; i++)
	{
		rover[index][i].display(x, y+i);
	}
}


void CLogo::showString(const char* str, int x, int y)
{
	int index=0, r=0, c=0;
	while (str[index]!='\0')
	{
		showWord(toupper(str[index])-'A', x+c*(PatternSize+2), y+r*(PatternSize+2));
		if (x+c*(PatternSize+2)<DefaultScreenWidth-PatternSize)
		{
			c++;			
		}
		else
		{
			c=0;
			r++;
		}
		index++;
	}
}






file name: scoreboard.h
#ifndef SCOREBOARD_H
#define SCOREBOARD_H
#include "RoverType.h"
#include "tiles.h"
#include "frame.h"

class CScoreBoard
{
private:
	CTiles scores[2][3];
	//CFrame frame(DefaultScoreBoard_X-1, DefaultScoreBoard_Y-1, 3+2,	DefaultScoreBoardWidth*2+2);
	CFrame frame;
	void initialize();
	int turn;
	/*
	CTile* tiles;
	int len;
	WORD ftColor;
	WORD bkColor;
	bool isVertical;
	
	*/
	//void clearScore();
	void doSetName(int index, char* theName);
public:
	CScoreBoard();
	void setPlayerName(char *first, char*second);
	void setPlayerScore(int theScore);
	void switchCurrentPlayer();
	int getTotalScore(int index);
	void show();
};

#endif
¡¡
file name: scoreboard.cpp
#include "ScoreBoard.h"

CScoreBoard::CScoreBoard()
{
	initialize();
}

void CScoreBoard::initialize()
{
	turn=0;
	frame.setFrame(DefaultScoreBoard_X, DefaultScoreBoard_Y, 3,
		DefaultScoreBoardWidth*2);
	frame.show();
	for (int c=0; c<2; c++)
	{
		for (int r=1; r<3; r++)
		{
			scores[c][r].setNumber(0);
		}
	}
}

void CScoreBoard::doSetName(int index, char* theName)
{
	scores[index][0].setValue(theName);
}

void CScoreBoard::setPlayerName(char* first, char* second)
{
	doSetName(0, first);
	doSetName(1, second);
}
	
void CScoreBoard::show()
{
	scores[turn][0].setBKGroundColor(DefaultSelectedPlayerBKColor);
	frame.show();
	for (int c=0; c<2; c++)
	{
		for (int r=0; r<3; r++)
		{
			scores[c][r].display(DefaultScoreBoard_X+c*DefaultScoreBoardWidth, 
				DefaultScoreBoard_Y+r);
		}
	}
	//frame.show();
}

void CScoreBoard::switchCurrentPlayer()
{
	scores[turn][0].setBKGroundColor(DefaultBKGroundColor);
	turn=(turn+1)%2;
	scores[turn][0].setBKGroundColor(DefaultSelectedPlayerBKColor);
}

void CScoreBoard::setPlayerScore(int theScore)
{
	int total;
	total=scores[turn][2].getNumber();
	//scores[turn][1].clear();
	scores[turn][1].setNumber(0);
	scores[turn][1].setNumber(theScore);
	//scores[turn][2].clear();
	scores[turn][2].setNumber(0);
	scores[turn][2].setNumber(theScore+total);
}

int CScoreBoard::getTotalScore(int index)
{
	return scores[index][2].getNumber();
}



¡¡

file name: main.cpp(main)
/*
#include "tokens.h"
#include "tiles.h"
#include "board.h"
#include "block.h"
#include "listener.h"
#include "rummy.h"
#include "dictionary.h"
#include "background.h"
#include "deck.h"
#include "rack.h"
#include "bag.h"
#include "player.h"
#include "logo.h"
#include "scoreBoard.h"
*/

#include "control.h"
#include <time.h>

//#include <iostream>
//using namespace std;



int  main()
{
	
//	const int Size=14;
	
/*
	char** matrix;
	
	matrix=new char*[Size];
	for (int i=0; i<Size; i++)
	{
		matrix[i]=new char[Size];
		for (int j=0; j<Size; j++)
		{
			matrix[i][j]='A'+i+j;
		}
	}
	
	CBoard C(Size);
	//normally display a string
	C.placeWord(5, 4, "first");
	C.update();//with updates, change color to normal
	//C.display(1,1);
	//try to place a string which will exceed bounds
	C.placeWord(6, 5, "invisable");
	C.update();
	//update with "roll back" and erase it
	//C.update(true);
	//so you see nothing of this new string
	//C.display(1,1);
	//place a third string for comparison and vertically
	C.placeWord(2, 7, "vertical", true);
	C.update();
	//C.update();
	C.placeWord(7, 5, "newstring");
	C.update();
	C.placeWord(8, 3, "third");
	C.update();
	C.placeWord(9, 6, "fourth");
	//so you will see 1st, 3rd string
	C.display(1,1);

	CTiles D;
	char* ptr;
	int i=0;
	while ((ptr=C.getNextStr())!=NULL)
	{
		D.setValue(ptr);
		D.display(18, 37+i);
		i++;
	}
*/
	//CListener C;
	//CToken T;
	//T.setNumber(C.listenMenu());
	//T.display(10, 10);

	//CTokens tokens;//(C.listenStr());
	//tokens.setValue(C.listenStr());
	//tokens.display(1, 15);
	/*
	const int len=3;
	CTiles ok("ok");
	CToken tokens[len];
	/*
	for (int i=0; i<len; i++)
	{
		tokens[i].setNumber((i+1)*2);
		tokens[i].setSuit(
	}

	tokens[0].setNumber(7);
	tokens[0].setSuit(Spade);
	tokens[1].setNumber(7);
	tokens[1].setSuit(Heart);
	tokens[2].setNumber(7);
	tokens[2].setSuit(Diamond);
	CRummy R;
	if (R.verify(tokens, 3))
	{
		ok.display(1,1);
	}

	for (int i=0; i<len; i++)
	{
		tokens[i].display(i*4+3, 5);
	}
		*/
	//char buffer[15]={'a','B', 'c', 'g','x', 'u','o','\0'};
	//CTiles C("ok");
	//Dictionary D(false);
	//D.readFile("wordsource.txt");
	//CDeck deck;
	//deck.setFace();
	//deck.display(5, 5);
	/*
	for (int i=0; i<4; i++)
	{
		CToken token;
		token.setValue(buffer[i]);
		deck.addCard(token);
	}
	//deck.setFace(false);
	
	//deck.
	
	//deck.display(15,15);
	CToken card;
	card.setValue('B');
	//card.display(23, 23);
	deck.shuffle();
	deck.showHand();
	*/
	/*
	CRack C;
	CToken token;
	int i=0;
	while (C.canAdd())
	{
		token.setValue(buffer[i]);

		C.AddToken(token);
		i++;
	}
	C.showRack();

	C.SelectToken(3);
	C.SelectToken(5);
	C.addExchanged('A');
	C.SelectToken(0);
	C.SelectToken(5);
	CTiles t(C.exportSelected());
	t.display(10,10);
	//C.updateRack();
	C.showRack();

	t.setNumber(C.exchangedIndex);
	t.display(5,5);
	*/
	//CBag C;
	//CToken hold;
	
	//C.display(0,0);
	//C.showBag();
	/*
	int x=0, y=0;
	CToken token;

	while (C.getToken(token))
	{
		x+=6;
		if (x>100)
		{
			x=0;
			y+=6;
		}
		//hold.setValue(token.setValue())
		//hold.display(2,2);
		token.display(x,y);
		if (x>15)
			break;
		
	}
	C.showBag();

	CPlayer P;
	CListener C;
	P.display();
	CToken t;
	int i=Heart;
	while (P.canAddCard())
	{
		t.setSuit(i%4+Heart);
		t.setNumber(i+1);
		P.addCard(t);
		i=C.listenMenu();
	}
	while (P.canAddLetter())
	{
		t.setValue(i+'B');
		P.addLetter(t);
		i=C.listenMenu();
	}
*/
	

	srand(time(0));
	CControl C;
	C.setInputFile("readme.txt");
	C.startLogo();
	C.startGame();
	C.playGame();
	C.endGame();
	//C.startLogo();
/*
	int test[2][3][3]=
	{
		{ {1,2,3},{4,5,6}, {7,8,9}},
		{ {1,2,3},{4,5,6},{7,8,9}}
	};
	*/
	return 0;


}








The input is something like following:
Here is the executable file and dictionary file.

¡¡





                                 back.gif (341 bytes)       up.gif (335 bytes)         next.gif (337 bytes)