自己動手寫俄羅斯方塊(三)

最後綜合
1.經過調試和修改,最後的運行效果如下:
 
2.代碼
#include<stdlib.h>
#include<windows.h>

#define ID_TIMER        1

#define NUM 200
const int SquareSize=20;
const int GameSizeX=300;
const int GameSizeY=50;
const int GameRegionWidth=10;
const int GameRegionHeight=20;

struct GameMapStates
{
        int states;
        int shapes;
}GameMapStatesInfo[10][20];

int nx[4],ny[4];
int count=0;
int score=0;
int szshape[NUM];

struct CurrentTerics
{
  int shape,dir,x,y;
}CurrentTericsInfo;

const COLORREF color[7] =        
{        
  RGB(255,0,0),        
  RGB(240,100,5),        
  RGB(150,250,60),        
  RGB(27,229,50),        
  RGB(10,125,145),        
  RGB(20,12,184),        
  RGB(116,34,156)        
        
};        

const POINT Terics[7][4][4] =                    
{                
    {                
        
    0,0,1,0,0,1,-1,1,                
        
    0,0,0,1,1,1,1,2,                
        
    0,0,1,0,0,1,-1,1,                
        
    0,0,0,1,1,1,1,2                
        
    },                
    {                
        
    0,0,1,0,1,1,2,1,                
        
    0,0,0,1,-1,1,-1,2,                
        
    0,0,1,0,1,1,2,1,                
        
    0,0,0,1,-1,1,-1,2                
        
    },                
    {                
        
    0,0,0,1,0,2,1,2,                
        
    0,0,0,1,-1,1,-2,1,                
        
    0,0,1,0,1,1,1,2,                
        
    0,0,0,1,1,0,2,0                
        
    },                
    {                
        
    0,0,0,1,0,2,-1,2,                
        
    0,0,1,0,2,0,2,1,                
        
    0,0,1,0,0,1,0,2,                
        
    0,0,0,1,1,1,2,1                
        
    },                
    {                
        
    0,0,0,1,0,2,0,3,                
        
    0,0,1,0,2,0,3,0,                
        
    0,0,0,1,0,2,0,3,                
        
    0,0,1,0,2,0,3,0                
        
    },                
    {                
        
    0,0,1,0,0,1,1,1,                
        
    0,0,1,0,0,1,1,1,                
        
     0,0,1,0,0,1,1,1,                
        
    0,0,1,0,0,1,1,1                
        
    },                
    {                
        
    0,0,1,0,2,0,1,1,                
        
         0,0,0,1,0,2,1,1,                
        
    0,0,0,1,-1,1,1,1,                
        
    0,0,0,1,0,2,-1,1                
        
    }                    
};        

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
void DrawGameRegion(HDC hdc);//繪製遊戲區
void EraseGameRegion(HDC hdc);//擦除遊戲區
void DrawRectangle(HDC hdc,int shape,int x,int y);//繪製矩形,x,y表示相對於遊戲區邊界的偏移量,單位是一個方格的大小
void DrawTerics(HDC hdc,int shape,int dir,int x,int y);//繪製俄羅斯方塊
BOOL IsOutOfRegion(int shape,int dir,int x,int y);//判斷圖形是否出界
void InitTericsInfo();//初始化俄羅斯方塊
void SaveStateOfTerics(int shape, int dir, int x, int y);//保存遊戲區狀態    
void LoadCurrentTerics(HDC hdc);//加載已有的俄羅斯方塊    
void PrintInfo(HDC hdc,int *shape);//輸出函數
BOOL IsGameOver(int shape,int dir,int x,int y);//遊戲結束
    

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                
                                     PSTR szCmdLine, int iCmdShow)
                
