C++ Windows Programming
上QQ阅读APP看书,第一时间看更新

The GameGrid class

Finally, the GameGrid class is quite simple. It keeps track of the squares on the game board. The gridArea field is the portion of the total client area that is occupied by the grid:

GameGrid.h

const int Rows = 20, Cols = 10;  
 
class GameGrid { 
  public: 
    GameGrid(Rect gridArea); 
    void ClearGameGrid(); 
 
    Color* operator[](int row) {return gameGrid[row];} 
    void InvalidateSquare(Window* windowPtr, int row, 
                          int col, Size offsetSize); 
    void DrawGameGrid(Graphics& graphics, bool inverse) const; 



    void DrawSquare(Graphics& graphics, int row, int col, 
                    Color penColor, Color brushColor, 
                    Size offsetSize = ZeroSize) const; 
 
    Rect GridArea() const {return gridArea;} 
 
  private: 
    Rect gridArea; 
    Color gameGrid[Rows][Cols]; 
}; 

When called by the TetrisWindow constructor, the grid area will be set to (0, 20, 100, 100) units, placing it in the lower 80 percent of the client area of the window:

GameGrid.cpp

#include "..\\SmallWindows\\SmallWindows.h" 
#include "GameGrid.h" 
 


GameGrid::GameGrid(Rect gridArea) 
 :gridArea(gridArea) { 
  ClearGameGrid(); 
} 

When clearing the grid, we actually set every square to white:

void GameGrid::ClearGameGrid () { 
  for (int row = 0; row < Rows; ++row) { 
    for (int col = 0; col < Cols; ++col) { 
      gameGrid[row][col] = White; 
    } 
  } 
} 

Invalidating and drawing squares

The DrawGameGrid iterates through the squares of the grid. White squares are surrounded by white borders, while squares of every other color are surrounded by black borders. If the inverseColor parameter is true, the square color is inversed before drawn. This is useful when flashing rows:

void GameGrid::DrawGameGrid(Graphics& graphics, bool inverse) 
                            const { 
  for (int row = 0; row < Rows; ++row) { 
    for (int col = 0; col < Cols; ++col) { 
      Color squareColor = gameGrid[row][col]; 
      Color penColor = (squareColor == White) ? White : Black; 
      Color brushColor = inverse ? squareColor.Inverse() 
                                 : squareColor; 
      DrawSquare(graphics, row, col, penColor, brushColor); 
    } 
  } 
} 

Note that the InvalidateSquare and DrawSquare methods add an offset. It is zero in all cases except when invalidating or drawing the next figure in the TetrisWindow class. Both methods calculate the size of the rows and columns of the grid and define the area of the square invalidated or drawn:

void GameGrid::InvalidateSquare(Window* windowPtr, int row, 
                                int col, Size offsetSize) { 
  int colWidth = gridArea.Width() / Cols, 
      rowHeight = gridArea.Height() / Rows; 
 

  Rect squareArea(col * colWidth, row * rowHeight, 
                  (col + 1) * colWidth, (row + 1) * rowHeight); 
  windowPtr->Invalidate(gridArea.TopLeft() + squareArea + 
                        offsetSize); 
} 
 
void GameGrid::DrawSquare(Graphics& graphics, int row, int col, 
                          Color penColor, Color brushColor, 
                          Size offsetSize /* = ZeroSize */) const{ 
  int colWidth = gridArea.Width() / Cols, 
      rowHeight = gridArea.Height() / Rows; 
 
  Rect squareArea (col * colWidth, row * rowHeight, 
                  (col + 1) * colWidth, (row + 1) * rowHeight); 
  graphics.FillRectangle(gridArea.TopLeft() + squareArea + 
                         offsetSize, penColor, brushColor); 
}