C语言/C++编程学习:C语言实现《黑夜迷宫逃亡》小游戏

C语言是面向过程的,而C++是面向对象的

C和C++的区别:

C是一个结构化语言,它的重点在于算法和数据结构。C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到输出(或实现过程(事务)控制)。

C++,首要考虑的是如何构造一个对象模型,让这个模型能够契合与之对应的问题域,这样就可以通过获取对象的状态信息得到输出或实现过程(事务)控制。 所以C与C++的最大区别在于它们的用于解决问题的思想方法不一样。之所以说C++比C更先进,是因为“ 设计这个概念已经被融入到C++之中 ”。

C与C++的最大区别:在于它们的用于解决问题的思想方法不一样。之所以说C++比C更先进,是因为“ 设计这个概念已经被融入到C++之中 ”,而就语言本身而言,在C中更多的是算法的概念。那么是不是C就不重要了,错!算法是程序设计的基础,好的设计如果没有好的算法,一样不行。而且,“C加上好的设计”也能写出非常好的东西。

今天给大家带来的是一个迷宫游戏,可能大家就会觉得迷宫游戏有什么好玩的,写出来也很简单,不过呢,今天的迷宫游戏却比一般的迷宫游戏要有趣多了。

从标题上就透露出了一些信息,既然是《黑夜迷宫逃亡》,那么游戏的环境肯定是在黑夜中进行来的了,是不是难度就大了许多,那我们先去看看游戏的情况吧。

首先游戏开始的时候,可以看到迷宫地图的全貌,当然了,也只会持续很短的时间,实际上考验的就是大家的记忆力,你要是能够把游戏地图全貌都能记下来,我只能说 :“ 你不适合玩这种游戏!”

小编推荐一个学C语言/C++的学习裙【 六九九,四七零,五九六 】,无论你是大牛还是小白,是想转行还是想入行都可以来了解一起进步一起学习!裙内有开发工具,很多干货和技术资料分享!

然后呢,当夜幕降临的时候,整个地图就都会陷入一片黑漆漆的环境中,想要在这样的环境中走出迷宫是很难的。不过啦,因为主角光环的需要,我们的主角获得了 “ 随身小手电 +1 ”,用来帮助主角走出迷宫。

随身小手电的方向随着鼠标的移动而移动,然后根据黑夜降临前我们所记住的整个迷宫的地图大概位置项前行走,逃出黑夜中的迷宫。

最后,主角凭借着光环效果,走到了出口,我们的游戏就这样结束了! “ o_O 此处应有掌声 ”

喜欢的可以自己对照源码写出来玩玩,可以的话,请大家多多转发关注哦!

下期看下源码:

#include

#include

#include

#include

// 定义常量

#define PI3.14// 圆周率

#define UNIT_GROUND0// 表示地面

#define UNIT_WALL1// 表示墙

#define LIGHT_API / 3// 灯光的角度范围

#defineLIGHT_R120// 灯光的照射距离

#defineWIDTH480// 迷宫的宽度

#defineHEIGHT480// 迷宫的高度

#define SCREENWIDTH640// 屏幕宽度

#defineSCREENHEIGHT480// 屏幕高度

#defineUNIT20// 每个墙壁单位的大小

#define PLAYER_R5// 游戏者的半径

// 定义常量

constSIZEg_utMap = { 23, 23 };// 迷宫地图的尺寸(基于 UNIT 单位)

constPOINTg_utPlayer = { 1, 1 };// 游戏者的位置(基于 UNIT 单位)

constPOINTg_utExit = { 21, 22 };// 出口位置(基于 UNIT 单位)

constPOINTg_ptOffset = { 10, 10 };// 迷宫显示在屏幕上的偏移量

// 定义全局变量

POINTg_ptPlayer;// 游戏者的位置

POINTg_ptMouse;// 鼠标位置

IMAGEg_imgMap(WIDTH, HEIGHT);// 迷宫平面图

DWORD*g_bufMap;// 迷宫平面图的显存指针

IMAGEg_imgRender(WIDTH, HEIGHT);// 渲染

DWORD*g_bufRender;// 渲染的显存指针

DWORD*g_bufScreen;// 屏幕的显存指针

// 枚举用户的控制命令

enum CMD { CMD_QUIT = 1, CMD_UP = 2, CMD_DOWN = 4, CMD_LEFT = 8, CMD_RIGHT = 16, CMD_RESTART = 32 };

// 函数声明

voidWelcome();// 绘制游戏界面

voidReadyGo();// 准备开始游戏

voidInitGame();// 初始化游戏数据

// 迷宫生成

voidMakeMaze(int width, int height);// 初始化(注:宽高必须是奇数)

voidTravelMaze(int x, int y, BYTE** aryMap);// 遍历 (x, y) 四周

voidDrawWall(int x, int y, bool left, bool top, bool right, bool bottom);

// 画一面墙

// 绘制

voidPaint();// 绘制视野范围内的迷宫

voidLighting(int _x, int _y, double _a);// 在指定位置和角度“照明”

voidDrawPlayer();// 绘制游戏者

voidDrawExit();// 绘制出口

// 处理用户控制

intGetCmd();// 获取用户输入的命令

voidOnUp();// 向上移动

voidOnLeft();// 向左移动

voidOnRight();// 向右移动

voidOnDown();// 向下移动

boolCheckWin();// 检查是否到出口

// 主程序

void main()

{

// 初始化

initgraph(SCREENWIDTH, SCREENHEIGHT);// 创建绘图窗口

srand((unsigned)time(NULL));// 设置随机种子

// 显示主界面

Welcome();

// 游戏过程

int c;

do

{

ReadyGo();

while (true)

{

// 获得用户输入

c = GetCmd();

// 处理用户输入

if (c & CMD_UP)OnUp();

if (c & CMD_DOWN)OnDown();

if (c & CMD_LEFT)OnLeft();

if (c & CMD_RIGHT)OnRight();

if (c & CMD_RESTART)

{

if (MessageBox(GetHWnd(), _T("您要重来一局吗?"), _T("询问"), MB_OKCANCEL | MB_ICONQUESTION) == IDOK)

break;

}

if (c & CMD_QUIT)

{

if (MessageBox(GetHWnd(), _T("您确定要退出游戏吗?"), _T("询问"), MB_OKCANCEL | MB_ICONQUESTION) == IDOK)

break;

}

// 绘制场景

Paint();

// 判断是否走出迷宫

if (CheckWin())

{

// 是否再来一局

HWND hwnd = GetHWnd();

if (MessageBox(hwnd, _T("恭喜你走出来了! 您想再来一局吗?"), _T("恭喜"), MB_YESNO | MB_ICONQUESTION) != IDYES)

c = CMD_QUIT;

break;

}

// 延时

Sleep(16);

}

} while (!(c & CMD_QUIT));

// 关闭图形模式

closegraph();

}

// 准备开始游戏

void ReadyGo()

{

// 初始化

InitGame();

// 黑夜降临前兆

int time[7] = { 1000, 50, 500, 50, 50, 50, 50 };

int i, x, y;

for (i = 0; i < 7; i++)

{

if (i % 2 == 0)

{

putimage(0, 0, &g_imgMap);

DrawPlayer();

DrawExit();

}

else

clearrectangle(0, 0, WIDTH - 1, HEIGHT - 1);

Sleep(time[i]);

}

// 黑夜缓慢降临

for (i = 255; i >= 0; i -= 5)

{

for (y = (HEIGHT - 1) * SCREENWIDTH; y >= 0; y -= SCREENWIDTH)

for (x = 0; x < WIDTH; x++)

if (g_bufScreen[y + x] != 0)

g_bufScreen[y + x] = g_bufScreen[y + x] - 0x050505;

FlushBatchDraw();

DrawPlayer();

DrawExit();

Sleep(50);

}

// 绘制游戏区

Paint();

}

// 绘制游戏界面

void Welcome()