{
                
        static TCHAR szAppName[] = TEXT ("MyTerics") ;
                
        HWND                    hwnd ;
                
        MSG                     msg ;
                
        WNDCLASS            wndclass ;
                
        
                
        wndclass.style                = CS_HREDRAW | CS_VREDRAW ;
                
        wndclass.lpfnWndProc    = WndProc ;
                
        wndclass.cbClsExtra     = 0 ;
                
        wndclass.cbWndExtra     = 0 ;
                
        wndclass.hInstance        = hInstance ;
                
        wndclass.hIcon                = LoadIcon (NULL, IDI_APPLICATION) ;
                
        wndclass.hCursor            = LoadCursor (NULL, IDC_ARROW) ;
                
        wndclass.hbrBackground= (HBRUSH) GetStockObject (WHITE_BRUSH) ;
                
        wndclass.lpszMenuName    = NULL ;
                
        wndclass.lpszClassName = szAppName ;
                
                
                
        if (!RegisterClass (&wndclass))
                
        {
                
                        MessageBox (    NULL, TEXT ("Program requires Windows NT!"),
                
                                     szAppName, MB_ICONERROR) ;
                
                                     return 0 ;
                
        }
                
        
                
        hwnd = CreateWindow ( szAppName, TEXT ("MyTerics"),
                
                                                    WS_OVERLAPPEDWINDOW,
                
                                                     CW_USEDEFAULT, CW_USEDEFAULT,
                
                                                     CW_USEDEFAULT, CW_USEDEFAULT,
                
                                                     NULL, NULL, hInstance, NULL) ;
                
        ShowWindow (hwnd, iCmdShow) ;
                
        UpdateWindow (hwnd) ;
                    
                
        while (GetMessage (&msg, NULL, 0, 0))
                
        {
                
                        TranslateMessage (&msg) ;
                
                        DispatchMessage (&msg) ;
                
        }
                
                        return msg.wParam ;
                
}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
                
