Console rummy
A. Fourth Edition
These classes are all base classes for console displays and on this edition I finished a board class.
How to display in console without using iostream class?
These classes are for our comp354 project which is going to make a little game like cross word.
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. rummy.h
17. rummy.cpp
18. dictionary.h
19. dictionary.cpp
20. listener.h
21. listener.cpp
22. 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 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); }; #endif
file name: tiles.cpp
#include "tiles.h" CTiles::CTiles() { initialize(); } void CTiles::initialize() { len=0; tiles=NULL; isVertical=false; ftColor=DefaultFontColor; bkColor=DefaultBKGroundColor; } 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]); } } 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); const CToken& operator=(const CToken& theToken); int getNumber(); void setNumber(int num); void setSuit(int theSuit); int getSuit(); }; #endif
file name: token.cpp
#include "token.h" #include "tile.h" const 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 if (num>99) { return ; } 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(); }
file name: tokens.h
#ifndef TOKENS_H #define TOKENS_H #include "token.h" class CTokens { protected: CToken* tokens; int len; WORD ftColor; WORD bkColor; WORD frColor; bool isVertical;//default is false void initialize(); 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); }; #endif
file name: tokens.cpp
#include "tokens.h" CTokens::CTokens(int theLen) { initialize(); setLength(theLen); } CTokens::CTokens(const char* str) { initialize(); setValue(str); } void CTokens::initialize() { len=0; tokens=NULL; isVertical=false; ftColor=DefaultFontColor; bkColor=DefaultBKGroundColor; frColor=DefaultFrameColor; } 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) { len=strlen(str); //tokens=new CToken[len]; setLength(len); 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) { tokens[i].display(x+i*4, y); } else { tokens[i].display(x, y+i*4); } } } CTokens::~CTokens() { delete [] tokens; }
file name: RoverType.h
#include <windows.h> /*****************************nick****************************/ //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 #define DefaultBoardSize 15 #define MaxBoardSize 20 #define DefaultCharacter 0 #define DefaultTokenLength 7 #define MinimumLengthOfWord 2 #define MaxInputBufferLength 20 #define LetterCount 26 #define MaxLengthOfWord 20 /* enum Suit {Club=5, Diamond=4, Heart=3, Spade=6}; */ #define Club 5 #define Diamond 4 #define Heart 3 #define Spade 6 /****************************nick*****************************/
file name: board.h
#ifndef BOARD_H #define BOARD_H #include "cell.h" class CBoard { private: int curRow, curCol; int headRow, headCol; bool isVer; bool isFirst; char buffer[MaxBoardSize]; bool doFindStr(); void setStartPoint(); void getFirstStr(); int findHead(int startRow, int startCol, bool isVertical); 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=false); void update(bool rollBack=false); char* getNextStr(); }; #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]; } } } 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); 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); } } void CBoard::getFirstStr() { int row=headRow, col=headCol, pos=0; while (board[row][col].getValue()!=0) { buffer[pos]=board[row][col].getValue(); pos++; if (isVer) { row++; } else { col++; } if (row==boardWidth||col==boardWidth) { break; } } buffer[pos]='\0'; } char* CBoard::getNextStr() { if (isFirst) { setStartPoint(); isFirst=false; getFirstStr(); return buffer;//the original one will always return } if (doFindStr()) { return buffer; } else { return NULL; } } bool CBoard::doFindStr() { int row=headRow, col=headCol, pos=0; 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(); } col=findHead(row, col, !isVer);//the crossing direction do//the boardWidth is one more than the real size { buffer[pos]=board[row][col].getValue(); col++; pos++; if (col>boardWidth) { break; } } while (board[row][col].getValue()!=0); buffer[pos]='\0'; headRow++; if (pos>MinimumLengthOfWord) { return true; } else { return doFindStr(); } } else { if (board[row][col].getStatus()) { headCol++; return doFindStr(); } row=findHead(row, col, !isVer); do { buffer[pos]=board[row][col].getValue(); row++; pos++; if (row>boardWidth) { break; } }while (board[row][col].getValue()!=0); buffer[pos]='\0'; headCol++; if (pos>MinimumLengthOfWord) { return true; } else { return doFindStr(); } } } //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 row=r+1, col=c+1, pos=0; curRow=row; curCol=col; isVer=isVertical; 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 (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" 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 y=0; if (atBottom) { y=1; } if (num>9) { block[0][y].setValue(num/10+'0'); block[1][y].setValue(num%10+'0'); } else { block[0][y].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+i, y+j); } } }
file name: rummy.h
#include "token.h" class CRummy { private: int array[7]; int pos; void addOne(CToken* tokens, int index); public: bool verify(CToken* tokens, int len); CRummy(); };
file name: rummy.cpp
#include "rummy.h" bool CRummy::verify(CToken* tokens, int len) { bool sameSuit=true, isSequence=true, isGroup=true; int theSuit, theBase, theNext; for (int i=0; i<len; i++) { addOne(tokens, i); } theSuit=tokens[array[0]].getSuit(); theBase=tokens[array[0]].getNumber(); for (i=1; i<len; i++) { if (tokens[array[i]].getSuit()!=theSuit) { sameSuit=false; } theNext=tokens[array[i]].getNumber(); 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: dictionary.h
#include "RoverType.h" struct Letter { char ch; Letter* next; Letter* son; bool end; }; class Dictionary { 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); public: bool addWord(char* str); bool findWord(char* str); void readFile(const char* fileName); void setCaseSensitive(bool isCaseSensitive); Dictionary(bool isCaseSensitive=true); };
file name: dictionary.cpp
#include <stdio.h> #include "dictionary.h" void Dictionary::change2Capital(char* target, char* source) { char* tgt=target, *src=source; do { *tgt=toupper(*src); tgt++; src++; }while (*src!='\0'); *tgt='\0'; } void Dictionary::readFile(const char* fileName) { char buffer[MaxLengthOfWord]; char*ptr=buffer; char ch; FILE* stream; stream=fopen(fileName, "r"); while (!feof(stream)) { ch=fgetc(stream); if (isalnum(ch)) { if (!caseSensitive) { *ptr=toupper(ch); } else { *ptr=ch; } ptr++; } else { *ptr='\0'; if (ptr!=buffer) { addWord(buffer); ptr=buffer; } //else remain the same ptr. } } } bool Dictionary::findWord(char* str) { char* ptr=str; char buffer[MaxLengthOfWord]; 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* Dictionary::createLetter(char ch) { Letter* ptr=new Letter; ptr->ch=ch; ptr->end=false; ptr->next=NULL; ptr->son=NULL; return ptr; } //ch is not '\0' Letter* Dictionary::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* Dictionary::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 Dictionary::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; } Dictionary::Dictionary(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; } 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; } } } int Dictionary::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; }
file name: listener.h
#include "RoverType.h" class CListener { protected: static HANDLE hOut; static char buffer[MaxInputBufferLength]; void initialize(); public: CListener(); int listenMenu(); char* listenStr();//must ended by entering return };
file name: listener.cpp
#include "listener.h" 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::listenStr() { DWORD temp; SetConsoleMode(hOut, ENABLE_LINE_INPUT); ReadConsole(hOut, buffer, MaxInputBufferLength, &temp, NULL); buffer[temp-1]='\0'; return buffer; }
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 <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', '5','\0'}; CTiles C("ok"); Dictionary D(false); D.readFile("wordsource.txt"); if (D.findWord("eye")) { C.display(1,1); } return 0; }
The input is something like following:
Here is the result: