由于代码插入错位,对不久前发的博文重新发布
(一)运行图
<1开头动画
<2游戏截图
(二)前言
大二下学期了,小编学的是软件工程专业.学了大量书本后发现根本没有好的实践,没弄出来什么立体的可感的游戏,于是乎在学校实验室花了3到4天的从早到晚的冥思苦想做出来了这个俄罗斯方块的小游戏.其中查了大量的资料.当立体呈现的时候,小编发现了几个BUG,一是加速下落的键盘不灵(⊙o⊙)…!囧.二是控制左右下的键有时差额(⊙o⊙)…!三是当按动键盘的时候开始和暂停的键有闪烁(⊙o⊙)…!四是暂停后还可以左右移动啊!五是还有一些代码算法有点缺陷!在发放给大量的好友测试后返回的信息还有就是程序开始的过场动画不能移动框架,一移动就要卡,等动画结束就好了(⊙o⊙)…!总之经过大量的测试基本功能就有了,但是做完才发现没有显示下一块方块摸样的窗口(⊙o⊙)…先截图再上代码,再详细解释一些函数的用法.
(三)主要部分代码
// Test_ProgramDlg.cpp : 实现文件
//
#include "stdafx.h"
#include "Test_Program.h"
#include "Test_ProgramDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// 用于应用程序“关于”菜单项的 CAboutDlg 对话框
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// 对话框数据
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
// 实现
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()
// CTest_ProgramDlg 对话框
CTest_ProgramDlg::CTest_ProgramDlg(CWnd* pParent /*=NULL*/)
: CDialog(CTest_ProgramDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CTest_ProgramDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_SHOCKWAVEFLASH1, m_flash);
}
BEGIN_MESSAGE_MAP(CTest_ProgramDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
// ON_WM_SYSCOMMAND()
// ON_WM_NCHITTEST()
//}}AFX_MSG_MAP
ON_BN_CLICKED(IDC_BUTTON2, &CTest_ProgramDlg::OnBnClickedButton2)
ON_BN_CLICKED(IDC_BUTTON1, &CTest_ProgramDlg::OnBnClickedButton1)
ON_BN_CLICKED(IDC_BUTTON4, &CTest_ProgramDlg::OnBnClickedButton4)
END_MESSAGE_MAP()
// CTest_ProgramDlg 消息处理程序
BOOL CTest_ProgramDlg::OnInitDialog()
{
CDialog::OnInitDialog();
//pWnd=GetDlgItem(IDC_SHOCKWAVEFLASH1);
//pWnd->SetWindowPos(-1,0,0,600,600,NULL);
// 将“关于...”菜单项添加到系统菜单中。
// IDM_ABOUTBOX 必须在系统命令范围内。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
// TODO: 在此添加额外的初始化代码
//Action();
CreateThread(NULL,0,Move,this,0,NULL);
f=0;
m_speed=500;
mark=0;
score=0;
down=0;
d=0;
stop=0;
sq[0].arr[0][0]=0;
sq[0].arr[0][1]=1;
sq[0].arr[0][2]=0;
sq[0].arr[0][3]=0;
sq[0].arr[1][0]=0;
sq[0].arr[1][1]=1;
sq[0].arr[1][2]=0;
sq[0].arr[1][3]=0;
sq[0].arr[2][0]=0;
sq[0].arr[2][1]=1;
sq[0].arr[2][2]=0;
sq[0].arr[2][3]=0;
sq[0].arr[3][0]=0;
sq[0].arr[3][1]=1;
sq[0].arr[3][2]=0;
sq[0].arr[3][3]=0;
//条状
sq[1].arr[0][0]=0;
sq[1].arr[0][1]=1;
sq[1].arr[0][2]=0;
sq[1].arr[0][3]=0;
sq[1].arr[1][0]=0;
sq[1].arr[1][1]=1;
sq[1].arr[1][2]=0;
sq[1].arr[1][3]=0;
sq[1].arr[2][0]=0;
sq[1].arr[2][1]=1;
sq[1].arr[2][2]=1;
sq[1].arr[2][3]=0;
sq[1].arr[3][0]=0;
sq[1].arr[3][1]=0;
sq[1].arr[3][2]=0;
sq[1].arr[3][3]=0;
//右倒钩
sq[2].arr[0][0]=0;
sq[2].arr[0][1]=0;
sq[2].arr[0][2]=1;
sq[2].arr[0][3]=0;
sq[2].arr[1][0]=0;
sq[2].arr[1][1]=0;
sq[2].arr[1][2]=1;
sq[2].arr[1][3]=0;
sq[2].arr[2][0]=0;
sq[2].arr[2][1]=1;
sq[2].arr[2][2]=1;
sq[2].arr[2][3]=0;
sq[2].arr[3][0]=0;
sq[2].arr[3][1]=0;
sq[2].arr[3][2]=0;
sq[2].arr[3][3]=0;
//左倒钩
sq[3].arr[0][0]=0;
sq[3].arr[0][1]=0;
sq[3].arr[0][2]=0;
sq[3].arr[0][3]=0;
sq[3].arr[1][0]=0;
sq[3].arr[1][1]=1;
sq[3].arr[1][2]=1;
sq[3].arr[1][3]=0;
sq[3].arr[2][0]=0;
sq[3].arr[2][1]=1;
sq[3].arr[2][2]=1;
sq[3].arr[2][3]=0;
sq[3].arr[3][0]=0;
sq[3].arr[3][1]=0;
sq[3].arr[3][2]=0;
sq[3].arr[3][3]=0;
//方形
sq[4].arr[0][0]=0;
sq[4].arr[0][1]=1;
sq[4].arr[0][2]=0;
sq[4].arr[0][3]=0;
sq[4].arr[1][0]=0;
sq[4].arr[1][1]=1;
sq[4].arr[1][2]=1;
sq[4].arr[1][3]=0;
sq[4].arr[2][0]=0;
sq[4].arr[2][1]=0;
sq[4].arr[2][2]=1;
sq[4].arr[2][3]=0;
sq[4].arr[3][0]=0;
sq[4].arr[3][1]=0;
sq[4].arr[3][2]=0;
sq[4].arr[3][3]=0;
//右Z
sq[5].arr[0][0]=0;
sq[5].arr[0][1]=0;
sq[5].arr[0][2]=1;
sq[5].arr[0][3]=0;
sq[5].arr[1][0]=0;
sq[5].arr[1][1]=1;
sq[5].arr[1][2]=1;
sq[5].arr[1][3]=0;
sq[5].arr[2][0]=0;
sq[5].arr[2][1]=1;
sq[5].arr[2][2]=0;
sq[5].arr[2][3]=0;
sq[5].arr[3][0]=0;
sq[5].arr[3][1]=0;
sq[5].arr[3][2]=0;
sq[5].arr[3][3]=0;
//左z
sq[6].arr[0][0]=0;
sq[6].arr[0][1]=0;
sq[6].arr[0][2]=0;
sq[6].arr[0][3]=0;
sq[6].arr[1][0]=0;
sq[6].arr[1][1]=1;
sq[6].arr[1][2]=0;
sq[6].arr[1][3]=0;
sq[6].arr[2][0]=1;
sq[6].arr[2][1]=1;
sq[6].arr[2][2]=1;
sq[6].arr[2][3]=0;
sq[6].arr[3][0]=0;
sq[6].arr[3][1]=0;
sq[6].arr[3][2]=0;
sq[6].arr[3][3]=0;
//飞机形
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
void CTest_ProgramDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
/*
if (nID == SC_MOVE || nID==0xF012)
return;
else
CDialog::OnSysCommand(nID, lParam);
*/
}
// 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。
void CTest_ProgramDlg::OnPaint()
{
if(1==d)
{
CPaintDC dc(this); // 用于绘制的设备上下文 //加载背景位图
CBitmap bmp;
bmp.LoadBitmap(IDB_BITMAP1);
CDC dcMemory;
dcMemory.CreateCompatibleDC(&dc);//创建内存DC
CBitmap *pOldBmp = dcMemory.SelectObject(&bmp);
CRect rect;
GetClientRect(rect);
dc.BitBlt(0, 0, rect.Width(), rect.Height(), &dcMemory, 0, 0, SRCCOPY);
dcMemory.SelectObject(pOldBmp);
CWnd *pWnd=GetDlgItem(IDC_STATIC_TEST);
CDC *pControlDC=pWnd->GetDC();
CBrush br(RGB(0,0,0));//创建背景色笔刷
pControlDC->SelectObject(&br);
pWnd->Invalidate();
pWnd->UpdateWindow();
for(int i=0;i<360;i+=20)
{
for(int j=0;j<300;j+=20)
{
pControlDC->Rectangle(j,i,j+20,i+20);
}
}
}
//::AfxMessageBox("版本号1.0\n作者:奇迹冬瓜\n版权所有 翻版必究");
}
//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CTest_ProgramDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CTest_ProgramDlg::OnBnClickedButton2()
{
::exit(1);
// TODO: 在此添加控件通知处理程序代码
}
void CTest_ProgramDlg::OnBnClickedButton4()
{
stop+=1;
// TODO: 在此添加控件通知处理程序代码
}
void CTest_ProgramDlg::OnBnClickedButton1()
{
// play();
if(0==f)
{
f=1;
CreateThread(NULL,0,play,this,0,NULL);
}
// TODO: 在此添加控件通知处理程序代码
}
void CTest_ProgramDlg::InitBackground(int (*Ba)[15])
{
for(int i=0;i<18;i++)
{
for(int j=0;j<15;j++)
{
Ba[i][j]=0;
}
}
//::AfxMessageBox("OK");
}
bool CTest_ProgramDlg::GameOver(int (*Ba)[15])
{
int flag=0;
for(int i=0;i<18;i++)
{
for(int j=0;j<15;j++)
{
if(1==Ba[i][j])
{
flag+=1;
break;
}
}
}
if(flag>=18)
{
//::AfxMessageBox("true");
return true;
}
else
{
//::AfxMessageBox("flase");
return false;
}
}
int CTest_ProgramDlg::RandomGenSquare()
{
srand((unsigned)time(NULL));
return rand()%7;
//CString as;
//as.Format("%d",i);
//::AfxMessageBox(as);
}
void CTest_ProgramDlg::DrawSquare(Squares s,int (*Ba)[15],CPoint p1,CPoint p2)
{
int k=0;
for(int i=p1.y;i<=p2.y;i++,k++)
{
for(int j=p1.x,l=0;j<=p2.x;j++,l++)
{
if(1==s.arr[k][l]&&0==Ba[i][j])
{
Ba[i][j]=1;
}
}
}
}
void CTest_ProgramDlg::DrawBackground(int ID,int (*Ba)[15])
{
CWnd *pWnd=GetDlgItem(ID);
CDC *pControlDC=pWnd->GetDC();
// pWnd->Invalidate();
// pWnd->UpdateWindow();
COLORREF clr;
for(int i=0;i<18;i++)
{
for(int j=0;j<15;j++)
{
if(0==Ba[i][j])
{
clr=RGB(0,0,0);
}
else
{
clr=RGB(0,255,255);
}
CBrush brush(clr);
pControlDC->SelectObject(&brush);
pControlDC->Rectangle(j*20,i*20,j*20+20,i*20+20);
brush.DeleteObject();
}
}
pWnd->ReleaseDC(pControlDC);
}
bool CTest_ProgramDlg::HitBottomJudge(int (*Ba)[15],Squares s,CPoint p1,CPoint p2)
{
int k=0;
for(int i=p1.y;i<=p2.y;i++,k++)
{
for(int j=p1.x,l=0;j<=p2.x;j++,l++)
{
if((1==s.arr[k][l]&&18==i+1)||(1==s.arr[k][l]&&1==Ba[i+1][j]&&1!=s.arr[k+1][l]))
{
return true;
}
}
}
return false;
}
void CTest_ProgramDlg::MoveDown(Squares s,int (*Ba)[15],CPoint *p1,CPoint *p2)
{
for(int i=p1->y;i<=p2->y;i++)
{
for(int j=p1->x;j<=p2->x;j++)
{
if(1==Ba[i][j])
{
Ba[i][j]=0;
}
}
}
p1->y+=1;
p2->y+=1;
if(0==down)
{
m_speed=300;
}
else
{
m_speed=10;
}
DrawSquare(s,Ba,*p1,*p2);
::Sleep(m_speed);
down=0;
}
DWORD WINAPI play(LPVOID lpParam)
{
CTest_ProgramDlg *c=(CTest_ProgramDlg*)lpParam;
c->score=0;
c->InitBackground(c->Background);//初始化背景方块
for(int i=0;i<18;i++)
{
for(int j=0;j<15;j++)
{
c->temp[i][j]=0;
}
}
while(!c->GameOver(c->Background))//判断是否游戏结束
{
c->i=c->RandomGenSquare();//随机生成方块
c->p1.x=6;
c->p1.y=-3;
c->p2.x=9;
c->p2.y=0;
c->Copy(c->Background,c->temp);
c->DrawSquare(c->sq[c->i],c->Background,c->p1,c->p2);
c->DrawBackground(IDC_STATIC_TEST,c->Background);
//c->Copy(c->Background,c->temp);
//判断方块是否触底
while(!c->HitBottomJudge(c->Background,c->sq[c->i],c->p1,c->p2))
{
while(c->stop%2)
{
c->Copy(c->temp,c->Background);
c->DrawBackground(IDC_STATIC_TEST,c->Background);
::Sleep(1);
}
c->MoveDown(c->sq[c->i],c->Background,&c->p1,&c->p2);//下移方块一次
c->Copy(c->temp,c->Background);
c->DrawBackground(IDC_STATIC_TEST,c->Background);//绘制背景
}
c->EliminateSquare();//消除方格
//c->Copy(c->temp,c->Background);
/* for(int i=0;i<18;i++)
{
for(int j=0;j<15;j++)
{
c->temp[i][j]=0;
}
}*/
c->Copy(c->Background,c->temp);
c->DrawBackground(IDC_STATIC_TEST,c->Background);//绘制背景
//c->InitBackground(c->Background);
//c->Copy(c->temp,c->Background);
//::Sleep(10000);
//c->Copy(c->temp,c->Background);
//c->Copy(c->Background,c->temp);
}
::AfxMessageBox("游戏结束!");
c->f=0;
return 0;
}
DWORD WINAPI Move(LPVOID lpParam)
{
CTest_ProgramDlg *c=(CTest_ProgramDlg*)lpParam;
//c->Lock();
CString Type="swf";
HRSRC res=FindResource (NULL,MAKEINTRESOURCE(IDR_SWF1),Type);
HGLOBAL gl=LoadResource (NULL,res);
//返回指向资源内存的地址的指针
LPVOID lp=LockResource(gl);
//保存的临时文件名
CString filename="search.swf";
HANDLE fp= CreateFile(filename,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,0,NULL);
DWORD a;
//sizeofResource 得到资源文件的大小
if (!WriteFile (fp,lp,SizeofResource (NULL,res),&a,NULL))
return 1;
//关闭句柄
CloseHandle (fp);
//释放内存
FreeResource (gl);
//查找flash文件并加载
TCHAR strCurDrt[500];
int nLen = ::GetCurrentDirectory(500,strCurDrt);
if( strCurDrt[nLen]!='\\' )
{
strCurDrt[nLen++] = '\\';
strCurDrt[nLen] = '\0';
}
CString strFileName = strCurDrt;
strFileName += "search.swf";
c->m_flash.LoadMovie(0, strFileName);
c->m_flash.Stop();
c->No();
return true;
}
void CTest_ProgramDlg::No()
{
::Sleep(30000);
CWnd *pWnd=GetDlgItem(IDC_SHOCKWAVEFLASH1);
pWnd->ShowWindow(SW_HIDE);
pWnd=GetDlgItem(IDC_STATIC_TEST);
pWnd->SetWindowPos(NULL,80,110,300,360,NULL);
//pWnd=GetDlgItem(IDD_TEST_PROGRAM_DIALOG);
//pWnd->EnableWindow(TRUE);
d=1;
//WS_POPUP
}
/*
void CTest_ProgramDlg::Lock()
{
CWnd *pWnd=GetDlgItem(IDD_TEST_PROGRAM_DIALOG);
pWnd->EnableWindow(FALSE);
}*/
void CTest_ProgramDlg::Copy(int (*Ba)[15], int (*Ca)[15])
{
for(int i=0;i<18;i++)
{
for(int j=0;j<15;j++)
{
if(1==Ba[i][j])
{
Ca[i][j]=Ba[i][j];
}
}
}
}
void CTest_ProgramDlg::MoveRight(Squares s, int (*Ba)[15], CPoint *p1, CPoint *p2)
{
Copy(temp,Background);
for(int i=p1->y;i<=p2->y;i++)
{
for(int j=p1->x;j<=p2->x;j++)
{
if(1==Ba[i][j])
{
Ba[i][j]=0;
}
}
}
p1->x+=1;
p2->x+=1;
Copy(temp,Background);
DrawSquare(s,Ba,*p1,*p2);
// ::Sleep(10);
// Copy(temp,Background);
}
void CTest_ProgramDlg::MoveLeft(Squares s, int (*Ba)[15], CPoint *p1, CPoint *p2)
{
Copy(temp,Background);
for(int i=p1->y;i<=p2->y;i++)
{
for(int j=p1->x;j<=p2->x;j++)
{
if(1==Ba[i][j])
{
Ba[i][j]=0;
}
}
}
p1->x-=1;
p2->x-=1;
Copy(temp,Background);
DrawSquare(s,Ba,*p1,*p2);
// Copy(temp,Background);
// ::Sleep(10);
}
bool CTest_ProgramDlg::RightJudge(int (*Ba)[15],Squares s,CPoint p1,CPoint p2)
{
int k=0;
for(int i=p1.y;i<=p2.y;i++,k++)
{
for(int j=p1.x,l=0;j<=p2.x;j++,l++)
{
if((1==s.arr[k][l]&&15==j+1)||(1==s.arr[k][l]&&1==Ba[i][j+1]&&1!=s.arr[k][l+1]))
{
return true;
}
}
}
return false;
}
bool CTest_ProgramDlg::LeftJudge(int (*Ba)[15],Squares s,CPoint p1,CPoint p2)
{
int k=0;
for(int i=p1.y;i<=p2.y;i++,k++)
{
for(int j=p1.x,l=0;j<=p2.x;j++,l++)
{
if((1==s.arr[k][l]&&-1==j-1)||(1==s.arr[k][l]&&1==Ba[i][j-1]&&1!=s.arr[k][l-1]))
{
return true;
}
}
}
return false;
}
void CTest_ProgramDlg::EliminateSquare()
{
int flag=0,a[18],k=0,te;
for(int i=0;i<18;i++)
{
int markNum=0;
for(int j=0;j<15;j++)
{
if(1==Background[i][j])
{
markNum++;
}
}
if(15==markNum)
{
a[k++]=i;
flag++;
score+=100;
ShowScores(IDC_STATIC_SCORE,score);
}
}
te=k;
k=0;
while(k<te)
{
for(int i=a[k];i>0;i--)
{
for(int j=0;j<15;j++)
{
Background[i][j]=Background[i-1][j];
}
}
k++;
}
for(int i=0;i<18;i++)
{
for(int j=0;j<15;j++)
{
temp[i][j]=0;
}
}
Copy(Background,temp);
/*
while(flag)
{
for(int i=17;i>=1;i--)
{
for(int j=0;j<15;j++)
{
Background[i][j]=Background[i-1][j];
}
}
for(int i=0,j=0;j<15;j++)
{
Background[i][j]=0;
}
flag--;
//c->EliminateSquare();
}
*/
//DrawBackground(IDC_STATIC_TEST,Background);
//Copy(Background,temp);
//DrawBackground(IDC_STATIC_TEST,Background);
}
void CTest_ProgramDlg::ShowScores(int ID, long score)
{
CString as;
as.Format("%d",score);
GetDlgItem(ID)->SetWindowText(as);
}
BOOL CTest_ProgramDlg::PreTranslateMessage(MSG* pMsg)
{
if (pMsg-> message == WM_KEYDOWN)
{
if(pMsg-> wParam== VK_UP)//
{
if(!LeftJudge(Background,sq[CTest_ProgramDlg::i],p1,p2)&&!RightJudge(Background,sq[CTest_ProgramDlg::i],p1,p2)&&!HitBottomJudge(Background,sq[CTest_ProgramDlg::i],p1,p2))
{
int temp[4][4];
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++)
{
temp[i][j]=sq[CTest_ProgramDlg::i].arr[j][3-i];
}
}
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++)
{
sq[CTest_ProgramDlg::i].arr[i][j]=temp[i][j];
}
}
for(int i=p1.y;i<=p2.y;i++)
{
for(int j=p1.x;j<=p2.x;j++)
{
if(1==Background[i][j])
{
Background[i][j]=0;
}
}
}
DrawSquare(sq[CTest_ProgramDlg::i],Background,p1,p2);
Copy(CTest_ProgramDlg::temp,Background);
}
}
if(pMsg-> wParam== VK_DOWN)//
{
down=1;
}
if(pMsg-> wParam== VK_LEFT)//
{
Copy(CTest_ProgramDlg::temp,Background);
if(!LeftJudge(Background,sq[CTest_ProgramDlg::i],p1,p2))
{
MoveLeft(sq[i],Background,&p1,&p2);
Copy(CTest_ProgramDlg::temp,Background);
DrawBackground(IDC_STATIC_TEST,Background);//绘制背景
}
}
if(pMsg-> wParam== VK_RIGHT)//
{
Copy(CTest_ProgramDlg::temp,Background);
if(!RightJudge(Background,sq[CTest_ProgramDlg::i],p1,p2))
{
MoveRight(sq[i],Background,&p1,&p2);
Copy(CTest_ProgramDlg::temp,Background);
DrawBackground(IDC_STATIC_TEST,Background);
}
}
}
return CDialog::PreTranslateMessage(pMsg);
}
/*
UINT CTest_ProgramDlg::OnNcHitTest(CPoint point)
{
int ret = CDialog::OnNcHitTest(point);
if( HTCAPTION == ret)
return HTCLIENT;
return ret;
}
*/
/*
void CTest_ProgramDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
}
*/