{
        HDC                 hdc ;
                
        PAINTSTRUCT ps ;

        RECT             rect;        

  HBRUSH         brush;
                
        switch (message)
                
        {
          case     WM_CREATE:

            SetTimer(hwnd,ID_TIMER,500,NULL);

      return 0;

    case     WM_TIMER:

      hdc = GetDC (hwnd) ;

      if(!IsOutOfRegion(CurrentTericsInfo.shape,CurrentTericsInfo.dir,
          CurrentTericsInfo.x,(CurrentTericsInfo.y+1)))
        {    
                ++CurrentTericsInfo.y;
          EraseGameRegion(hdc);
          DrawGameRegion(hdc);
          LoadCurrentTerics(hdc);
          DrawTerics(hdc,CurrentTericsInfo.shape,CurrentTericsInfo.dir,
            CurrentTericsInfo.x,CurrentTericsInfo.y);
        }
      else
      {
        SaveStateOfTerics(CurrentTericsInfo.shape,CurrentTericsInfo.dir,
          CurrentTericsInfo.x,CurrentTericsInfo.y);
        InvalidateRect (hwnd, NULL, FALSE) ;
      }
                        
                        ReleaseDC (hwnd, hdc) ;

      return 0;

    case     WM_PAINT:

      hdc = BeginPaint (hwnd, &ps) ;

      brush=CreateSolidBrush(RGB(165,180,255));

      GetClientRect (hwnd, &rect) ;

                  FillRect(hdc,&rect,brush);

      EraseGameRegion(hdc);

      DrawGameRegion(hdc);

      InitTericsInfo();    

      PrintInfo(hdc,szshape);

      LoadCurrentTerics(hdc);

      if(!(IsGameOver(CurrentTericsInfo.shape,CurrentTericsInfo.dir,
        CurrentTericsInfo.x,CurrentTericsInfo.y)))
      {
        DrawTerics(hdc,CurrentTericsInfo.shape,CurrentTericsInfo.dir,
          CurrentTericsInfo.x,CurrentTericsInfo.y);    
      }
      else
      {
        char szscore[200];
        wsprintf(szscore,"complete %d score",score);
        KillTimer (hwnd, ID_TIMER) ;
        MessageBox(hwnd,szscore,TEXT("GameOver"),MB_OK);
      }

      EndPaint(hwnd,&ps);

                        return 0 ;

    case     WM_KEYDOWN:
        
                        hdc=GetDC(hwnd);

      switch(wParam)
      {
      case VK_UP:

        if(!IsOutOfRegion(CurrentTericsInfo.shape,(CurrentTericsInfo.dir+1)%4,
          CurrentTericsInfo.x,CurrentTericsInfo.y))
        {
          CurrentTericsInfo.dir=++CurrentTericsInfo.dir%4;
          EraseGameRegion(hdc);
          DrawGameRegion(hdc);
          LoadCurrentTerics(hdc);
          DrawTerics(hdc,CurrentTericsInfo.shape,CurrentTericsInfo.dir,
            CurrentTericsInfo.x,CurrentTericsInfo.y);
        }

        return 0;
      case VK_DOWN:

                                if(!IsOutOfRegion(CurrentTericsInfo.shape,CurrentTericsInfo.dir,
          CurrentTericsInfo.x,(CurrentTericsInfo.y+1)))
        {
          ++CurrentTericsInfo.y;
          EraseGameRegion(hdc);
          DrawGameRegion(hdc);
          LoadCurrentTerics(hdc);
          DrawTerics(hdc,CurrentTericsInfo.shape,CurrentTericsInfo.dir,
            CurrentTericsInfo.x,CurrentTericsInfo.y);
        }
        else
        {
          SaveStateOfTerics(CurrentTericsInfo.shape,CurrentTericsInfo.dir,
                  CurrentTericsInfo.x,CurrentTericsInfo.y);
//          PrintInfo(hdc,szshape[rj++]);
          InvalidateRect(hwnd,NULL,FALSE);
        }
                                    
        return 0;
      case VK_LEFT:
        
                                if(!IsOutOfRegion(CurrentTericsInfo.shape,CurrentTericsInfo.dir,
          (CurrentTericsInfo.x-1),CurrentTericsInfo.y))
        {
          --CurrentTericsInfo.x;
          EraseGameRegion(hdc);
          DrawGameRegion(hdc);
          LoadCurrentTerics(hdc);
          DrawTerics(hdc,CurrentTericsInfo.shape,CurrentTericsInfo.dir,
            CurrentTericsInfo.x,CurrentTericsInfo.y);
        }

        return 0;
      case VK_RIGHT:

                                if(!IsOutOfRegion(CurrentTericsInfo.shape,CurrentTericsInfo.dir,
          (CurrentTericsInfo.x+1),CurrentTericsInfo.y))
        {
          ++CurrentTericsInfo.x;
          EraseGameRegion(hdc);
          DrawGameRegion(hdc);
          LoadCurrentTerics(hdc);
          DrawTerics(hdc,CurrentTericsInfo.shape,CurrentTericsInfo.dir,
            CurrentTericsInfo.x,CurrentTericsInfo.y);
        }

        return 0;
      }
      ReleaseDC(hwnd,hdc);
      return 0;


    case     WM_DESTROY:

//      KillTimer (hwnd, ID_TIMER) ;
                
                        PostQuitMessage (0) ;
                
                        return 0 ;
    default:

      return DefWindowProc (hwnd, message, wParam, lParam);    
                
        }
                
        return 0;
                
}

void DrawGameRegion(HDC hdc)
{
  HBRUSH brush;
  int LeftX,LeftY,RightX,RightY;
  LeftX=GameSizeX;
  LeftY=GameSizeY;
  RightX=LeftX+GameRegionWidth*SquareSize;
  RightY=LeftY+GameRegionHeight*SquareSize;
  brush=CreateSolidBrush(RGB(165,180,255));
  SelectObject(hdc,brush);
  Rectangle(hdc,LeftX,LeftY,RightX,RightY);
  DeleteObject(brush);
}

void DrawRectangle(HDC hdc,int shape,int x,int y)
{
  HBRUSH brush;
  int leftx=GameSizeX+SquareSize*x;
  int lefty=GameSizeY+SquareSize*y;
  int rightx=leftx+SquareSize;
  int righty=lefty+SquareSize;
  brush=CreateSolidBrush(color[shape]);
  SelectObject(hdc,brush);
  Rectangle(hdc,leftx,lefty,rightx,righty);
  DeleteObject(brush);
}

void DrawTerics(HDC hdc,int shape,int dir,int x,int y)
{
  int index;
  RECT rect;
  for(index=0;index<4;index++)
  {
    nx[index]=Terics[shape][dir][index].x+x;
    ny[index]=Terics[shape][dir][index].y+y;
    rect.left=nx[index];
    rect.top=ny[index];
    rect.right=nx[index]+SquareSize;
    rect.bottom=ny[index]+SquareSize;
    DrawRectangle(hdc,shape,nx[index],ny[index]);
  }
}

