#include <OWL.h> | |
#include <Dialog.h> | |
#include <Button.h> | |
#define HAIWIDTH (24) //牌の幅(Local) | |
#define HAIHEIGHT (30) //牌の高さ(Local) | |
#define STANDARDWIDTH (10*HAIWIDTH+64+192+16) //画面の幅 | |
#define STANDARDHEIGHT (HAIHEIGHT*13+GetSystemMetrics(SM_CYMENU) \ | |
+GetSystemMetrics(SM_CYCAPTION)+GetSystemMetrics(SM_CYBORDER)*2+32) | |
//画面の高さ | |
#define SMALLWIDTH (STANDARDWIDTH/2) //縮小時の幅 | |
#define SMALLHEIGHT (HAIHEIGHT*13/2+GetSystemMetrics(SM_CYMENU) \ | |
+GetSystemMetrics(SM_CYCAPTION)+GetSystemMetrics(SM_CYBORDER)*2+32/2) | |
void SankakuCBF(void); | |
void HishiCBF(void); | |
void TokeiCBF(void); | |
void GyakuCBF(void); | |
HBITMAP Hai[7]; //牌のビットマップ | |
HBITMAP Logo; //ロゴビットマップ | |
int Board[13][13]; //ボードの状態 | |
int NextHai; //次の牌 | |
int CurMode=1; //現在の難易度 | |
int CurTumi=0; //現在の牌の積み方 | |
POINT History[13*13]; //過去のヒストリ | |
int HP=0; //ヒストリのポインタ | |
BOOL UseSmall=FALSE; //縮小セットの使用 | |
void (*ClearBoardFunc[])(void)= | |
{ | |
SankakuCBF,HishiCBF,TokeiCBF,GyakuCBF | |
}; | |
int HaiNum[]= //牌の数 | |
{ | |
91,127-1,81-4,93-2 | |
}; | |
int LogoPos[]= //ロゴの表示位置 | |
{ | |
0,0,1,2 | |
}; | |
class Apr : public TApplication | |
{ | |
public: | |
Apr(LPSTR a, HANDLE b, HANDLE c, LPSTR d, int e) | |
:TApplication(a,b,c,d,e){}; | |
virtual void InitMainWindow(void); | |
}; | |
class Win : public TWindow | |
{ | |
public: | |
Win(PTWindowsObject Parent,LPSTR Title); | |
virtual LPSTR GetClassName(void); | |
virtual void GetWindowClass(WNDCLASS& WndClass); | |
virtual void WMCreate(RTMessage Msg)=[WM_FIRST+WM_CREATE]; | |
virtual void WMPaint(RTMessage Msg)=[WM_FIRST+WM_PAINT]; | |
virtual void WMLButtonDown(RTMessage Msg)=[WM_FIRST+WM_LBUTTONDOWN]; | |
virtual void CMNewGame(RTMessage Msg)=[CM_FIRST+101]; | |
virtual void IDNewGame(RTMessage Msg)=[ID_FIRST+101]; | |
virtual void CMOption(RTMessage Msg)=[CM_FIRST+102]; | |
virtual void CMBackStep(RTMessage Msg)=[CM_FIRST+103]; | |
virtual void CMRetry(RTMessage Msg)=[CM_FIRST+104]; | |
virtual void CMUseSmallSet(RTMessage Msg)=[CM_FIRST+105]; | |
void InvalidateNextHai(void); | |
void InvalidateHai(int x,int y); | |
}; | |
class OptDlg : public TDialog | |
{ | |
public: | |
OptDlg(PTWindowsObject a,LPSTR b):TDialog(a,b){}; | |
virtual void WMInitDialog(RTMessage Msg)=[WM_FIRST+WM_INITDIALOG]; | |
virtual void Ok(RTMessage Msg)=[ID_FIRST+IDOK]; | |
}; | |
void SankakuCBF(void) | |
{ | |
int x,y; | |
for(y=0;y<13;y++) | |
for(x=6-(y+1)/2;x<=6+y/2;x++) | |
Board[x][y]=-2; | |
} | |
void HishiCBF(void) | |
{ | |
int x,y; | |
for(y=0;y<=6;y++) | |
for(x=6-(y+3)/2-2;x<=7+y/2+2;x++) | |
Board[x][y]=Board[x][12-y]=-2; | |
} | |
void TokeiCBF(void) | |
{ | |
int x,y; | |
for(y=0;y<=6;y++) | |
for(x=6-(y+3)/2;x<=7+y/2;x++) | |
Board[x][6-y]=Board[x][6+y]=-2; | |
} | |
void GyakuCBF(void) | |
{ | |
int x,y; | |
for(y=0;y<13;y++) | |
for(x=6-(y+1)/2;x<=6+y/2;x++) | |
Board[x][12-y]=-2; | |
Board[5][12]=Board[7][12]=-2; | |
} | |
void Apr::InitMainWindow(void) | |
{ | |
MainWindow=new Win(NULL,"九龍"); | |
} | |
Win::Win(PTWindowsObject Parent,LPSTR Title) | |
:TWindow(Parent,Title) | |
{ | |
Attr.Style=WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX; | |
if(!UseSmall) | |
{ | |
Attr.H=STANDARDHEIGHT; | |
Attr.W=STANDARDWIDTH; | |
} | |
else | |
{ | |
Attr.H=SMALLHEIGHT; | |
Attr.W=SMALLWIDTH; | |
} | |
} | |
LPSTR Win::GetClassName(void) | |
{ | |
return "Syanhai"; | |
} | |
void Win::GetWindowClass(WNDCLASS& WndClass) | |
{ | |
TWindow::GetWindowClass(WndClass); | |
WndClass.hIcon= | |
LoadIcon(GetApplication()->hInstance,"Main2"); | |
WndClass.lpszMenuName= | |
"Main"; | |
} | |
////////////////////////////////////////////////////////////////////////////// | |
//メインウィンドウメッセージ処理関数 | |
////////////////////////////////////////////////////////////////////////////// | |
void Win::WMCreate(RTMessage Msg) | |
{ | |
TWindow::WMCreate(Msg); | |
CMNewGame(Msg); | |
if(UseSmall) | |
CheckMenuItem(GetMenu(HWindow),105,MF_CHECKED); | |
} | |
void Win::WMPaint(RTMessage Msg) | |
{ | |
PAINTSTRUCT ps;int x,y;HDC DC; | |
BeginPaint(HWindow,&ps); | |
DC=CreateCompatibleDC(ps.hdc); | |
for(y=0;y<13;y++) | |
for(x=0;x<13;x++) | |
{ | |
if(Board[x][y]<0) continue; | |
SelectObject(DC,Hai[Board[x][y]]); | |
if(UseSmall) | |
StretchBlt(ps.hdc,x*12+((y%2)?6:0)+8,y*15+8,12,15, | |
DC,0,0,24,30,SRCCOPY); | |
else | |
BitBlt(ps.hdc,x*24+((y%2)?12:0)+16,y*30+16,24,30,DC,0,0,SRCCOPY); | |
} | |
//ロゴ描画 | |
SelectObject(DC,Logo); | |
if(UseSmall) | |
StretchBlt(ps.hdc,10*12+32,15*LogoPos[CurTumi]*5,96,36, | |
DC,0,0,192,72,SRCCOPY); | |
else | |
BitBlt(ps.hdc,10*24+64,30*LogoPos[CurTumi]*5,192,72,DC,0,0,SRCCOPY); | |
SelectObject(DC,Hai[NextHai]); | |
if(UseSmall) | |
StretchBlt(ps.hdc,10*12+32+10,18+15*LogoPos[CurTumi]*5,12,15, | |
DC,0,0,24,30,SRCCOPY); | |
else | |
BitBlt(ps.hdc,10*24+64+20,36+30*LogoPos[CurTumi]*5,24,30,DC,0,0,SRCCOPY); | |
DeleteDC(DC); | |
EndPaint(HWindow,&ps); | |
} | |
void Win::WMLButtonDown(RTMessage Msg) | |
{ | |
int x,y; | |
if(UseSmall) | |
{ | |
Msg.LP.Hi*=2; | |
Msg.LP.Lo*=2; | |
} | |
y=(Msg.LP.Hi-16)/30; | |
if(((Msg.LP.Hi-16)/30)%2==1) | |
Msg.LP.Lo-=12; | |
x=(Msg.LP.Lo-16)/24; | |
//正常な位置か判定 | |
if(y<0 || y>12 || x<0 || x>12) {MessageBeep(0);return;} | |
//牌が取る牌と違う | |
if(Board[x][y]!=NextHai) {MessageBeep(0);return;} | |
//判定の例外による分岐処理 | |
if(y!=0) | |
{//最上段なら判定省略 | |
if(x!=0) | |
{//一番左なら左判定は行わない | |
//左判定 | |
if(Board[x+((y%2)?0:-1)][y-1]>=0 && Board[x-1][y]<0) | |
{MessageBeep(0);return;} | |
} | |
if(x!=12) | |
{//一番右なら右判定は行わない | |
//右判定 | |
if(Board[x+((y%2)?1:0)][y-1]>=0 && Board[x+1][y]<0) | |
{MessageBeep(0);return;} | |
} | |
} | |
//OKとみなす | |
History[HP].x=x;History[HP].y=y;HP++; //ヒストリ前進!! | |
EnableMenuItem(GetMenu(HWindow),103,MF_ENABLED); | |
Board[x][y]=-1; | |
NextHai++; | |
if(NextHai==7) NextHai=0; | |
InvalidateNextHai(); | |
InvalidateHai(x,y); | |
} | |
////////////////////////////////////////////////////////////////////////////// | |
//メニュー処理関数 | |
////////////////////////////////////////////////////////////////////////////// | |
void Win::IDNewGame(RTMessage Msg) | |
{ | |
CMNewGame(Msg); | |
} | |
void Win::CMNewGame(RTMessage Msg) | |
{ | |
int x,y,i,j; | |
//初期化 | |
for(y=0;y<13;y++) | |
for(x=0;x<13;x++) | |
Board[x][y]=-1; | |
ClearBoardFunc[CurTumi](); | |
//穴開け | |
for(i=0;i<7*CurMode;i++) | |
{ | |
do | |
{ | |
y=random(13); | |
x=random(13); | |
}while(Board[x-1][y]!=-2 || Board[x][y]!=-2 || Board[x+1][y]!=-2 || x==0 || x==12); | |
Board[x][y]=-3; | |
} | |
//逆を辿る | |
i=6; | |
for(j=0;j<HaiNum[CurTumi]-7*CurMode;j++) | |
{//一つ一つ置く | |
while(TRUE) | |
{ | |
y=random(13); | |
x=random(13); | |
//物理的におけないところ | |
if(Board[x][y]!=-2) | |
continue; | |
//最下段は無条件にOK | |
if(y==12) | |
break; | |
//下に牌があればOK | |
if(Board[x][y+1]>=0) | |
break; | |
//この状態で端であればやりなおし | |
if(x+((y%2)?1:-1)==-1 || x+((y%2)?1:-1)==13) | |
continue; | |
//下2に牌があればOK | |
if(Board[x+((y%2)?1:-1)][y+1]>=0) | |
break; | |
} | |
Board[x][y]=i; | |
i--; | |
if(i==-1) i=6; | |
} | |
NextHai=0; | |
HP=0; | |
EnableMenuItem(GetMenu(HWindow),103,MF_GRAYED); | |
InvalidateRect(HWindow,NULL,TRUE); | |
SendMessage(HWindow,WM_PAINT,0,0); | |
} | |
void Win::CMOption(RTMessage Msg) | |
{ | |
GetApplication()->ExecDialog(new OptDlg(this,"Option")); | |
} | |
void Win::CMBackStep(RTMessage Msg) | |
{ | |
if(HP==0) | |
{ | |
MessageBox(HWindow,"これ以上戻れません","九龍",MB_OK|MB_ICONSTOP); | |
return; | |
} | |
HP--; | |
if(HP==0) | |
EnableMenuItem(GetMenu(HWindow),103,MF_GRAYED); | |
NextHai--; | |
if(NextHai==-1) NextHai=6; | |
Board[History[HP].x][History[HP].y]=NextHai; | |
InvalidateNextHai(); | |
InvalidateHai(History[HP].x,History[HP].y); | |
} | |
void Win::CMRetry(RTMessage Msg) | |
{ | |
while(HP!=0) | |
CMBackStep(Msg); | |
} | |
void Win::CMUseSmallSet(RTMessage Msg) | |
{ | |
RECT r; | |
UseSmall=!UseSmall; | |
CheckMenuItem(GetMenu(HWindow),105,UseSmall?MF_CHECKED:MF_UNCHECKED); | |
GetWindowRect(HWindow,&r); | |
if(UseSmall) | |
MoveWindow(HWindow, r.left, r.top, SMALLWIDTH , SMALLHEIGHT , TRUE); | |
else | |
MoveWindow(HWindow, r.left, r.top, STANDARDWIDTH, STANDARDHEIGHT, TRUE); | |
} | |
////////////////////////////////////////////////////////////////////////////// | |
//その他private関数 | |
////////////////////////////////////////////////////////////////////////////// | |
void Win::InvalidateNextHai(void) | |
{ | |
RECT r={10*24+64+20,0,10*24+64+20+24,0}; | |
r.top=36+30*LogoPos[CurTumi]*5; | |
r.bottom=r.top+30; | |
if(UseSmall) | |
{ | |
r.left/=2; | |
r.top/=2; | |
r.right/=2; | |
r.bottom/=2; | |
} | |
InvalidateRect(HWindow,&r,TRUE); | |
} | |
void Win::InvalidateHai(int x,int y) | |
{ | |
RECT r; | |
r.left=16+x*24+((y%2)?12:0); | |
r.top=16+y*30; | |
r.right=r.left+24; | |
r.bottom=r.top+30; | |
if(UseSmall) | |
{ | |
r.left/=2; | |
r.top/=2; | |
r.right/=2; | |
r.bottom/=2; | |
} | |
InvalidateRect(HWindow,&r,TRUE); | |
} | |
////////////////////////////////////////////////////////////////////////////// | |
//ダイアログ処理関数 | |
////////////////////////////////////////////////////////////////////////////// | |
void OptDlg::WMInitDialog(RTMessage Msg) | |
{ | |
SendDlgItemMessage(HWindow,100+CurMode,BM_SETCHECK,TRUE,0); | |
SendDlgItemMessage(HWindow,200+CurTumi,BM_SETCHECK,TRUE,0); | |
SetFocus(GetDlgItem(HWindow,100+CurMode)); | |
Msg.Result=FALSE; | |
} | |
void OptDlg::Ok(RTMessage Msg) | |
{ | |
int i; | |
for(i=0;i<5;i++) | |
if(SendMessage(GetDlgItem(HWindow,100+i),BM_GETCHECK,0,0)) | |
CurMode=i; | |
for(i=0;i<4;i++) | |
if(SendMessage(GetDlgItem(HWindow,200+i),BM_GETCHECK,0,0)) | |
CurTumi=i; | |
TDialog::Ok(Msg); | |
((Win *)Parent)->CMNewGame(Msg); | |
} | |
int PASCAL WinMain(HANDLE a,HANDLE b,LPSTR c,int d) | |
{ | |
int x,y; | |
Apr Ap("九龍",a,b,c,d); | |
static char w[5]="HAI@"; | |
CurMode=GetPrivateProfileInt("九龍","難易度",1,"Kuron.ini"); | |
CurTumi=GetPrivateProfileInt("九龍","積み方",0,"Kuron.ini"); | |
if(GetSystemMetrics(SM_CYSCREEN)<480) //VGA以下 | |
UseSmall=TRUE; | |
randomize(); | |
for(y=0;y<13;y++) | |
for(x=0;x<13;x++) | |
Board[x][y]=-1; | |
NextHai=0; | |
for(x=0;x<7;x++) | |
{ | |
w[3]='1'+x; | |
Hai[x]=LoadBitmap(a,w); | |
} | |
Logo=LoadBitmap(a,"Logo"); | |
Ap.Run(); | |
for(x=0;x<7;x++) | |
DeleteObject(Hai[x]); | |
DeleteObject(Logo); | |
w[1]=0;w[0]='0'+CurMode; | |
WritePrivateProfileString("九龍","難易度",w,"Kuron.ini"); | |
w[0]='0'+CurTumi; | |
WritePrivateProfileString("九龍","積み方",w,"Kuron.ini"); | |
return Ap.Status; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment