C語言/C加加編程基礎入門俄羅斯方塊源代碼分享

[代碼運行效果截圖]

[c++]代碼庫

/*

*/


#include

#include

#include


#define CELL 20

#define ROWS 25

#define COLS 15

//升級所需分數值

#define SCORE_LEVEL_INC 80

#define ID_TIMER 1


/////////////////全局變量/////////////////////////////

HWND?hwnd;?//保存窗口句柄


int?score=0;?//分數

int?level=0;?//級數

int?interval_unit=25;?//隨級數遞增的時間間隔增量

int?interval_base=300;?//時間間隔基量

int?old_interval;?//保存當前的時間間隔,用于加速操作


int?cur_left,cur_top;?//記錄方塊當前的位置

int?width_block,height_block;?//方塊的寬帶和高度


bool?isPause=false;?//暫停標識

UINT?timer_id=0;?//保存計時器ID


static?byte *block=NULL;?//方塊,方塊為隨機大小,采用動態分配內存方式,所以這里是指針變量

byte g_panel[ROWS][COLS]={0};

////////////////////////////////////////////////////

LRESULT?CALLBACK WndProc (?HWND,UINT,WPARAM,LPARAM?);

void?DrawPanel (?HDC?hdc );?//繪制表格

void?RefreshPanel (?HDC?hdc );?//刷新面板

void?DoDownShift (?HDC?hdc );?//下移

void?DoLeftShift (?HDC?hdc );?//左移

void?DoRightShift (?HDC?hdc );?//右移

void?DoAccelerate (?HDC?hdc );?//加速

void?DoRedirection (?HDC?hdc );?//改變方向

void?ClearRow (?HDC?hdc );?//消行

bool?ExportBlock();?//輸出方塊,

//該函數會直接修改全局變量block,width_block,height_block,

//cur_left和cur_top

bool?IsTouchBottom (?HDC?hdc );?//判斷是否到達底部


int?main()

{

????HINSTANCE?hInstance=GetModuleHandle ( NULL );

????TCHAR?szAppName[]=TEXT (?"teris"?);

????MSG msg;

????WNDCLASS wc;


????wc.style=CS_HREDRAW|CS_VREDRAW;

????wc.lpfnWndProc=WndProc;

????wc.cbClsExtra=0;

????wc.cbWndExtra=0;

????wc.hInstance=hInstance;

????wc.hIcon=LoadIcon ( NULL,IDI_APPLICATION );

????wc.hCursor=LoadCursor ( NULL,IDC_ARROW );

????wc.hbrBackground= (?HBRUSH?) GetStockObject ( WHITE_BRUSH );

????wc.lpszMenuName=NULL;

????wc.lpszClassName=szAppName;

????if?( !RegisterClass ( &wc ) )

????{

????????printf?(?"RegisterClass occur errors!"?);

????????return?0;

????}

????hwnd=CreateWindow ( szAppName,TEXT (?"Teris Demo"?),

????????????????????????WS_OVERLAPPEDWINDOW,

????????????????????????0,0,0,0,

????????????????????????NULL,

????????????????????????NULL,

????????????????????????hInstance,

????????????????????????NULL );

????ShowWindow ( hwnd,SW_SHOW );

????UpdateWindow ( hwnd );

????while?( GetMessage ( &msg,NULL,0,0 ) )

????{

????????TranslateMessage ( &msg );

????????DispatchMessage ( &msg );

????}

????return?msg.wParam;

}


void?DrawPanel (?HDC?hdc )?//繪制游戲面板

