带爆炸效果的扫雷(源码2)

游戏中处理地图生成,绘制,单击处理等主要逻辑的类 map.h,所有格子放在20*20=400的一个数组中,即最大支持长宽各20个格子。每个格子用一个字节表示,低四位0表示空格,1~8表示数字,9表示雷。高四位bit7~bit4: bit7表示该格子是否打开,bit6表示是否已经标记,bit5表示是否要打叉(点错或标记错的时候)。说明:除了动画以外,所有的图形元素都是32*32像素。

简单的动画:与每个格子一一对应,也用20*20=400的一个数组表示,仍是一个字节表示。低四位表示帧数,bit7表示是否播放。时间间隔150ms,在窗口的初始化InitInstance()函数中启动定时器。图形大小48*48像素。

图形处理:先用一张黑白图与DC相“与”,将要显示的地方清零,再用图案相“或”。这个方法叫“去背”。这是动画效果中用的图:

附: map.h  map.cpp

 

// 扫雷地图

#ifndef __MAP_H
#define  __MAP_H

#include 
" queue.h "

#define  G_NULL 0  // 游戏未开始
#define  G_END 1  // 游戏结束

// 表示雷
#define  BOMB 9

// 判断坐标是否合法的宏
#define  INCLOSEAREA(x,y,xsize,ysize)  ((x)>=0 && (x)<=(xsize) && (y)>=0 && (y)<=(ysize))
#define  INCLOSEINDEX(x,y)  ((x)>=0 && (x)<=(iWidth-1) && (y)>=0 && (y)<=(iHeight-1))

// 取低4位
#define  LOWBYTE(x) ((x) & 0x0f)
// 取第i个bit(0~7)
#define  GETBIT(x,i) ((x) & (1<<(i)))
#define  IS1TO9(x) ((x)>=1 && (x)<=9)

class  GameMap
{
public:
 GameMap();
 
~GameMap();

 
void Draw(void);
 
void DrawButton(void);
 
void SetMine(int iNum);
 
void SetMapSize(int w,int h);
 
int  CreateMap(void);
 
int CountBombNum(int x,int y);
 
int OpenGrid(int x,int y);//x,y是方格坐标0-8
 int Open8around(int x,int y);
 
void SetFlag(int x,int y);//作标记
 void ClearFlag(int x,int y);//作标记
 void SearchBlank(int x,int y);
 
int CheckWin(void);

 
//排行榜
 void LoadScore(void);
 
int IsNewScore(int l,int score);
 
void WriteScore(int l,char *pname, int time);
 
void GetName(int l, char *pname);
 
int GetTimeValue(int l);
 
void ResetScore(int iLevel);

 
void SetMap(int w,int h,int num);
 
void SetDC(HDC h);
 
void SetHWND(HWND h);
 
void SetHINSTANCE(HINSTANCE h);
 
void SetLevel(int l);
 
void LoadPic(void);

 
int GetHeight(void);
 
int GetWidth(void);
 
int GetNum(void);
 
int GetLevel(void);

 
//动画效果
 void DrawAnimation(void);

public:
 
int iState;
 
int iSubState;
 POINT button_pos;
 
int iFaceState;

private:
 
int iWidth;
 
int iHeight;
 
int iMineNum;
 
char pData[400];//map
 char pGray[400];
 
int nowx;
 
int nowy;
 
char info[100];
 
int iLevel;
  
 HDC hdc;
 HDC hdcmem;
 HWND hwnd;
 HINSTANCE hinstance;
 HBITMAP hbm_earth;
 HBITMAP hbm_number;
 HBITMAP hbm_bomb;
 HBITMAP hbm_mask;
 HBITMAP hbm_sign;
 HBITMAP hbm_face;
 HBITMAP hbm_flag;
 HBITMAP hbm_gray;
 HBITMAP hbm_back;

 BITMAP strBm;

 
//队列
 GQUEUE queue;

 
//score
 char scorename[80];
 
int scoretime[3];
}
;

#endif  

//// map.cpp


#include 
" stdafx.h "
#include 
" resource.h "

#include 
" map.h "

// 使用队列
#include  " queue.h "

#include 
< stdio.h >
#include 
< stdlib.h >
#include 
< time.h >

GameMap::GameMap()
{
 iWidth
=9;
 iHeight
=9;
 iMineNum
=0;

 iState
=G_NULL;//游戏没有开始

 iFaceState
=0;//NORMAL 笑脸标志

 nowx
=0;//鼠标坐标索引
 nowy=0;

 button_pos.x
= 32*iWidth+50;//定义笑脸按钮的坐标
 button_pos.y= 20;

 
//提示字符串 
 memset(info,0,sizeof(info));

 
//初始化等级
 iLevel=0;

 
//初始化成绩
 memset(scorename,0,sizeof(scorename));
 memset(scoretime,
-1,sizeof(scoretime));
}


GameMap::
~ GameMap()
{
 
//清除绘图句柄
 DeleteObject(hbm_earth);
 DeleteObject(hbm_number);
 DeleteObject( hbm_bomb);
 DeleteObject( hbm_mask);
 DeleteObject( hbm_sign);
 DeleteObject( hbm_face);
 DeleteObject( hbm_flag);
 DeleteObject( hbm_gray);
 DeleteObject( hbm_back);
}

void  GameMap::Draw( void )
{
 
int iLeft=0;
 
int ivisible=0;
 
int xStart=0;
 
int yStart=0;
 
int i=0;
 
int j=0;
 
char temp[50]={0};
 
char igrid=0;
 RECT rect;
 
 iLeft
=iMineNum;//当前雷的数量

 yStart
=0;//绘图坐标
 for(j=0;j<iHeight;j++)
 
{
  xStart
=0;
  
for(i=0;i<iWidth;i++)
  
{
   igrid
=pData[j*iWidth+i];
   
//图形显示,字节(bit7~bit0)的bit7,1,已打开,0,没有打开
   if(GETBIT(igrid,7))
   
{
    
//先画地面背景
    SelectObject(hdcmem,hbm_earth);
    BitBlt(hdc,xStart,yStart,
32,32,hdcmem,0,0,SRCCOPY);

    
//bit3~bit0 表示周围雷的数量(1~8),9表示雷
    if(BOMB==LOWBYTE(igrid) )
    
{
     
//
     SelectObject(hdcmem,hbm_bomb);
     BitBlt(hdc,xStart,yStart,
32,32,hdcmem,0,32,SRCAND);
     BitBlt(hdc,xStart,yStart,
32,32,hdcmem,0,0,SRCPAINT);
    }

    
else if(IS1TO9(LOWBYTE(igrid)))
    
{
     
//数字
     SelectObject(hdcmem,hbm_number);
     BitBlt(hdc,xStart
+8,yStart,16,32,hdcmem,LOWBYTE(igrid)*16,32,SRCAND);
     BitBlt(hdc,xStart
+8,yStart,16,32,hdcmem,LOWBYTE(igrid)*16,0,SRCPAINT);
    }

    
else
    
{
     
//空格,什么都不画
    }


   }

   
else
   
{
    
//画默认的遮盖图像
    SelectObject(hdcmem,hbm_mask);
    BitBlt(hdc,xStart,yStart,
32,32,hdcmem,0,0,SRCCOPY);

    
//bit6表示是否标记过
    if(GETBIT(igrid,6))
    
{
     
//显示标记旗帜
     SelectObject(hdcmem,hbm_flag);
     BitBlt(hdc,xStart,yStart,
32,32,hdcmem,0,0,SRCCOPY);

     iLeft
--;
    }

   }

        
   
if(G_END == iState && GETBIT(igrid,5))
   
{
    
//显示叉
    SelectObject(hdcmem,hbm_sign);
    BitBlt(hdc,xStart,yStart,
32,32,hdcmem,0,32,SRCAND);
    BitBlt(hdc,xStart,yStart,
32,32,hdcmem,0,0,SRCPAINT);
   }

   

   xStart
+=32;
  }

  yStart
+=32;
 }


 sprintf(temp,
"剩余: %d 个        ",iLeft);
 TextOut(hdc,
32*iWidth+40,150,temp, strlen(temp));

 sprintf(info,
"w:%d,h: %d, num:%d",iWidth,iHeight,iMineNum);
 TextOut(hdc,
0,32*iHeight+10,info, strlen(info)); 
}


void  GameMap::SetMine( int  iNum)
{
 iMineNum
=iNum;
}


