📄 playzone.cpp
字号:
/*
Copyright (c) 2005 william.
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.2
or any later version published by the Free Software Foundation;
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
Texts. A copy of the license is included in the section entitled "GNU
Free Documentation License".
*/
#include "stdafx.h"
#include "resource.h"
const CTagPos TagPosZero;
const COLORREF BLACK = RGB(0,0,0);
const COLORREF BLUE = RGB(136,174,255);
const CPen BlackPen(PS_SOLID,1,BLACK);
const CPen BluePen(PS_SOLID,1,BLUE);
//using for detect which direction a tail can put.
const UINT Cell_dir_x[14]={0,4,4,4,14,15,15,15,15,15,11,1,1,1};
const UINT Cell_dir_y[14]={0,2,2,2,7,15,15,15,15,15,13,8,8,8};
inline UINT GetCellPlaneDirect(UINT cell_x,UINT cell_y){
return Cell_dir_x[cell_x] & Cell_dir_y[cell_y];
}
bool APlane::IsPlane(CTagPos pos) const
{
CRect rect;
GetPlaneRect(rect);
CPoint pt(pos.x,pos.y);
if(rect.PtInRect(pt))
{
CTagPos planePos;
for(int i=1;i<14;++i)
{
GetNumPos(i,planePos);
if(planePos == pos)return true;
}
}
return false;
}
//if a plane across the other?
//at least One is no a GuessPlane
//GuessPlane & GuessPlane no need to test.
bool operator &(const APlane& plane1,const APlane& plane2)
{
CTagPos pos1;
CTagPos pos2;
int Dir_x1 = Dir_x[D2N[plane1.Dir]];
int Dir_y1 = Dir_y[D2N[plane1.Dir]];
int Dir_x2 = Dir_x[D2N[plane2.Dir]];
int Dir_y2 = Dir_y[D2N[plane2.Dir]];
for(int i=1;i<14;++i)
{
int offset_r = HeadOffset[Dir_x1][i];
int offset_b = HeadOffset[Dir_y1][i];
pos1.x = plane1.Head.x + offset_r;
pos1.y = plane1.Head.y + offset_b;
for(int j=1;j<14;++j)
{
int offset_r = HeadOffset[Dir_x2][j];
int offset_b = HeadOffset[Dir_y2][j];
pos2.x = plane2.Head.x + offset_r;
pos2.y = plane2.Head.y + offset_b;
if(pos1 == pos2) return true;
}
}
return false;
}
////////////////////////////////////////////////////////////////
//
// CPlanes
//
//
//
void CPlanes::GetPlane(const CTagPos& pos,APlane& plane) const
{
APlane pl;
for(UINT i =1;i<=GetNum();++i)
{
GetPlane(i,pl);
if(pl.IsPlane(pos))
{
plane.Head = pl.Head;
plane.Dir = pl.Dir;
return;
}
}
plane.Head = CTagPos(0,0);
plane.Dir = pdNO;
}
UINT CPlanes::AddPlane(const CTagPos& head,PlaneDirect dir)
{
if(planes.GetCount()==(int)Max)return Max;
//add it
APlane plane(head,dir);
//set the grid
CTagPos posTure;
for(int i=1;i<14;++i)
{
plane.GetNumPos(i,posTure);
Grid4Plane[posTure.x][posTure.y] = true;
}
return (UINT)planes.Add(plane);
}
void CPlanes::RemovePlane(int num)
{
ASSERT(num>0 && num<=(int)GetMaxNum());
APlane plane;
GetPlane(num,plane);
//del it.
planes.RemoveAt(num-1);
#ifdef _DEBUG
//affirm no other same-head plane
APlane pl;
for(UINT i=1;i<GetNum();++i)
{
GetPlane(i,pl);
ASSERT(pl.Head != plane.Head);
}
#endif
//clear the grid.
CTagPos posTure;
for(int i=1;i<14;++i)
{
plane.GetNumPos(i,posTure);
Grid4Plane[posTure.x][posTure.y] = false;
}
}
bool CPlanes::NoAnotherPlane(const CTagPos& pos) const
{
bool retval = !Grid4Plane[pos.x][pos.y];
#ifdef _DEBUG
//affirm
bool val=true;
APlane planeSetted;
for(UINT i=1;i<=GetNum();++i)
{
GetPlane(i,planeSetted);
if(planeSetted.IsPlane(pos)){
val = false;goto END;}
}
END:
ASSERT(val == retval);
#endif
return retval;
}
bool CPlanes::NoAnotherPlane(const APlane& plane) const
{
bool retval = true;
CTagPos pos;
//test every planes-cells(13)
for(int i=1;i<14;++i)
{
plane.GetNumPos(i,pos);
if(Grid4Plane[pos.x][pos.y]){
retval = false;break;
}
}
#ifdef _DEBUG
//affirm
bool val =true;
APlane planeSetted;
for(UINT i=1;i<=GetNum();++i)
{
GetPlane(i,planeSetted);
if(plane & planeSetted){
val = false;goto END;}
}
END:
ASSERT(val == retval);
#endif
return retval;
}
/////////////////////////////////////////////////////////
//
//
//
//
//
IMPLEMENT_DYNAMIC(CPlayZone, CStatic)
BEGIN_MESSAGE_MAP(CPlayZone, CStatic)
ON_WM_PAINT()
ON_WM_ERASEBKGND()
END_MESSAGE_MAP()
HICON CPlayZone::HeadTag = 0;
HICON CPlayZone::BodyTag = 0;
HICON CPlayZone::GuessTag = 0;
HICON CPlayZone::NoneTag = 0;
CDC* CPlayZone::PlaneDC=0;
CSize* CPlayZone::PlaneSize=0;
HICON CPlayZone::TailTagHEAD = 0;
HICON CPlayZone::TailTagTAIL = 0;
CDC* CPlayZone::BackgroundDC = 0;
CSize* CPlayZone::BackgroundSize = 0;
void CPlayZone::OnInit()
{
CRect rect;
GetClientRect(&rect);
Height = rect.bottom - rect.top;
cell = Height/MaxCell;
Height = MaxCell*cell;
ClientRect.top = rect.top;
ClientRect.left = rect.left;
ClientRect.right = rect.left+Height;
ClientRect.bottom = rect.top+Height;
TargetSet.InitHashTable(MaxCell);
CClientDC dc(this);
CBitmap mem;
mem.CreateCompatibleBitmap(&dc,ClientRect.Width(),ClientRect.Height());
MemDC.CreateCompatibleDC(&dc);
MemDC.SelectObject(mem);
if(HeadTag==0){
HeadTag = AfxGetApp()->LoadIcon(IDI_HEAD);
BodyTag = AfxGetApp()->LoadIcon(IDI_BODY);
GuessTag = AfxGetApp()->LoadIcon(IDI_GUESS);
NoneTag = AfxGetApp()->LoadIcon(IDI_NONE);
}
//load put-test-tag
if(TailTagHEAD==0){
TailTagHEAD = AfxGetApp()->LoadIcon(IDI_TAIL);
TailTagTAIL = AfxGetApp()->LoadIcon(IDI_TAILS);
}
if(PlaneDC != 0) return;
PlaneDC = new CDC[4];
PlaneSize = new CSize[4];
CBitmap Plane[4];
Plane[D2N[pdLEFT]].LoadBitmap(IDB_PLANE_LEFT);
Plane[D2N[pdDOWN]].LoadBitmap(IDB_PLANE_DOWN);
Plane[D2N[pdRIGHT]].LoadBitmap(IDB_PLANE_RIGHT);
Plane[D2N[pdUP]].LoadBitmap(IDB_PLANE_UP);
BITMAP bt;
for(int i=0;i<4;++i)
{
Plane[i].GetBitmap(&bt);
PlaneSize[i].cx = bt.bmWidth;
PlaneSize[i].cy = bt.bmHeight;
PlaneDC[i].CreateCompatibleDC(&dc);
PlaneDC[i].SelectObject(&Plane[i]);
}
BackgroundDC = new CDC[2];
BackgroundSize = new CSize[2];
CBitmap bkgnd[2];
bkgnd[0].LoadBitmap(IDB_BKGND_LIGHT);
bkgnd[1].LoadBitmap(IDB_BKGND_DARK);
for(int i=0;i<2;++i)
{
bkgnd[i].GetBitmap(&bt);
BackgroundSize[i].cx = bt.bmWidth;
BackgroundSize[i].cy = bt.bmHeight;
BackgroundDC[i].CreateCompatibleDC(&dc);
BackgroundDC[i].SelectObject(&bkgnd[i]);
}
//Test:
//TargetSet[CTagPos(7,7)] = tagHEAD;
//TargetSet[CTagPos(6,6)] = tagBODY;
//TargetSet[CTagPos(6,8)] = tagNONE;
}
bool CPlayZone::SetGuessPlane(const CTagPos& head,PlaneDirect dir)
{
if(dir == pdNO) return false;
int allDir = GetCellPlaneDirect(head.x,head.y);
APlane plan;
plan.Head = head;
if(dir & allDir){
plan.Dir = dir;
if(Planes.NoAnotherPlane(plan))
{
Planes.AddPlane(plan);
return true;
}
}
return false;
}
//used for tell player where can put a plane
//and where can't, need the player to set a head point,
bool CPlayZone::SetFourGuessPlaneTail(const CTagPos& head)
{
int dir = GetCellPlaneDirect(head.x,head.y);
if(dir == pdNO) return false;
SetHeadPos = CTagPos(head.x,head.y);
APlane plan;
plan.Head = head;
CTagPos TailPos;
bool retval = false;
for(int i=0;i<4;++i)
{
if(dir & N2D[i]){
plan.Dir = N2D[i];
if(Planes.NoAnotherPlane(plan))
{
plan.GetPlaneTailPos(TailPos);
ShowTailTag[i] = TailPos;
retval = true;
}
}
}
return retval;
}
void CPlayZone::DrawBkGroud()
{
if(IsActive){
MemDC.StretchBlt(ClientRect.left,ClientRect.top,
ClientRect.Width(),ClientRect.Height(),&BackgroundDC[0],
0,0,BackgroundSize[0].cx,BackgroundSize[0].cy,SRCCOPY);
}else{
MemDC.StretchBlt(ClientRect.left,ClientRect.top,
ClientRect.Width(),ClientRect.Height(),&BackgroundDC[1],
0,0,BackgroundSize[1].cx,BackgroundSize[1].cy,SRCCOPY);
}
}
void CPlayZone::DrawMainGrid()
{
if(!IsActive){
MemDC.SelectObject(BluePen);
}
int step = 0;
for(UINT i = 1;i<MaxCell;i+=2)
{
step += cell;
MemDC.MoveTo(0,step);
MemDC.LineTo(Height,step);
MemDC.MoveTo(step,0);
MemDC.LineTo(step,Height);
step += cell;
MemDC.MoveTo(0,step);
MemDC.LineTo(Height,step);
MemDC.MoveTo(step,0);
MemDC.LineTo(step,Height);
}
if(!IsActive){
MemDC.SelectObject(BlackPen);
}
}
void CPlayZone::DrawPosiblePos()
{
for(int i=0;i<4;++i)
{
if(ShowTailTag[i] != TagPosZero)
{
LONG x = ShowTailTag[i].x;
LONG y = ShowTailTag[i].y;
CellToUnit(x,y);
DrawIconEx(MemDC.GetSafeHdc(),x,y,TailTagTAIL,cell,cell,0,0,DI_NORMAL);
}
}
if(SetHeadPos!= TagPosZero)
{
LONG x = SetHeadPos.x;
LONG y = SetHeadPos.y;
CellToUnit(x,y);
DrawIconEx(MemDC.GetSafeHdc(),x,y,TailTagHEAD,cell,cell,0,0,DI_NORMAL);
}
}
void CPlayZone::DrawPlane()
{
//put palnes under flag;
APlane plane;
for(UINT i =1;i<=Planes.GetNum();++i)
{
Planes.GetPlane(i,plane);
CRect rect;
plane.GetPlaneRect(rect);
CellToUnit(rect);
CDC* source = &PlaneDC[D2N[plane.Dir]];
int PlaneWidth = PlaneSize[D2N[plane.Dir]].cx;
int PlaneHeight = PlaneSize[D2N[plane.Dir]].cy;
MemDC.TransparentBlt(rect.left,rect.top,rect.Width()+1,rect.Height()+1,source,0,0,PlaneWidth,PlaneHeight,RGB(255,0,255));
}
}
void CPlayZone::DoDrawFlag(const CTagPos& pos,_tag flag) const
{
LONG ix = pos.x,iy = pos.y;
CellToUnit(ix,iy);
HICON TheTag = 0;
switch(flag)
{
case tagBODY:
TheTag = BodyTag;
break;
case tagHEAD:
TheTag = HeadTag;
break;
case tagTEST:
TheTag = GuessTag;
break;
case tagNONE:
TheTag = NoneTag;
break;
}
ASSERT(TheTag!=0);
DrawIconEx(MemDC.GetSafeHdc(),ix,iy,TheTag,cell,cell,0,0,DI_NORMAL);
DUMP2(L"Draw flag",pos.x,pos.y);
}
void CPlayZone::OnPaint()
{
CPaintDC dc(this); // device context for painting
DrawBkGroud();
DrawPlane();
DrawFlag();
DrawPosiblePos();
DrawMainGrid();
dc.BitBlt(0,0,ClientRect.Width(),ClientRect.Height(),&MemDC,0,0,SRCCOPY);
}
PlaneDirect GetPlaneDir(const CTagPos& base,const CTagPos& offset)
{
if(offset.x > base.x && offset.y == base.y)return pdRIGHT;
if(offset.x < base.x && offset.y == base.y)return pdLEFT;
if(offset.x == base.x && offset.y > base.y)return pdDOWN;
if(offset.x == base.x && offset.y < base.y)return pdUP;
return pdNO;
}
MBU CPlayZone::On1stMButtonUp(const CTagPos& HitPos)
{
//if clicked on a plane,del it
if(!Planes.NoAnotherPlane(HitPos))
{
UINT n = Planes.IsBody(HitPos);
ASSERT(n>0 && n<=Planes.GetMaxNum());
Planes.RemovePlane(n);
InvalidateRect(0,false);
return mbDEL;
}
//plane is use-out
if(Planes.GetMaxNum() == Planes.GetNum()){
return mbMax;
}
SetHeadPos = HitPos;
if(SetFourGuessPlaneTail(HitPos)){
//put a 1-4 tag means the tail pos
InvalidateRect(0,false);
return mbSEL;
}else{
//cannot set a plan here
SetHeadPos = TagPosZero;
return mbCANT;
}
}
MBU CPlayZone::On2ndMButtonUp(const CTagPos& HitPos){
MBU retval=mbCANCEL;
if(Planes.NoAnotherPlane(HitPos)){
PlaneDirect dir = GetPlaneDir(SetHeadPos,HitPos);
if(dir != pdNO){
SetGuessPlane(SetHeadPos,dir);
if(Planes.GetMaxNum() == Planes.GetNum()){
//reach the max num
retval =mbOKMAX;
}else{
retval = mbNEXT;}
}
}
ShowTailTag[0] = ShowTailTag[1] = ShowTailTag[2] = ShowTailTag[3] = TagPosZero;
SetHeadPos = TagPosZero;
InvalidateRect(0,false);
return retval;
}
MBU CPlayZone::OnMButtonUp(CPoint point)
{
if(!IsStart)return mbNONE;
if(!GuessZone && !IsActive)return mbNONE;
CTagPos HitPos(point.x,point.y);
UnitToCell(HitPos);
//please click the head wanted
if(SetHeadPos == TagPosZero){
return On1stMButtonUp(HitPos);
//click the tail wanted
}else{
return On2ndMButtonUp(HitPos);
}
}
void CPlayZone::OnGuessRButtonUp(CPoint point)
{
if(!IsStart)return;
//if(!GuessZone)return;
ASSERT(GuessZone);
//on other operator now.
if(SetHeadPos != TagPosZero)return;
CTagPos pos(point.x,point.y);
UnitToCell(pos);
_tag tagHere = GetFlag(pos);
UINT IDS_id = IDS_GU_NONE_FLAG;
switch(tagHere)
{
case tagBLACK:
SetFlag(pos,tagTEST);
IDS_id=IDS_GU_TEST_FLAG;
break;
case tagBODY:
//SetFlag(pos,tagHEAD);
IDS_id=IDS_GU_HEAD_FLAG;
break;
case tagHEAD:
//SetFlag(pos,tagBODY);
IDS_id=IDS_GU_BODY_FLAG;
break;
case tagTEST:
//SetFlag(pos,tagHEAD);
TargetSet.RemoveKey(pos);
IDS_id=IDS_GU_BLACK_FLAG;
break;
}
SetGuide(IDS_id);
InvalidateRect(0,false);
}
bool CPlayZone::OnGuessLButtonUp(CPoint point,int& cell_x,int& cell_y)
{
if(!IsStart)return false;
if(!IsActive)return false;
if(SetHeadPos != TagPosZero){
ShowTailTag[0] = ShowTailTag[1] = ShowTailTag[2] = ShowTailTag[3] = TagPosZero;
SetHeadPos = TagPosZero;
}
//if(!GuessZone)return;
ASSERT(GuessZone);
CTagPos pos(point.x,point.y);
UnitToCell(pos);
_tag Tag;
//clicked on a Tag?
if(TargetSet.Lookup(pos,Tag))
{
if(Tag == tagBODY || Tag == tagHEAD){
SetGuide(IDS_GU_AFFIRM);
cell_x=cell_x=0;
return false;
}
if(Tag == tagNONE){
SetGuide(IDS_GU_AFFIRM_NO);
cell_x=cell_x=0;
return false;
}
}
cell_x= pos.x; cell_y = pos.y;
SetGuide(IDS_GU_SEND);
return true;
//CStatic::OnLButtonUp(nFlags, point);
}
_tag CPlayZone::IsBombed(int x,int y) const
{
#ifdef _DEBUG
ASSERT_CELL_RANGE(x,y);
#endif
CTagPos pos(x,y);
int planeNum = Planes.IsBody(pos);
if(planeNum !=0 )
if(Planes.IsHead(planeNum,pos))
return tagHEAD;
else
return tagBODY;
else
return tagNONE;
}
void CPlayZone::CellToUnit(LONG& x,LONG& y) const
{
LONG min = 1;
LONG max = MaxCell+1;
if(x<min)x=min;
if(y<min)y=min;
if(x>max)x=max;
if(y>max)y=max;
x = (x-1)*cell;
y = (y-1)*cell;
#ifdef _DEBUG
ASSERT_UNIT_RANGE(x,y);
#endif
}
void CPlayZone::UnitToCell(LONG& x,LONG& y) const
{
LONG min = 0;
LONG max = Height;
if(x<min)x=min;
if(y<min)y=min;
if(x>max)x=max;
if(y>max)y=max;
x = x/cell+1;
y = y/cell+1;
#ifdef _DEBUG
ASSERT_CELL_RANGE(x,y);
#endif
}
void CPlayZone::SetActive(bool act)
{
if(IsActive != act)
{
IsActive = act;
InvalidateRect(0,false);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -