栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++制作俄罗斯方块

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++制作俄罗斯方块

缘起:

  在玩Codeblocks自带的俄罗斯方块时觉得不错,然而有时间限制。所以想自己再写一个。

程序效果:

主要内容:

  程序中有一个board数组,其中有要显示的部分,也有不显示的部分,不显示的部分都存储1。

  如下图:

  shape采用4*4数组(shape)保存。如:

    0 0 0 0
    0 1 0 0
    1 1 1 0
    0 0 0 0

  另外用变量row和column保存shape数组左上角在board中的位置。

  每次下落或左右移动,先对row和column做出改变,然后检测当前row和column下,shape是否重合了为1的格子,如果有重合,就说明shape出界了或者到达下落最低点,则要恢复row和column值。另外,如果是下落,还要将shape放在board上,并产生新的shape。

  旋转时,先对shape数组进行旋转操作,然后检测重合,如果有重合,则反向旋转回来。

代码:

#if defined(UNICODE) && !defined(_UNICODE)
#define _UNICODE
#elif defined(_UNICODE) && !defined(UNICODE)
#define UNICODE
#endif

#include 
#include 
#include 
#include 
#include 

#define WIDTH 180
#define HEIGHT 400
#define LONG_SLEEP 300
#define BKCOLOR RGB(238,238,238)//背景色

static int shapes[7][4][4];//存储7个形状
static int high_score[4]= {0,0,0,0};//前三个元素存储最高分,最后一个元素存储此次得分
static int **shape;//当前形状
static int **board;
static int M=15;//显示的列数
static int N=30;//显示的行数
static int MM=M+8;//board的列数
static int NN=N+4;//board的行数
static int LEFT=4;//显示的最左一列
static int RIGHT=LEFT+M-1;//显示的最右一列
static int TOP=0;//显示的最上一列
static int BOTTOM=N-1;//显示的最下一列
static int score=0;
static int row=0;//形状所在行
static int column=MM/2;//形状坐在列
static bool is_pause=false;
static HBRUSH grey_brush =CreateSolidBrush (RGB(210,210,210));
static HBRUSH white_brush =CreateSolidBrush (RGB(130,130,130));
static HBRUSH bk_brush =CreateSolidBrush (BKCOLOR);
static HPEN hPen = CreatePen(PS_SOLID,1,RGB(147,155,166));
static int lattices_top=40;//上面留白
static int lattices_left=20;//左侧留白
static int width=WIDTH/M;//每个格子的宽度
static int height=(HEIGHT-lattices_top)/N;//每个格子的高度

void add_score() ;
bool check_is_lose() ;
void clear_up() ;//消除没有空格子的行
void* down_thread_function(void * args) ;//形状下落进程要执行的函数
void exit_game(HWND hwnd) ;
void give_new_shape() ;//随机生成一个新形状
int handle_key(HWND hwnd,WPARAM wParam) ;
int init_down_thread(HWND hwnd) ;//初始化形状下落进程
int init_game(HWND hwnd) ;//初始化游戏程序
void init_play() ;//初始化游戏数据
bool is_legel() ;//检测形状在当前位置是否合法(即是否重合了非空的格子)
int load_scores(int* a) ;//读取游戏最高分数据
int load_shape() ;//从文件中加载7个形状
void lose_game(HWND hwnd) ;
int move_down(HWND hwnd) ;//形状下落
int move_lr(HWND hwnd,int lr) ;//形状左右移动
void paint_lattice(HDC hdc,int x,int y,int color) ;//显示一个格子
void paint_UI(HDC hdc) ;//画界面
void reset_rc() ;
void rerotate_matrix(int mn) ;//顺时针旋转一个行列数为mn的方阵
void rotate_matrix(int mn) ;//逆时针旋转一个行列数为mn的方阵
int rotate_shape(HWND hwnd) ;//旋转当前形状并更新界面
bool save_score(HWND hwnd) ;//保存最高分数据
void shape_to_ground() ;//当前形状落地之后,更新board
bool sort_scores(int* a) ;//对最高分和此次得分排序,若创造新纪录则返回true
void update_UI(HWND hwnd) ;//更新界面,仅更新Rect区域(形状所在的那几行)内
void update_UI_all(HWND hwnd) ;//更新界面,更新整个界面
int write_scores(int* a) ;//写最高分数据





LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);


TCHAR szClassName[ ] = _T("Tris");

int WINAPI WinMain (HINSTANCE hThisInstance,
   HINSTANCE hPrevInstance,
   LPSTR lpszArgument,
   int nCmdShow) {
  HWND hwnd; 
  MSG messages;      
  WNDCLASSEX wincl;    

  
  wincl.hInstance = hThisInstance;
  wincl.lpszClassName = szClassName;
  wincl.lpfnWndProc = WindowProcedure;   
  wincl.style = CS_DBLCLKS;  
  wincl.cbSize = sizeof (WNDCLASSEX);

  
  wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
  wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
  wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
  wincl.lpszMenuName = NULL;  
  wincl.cbClsExtra = 0;    
  wincl.cbWndExtra = 0;    
  
  wincl.hbrBackground =bk_brush;
  
  if (!RegisterClassEx (&wincl))
    return 0;

  
  hwnd = CreateWindowEx (
 0,   
 szClassName,     
 _T("Tris"),    
 WS_OVERLAPPEDWINDOW, 
 CW_USEDEFAULT,    
 CW_USEDEFAULT,    
 WIDTH+200,  
 HEIGHT+70,  
 HWND_DESKTOP,    
 NULL, 
 hThisInstance,    
 NULL  
      );

  
  ShowWindow (hwnd, nCmdShow);

  
  while (GetMessage (&messages, NULL, 0, 0)) {
    
    TranslateMessage(&messages);
    
    DispatchMessage(&messages);
  }

  
  return messages.wParam;
}
//从文件中加载7个形状
int load_shape() {
  FILE* f=fopen("shapes.txt","rb");
  if(f==NULL) {
    return -1;
  }
  for(int i=0; i<7; i++) {
    for(int j=0; j<4; j++) {
      for(int k=0; k<4; k++) {
 if(fscanf(f,"%d",&shapes[i][j][k])!=1) {
   return -1;
 }
      }
    }
  }
  fclose(f);
  return 0;
}
//随机生成一个新形状
void give_new_shape() {
  int shape_num=rand()%7;
  for(int i=0; i<4; i++) {
    for(int j=0; j<4; j++) {
      shape[i][j]=shapes[shape_num][i][j];
    }
  }
}
void add_score() {
  score+=100;
}
//消除没有空格子的行
void clear_up() {
  for(int i=row; i<=row+3; i++) {
    if(i>BOTTOM)continue;
    bool there_is_blank=false;
    for(int j=LEFT; j<=RIGHT; j++) {
      if(board[i][j]==0) {
 there_is_blank=true;
 break;
      }
    }
    if(!there_is_blank) {
      add_score();
      for(int r=i; r>=1; r--) {
 for(int c=LEFT; c<=RIGHT; c++) {
   board[r][c]=board[r-1][c];
 }
      }
    }
  }
}
//检测形状在当前位置是否合法(即是否重合了非空的格子)
bool is_legel() {
  for(int i=0; i<4; i++) {
    for(int j=0; j<4; j++) {
      if(shape[i][j]==1&&board[row+i][column+j]==1) {
 return false;
      }
    }
  }
  return true;
}
//逆时针旋转一个行列数为mn的方阵
void rotate_matrix(int mn) {
  int** a=shape;
  int s=0;
  for(int n=mn; n>=1; n-=2) {
    for(int i=0; i=1; n-=2) {
    for(int i=0; iBOTTOM||yRIGHT) {
    return ;
  }
  x-=TOP;
  y-=LEFT;
  int left=lattices_left+y*width;
  int right=lattices_left+y*width+width;
  int top=lattices_top+x*height;
  int bottom=lattices_top+x*height+height;
  MoveToEx (hdc,left,top, NULL) ;
  LineTo (hdc,right,top) ;
  MoveToEx (hdc,left,top, NULL) ;
  LineTo (hdc,left,bottom) ;
  MoveToEx (hdc,left,bottom, NULL) ;
  LineTo (hdc,right,bottom) ;
  MoveToEx (hdc,right,top, NULL) ;
  LineTo (hdc,right,bottom) ;
  SelectObject(hdc, grey_brush);
  if(color==0) {
    SelectObject(hdc, white_brush);
  }
  Rectangle(hdc,left,top,right,bottom);
}
//更新界面,仅更新Rect区域(形状所在的那几行)内
void update_UI(HWND hwnd) {
  static RECT rect;
  rect.left=lattices_left;
  rect.right=lattices_left+M*width+width;
  rect.top=lattices_top+(row-1)*height;
  rect.bottom=lattices_top+(row+4)*height;
  InvalidateRect (hwnd,&rect, false) ;
}
//更新界面,更新整个界面
void update_UI_all(HWND hwnd) {
  InvalidateRect (hwnd,NULL, false) ;
}
//画界面
void paint_UI(HDC hdc) {
  SetBkColor(hdc,BKCOLOR);
  SelectObject(hdc,hPen); //选用画笔
  char score_str[20];
  sprintf(score_str,"Score:%d",score);
  TextOut(hdc,10,10,score_str,strlen(score_str));
  sprintf(score_str,"Highest Scores:");
  TextOut(hdc,WIDTH+50,50,score_str,strlen(score_str));
  for(int i=0; i<3; i++) {
    sprintf(score_str,"%d",high_score[i]);
    TextOut(hdc,WIDTH+50,50+(i+1)*20,score_str,strlen(score_str));
  }
  for(int i=TOP; i<=BOTTOM; i++) {
    for(int j=LEFT; j<=RIGHT; j++) {
      paint_lattice(hdc,i,j,board[i][j]);
    }
  }
  for(int i=0; i<4; i++) {
    for(int j=0; j<4; j++) {
      if(shape[i][j]==1)
 paint_lattice(hdc,row+i,column+j,shape[i][j]);
    }
  }
}
//旋转当前形状并更新界面
int rotate_shape(HWND hwnd) {
  int mn=4;
  rotate_matrix(mn);
  if(!is_legel()) {
    rerotate_matrix(mn);
  }
  update_UI(hwnd);
}
void reset_rc() {
  row=0;
  column=MM/2-2;
}
//读取游戏最高分数据
int load_scores(int* a) {
  FILE* f=fopen("scores.txt","r");
  if(f==NULL)return -1;
  fscanf(f,"%d%d%d",&a[0],&a[1],&a[2]);
  return 0;
}
//初始化游戏数据
void init_play() {
  load_scores(high_score);
  for(int i=0; iarg_hwnd;
  while(true) {
    if(is_pause) {
      Sleep(300);
      continue;
    }
    move_down(dhwnd);
    Sleep(LONG_SLEEP);
  }
}
//初始化形状下落进程
int init_down_thread(HWND hwnd) {
  int ret;
  pthread_t t;
  thread_arg *argp=new thread_arg;
  argp->arg_hwnd=hwnd;
  ret=pthread_create(&t,NULL,down_thread_function,argp);
  delete argp;
  if(ret!=0) {
    return -1;
  }
  return 0;
}
//初始化游戏程序
int init_game(HWND hwnd) {
  board=new int*[NN];
  for(int i=0; i

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/64390.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号