用汽车把艾萨拉之眼3箱子路线推到指定位置,路线可以自己画(游戏)

君,已阅读到文档的结尾了呢~~
c语言推箱子游戏--c语言实训
扫扫二维码,随身浏览文档
手机或平板扫扫即可继续访问
c语言推箱子游戏--c语言实训
举报该文档为侵权文档。
举报该文档含有违规或不良信息。
反馈该文档无法正常浏览。
举报该文档为重复文档。
推荐理由:
将文档分享至:
分享完整地址
文档地址:
粘贴到BBS或博客
flash地址:
支持嵌入FLASH地址的网站使用
html代码:
&embed src='/DocinViewer--144.swf' width='100%' height='600' type=application/x-shockwave-flash ALLOWFULLSCREEN='true' ALLOWSCRIPTACCESS='always'&&/embed&
450px*300px480px*400px650px*490px
支持嵌入HTML代码的网站使用
您的内容已经提交成功
您所提交的内容需要审核后才能发布,请您等待!
3秒自动关闭窗口23:09 提问
c语言实现推箱子游戏,求详细思路,谢谢
游戏说明:玩家通过键盘录入 w,s,a,d控制小人向不同方向移动,
其中w代表向上移动,s代表向下移动,a代表向左移动,d 代表向右移动,
当小人在箱子后面的时候可以推着箱子向前移动,当箱子移动到出口的位置,玩家胜利
地图如下:
##########
##########
说明: # 代表墙, O代表小人 ,' ' 代表路, X代表箱子
按赞数排序
推箱子游戏代码
二维数组描述游戏网格, 每个网格对应四种状态.
= 2 , O = 1
= 0 , X = 3 , 出口 = 4
w,s,a,d 当前小人位置为a[i][j],
以w键为例:
判断a[i+1][j]的值
如果是0or4, [i][j] = 0, a[++i][j] = 1, 刷新显示;
如果是3, a[i][j] = 0, 判断a[i+2][j]的值,
如果是4, a[++i][j] = 1, a[i+1][j] = 3, 胜利
如果是0, a[++i][j] = 1, a[i+1][j] = 3 , 刷新显示
推箱子其实关键就是碰撞判断,楼上的代码啊都不错
4093关注|3233收录
其他相似问题1975人阅读
VC/MFC(47)
推箱子(3)
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &MFC开发自己的推箱子游戏
源码下载地址:
第一:推箱子游戏的主界面
游戏的主界面其实就是8×8的区域,在初始化函数中定义它们的矩形区域,里面是我自己收集的8个选关
void CPushBoxDlg::Initi_State(int i,int j)
//int i,j;
video_flag=0;
num_video=-1;
num_step=0;
num_DB=0;//初始化箱子和目的地重合个数
for(i=0;i&8;i++)
for(j=0;j&8;j++)
face[i][j]=-1;//先全部表示成空
switch(num_hard)
case 1:sitex=4;sitey=4;//初始化人的初位置
num_box=4;
//初始化墙的位置
for(i=2;i&=4;i++)
face[0][i]=0;
for(i=1;i&=3;i++)
face[i][2]=0;
for(i=0;i&=2;i++)
face[3][i]=0;
face[4][0]=0;
for(i=0;i&=3;i++)
face[5][i]=0;
face[6][3]=0;
for(i=3;i&=5;i++)
face[7][i]=0;
for(i=4;i&=6;i++)
face[i][5]=0;
face[4][6]=0;
for(i=2;i&=4;i++)
face[i][7]=0;
for(i=4;i&=7;i++)
face[2][i]=0;
face[1][4]=0;
//初始化箱子的位置
face[3][3]=face[3][5]=face[4][3]=face[5][4]=2;
//初始化目的地的位置
face[1][3]=face[4][1]=face[6][4]=face[3][6]=4;
//初始化人的位置
face[4][4]=3;
//初始化通道的位置
face[2][3]=face[4][2]=face[3][4]=1;
case 2:sitex=6;sitey=3;
num_box=4;
//初始化墙的位置
for(i=2;i&=5;i++)
face[0][i]=0;
for(i=1;i&=2;i++)
face[i][2]=0;face[i][5]=0;
for(i=2;i&=4;i++)
face[i][1]=face[i][6]=0;
for(i=4;i&=7;i++)
face[i][0]=face[i][7]=0;
for(i=0;i&=7;i++)
face[7][i]=0;
face[5][3]=0;
//初始化箱子的位置
face[1][3]=face[1][4]=face[2][4]=face[3][5]=4;
//初始化人的位置
face[6][3]=3;
//初始化目的地的位置
face[3][4]=face[4][3]=face[5][4]=face[5][5]=2;
//初始化通道的位置
for(i=3;i&=6;i++)
face[i][2]=1;
face[5][1]=face[6][1]=face[4][4]=face[4][5]=1;
for(i=4;i&=6;i++)
face[6][i]=1;
face[2][3]=face[3][3]=1;
face[5][6]=1;
case 3:sitex=3;sitey=1;
num_box=5;
//初始化墙
for(i=2;i&=7;i++)
face[0][i]=0;
face[1][2]=0;
for(i=0;i&=2;i++)
face[2][i]=0;
for(i=3;i&=5;i++)
face[i][0]=0;
for(i=1;i&=3;i++)
face[5][i]=0;
for(i=3;i&=6;i++)
face[6][i]=0;
for(i=1;i&=4;i++)
face[i][7]=0;
face[4][6]=face[5][6]=0;
//初始化人
face[3][1]=3;//初始化箱子
face[4][2]=face[3][3]=face[2][3]=face[2][4]=face[2][5]=2;
//初始化目的地
face[3][4]=face[3][5]=face[4][3]=face[4][4]=face[4][5]=4;
//初始化通道
for(i=3;i&=6;i++)
face[1][i]=1;
face[2][6]=face[3][6]=face[3][2]=face[5][4]=face[5][5]=face[4][1]=1;
case 4:sitex=1;sitey=5;
num_box=4;
//初始化墙
for(i=2;i&=6;i++)
face[0][i]=0;
for(i=0;i&=2;i++)
face[1][i]=0;
for(i=2;i&=4;i++)
face[i][0]=face[5][6]=face[1][6]=face[2][6]=0;
face[4][1]=0;
for(i=4;i&=6;i++)
face[i][2]=0;
for(i=2;i&=6;i++)
face[6][i]=0;
for(i=2;i&=5;i++)
face[i][7]=0;
face[1][5]=3;
face[2][3]=face[3][4]=face[4][5]=2;
face[2][4]=face[3][3]=face[3][5]=4;
face[4][4]=6;
//初始化通道
face[1][3]=face[1][4]=face[2][1]=face[2][2]=face[2][5]=1;
face[3][1]=face[3][2]=face[3][6]=face[4][3]=face[4][6]=1;
for(i=3;i&=5;i++)
face[5][i]=1;
case 5:sitex=3;sitey=1;
num_box=6;
for(i=0;i&=7;i++)
face[0][i]=0;
face[6][i]=0;
for(i=0;i&=6;i++)
face[i][0]=0;
face[i][7]=0;
face[1][3]=face[3][6]=face[5][3]=0;
face[3][1]=3;//人
for(i=2;i&=4;i++)
face[i][2]=2;
face[2][5]=face[4][5]=2;
face[3][4]=6;
for(i=2;i&=4;i++)
face[i][3]=4;
face[2][4]=face[4][4]=4;
for(i=4;i&=6;i++)
face[1][i]=1;
face[5][i]=1;
face[1][1]=face[1][2]=face[2][1]=1;
face[4][1]=face[5][1]=face[5][2]=1;
face[2][6]=face[3][5]=face[4][6]=1;
case 6:sitex=4;sitey=2;
num_box=8;
for(i=0;i&=6;i++)
face[0][i]=face[7][i]=0;
for(i=0;i&=7;i++)
face[i][0]=face[i][6]=0;
face[2][3]=face[6][3]=0;
face[4][2]=3;
for(i=2;i&=4;i++)
face[3][i]=face[5][i]=2;
face[1][3]=face[4][3]=2;
for(i=1;i&=2;i++)
face[1][i]=face[2][i]=4;
face[1][i+3]=face[2][i+3]=4;
for(i=3;i&=6;i++)
face[i][1]=face[i][5]=1;
face[6][2]=face[6][4]=face[4][4]=1;
case 7:sitex=5;sitey=3;
num_box=6;
for(i=1;i&=6;i++)
face[0][i]=0;
for(i=1;i&=5;i++)
face[i][0]=face[i][7]=0;
for(i=2;i&=5;i++)
face[6][i]=0;
face[1][1]=face[1][6]=face[5][1]=face[5][2]=face[5][5]=face[5][6]=0;
face[5][3]=3;
for(i=1;i&=6;i++)
face[3][i]=4;
face[2][2]=face[2][4]=face[2][5]=face[4][2]=face[4][3]=face[4][5]=2;
for(i=2;i&=5;i++)
face[1][i]=1;
face[2][1]=face[2][3]=face[2][6]=face[4][1]=face[4][4]=face[4][6]=face[5][4]=1;
sitex=6;sitey=2;
num_box=5;
for(i=1;i&=6;i++)
face[0][i]=0;
for(i=1;i&=3;i++)
face[i][1]=face[i][6]=0;
for(i=3;i&=7;i++)
face[i][0]=face[i][7]=0;
for(i=0;i&=7;i++)
face[7][i]=0;
face[3][2]=face[5][2]=face[5][4]=face[5][5]=0;
face[6][2]=3;
face[1][2]=face[2][2]=face[1][4]=face[1][5]=face[2][5]=4;
face[2][4]=face[3][5]=face[4][5]=face[4][2]=face[5][3]=2;
for(i=1;i&=4;i++)
face[i][3]=1;
for(i=4;i&=6;i++)
face[i][1]=face[i][6]=1;
for(i=3;i&=6;i++)
face[6][i]=1;
face[3][4]=face[4][4]=1;
for(i=0;i&=MAX-1;i++)
CPushBoxDlg::face_to_video(&record[i]);
&&&&&&&&&&&&&&&&&&&&
&界面是绘制,将箱子,人,通道,墙等各种状态分别用枚举或数值表示出来
&&&&&&&&&&&&&&&&& 由于枚举赋值比较麻烦,我就用数值表示状态,
-1:空,0:墙;1:通道;2:箱子;3:人;4:目的地;5:人和目的地重合;6:箱子和目的地重合
&接下来就是根据状态绘制不同的图形了,
void CPushBoxDlg::draw_box(CRect rect,CDC *dc)
//CClientDC dc(this);
pold=dc-&SelectObject(&low);
dc-&Rectangle(rect);
pold=dc-&SelectObject(&yellow);
dc-&Rectangle(rect.left,rect.top,rect.right,rect.top+5);
dc-&Rectangle(rect.left,rect.bottom,rect.right,rect.bottom-5);
dc-&Rectangle(rect.left,rect.top,rect.left+5,rect.bottom);
dc-&Rectangle(rect.right-5,rect.top,rect.right,rect.bottom);
dc-&Rectangle(rect.left+22,rect.top,rect.left+28,rect.bottom);
dc-&Rectangle(rect.left,rect.top+22,rect.right,rect.top+28);
dc-&SelectObject(pold);
DeleteObject(&low);
// delete &
// delete &
DeleteObject(&yellow);
DeleteObject(dc);
void CPushBoxDlg::draw_box_place(CRect rect,CDC *dc)
//只需要将箱子改变颜色,改成红色就可以
pold=dc-&SelectObject(&low);
dc-&Rectangle(rect);
pold=dc-&SelectObject(&red);
dc-&Rectangle(rect.left,rect.top,rect.right,rect.top+5);
dc-&Rectangle(rect.left,rect.bottom,rect.right,rect.bottom-5);
dc-&Rectangle(rect.left,rect.top,rect.left+5,rect.bottom);
dc-&Rectangle(rect.right-5,rect.top,rect.right,rect.bottom);
dc-&Rectangle(rect.left+22,rect.top,rect.left+28,rect.bottom);
dc-&Rectangle(rect.left,rect.top+22,rect.right,rect.top+28);
dc-&SelectObject(pold);
DeleteObject(&low);
DeleteObject(&red);
//delete &
// delete &
DeleteObject(dc);
void CPushBoxDlg::draw_man(CRect rect,CDC *dc)
CPushBoxDlg::draw_path(rect,dc);
pold=dc-&SelectObject(&red);
dc-&Ellipse(CRect(rect.left+15,rect.top+5,rect.left+35,rect.top+25));//话头
dc-&Rectangle(rect.left+23,rect.top+25,rect.left+27,rect.bottom);
dc-&Rectangle(rect.left+5,rect.top+33,rect.right-5,rect.top+37);
dc-&SelectObject(pold);
DeleteObject(dc);
DeleteObject(&red);
//delete &
//delete &
void CPushBoxDlg::draw_path(CRect rect,CDC *dc)
pold=dc-&SelectObject(&low1);
dc-&Rectangle(rect);
pold=dc-&SelectObject(&blue);
dc-&Rectangle(rect.left,rect.top,rect.left+20,rect.top+20);
dc-&Rectangle(rect.right-20,rect.top,rect.right,rect.top+20);
dc-&Rectangle(rect.left,rect.bottom-20,rect.left+20,rect.bottom);
dc-&Rectangle(rect.right-20,rect.bottom-20,rect.right,rect.bottom);
dc-&Rectangle(rect.left+20,rect.top+20,rect.left+30,rect.top+30);
dc-&SelectObject(pold);
DeleteObject(dc);
DeleteObject(&low1);
DeleteObject(&blue);
//delete &
void CPushBoxDlg::draw_place(CRect rect,CDC *dc)
CPushBoxDlg::draw_path(rect,dc);
CBrush *pold=dc-&SelectObject(&low2);
dc-&Ellipse(rect.left+10,rect.top+10,rect.right-10,rect.bottom-10);
pold=dc-&SelectObject(&blue1);
dc-&Ellipse(rect.left+20,rect.top+20,rect.right-20,rect.bottom-20);
dc-&SelectObject(pold);
DeleteObject(&blue1);
DeleteObject(&low2);
DeleteObject(dc);
// delete &
void CPushBoxDlg::draw_wall(CRect rect,CDC *dc)
pold=dc-&SelectObject(&low_gray);//先全部绘成浅灰
dc-&Rectangle(rect);
pold=dc-&SelectObject(&gray);
dc-&Rectangle(rect.left,rect.top,rect.left+20,rect.top+20);
dc-&Rectangle(rect.left+30,rect.top,rect.left+50,rect.top+20);
dc-&Rectangle(rect.left,rect.top+30,rect.left+20,rect.top+50);
dc-&Rectangle(rect.left+30,rect.top+30,rect.left+50,rect.top+50);
dc-&SelectObject(pold);
DeleteObject(&gray);
DeleteObject(&low_gray);
DeleteObject(dc);
&接下来就是绘制整个界面的函数,就是根据各个区域的状态绘制不同的图形
void CPushBoxDlg::draw_game_face(CDC *dc)
//int i,j;
rect=new CR
for(ii=0;ii&=7;ii++)
for(jj=0;jj&=7;jj++)
rect-&left=START+jj*50;
rect-&right=START+(jj+1)*50;
rect-&top=START+ii*50;
rect-&bottom=START+(ii+1)*50;
switch(face[ii][jj])
case 0:CPushBoxDlg::draw_wall(rect,dc);
case 1:CPushBoxDlg::draw_path(rect,dc);
case 2:CPushBoxDlg::draw_box(rect,dc);
case 3:CPushBoxDlg::draw_man(rect,dc);
case 4:CPushBoxDlg::draw_place(rect,dc);
case 5:CPushBoxDlg::draw_man(rect,dc);
case 6:CPushBoxDlg::draw_box_place(rect,dc);
&最后就是控制键盘来移动了,其实原理很简单,就是通过改变不同区域的状态,然后重绘图形就好了。但是这需要在虚函数PreTranslateMessage(MSG* pMsg)中实现,推箱子的算法其实很简单就是多一些switch语句罢了,耐心一点就不会错了
BOOL CPushBoxDlg::PreTranslateMessage(MSG* pMsg) //处理按键消息函数
if(pMsg-&message==WM_KEYDOWN)
switch(pMsg-&wParam)
case VK_LEFT: CPushBoxDlg::start_video();
CPushBoxDlg::move_up();
case VK_RIGHT: CPushBoxDlg::start_video();
CPushBoxDlg::move_down();
case VK_UP: CPushBoxDlg::start_video();
CPushBoxDlg::move_left();
case VK_DOWN: CPushBoxDlg::start_video();
CPushBoxDlg::move_right();
//case VK_RETURN:MessageBox(&kkk&);
CPushBoxDlg::face_to_video(&record[MAX-1]);
//RedrawWindow();
text.Format(&你的位置 X: %d
%d&,sitey,sitex);
m_StatusBar.SetPaneText(0,text);
text.Format(&你走的步骤数: %d&,num_step);
m_StatusBar.SetPaneText(1,text);
//RepositionBars(AFX_IDW_CONTROLBAR_FIRST,AFX_IDW_CONTROLBAR_LAST,0);
//CPushBoxDlg::OnPaint();
CPushBoxDlg::check_result();
if(num_DB==num_box)
if(flag==false)
MessageBox(&Well done!&,&友情提示&);
return CDialog::PreTranslateMessage(pMsg);
}当然为了避免繁琐,我把上下左右移动设成函数了:void CPushBoxDlg::move_down()
switch(face[sitex][sitey+1])
case 0://遇到墙
case 1:if(face[sitex][sitey]==3)
face[sitex][sitey]=1;
face[sitex][sitey]=3;
if(face[sitex][sitey]==5)
face[sitex][sitey]=4;
face[sitex][sitey]=3;
CPushBoxDlg::draw_game_face(dc);num_step++;
case 2:switch(face[sitex][sitey+2])
case 1:if(face[sitex][sitey]==3)
face[sitex][sitey]=1;
face[sitex][sitey+1]=3;
face[sitex][sitey+2]=2;
if(face[sitex][sitey]==5)
face[sitex][sitey]=4;
face[sitex][sitey+1]=3;
face[sitex][sitey+2]=2;
}CPushBoxDlg::draw_game_face(dc);num_step++;
case 4:if(face[sitex][sitey]==3)//人时
face[sitex][sitey]=1;
face[sitex][sitey+1]=3;
face[sitex][sitey+2]=6;
if(face[sitex][sitey]==5)
face[sitex][sitey]=4;
face[sitex][sitey+1]=3;
face[sitex][sitey+2]=6;
}CPushBoxDlg::draw_game_face(dc);num_step++;
case 4:if(face[sitex][sitey]==3)//人时
face[sitex][sitey]=1;
face[sitex][sitey]=5;
if(face[sitex][sitey]==5)
face[sitex][sitey]=4;
face[sitex][sitey]=5;
}CPushBoxDlg::draw_game_face(dc);num_step++;
case 6:switch(face[sitex][sitey+2])
case 1:if(face[sitex][sitey]==3)//人时
face[sitex][sitey]=1;
face[sitex][sitey+1]=5;
face[sitex][sitey+2]=2;
if(face[sitex][sitey]==5)
face[sitex][sitey]=4;
face[sitex][sitey+1]=5;
face[sitex][sitey+2]=2;
}CPushBoxDlg::draw_game_face(dc);num_step++;
case 4:if(face[sitex][sitey]==3)//人时
face[sitex][sitey]=1;
face[sitex][sitey+1]=5;
face[sitex][sitey+2]=6;
if(face[sitex][sitey]==5)
face[sitex][sitey]=4;
face[sitex][sitey+1]=5;
face[sitex][sitey+2]=6;
}CPushBoxDlg::draw_game_face(dc);num_step++;
void CPushBoxDlg::move_left()
switch(face[sitex-1][sitey])
case 0://遇到墙
case 1:if(face[sitex][sitey]==3)
face[sitex][sitey]=1;
face[sitex][sitey]=3;
if(face[sitex][sitey]==5)
face[sitex][sitey]=4;
face[sitex][sitey]=3;
}CPushBoxDlg::draw_game_face(dc);num_step++;
case 2:switch(face[sitex-2][sitey])
case 1:if(face[sitex][sitey]==3)
face[sitex][sitey]=1;
face[sitex-1][sitey]=3;
face[sitex-2][sitey]=2;
if(face[sitex][sitey]==5)
face[sitex][sitey]=4;
face[sitex-1][sitey]=3;
face[sitex-2][sitey]=2;
}CPushBoxDlg::draw_game_face(dc);num_step++;
case 4:if(face[sitex][sitey]==3)//人时
face[sitex][sitey]=1;
face[sitex-1][sitey]=3;
face[sitex-2][sitey]=6;
if(face[sitex][sitey]==5)
face[sitex][sitey]=4;
face[sitex-1][sitey]=3;
face[sitex-2][sitey]=6;
}CPushBoxDlg::draw_game_face(dc);num_step++;
case 4:if(face[sitex][sitey]==3)//人时
face[sitex][sitey]=1;
face[sitex][sitey]=5;
if(face[sitex][sitey]==5)
face[sitex][sitey]=4;
face[sitex][sitey]=5;
}CPushBoxDlg::draw_game_face(dc);num_step++;
case 6:switch(face[sitex-2][sitey])
case 1:if(face[sitex][sitey]==3)//人时
face[sitex][sitey]=1;
face[sitex-1][sitey]=5;
face[sitex-2][sitey]=2;
if(face[sitex][sitey]==5)
face[sitex][sitey]=4;
face[sitex-1][sitey]=5;
face[sitex-2][sitey]=2;
}CPushBoxDlg::draw_game_face(dc);num_step++;
case 4:if(face[sitex][sitey]==3)//人时
face[sitex][sitey]=1;
face[sitex-1][sitey]=5;
face[sitex-2][sitey]=6;
if(face[sitex][sitey]==5)
face[sitex][sitey]=4;
face[sitex-1][sitey]=5;
face[sitex-2][sitey]=6;
}CPushBoxDlg::draw_game_face(dc);num_step++;
void CPushBoxDlg::move_right()
switch(face[sitex+1][sitey])
case 0://遇到墙
case 1:if(face[sitex][sitey]==3)
face[sitex][sitey]=1;
face[sitex][sitey]=3;
if(face[sitex][sitey]==5)
face[sitex][sitey]=4;
face[sitex][sitey]=3;
}CPushBoxDlg::draw_game_face(dc);num_step++;
case 2:switch(face[sitex+2][sitey])
case 1:if(face[sitex][sitey]==3)
face[sitex][sitey]=1;
face[sitex+1][sitey]=3;
face[sitex+2][sitey]=2;
if(face[sitex][sitey]==5)
face[sitex][sitey]=4;
face[sitex+1][sitey]=3;
face[sitex+2][sitey]=2;
}CPushBoxDlg::draw_game_face(dc);num_step++;
case 4:if(face[sitex][sitey]==3)//人时
face[sitex][sitey]=1;
face[sitex+1][sitey]=3;
face[sitex+2][sitey]=6;
if(face[sitex][sitey]==5)
face[sitex][sitey]=4;
face[sitex+1][sitey]=3;
face[sitex+2][sitey]=6;
}CPushBoxDlg::draw_game_face(dc);num_step++;
case 4:if(face[sitex][sitey]==3)//人时
face[sitex][sitey]=1;
face[sitex][sitey]=5;
if(face[sitex][sitey]==5)
face[sitex][sitey]=4;
face[sitex][sitey]=5;
}CPushBoxDlg::draw_game_face(dc);num_step++;
case 6:switch(face[sitex+2][sitey])
case 1:if(face[sitex][sitey]==3)//人时
face[sitex][sitey]=1;
face[sitex+1][sitey]=5;
face[sitex+2][sitey]=2;
if(face[sitex][sitey]==5)
face[sitex][sitey]=4;
face[sitex+1][sitey]=5;
face[sitex+2][sitey]=2;
}CPushBoxDlg::draw_game_face(dc);num_step++;
case 4:if(face[sitex][sitey]==3)//人时
face[sitex][sitey]=1;
face[sitex+1][sitey]=5;
face[sitex+2][sitey]=6;
if(face[sitex][sitey]==5)
face[sitex][sitey]=4;
face[sitex+1][sitey]=5;
face[sitex+2][sitey]=6;
}CPushBoxDlg::draw_game_face(dc);num_step++;
这样游戏的主体已经完成了
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:229844次
积分:3314
积分:3314
排名:第7605名
原创:87篇
转载:15篇
评论:176条
文章:10篇
阅读:74318
(1)(1)(1)(1)(4)(4)(4)(3)(5)(1)(21)(5)(2)(48)(1)

我要回帖

更多关于 命运冠位指定箱子 的文章

 

随机推荐