BOOL IsOutOfRegion(int shape,int dir,int x,int y)
{
  int index;
  int nx,ny;
  for(index=0;index<4;index++)
  {
    nx=Terics[shape][dir][index].x+x;
    ny=Terics[shape][dir][index].y+y;
    if(nx<0||nx>=GameRegionWidth||ny<0||ny>=GameRegionHeight||GameMapStatesInfo[nx][ny].states!=0)
    {
      return TRUE;
    }
  }
  return FALSE;
    
}

void InitTericsInfo()
{        
  int *p=szshape;
  srand((unsigned)time(NULL));
  CurrentTericsInfo.shape=rand()%7;
  CurrentTericsInfo.dir=0;
  CurrentTericsInfo.x=4;
  CurrentTericsInfo.y=0;
  *p++=CurrentTericsInfo.shape;
}


void EraseGameRegion(HDC hdc)
{
  RECT rect;
  HBRUSH brush;
  rect.left=GameSizeX;
  rect.top=GameSizeY;
  rect.right=GameSizeX+GameRegionWidth*SquareSize;
  rect.bottom=GameSizeY+GameRegionHeight*SquareSize;
  brush=CreateSolidBrush(RGB(255,255,255));
  FillRect(hdc,&rect,brush);
  DeleteObject(brush);
}

void SaveStateOfTerics(int shape, int dir, int x, int y)                    
{        
  int index;
  int nx,ny;    
        int indexX,indexY;
  BOOL flag;
  int m,n;
  for ( index = 0; index < 4; ++index)                
  {        
    nx=Terics[shape][dir][index].x+x;
    ny=Terics[shape][dir][index].y+y;
         GameMapStatesInfo[nx][ny].states = 1;    
    GameMapStatesInfo[nx][ny].shapes=shape;
  }    
  for(indexX=0;indexX<GameRegionHeight;indexX++)
  {
    flag=TRUE;
    for(indexY=0;indexY<GameRegionWidth;indexY++)
    {
      if(GameMapStatesInfo[indexY][indexX].states!=1)
      {
        flag=FALSE;
      }
    }
    if(flag)
    {
      for(m=indexX;m>=1;--m)
      {
        for(n=0;n<GameRegionWidth;++n)
        {
          GameMapStatesInfo[n][m].states=GameMapStatesInfo[n][m-1].states;
          GameMapStatesInfo[n][m].shapes=GameMapStatesInfo[n][m-1].shapes;
        }
      }
      ++count;
    }
  }
}

void LoadCurrentTerics(HDC hdc)
{
  int indexX,indexY;
  for(indexX=0;indexX<GameRegionWidth;indexX++)
  {
    for(indexY=0;indexY<GameRegionHeight;indexY++)
    {
      if(GameMapStatesInfo[indexX][indexY].states==1)
      {
        DrawRectangle(hdc,GameMapStatesInfo[indexX][indexY].shapes,indexX,indexY);
      }
    }
  }
}

void PrintInfo(HDC hdc,int *shape)
{
  char szscore[200]="score:";
  char strscore[20];
  score=count*10;
  itoa(score,strscore,10);
  strcat(szscore,strscore);
  SetBkColor(hdc,RGB(165,180,255));
  TextOut(hdc,600,100,szscore,strlen(szscore));
  DrawTerics(hdc,*shape,0,15,5);
}

BOOL IsGameOver(int shape,int dir,int x,int y)
{
  int index;
  int nx,ny;
  for(index=0;index<4;index++)
  {
    nx=Terics[shape][dir][index].x+x;
    ny=Terics[shape][dir][index].y+y;
    if(ny==0 && GameMapStatesInfo[nx][ny].states==1)
    {
      return TRUE;
    }
  }
  return FALSE;

}
 
大家運行過這個代碼後肯定也會發現其中的一些問題,例如窗口“閃動”比較厲害等,希望大家可以給出一些比較好的建議,怎樣才能使效率更高,效果更好。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章