void  GameMap::SetMapSize( int  w, int  h)
{
 
if(w<=0 || h<=0)
 
{
  
return;
 }


 iWidth
=w;
 iHeight
=h;
}


// 返回0表示失败,非0表示成功
int  GameMap::CreateMap( void )
{
 
int i=0;
 
int x=0;
 
int y=0;
 
int flag=0;
 
char temp[20]={0};

 
//根据地图大小,雷的个数生成一张地图
 if(iWidth<=1 || iHeight<=1)
 
{
  
return 0;
 }


 
if(iMineNum<=1)
 
{
  
return 0;
 }


 memset(pData,
0xff,iWidth*iHeight);

 
//在地图中放置雷
 srand((unsigned int)time(NULL));
 
for(i=0;i<iMineNum;i++)
 
{
  flag
=0;//当前没有布雷
  while(0==flag)
  
{
   
//随机生成x,y坐标
   x=rand()%iWidth;
   y
=rand()%iHeight;
   
   
if(pData[y*iWidth+x]!=BOMB)
   
{
    pData[y
*iWidth+x]=BOMB;
    flag
=1;
   }

   
else
   
{
    flag
=0;//雷的坐标重复,继续选择坐标
   }

  }

 }


 
//生成数字
 for(y=0;y<iHeight;y++)
 
{
  
for(x=0;x<iWidth;x++)
  
{
   
if(BOMB==pData[y*iWidth+x])
   
{
    
continue;
   }

   pData[y
*iWidth+x]=CountBombNum(x,y);
  }
 
 }


 
//灰度图初始化
 memset(pGray,0,400);
 
return 1;
}


int  GameMap::CountBombNum( int  x, int  y)
{
 
//雷的计数
 
//0 1 2
 
//3   4 
 
//5 6 7
 int iNum[8]={0};
 
int iSum=0;
 
int i=0;

 
if(INCLOSEAREA(x-1,y-1,iWidth-1,iHeight-1))
 
{
  iNum[
0]=( pData[(y-1)*iWidth+x-1]==BOMB)?1:0;
 }


 
if(INCLOSEAREA(x,y-1,iWidth-1,iHeight-1))
 
{
  iNum[
1]=( pData[(y-1)*iWidth+x]==BOMB)?1:0;
 }


 
if(INCLOSEAREA(x+1,y-1,iWidth-1,iHeight-1))
 
{
  iNum[
2]=( pData[(y-1)*iWidth+x+1]==BOMB)?1:0;
 }


 
//第2层
 if(INCLOSEAREA(x-1,y,iWidth-1,iHeight-1))
 
{
  iNum[
3]=( pData[y*iWidth+x-1]==BOMB)?1:0;
 }


 
if(INCLOSEAREA(x+1,y,iWidth-1,iHeight-1))
 
{
  iNum[
4]=( pData[y*iWidth+x+1]==BOMB)?1:0;
 }


 
//第3层
 if(INCLOSEAREA(x-1,y+1,iWidth-1,iHeight-1))
 
{
  iNum[
5]=( pData[(y+1)*iWidth+x-1]==BOMB)?1:0;
 }


 
if(INCLOSEAREA(x,y+1,iWidth-1,iHeight-1))
 
{
  iNum[
6]=( pData[(y+1)*iWidth+x]==BOMB)?1:0;
 }


 
if(INCLOSEAREA(x+1,y+1,iWidth-1,iHeight-1))
 
{
  iNum[
7]=( pData[(y+1)*iWidth+x+1]==BOMB)?1:0;
 }



 
for(i=0;i<8;i++)
 
{
  iSum
+=iNum[i];
 }


 
return iSum;
}


void  GameMap::SetDC(HDC h)
{
 hdc
=h;
}


void  GameMap::SetHWND(HWND h)
{
 hwnd
=h;
}


void  GameMap::SetHINSTANCE(HINSTANCE h)
{
 hinstance
=h;
}


void  GameMap::LoadPic( void )
{
 
if(!hinstance)
 
{
  MessageBox(hwnd,
"Load Picture:instance is null","bitmap",MB_OK);
 }


 
//hbm_earth=LoadBitmap(hinstance,"pic/earth.bmp");
 hbm_earth=LoadBitmap(hinstance,MAKEINTRESOURCE(IDB_EARTH));
 hbm_number
=LoadBitmap(hinstance,MAKEINTRESOURCE(IDB_NUMBER)); 
 hbm_bomb
=LoadBitmap(hinstance,MAKEINTRESOURCE(IDB_BOMB)); 
 hbm_mask
=LoadBitmap(hinstance,MAKEINTRESOURCE(IDB_MASK)); 
 hbm_sign
=LoadBitmap(hinstance,MAKEINTRESOURCE(IDB_SIGN));
 hbm_face
=LoadBitmap(hinstance,MAKEINTRESOURCE(IDB_FACE));
 hbm_flag
=LoadBitmap(hinstance,MAKEINTRESOURCE(IDB_FLAG));
 hbm_gray
=LoadBitmap(hinstance,MAKEINTRESOURCE(IDB_GRAY));
 hbm_back
=LoadBitmap(hinstance,MAKEINTRESOURCE(IDB_BACK));

 hdc
=GetDC(hwnd);
 hdcmem
=CreateCompatibleDC(hdc);
 ReleaseDC(hwnd,hdc);
}


// return 1: 打开了雷
int  GameMap::OpenGrid( int  x, int  y)
{
 
int i;
 
 
if(GETBIT(pData[y*iWidth+x] , 7))
 
{
  
//已经打开的格子不处理
  return 0;
 }


 
if(GETBIT(pData[y*iWidth+x] , 6))
 
{
  
//已经标记的格子不处理
  return 0;
 }


 
//bit7 置1 ,表示打开
 pData[y*iWidth+x] |=0x80;
 
 
//动画效果
 pGray[y*iWidth+x] |=0x80;


 
if(BOMB==LOWBYTE(pData[y*iWidth+x]))
 
{
  iState
=G_END;
  iFaceState
=3;//笑脸标志,哭

  
//bit5置1,表示该雷被点击,要显示叉
  pData[y*iWidth+x] |=0x20;
  
  
//点中雷的界面处理  
  for(i=0;i<iWidth*iHeight;i++)
  
{
   
if(BOMB==LOWBYTE(pData[i]))
   
{
    
if! GETBIT(pData[i],6))
    
{
     
//还没有标记出的雷置为显示态
     pData[i]|=0x80;
    }
    
   }

   
else
   
{
    
if( GETBIT(pData[i],6) )
    
{
     
//不是雷的格子如果有标记,则要显示叉
     pData[i]|=0x20;
    }

   }

  }

  
return 1;
 }

 
else if(0==LOWBYTE(pData[y*iWidth+x]))
 
{
  
//空白格子搜索
  SearchBlank(x,y);
 }

 
return 0;
}


void  GameMap::DrawButton( void )
{
 SelectObject(hdcmem,hbm_face);
 BitBlt(hdc,button_pos.x,button_pos.y,
32,32,hdcmem,iFaceState*32,0,SRCCOPY);
}


void  GameMap::SearchBlank( int  x, int  y)
{
 
int tempindex[16]={-1-1,  0-11-1
                 
-1 ,0,          10
        
-11,   01,  11}
;              
 
int i;

 
//bit7: visible
 
//0 :earth
 
//9: bomb
 POINT temp;
 POINT temparound;
 
 
//表示可见
 pData[y*iWidth+x]|=0x80;
 temp.x
=x;
 temp.y
=y;
 
 queue.CreateQueue(iWidth
*iHeight);

 queue.InQueue(temp);
 
while(!queue.IsEmpty())
 
{

  temp
=queue.OutQueue();
  
if(temp.y>iWidth-1 || temp.x>iWidth-1)
  
{
   MessageBox(hwnd,
"index error","err",MB_OK);
   
return;
  }

  
//打开当前格子
  pData[temp.y*iWidth+temp.x] |= 0x80;
  
  
for(i=0;i<8;i++)
  
{
   
//判断周围8个格子
   temparound.x = temp.x+tempindex[i*2];
   temparound.y 
= temp.y+tempindex[i*2+1];

   
//判断坐标是否合法
   if ( INCLOSEINDEX(temparound.x, temparound.y))
   
{
    
//周围的格子是空格,并且没有打开
    if( (0== LOWBYTE(pData[temparound.y*iWidth+temparound.x]) )
     
&& !GETBIT(pData[temparound.y*iWidth+temparound.x],7) )
    
{
     
//该格子进队列
     queue.InQueue(temparound);
    }

    
//打开格子
    pData[(temparound.y)*iWidth + temparound.x ] |= 0x80;

    
//动画效果
    pGray[(temparound.y)*iWidth + temparound.x ] |=0x80;
   }

  }

 }
 
 queue.DeleteQueue();
}


void  GameMap::SetFlag( int  x, int  y)
{
 
//已经打开的格子不允许置标记
 if( GETBIT(pData[y*iWidth+x],7) )
 
{
  
return;
 }


 
//bit6表示是否做标记,通过异或操作实现bit翻转
 pData[y*iWidth+x] ^= 0x40;
}

void  GameMap::ClearFlag( int  x, int  y)
{
 
//清除标记
 pData[y*iWidth+x] &= (~0x40);
}


int  GameMap::CheckWin( void )
{
 
int i;

 
for(i=0;i<iWidth*iHeight;i++)
 
{
  
if( BOMB ==LOWBYTE(pData[i]))
  
{
   
if(!GETBIT(pData[i],6))
   
{
    
//有一个雷未被标记
    return 0;
   }

  }

  
else if(!GETBIT(pData[i],7))
  
{
   
//不是雷的格子没有打开
   return 0;
  }

 }


 
//游戏结束
 iState=G_END;

 
return 1;
}


void  GameMap::SetMap( int  w, int  h, int  num)
{
 iWidth
=w;
 iHeight
=h;
 iMineNum
=num;
 
 
//1,2,3表示初级,中级,高级,4为无效值
 iLevel=4;

 button_pos.x
= 32*iWidth+50;
 button_pos.y
= 20;
}


int  GameMap::GetHeight( void )
{
 
return iHeight;
}


int  GameMap::GetWidth( void )
{
 
return iWidth;
}

int  GameMap::GetNum( void )
{
 
return iMineNum;
}


// 左右键同时单击某个格子
int  GameMap::Open8around( int  x, int  y)
{
 
char temp[20]={0};
 
int value=0;
 
int sign_num=0;
 
int tempindex[16]={-1-1,  0-11-1
                 
-1 ,0,          10
        
-11,   01,  11}
;   
 
int i;

 memset(info,
0,sizeof(info));

 
if! GETBIT(pData[y*iWidth+x],7))
 
{
  strcpy(info,
"not open");  
  
//没有打开
  return 0;
 }


 value
=LOWBYTE(pData[y*iWidth+x]);
 
if(value ==0 || value ==BOMB )
 
{
  strcpy(info,
"not number");
  
//不是数字
  return 0;
 }


 
//周围的雷是否都已标记
 for(i=0;i<8;i++)
 
{
  
//下标合法
  if( INCLOSEINDEX(x+tempindex[i*2], y+tempindex[i*2+1]) )
  
{
   
//bit6是否标记出
   if(  GETBIT(pData[(y+tempindex[i*2+1])*iWidth + x+tempindex[i*2]],6))
   
{
    sprintf(temp,
"(%d)%d,%d:%x; ", i, 
     x
+tempindex[i*2],y+tempindex[i*2+1],
     pData[(y
+tempindex[i*2+1])*iWidth + x+tempindex[i*2]]);
    strcat(info,temp);
    sign_num
++;     
   }

  }

 }


 
//雷的个数和该格子的数字不等,没有标记出周围所有的雷
 if(sign_num != value)
 
{
  
//sprintf(info,"not equal ",sign_num, value);
  return 0
 }


 
//打开周围的格子
 for(i=0;i<8;i++)
 
{
  
//下标合法
  if( INCLOSEINDEX(x+tempindex[i*2], y+tempindex[i*2+1]) )
  
{
   
//没有打开的格子
   if(! GETBIT(pData[(y+tempindex[i*2+1])*iWidth + x+tempindex[i*2]], 7 ))
   
{
    
//没有标记的格子
    if(! GETBIT(pData[(y+tempindex[i*2+1])*iWidth + x+tempindex[i*2]], 6 ))
    
{
     
//pData[(y+tempindex[i*2+1])*iWidth + x+tempindex[i*2]] |= 0x80;
     OpenGrid(x+tempindex[i*2], y+tempindex[i*2+1]);
    }

   }

  }

 }


 