{

????int?x,y;

????RECT rect;


????for?( y=0; y

????{

????????for?( x=0; x

????????{

????????????//計算方塊的邊框范圍

????????????rect.top=y*CELL+1;

????????????rect.bottom= ( y+1 ) *CELL-1;

????????????rect.left=x*CELL+1;

????????????rect.right= ( x+1 ) *CELL-1;

????????????FrameRect ( hdc,&rect, (?HBRUSH?) GetStockObject ( BLACK_BRUSH ) );

????????}

????}

}


void?DoDownShift (?HDC?hdc )?//下移

{

????if?( NULL==block )?return;


????//判斷是否到達底部

????if?( IsTouchBottom ( hdc ) )?//到底部

????{

????????//消行處理

????????ClearRow ( hdc );

????????ExportBlock();?//輸出下一個方塊

????}


????cur_top++;

????RefreshPanel ( hdc );

}


void?DoLeftShift (?HDC?hdc )?//左移

{

????int?x,y;

????if?( NULL==block )?return;


????if?( 0==cur_left )?return;

????if?( cur_top<0 )?return;?//方塊沒有完整顯示前,不能左移

????for?( y=0; y

????{

????????for?( x=0; x

????????{

????????????if?( * ( block+y*width_block+x ) )

????????????{

????????????????//判斷當前方格在面板上面左邊一個方格是否為實心,是就代表不能再左移

????????????????if?( g_panel[cur_top+y][cur_left+x-1] )?return;


????????????????break;?//只判斷最左邊的一個實心方格,之后直接掃描下一行

????????????}

????????}

????}

????cur_left--;

????RefreshPanel ( hdc );

}


void?DoRightShift (?HDC?hdc )?//右移

{

????int?x,y;

????if?( NULL==block )?return;


????if?( COLS-width_block==cur_left )?return;

????if?( cur_top<0 )?return;?//方塊完整顯示前不能右移

????for?( y=0; y

????{

????????for?( x=width_block-1; x>=0; x-- )?//從右邊開始掃描,獲取該行最右邊的實心方格塊

????????{

????????????if?( * ( block+y*width_block+x ) )

????????????{

????????????????//判斷當前方格在面板上右邊一個方格是否為實心,是就代表不能再右移

????????????????if?( g_panel[cur_top+y][cur_left+x+1] )?return;


????????????????break;?//只判斷最右邊的一個實心方格

????????????}

????????}

????}

????cur_left++;

????RefreshPanel ( hdc );

}


void?DoRedirection (?HDC?hdc )?//改變方向

{

????int?i,j;

????byte * temp=NULL;

????if?( NULL==block )?return;

????if?( cur_top<0 )?return;?//方塊完整顯示前不能轉向


????temp= ( byte * )?malloc?(?sizeof?( byte ) *width_block*height_block );

????for?( i=0; i

????{

????????for?( j=0; j

????????{

????????????//temp[i][j]=block[height_block-j-1][i];

????????????* ( temp+i*height_block+j ) =* ( block+ ( height_block-j-1 ) *width_block+i );

????????}

????}


????//給方塊重新定位

????int?incHeight=width_block-height_block;

????int?incWidth=height_block-width_block;

????int?temp_cur_top=cur_top-incHeight/2;

????int?temp_cur_left=cur_left-incWidth/2;


????//system("cls");

????//printf("temp_top=%d, temp_left=%d",temp_cur_top,temp_cur_left);


????//判斷當前空間是否足夠讓方塊改變方向

????int?max_len=max ( width_block,height_block );

????//防止下標訪問越界

????if?( temp_cur_top+max_len-1>=ROWS||temp_cur_left<0||temp_cur_left+max_len-1>=COLS )

????{

????????free?( temp );?//退出前必須先釋放內存

????????return;

????}

????for?( i=0; i

????{

????????for?( j=0; j

????????{

????????????//轉向所需的空間內有已被占用的實心方格存在,即轉向失敗

????????????if?( g_panel[temp_cur_top+i][temp_cur_left+j] )

????????????{

????????????????free?( temp );?//退出前必須先釋放內存

????????????????return;

????????????}

????????}

????}


????//把臨時變量的值賦給block,只能賦值,而不能賦指針值

????for?( i=0; i

????{

????????for?( j=0; j

????????{

????????????//block[i][j]=temp[i][j];

????????????* ( block+i*width_block+j ) =* ( temp+i*width_block+j );

????????}

????}


????//全局變量重新被賦值

????cur_top=temp_cur_top;

????cur_left=temp_cur_left;

????//交換

????i=width_block;

????width_block=height_block;

????height_block=i;


????free?( temp );?//釋放為臨時變量分配的內存

????RefreshPanel ( hdc );

}


void?DoAccelerate (?HDC?hdc )?//加速

{

????if?( NULL==block )?return;


????if?( IsTouchBottom ( hdc ) )

????{

????????//消行處理

????????ClearRow ( hdc );

????????ExportBlock();

????}

????cur_top++;

????RefreshPanel ( hdc );

}


bool?IsTouchBottom (?HDC?hdc )

{

????int?x,y;

????int?i,j;


????if?( NULL==block )?return?false;

????if?( ROWS==cur_top+height_block )

????{

????????//固定方塊

????????for?( i=0; i

????????{

????????????for?( j=0; j

????????????{

????????????????if?( * ( block+i*width_block+j ) ) g_panel[cur_top+i][cur_left+j]=1;

????????????}

????????}

????????return?true;

????}

????for?( y=height_block-1; y>=0; y-- )?//從底行開始掃描

????{

????????//判斷第一個實心方塊在面板上鄰接的下方方格是否為實心,是就代表已經到達底部

????????for?( x=0; x

????????{

????????????if?( * ( block+y*width_block+x ) )

????????????{

????????????????if?( cur_top+y+1<0 )?return?false;

????????????????if?( g_panel[cur_top+y+1][cur_left+x] )

????????????????{

????????????????????//判斷是否gameover

????????????????????if?( cur_top<=0 )

????????????????????{

????????????????????????if?( timer_id )

????????????????????????{

????????????????????????????KillTimer ( hwnd,ID_TIMER );

????????????????????????????timer_id=0;

????????????????????????}

????????????????????????MessageBox ( hwnd,TEXT (?"游戲結束"?),TEXT (?"MSG"?),MB_OK|MB_ICONEXCLAMATION );

????????????????????????SendMessage ( hwnd,WM_CLOSE,0,0 );

????????????????????}

????????????????????//

????????????????????//固定方塊

????????????????????for?( i=0; i

????????????????????{

????????????????????????for?( j=0; j

????????????????????????{

????????????????????????????if?( * ( block+i*width_block+j ) ) g_panel[cur_top+i][cur_left+j]=1;

????????????????????????}

????????????????????}

????????????????????return?true;

????????????????}

????????????}

????????}

????}

????return?false;

}


void?ClearRow (?HDC?hdc )?//消行

{

????int?i,j,k;

????int?count=0;?//消行次數

????bool?isFilled;

????//消行處理

????for?( i=ROWS-1; i>=0; i-- )

????{

????????isFilled=true;

????????for?( j=0; j

????????{

????????????if?( !g_panel[i][j] )

????????????{

????????????????isFilled=false;

????????????????break;

????????????}

????????}

????????if?( isFilled )

????????{

????????????for?( j=0; j

????????????{

????????????????g_panel[i][j]=0;

????????????}

????????????//所有方塊往下移

????????????for?( k=i-1; k>=0; k-- )

????????????{

????????????????for?( j=0; j

????????????????{

????????????????????g_panel[k+1][j]=g_panel[k][j];

????????????????}

????????????}

????????????i=i+1;

????????????count++;

????????}

????}


????//最高級別為9級,所以分數極限為(9+1)*SCORE_LEVEL_INC-1

????if?( score>=10*SCORE_LEVEL_INC-1 )?return;


????//加分規則:消除行數,1行加10分,2行加15分,3行加20分,4行加30分

????switch?( count )

????{

????case?1:

????????score+=10;

????????break;

????case?2:

????????score+=15;

????????break;

????case?3:

????????score+=20;

????????break;

????case?4:

????????score+=30;

????????break;

????}


????int?temp_level=score/SCORE_LEVEL_INC;

????if?( temp_level>level )

????{

????????level=temp_level;

????????//撤銷當前計時器,然后重設

????????if?( timer_id ) KillTimer ( hwnd,ID_TIMER );

????????timer_id=SetTimer ( hwnd,ID_TIMER,interval_base-level*interval_unit,NULL );

????}


????system?(?"cls"?);

????printf?(?"score: %d, level: %d ",score,level );

}


void?RefreshPanel (?HDC?hdc )?//刷新面板

{

????int?x,y;

????RECT rect;

????HBRUSH?h_bSolid= (?HBRUSH?) GetStockObject ( GRAY_BRUSH ),

?????????????????????h_bEmpty= (?HBRUSH?) GetStockObject ( WHITE_BRUSH );

????if?( NULL==block )?return;


????//先刷屏

????for?( y=0; y

????{

????????for?( x=0; x

????????{

????????????//為避免刷掉方塊的邊框,rect范圍必須比邊框范圍小1

????????????rect.top=y*CELL+2;

????????????rect.bottom= ( y+1 ) *CELL-2;

????????????rect.left=x*CELL+2;

????????????rect.right= ( x+1 ) *CELL-2;

????????????if?( g_panel[y][x] )

????????????????FillRect ( hdc,&rect,h_bSolid );

????????????else

????????????????FillRect ( hdc,&rect,h_bEmpty );

????????}

????}

????//再定位方塊

????for?( y=0; y

????{

????????for?( x=0; x

????????{

????????????if?( * ( block+y*width_block+x ) )?//實心

????????????{

????????????????rect.top= ( y+cur_top ) *CELL+2;

????????????????rect.bottom= ( y+cur_top+1 ) *CELL-2;

????????????????rect.left= ( x+cur_left ) *CELL+2;

????????????????rect.right= ( x+cur_left+1 ) *CELL-2;

????????????????FillRect ( hdc,&rect,h_bSolid );

????????????}

????????}

????}

}


bool?ExportBlock()?//輸出方塊

{

????int?sel;

????if?( block )

????{

????????free?( block );?//釋放之前分配的內存

????????block=NULL;

????}


????sel=rand() %7;

????switch?( sel )

????{

????case?0:?//水平條

????????width_block=4;

????????height_block=1;

????????block= ( byte * )?malloc?(?sizeof?( byte ) *width_block*height_block );

????????* ( block+0 ) =1;?//可以理解為*(block+0*width_block+0)=1,即第一行的第一個方格,下面同理

????????* ( block+1 ) =1;?//*(block+0*width_block+1)=1

????????* ( block+2 ) =1;?//*(block+0*width_block+2)=1

????????* ( block+3 ) =1;?//*(block+0*width_block+3)=1


????????cur_top=0-height_block;

????????cur_left= ( COLS-width_block ) /2;

????????break;

????case?1:?//三角

????????width_block=3;

????????height_block=2;

????????block= ( byte * )?malloc?(?sizeof?( byte ) *width_block*height_block );

????????* ( block+0 ) =0;?//可以理解為*(block+0*width_block+0)=0,即第一行的第一個方格,下面同理

????????* ( block+1 ) =1;?//*(block+0*width_block+1)=1

????????* ( block+2 ) =0;?//*(block+0*width_block+2)=0

????????* ( block+3 ) =1;?//*(block+1*width_block+0)=1,第二行開始

????????* ( block+4 ) =1;?//*(block+1*width_block+1)=1

????????* ( block+5 ) =1;?//*(block+1*width_block+2)=1


????????cur_top=0-height_block;

????????cur_left= ( COLS-width_block ) /2;

????????break;

????case?2:?//左橫折

????????width_block=3;

????????height_block=2;

????????block= ( byte * )?malloc?(?sizeof?( byte ) *width_block*height_block );

????????* ( block+0 ) =1;?//可以理解為*(block+0*width_block+0)=1,下面同理

????????* ( block+1 ) =0;?//*(block+0*width_block+1)=0

????????* ( block+2 ) =0;?//*(block+0*width_block+2)=0

????????* ( block+3 ) =1;?//*(block+1*width_block+0)=1

????????* ( block+4 ) =1;?//*(block+1*width_block+1)=1

????????* ( block+5 ) =1;?//*(block+1*width_block+2)=1


????????cur_top=0-height_block;

????????cur_left= ( COLS-width_block ) /2;

????????break;

????case?3:?//右橫折

????????width_block=3;

????????height_block=2;

????????block= ( byte * )?malloc?(?sizeof?( byte ) *width_block*height_block );

????????* ( block+0 ) =0;?//可以理解為*(block+0*width_block+0)=0,下面同理

????????* ( block+1 ) =0;?//*(block+0*width_block+1)=0

????????* ( block+2 ) =1;?//*(block+0*width_block+2)=1

????????* ( block+3 ) =1;?//*(block+1*width_block+0)=1

????????* ( block+4 ) =1;?//*(block+1*width_block+1)=1

????????* ( block+5 ) =1;?//*(block+1*width_block+2)=1


????????cur_top=0-height_block;

????????cur_left= ( COLS-width_block ) /2;

????????break;

????case?4:?//左閃電

????????width_block=3;

????????height_block=2;

????????block= ( byte * )?malloc?(?sizeof?( byte ) *width_block*height_block );

????????* ( block+0 ) =1;?//可以理解為*(block+0*width_block+0)=1,下面同理

????????* ( block+1 ) =1;?//*(block+0*width_block+1)=1

????????* ( block+2 ) =0;?//*(block+0*width_block+2)=0

????????* ( block+3 ) =0;?//*(block+1*width_block+0)=0

????????* ( block+4 ) =1;?//*(block+1*width_block+1)=1

????????* ( block+5 ) =1;?//*(block+1*width_block+2)=1


????????cur_top=0-height_block;

????????cur_left= ( COLS-width_block ) /2;

????????break;

????case?5:?//右閃電

????????width_block=3;

????????height_block=2;

????????block= ( byte * )?malloc?(?sizeof?( byte ) *width_block*height_block );

????????* ( block+0 ) =0;?//可以理解為*(block+0*width_block+0)=0,下面同理

????????* ( block+1 ) =1;?//*(block+0*width_block+1)=1

????????* ( block+2 ) =1;?//*(block+0*width_block+2)=1

????????* ( block+3 ) =1;?//*(block+1*width_block+0)=1

????????* ( block+4 ) =1;?//*(block+1*width_block+1)=1

????????* ( block+5 ) =0;?//*(block+1*width_block+2)=0


????????cur_top=0-height_block;

????????cur_left= ( COLS-width_block ) /2;

????????break;

????case?6:?//石頭

????????width_block=2;

????????height_block=2;

????????block= ( byte * )?malloc?(?sizeof?( byte ) *width_block*height_block );

????????* ( block+0 ) =1;?//可以理解為*(block+0*width_block+0)=1,下面同理

????????* ( block+1 ) =1;?//*(block+0*width_block+1)=1

????????* ( block+2 ) =1;?//*(block+1*width_block+0)=1

????????* ( block+3 ) =1;?//*(block+1*width_block+1)=1


????????cur_top=0-height_block;

????????cur_left= ( COLS-width_block ) /2;

????????break;

????}

????return?block!=NULL;

}


LRESULT?CALLBACK WndProc (?HWND?hwnd,UINT?message,WPARAM?wParam,LPARAM?lParam )

{

????HDC?hdc;

????PAINTSTRUCT ps;

????//TCHAR szBuffer[1024];


????switch?( message )

????{

????case?WM_CREATE:

????????MoveWindow ( hwnd,400,10,CELL*COLS+8,CELL*ROWS+32,FALSE );?//補齊寬度和高度

????????srand?(?time?( NULL ) );

????????ExportBlock();


????????timer_id=SetTimer ( hwnd,ID_TIMER,interval_base-level*interval_unit,NULL );

????????return?0;

????case?WM_TIMER:

????????hdc=GetDC ( hwnd );

????????DoDownShift ( hdc );

????????ReleaseDC ( hwnd,hdc );

????????return?0;

????case?WM_KEYDOWN:

????????hdc=GetDC ( hwnd );

????????switch?( wParam )

????????{

????????case?VK_LEFT:?//左移

????????????if?( !isPause ) DoLeftShift ( hdc );

????????????break;

????????case?VK_RIGHT:?//右移

????????????if?( !isPause ) DoRightShift ( hdc );

????????????break;

????????case?VK_UP:?//轉向

????????????if?( !isPause ) DoRedirection ( hdc );

????????????break;

????????case?VK_DOWN:?//加速

????????????if?( !isPause ) DoAccelerate ( hdc );

????????????break;

????????case?VK_SPACE:?//暫停

????????????isPause=!isPause;

????????????if?( isPause )

????????????{

????????????????if?( timer_id ) KillTimer ( hwnd,ID_TIMER );

????????????????timer_id=0;

????????????}

????????????else

????????????{

????????????????timer_id=SetTimer ( hwnd,ID_TIMER,interval_base-level*interval_unit,FALSE );

????????????}

????????????break;

????????}

????????ReleaseDC ( hwnd,hdc );

????????return?0;

????case?WM_PAINT:

????????hdc=BeginPaint ( hwnd,&ps );

????????DrawPanel ( hdc );?//繪制面板

????????RefreshPanel ( hdc );?//刷新

????????EndPaint ( hwnd,&ps );

????????return?0;

????case?WM_DESTROY:

????????if?( block )?free?( block );

????????if?( timer_id ) KillTimer ( hwnd,ID_TIMER );

????????PostQuitMessage ( 0 );

????????return?0;

????}

????return?DefWindowProc ( hwnd,message,wParam,lParam );

}

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,501評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,673評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,610評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,939評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,668評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,004評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,001評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,173評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,705評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,426評論 3 359
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,656評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,139評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,833評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,247評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,580評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,371評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,621評論 2 380

推薦閱讀更多精彩內容