{

setfillcolor(DARKGRAY);

solidrectangle(WIDTH, 0, SCREENWIDTH - 1, SCREENHEIGHT - 1);

// 设置字体样式

settextcolor(WHITE);

setbkmode(TRANSPARENT);

// 绘制标题

settextstyle(24, 0, _T("宋体"));

outtextxy(490, 40, _T("黑夜迷宫逃亡"));

// 绘制操作说明

RECT r = { 488, 100, 632, 470 };

settextstyle(12, 0, _T("宋体"));

drawtext(_T("[游戏说明]:   黑夜降临啦,尽快离开黑夜中的迷宫哦。迅速借助你的小手电,在漆黑的迷宫里

找到出口逃出去吧。 [控制说明] 方向键: 移动 A/S/D/W:移动 鼠标:  控制照射

方向 F2:   重来一局 ESC:  退出游戏"), &r, DT_WORDBREAK);

}

// 初始化游戏数据

void InitGame()

{

// 获得窗口显存指针

g_bufRender = GetImageBuffer(&g_imgRender);

g_bufMap = GetImageBuffer(&g_imgMap);

g_bufScreen = GetImageBuffer(NULL);

// 设置 Render 环境

SetWorkingImage(&g_imgRender);

setbkmode(TRANSPARENT);

SetWorkingImage(NULL);

// 创建迷宫

MakeMaze(g_utMap.cx, g_utMap.cy);

// 设置游戏者位置

g_ptPlayer.x = g_utPlayer.x * UNIT + UNIT / 2 + g_ptOffset.x;

g_ptPlayer.y = g_utPlayer.y * UNIT + UNIT / 2 + g_ptOffset.y;

}

// 生成迷宫:初始化(注:宽高必须是奇数)

void MakeMaze(int width, int height)

{

if (width % 2 != 1 || height % 2 != 1)

return;

int x, y;

// 定义迷宫二维数组,并初始化全部为墙壁

// 宽高比实际多 2,是因为两端各有一个“哨兵”,用于方便处理数据

BYTE** aryMap = new BYTE*[width + 2];

for (x = 0; x < width + 2; x++)

{

aryMap[x] = new BYTE[height + 2];

memset(aryMap[x], UNIT_WALL, height + 2);

}

// 定义边界(哨兵功能)

for (x = 0; x <= width + 1; x++)

aryMap[x][0] = aryMap[x][height + 1] = UNIT_GROUND;

for (y = 1; y <= height; y++)

aryMap[0][y] = aryMap[width + 1][y] = UNIT_GROUND;

// 从任意点开始遍历生成迷宫

TravelMaze(((rand() % (width - 1)) & 0xfffe) + 2, ((rand() % (height - 1)) & 0xfffe) + 2, aryMap);

// 设置出口

aryMap[g_utExit.x + 1][g_utExit.y + 1] = UNIT_GROUND;

// 将迷宫绘制在 IMAGE 对象上

SetWorkingImage(&g_imgMap);

cleardevice();

for (y = 1; y <= height; y++)

for (x = 1; x <= width; x++)

if (aryMap[x][y] == UNIT_WALL)

DrawWall(x, y, aryMap[x - 1][y] == UNIT_WALL,

aryMap[x][y - 1] == UNIT_WALL,

aryMap[x + 1][y] == UNIT_WALL,

aryMap[x][y + 1] == UNIT_WALL);

SetWorkingImage(NULL);

}

小编推荐一个学C语言/C++的学习裙【 六九九,四七零,五九六 】,无论你是大牛还是小白,是想转行还是想入行都可以来了解一起进步一起学习!裙内有开发工具,很多干货和技术资料分享!

// 生成迷宫:遍历 (x, y) 四周

void TravelMaze(int x, int y, BYTE** aryMap)

{

// 定义遍历方向

int d[4][2] = { 0, 1, 1, 0, 0, -1, -1, 0 };

// 将遍历方向乱序

int n, t, i;

for (i = 0; i < 4; i++)

{

n = rand() % 4;

t = d[i][0], d[i][0] = d[n][0], d[n][0] = t;

t = d[i][1], d[i][1] = d[n][1], d[n][1] = t;

}

// 尝试周围四个方向

aryMap[x][y] = UNIT_GROUND;

for (i = 0; i < 4; i++)

if (aryMap[x + 2 * d[i][0]][y + 2 * d[i][1]] == UNIT_WALL)

{

aryMap[x + d[i][0]][y + d[i][1]] = UNIT_GROUND;

TravelMaze(x + d[i][0] * 2, y + d[i][1] * 2, aryMap);// 递归

}

}

// 生成迷宫:画一面墙

// 参数:left/top/right/bottom 表示墙壁是否与旁边连接

void DrawWall(int x, int y, bool left, bool top, bool right, bool bottom)

{

// 墙壁厚 4 pixel

int cx, cy;

cx = x * UNIT - UNIT / 2 - 2 + 10;

cy = y * UNIT - UNIT / 2 - 2 + 10;

if (left)solidrectangle(x * UNIT - UNIT + 10, cy, cx + 4, cy + 4);

if (top)solidrectangle(cx, y * UNIT - UNIT + 10, cx + 4, cy + 4);

if (right)solidrectangle(cx, cy, x * UNIT + 9, cy + 4);

if (bottom)solidrectangle(cx, cy, cx + 4, y * UNIT + 9);

}

// 绘制视野范围内的迷宫

void Paint()

{

// 设置绘图目标为 Render 对象

SetWorkingImage(&g_imgRender);

// 清空 Render 对象

cleardevice();

// 计算视野角度

double dx, dy, a;

dx = g_ptMouse.x - g_ptPlayer.x;

dy = g_ptMouse.y - g_ptPlayer.y;

if (dx == 0 && dy == 0)

a = 0;

else if (dx != 0 && dy != 0)

a = atan(dy / dx);

else if (dx == 0)

a = (dy > 0) ? PI / 2 : PI * 3 / 2;

else

a = 0;

if (dx < 0)a += PI;

if (a < 0) a += PI * 2;

// 绘制灯光

Lighting(g_ptPlayer.x, g_ptPlayer.y, a);

// 画游戏者

DrawPlayer();

// 画出口

DrawExit();

// 设置绘图目标为窗口

SetWorkingImage(NULL);

// 显示到窗口上

putimage(0, 0, &g_imgRender);

}

// 在指定位置和角度“照明”

void Lighting(int _x, int _y, double _a)

{

int i;// 定义循环变量

int x, y;// 定义临时坐标

double a;// 定义临时角度

// 计算灯光照亮的角度区域

double a1 = _a - LIGHT_A / 2;

double a2 = _a + LIGHT_A / 2;

for (a = a1; a < a2; a += PI / 360)// 扇形循环

{

for (int r = 0; r < LIGHT_R; r++)// 半径循环

{

// 计算照射到的位置

x = (int)(_x + cos(a) * r);

y = (int)(_y + sin(a) * r);

// 光线超出屏幕范围,终止

// (为了简化全凭模糊运算,不处理最上和最下一行)

if (x < 0 || x >= WIDTH || y <= 0 || y >= HEIGHT - 1)

break;

// 光线碰到墙壁,终止

if (g_bufMap[y * WIDTH + x])

break;

// 光线叠加

g_bufRender[y * WIDTH + x] += 0x202000;// 0x202000 是很淡的黄色

}

}

// 计算光照扇形区域的最小包围矩形

// 方法:获得 7 个点的最值:圆心、圆弧两端、圆与 xy 轴的 4 个交点

// 第一步:初始化 7 个点

POINT pt[7];

pt[0].x = _x;pt[0].y = _y;

pt[1].x = int(_x + LIGHT_R * cos(a1) + 0.5);pt[1].y = int(_y + LIGHT_R * sin(a1) + 0.5);

pt[2].x = int(_x + LIGHT_R * cos(a2) + 0.5);pt[2].y = int(_y + LIGHT_R * sin(a2) + 0.5);

for (a = ceil(a1 * 4 / (2 * PI)) * (PI / 2), i = 3; a < a2; a += PI / 2, i++)

{

pt[i].x = int(_x + LIGHT_R * cos(a) + 0.5);

pt[i].y = int(_y + LIGHT_R * sin(a) + 0.5);

}

// 第二步:获取 7 个点的最大最小值,得到最小包围矩形

i--;

RECT r = { pt[i].x, pt[i].y, pt[i].x, pt[i].y };

for (--i; i >= 0; i--)

{

if (pt[i].x < r.left)r.left = pt[i].x;

if (pt[i].x > r.right)r.right = pt[i].x;

if (pt[i].y < r.top)r.top = pt[i].y;

if (pt[i].y > r.bottom)r.bottom = pt[i].y;

}

// 调整矩形范围

if (r.left < 0)r.left = 0;

if (r.top < 1)r.top = 1;

if (r.right >= WIDTH)r.right = WIDTH - 1;

if (r.bottom >= HEIGHT - 1)r.bottom = HEIGHT - 2;

// 修正曝光过度的点

for (y = r.top; y <= r.bottom; y++)

for (x = r.left; x <= r.right; x++)

{

i = y * WIDTH + x;

if (g_bufRender[i] > 0xffff00)

g_bufRender[i] = 0xffff00;

}

// 将光线模糊处理(避开墙壁)

for (y = r.top; y <= r.bottom; y++)

for (x = r.left; x <= r.right; x++)

{

i = y * WIDTH + x;

if (!g_bufMap[i])

g_bufRender[i] = RGB(

(GetRValue(g_bufRender[i - WIDTH]) + GetRValue(g_bufRender[i - 1]) + GetRValue(g_bufRender[i])

+ GetRValue(g_bufRender[i + 1]) + GetRValue(g_bufRender[i + WIDTH])) / 5,

(GetGValue(g_bufRender[i - WIDTH]) + GetGValue(g_bufRender[i - 1]) + GetGValue(g_bufRender[i])

+ GetGValue(g_bufRender[i + 1]) + GetGValue(g_bufRender[i + WIDTH])) / 5,

(GetBValue(g_bufRender[i - WIDTH]) + GetBValue(g_bufRender[i - 1]) + GetBValue(g_bufRender[i])

+ GetBValue(g_bufRender[i + 1]) + GetBValue(g_bufRender[i + WIDTH])) / 5);

}

}

// 绘制游戏者

void DrawPlayer()

{

// 画安全帽

setlinecolor(DARKGRAY);

circle(g_ptPlayer.x, g_ptPlayer.y, 5);

}

// 绘制出口

void DrawExit()

{

settextstyle(12, 0, _T("宋体"));

outtextxy(g_utExit.x * UNIT + g_ptOffset.x, g_utExit.y * UNIT + g_ptOffset.y + 8, _T("出口"));

}

// 获取用户输入的命令

int GetCmd()

{

int c = 0;

if ((GetAsyncKeyState(VK_LEFT) & 0x8000) ||

(GetAsyncKeyState('A') & 0x8000))c |= CMD_LEFT;

if ((GetAsyncKeyState(VK_RIGHT) & 0x8000) ||

(GetAsyncKeyState('D') & 0x8000))c |= CMD_RIGHT;

if ((GetAsyncKeyState(VK_UP) & 0x8000) ||

(GetAsyncKeyState('W') & 0x8000))c |= CMD_UP;

if ((GetAsyncKeyState(VK_DOWN) & 0x8000) ||

(GetAsyncKeyState('S') & 0x8000))c |= CMD_DOWN;

if (GetAsyncKeyState(VK_F2) & 0x8000)c |= CMD_RESTART;

if (GetAsyncKeyState(VK_ESCAPE) & 0x8000)c |= CMD_QUIT;

MOUSEMSG m;

while (MouseHit())

{

m = GetMouseMsg();

g_ptMouse.x = m.x;

g_ptMouse.y = m.y;

}

return c;

}

// 向上移动

void OnUp()

{

int i = (g_ptPlayer.y - 6) * WIDTH + (g_ptPlayer.x - 5) + 1;

int j;

for (j = 0; j < 5; j++, i += 2)

if (g_bufMap[i])

break;

if (j == 5)

g_ptPlayer.y--;

}

// 向左移动

void OnLeft()

{

int i = (g_ptPlayer.y - 5) * WIDTH + (g_ptPlayer.x - 5);

int j;

for (j = 0; j < 5; j++, i += WIDTH)

if (g_bufMap[i])

break;

if (j == 5)

g_ptPlayer.x--;

}

// 向右移动

void OnRight()

{

int i = (g_ptPlayer.y - 5) * WIDTH + (g_ptPlayer.x + 5) + 1;

int j;

for (j = 0; j < 5; j++, i += WIDTH)

if (g_bufMap[i])

break;

if (j == 5)

g_ptPlayer.x++;

}

// 向下移动

void OnDown()

{

int i = (g_ptPlayer.y + 5) * WIDTH + (g_ptPlayer.x - 5) + 1;

int j;

for (j = 0; j < 5; j++, i += 2)

if (g_bufMap[i])

break;

if (j == 5)

g_ptPlayer.y++;

}

小编推荐一个学C语言/C++的学习裙【 六九九,四七零,五九六 】,无论你是大牛还是小白,是想转行还是想入行都可以来了解一起进步一起学习!裙内有开发工具,很多干货和技术资料分享!

// 检查是否到出口

bool CheckWin()

{

return (g_ptPlayer.y >= g_utExit.y * UNIT + UNIT / 2 + g_ptOffset.y);

}

这些是C/C++能做的

服务器开发工程师、人工智能、云计算工程师、信息安全(黑客反黑客)、大数据 、数据平台、嵌入式工程师、流媒体服务器、数据控解、图像处理、音频视频开发工程师、游戏服务器、分布式系统、游戏辅助等

可以的话,请大家多多转发关注!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容