return 1;
}


void  GameMap::SetLevel( int  l)
{
 iLevel
=l;
 
 
switch(iLevel)
 
{
 
case 0:
  iWidth
=9;
  iHeight
=9;
  iMineNum
=10;
  
break;
 
case 1:  
  iWidth
=15;
  iHeight
=15;
  iMineNum
=36;
  
//MessageBox(hwnd,"set level 1","set",MB_OK);
  break;
 
case 2:
  iWidth
=20;
  iHeight
=20;
  iMineNum
=50;
  
break;
 
default:
  
break;
 }


 button_pos.x
= 32*iWidth+50;
 button_pos.y
= 20;
}


int  GameMap::GetLevel( void )
{
 
return iLevel;
}


void  GameMap::LoadScore( void )
{
 FILE 
*f;
 f
=fopen("D:/score.dat","r");
 
 
if(!f)
 
{
  fopen(
"D:/score.dat","w");
  
return;
 }


 fread(scorename,
sizeof(char),80,f);
 fread(scoretime,
sizeof(int),3,f);
 fclose(f);
}


void  GameMap::GetName( int  l, char   * pname)
{
 
if(l>=0 && l<=2)
 
{
  
if( strlen(scorename+20*l) )
  
{
   strcpy(pname, scorename
+20*l);
  }

 }

}


void  GameMap::WriteScore( int  l, char   * pname, int  time)
{
 FILE 
*f;

 
if( strlen(pname)>=20)
 
{
  
return;
 }


 strcpy( scorename
+l*20, pname);
 scoretime[l]
=time;

 
//写到文件中
 f=fopen("D:/score.dat","w");
 
 
if(!f)
 
{
  
return;
 }


 fwrite(scorename,
sizeof(char),80,f);
 fwrite(scoretime,
sizeof(int ), 3,f);
 fclose(f);
}


int  GameMap::GetTimeValue( int  l)
{
 
if(l>=0 && l<=2)
 
{
  
if (0<=scoretime[l] && scoretime[l]<=999)
  
{
   
return scoretime[l];
  }

 }

 
return 999;
}


void  GameMap::ResetScore( int  l)
{
 FILE 
*f;

 memset(scorename
+l*20020);
 scoretime[l]
=999;

 
//写到文件中
 f=fopen("D:/score.dat","w");
 
 
if(!f)
 
{
  
return;
 }

 fwrite(scorename,
sizeof(char),80,f);
 fwrite(scoretime,
sizeof(int ), 3,f);
 fclose(f);
}


int  GameMap::IsNewScore( int  l, int  score)
{
 
if (! (l>=0 && l<=2))
 
{
  
return 0;
 }


 
if(  (unsigned)score < (unsigned)scoretime[l] )
 
{
  
//已经破了该等级的纪录
  return 1;
 }

 
return 0;
}


void  GameMap::DrawAnimation( void )
{
 
int xStart=0;
 
int yStart=0;
 
int i=0;
 
int j=0;
 
char temp[50]={0};
 
char igrid=0;
 
char iAnimation=0;
 
 yStart
=-8;//绘图坐标
 for(j=0;j<iHeight;j++)
 
{
  xStart
=-8;
  
for(i=0;i<iWidth;i++)
  
{
   igrid
=pGray[j*iWidth+i];
   
//动画显示,字节(bit7~bit0)的bit7,1,显示动画,0,没有
   if(GETBIT(igrid,7))
   
{
    iAnimation 
= LOWBYTE(igrid);
    
//先画地面背景
    SelectObject(hdcmem,hbm_gray);
    BitBlt(hdc,xStart,yStart,
48,48,hdcmem,iAnimation*48,48,SRCAND);
    BitBlt(hdc,xStart,yStart,
48,48,hdcmem,iAnimation*48,0,SRCPAINT);

    iAnimation
++;
    
if(iAnimation>2)
    
{
     
//清除播放标志bit7,恢复成0
     pGray[j*iWidth+i]=0;
    }

    
else
    
{
     
//改变动画帧,置播放标志
     pGray[j*iWidth+i]=iAnimation;
     pGray[j
*iWidth+i] |=0x80;
    }

   }

   xStart
+=32;
  }

  yStart
+=32;
 }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值