Skip to content

Instantly share code, notes, and snippets.

@elw00d
Created July 29, 2019 10:29
Show Gist options
  • Save elw00d/0bbf36408d104dc9bc549af3f8ca4032 to your computer and use it in GitHub Desktop.
Save elw00d/0bbf36408d104dc9bc549af3f8ca4032 to your computer and use it in GitHub Desktop.
/* Точки под Windows 9x/NT/ME/2000/XP */
/* Copyright (c) 2004 by Zealot [WB Team] */
#include <windows.h>
#pragma hdrstop
#include "points.h"
HDC hdc;
PAINTSTRUCT ps;
HPEN hpen;
HBRUSH hbrush;
RECT wr;
BOOL InitApp(HINSTANCE);
LRESULT __stdcall WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
void DrawZones();
void SearchZones();
void SearchBlocked();
void FindZone(char,char);
void FindBlocked(char,char);
int IsWay(char,char);
void Find(char,char);
char NextX(char,int);
char NextY(char,int);
char Player(char,char);
bool IsAlready(char,char);
void SetAlready(char,char);
bool IsBlocked(char,char);
void Push(char,char);
void Pop(void);
void DrawPoints(void);
int Search(void);
char const szClassName[] = "MainWndClass";
char const szWindowTitle[] = "Dots";
HINSTANCE hInst;
int D_U; /* Dialog unit */
unsigned char map[25][19];
char player=1;
int nZones=0; //Количество зон
int zIndex=0; //Адрес последнего элемента Zones
char Zones[100000]; //Зоны
unsigned char sp[5000];
unsigned char Already[25][19];
unsigned char Blocked[25][19];
char Local[25][19];
char LocalAlready[25][19];
int j; //Очень важный int
int PL; //Player for SearchBlocked()
bool blocked; //for -----------^^
#pragma argsused
int __stdcall WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpszCmdLine,
int nCmdShow)
{
MSG msg;
HWND hwnd;
hInst=hInstance;
if(!InitApp(hInst))
return FALSE;
HMENU hMenu=LoadMenu(hInst,"P_MENU");
HACCEL hAccel=LoadAccelerators(hInst,"P_ACCEL");
hwnd=CreateWindowEx(
0,
szClassName,szWindowTitle,
WS_OVERLAPPED|WS_SYSMENU|WS_DLGFRAME|WS_MINIMIZEBOX,
CW_USEDEFAULT,CW_USEDEFAULT,
CW_USEDEFAULT,CW_USEDEFAULT,
0,hMenu,hInst,NULL);
if(!hwnd) return FALSE;
ShowWindow(hwnd,nCmdShow);
UpdateWindow(hwnd);
while(GetMessage(&msg,0,0,0))
{
if(!hAccel||!TranslateAccelerator(hwnd,hAccel,&msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
DestroyMenu(hMenu);
return msg.wParam;
}
BOOL InitApp(HINSTANCE hInstance)
{
ATOM aWndClass;
WNDCLASS wc;
memset(&wc,0,sizeof(wc));
wc.style=0;
wc.lpfnWndProc=(WNDPROC)WndProc;
wc.cbClsExtra=0;
wc.hInstance=hInstance;
wc.hIcon=LoadIcon(hInst,"ICON_1");
wc.hCursor=LoadCursor(NULL,IDC_ARROW);
wc.hbrBackground=(HBRUSH)CreateSolidBrush(RGB(0x00,0x9F,0x00));//(COLOR_WINDOW+1);
wc.lpszMenuName=(LPSTR)NULL;
wc.lpszClassName=(LPSTR)szClassName;
aWndClass=RegisterClass(&wc);
return (aWndClass!=0);
}
LRESULT CALLBACK _export WndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
static HWND border1,border2;
switch(msg) {
case WM_PAINT:
{
hdc=BeginPaint(hwnd,&ps);
hpen=CreatePen(2,1,RGB(0x00,0x00,0x00));
SelectObject(hdc,hpen); // Чет макрокоманды не пашут...
SetBkMode(hdc,0);
for(int i=0;i<25;i++)
{
MoveToEx(hdc,2+i*15+25,12,NULL);
LineTo(hdc,2+i*15+25,300+10);
if(i<19)
{ /* Размер игрового поля - 25x19 */
MoveToEx(hdc,12,2+i*15+25,NULL);
LineTo(hdc,400,2+i*15+25);
}
}
SetTextColor(hdc,RGB(0x00,0x00,0x00));
TextOut(hdc,475,20,"GAME",4);
TextOut(hdc,450,40,"Ход : ",6);
////////////Подсчет очков////////////////////
int n1,n2;
n1=0;
n2=0;
for(int i=0;i<19;i++)
for(int n=0;n<25;n++)
{
if(IsBlocked(n,i))
{
if(map[n][i]==2)
n1++;
if(map[n][i]==1)
n2++;
}
}
char str[20];
wsprintf(str,"Очки красных : %u ",n1);
TextOut(hdc,431,60,str,18);
wsprintf(str,"Очки синих : %u ",n2);
TextOut(hdc,433,80,str,17);
//////////////////////////////////////////////
DeleteObject(hpen);
DrawZones();
DrawPoints();
//Draw();
EndPaint(hwnd,&ps);
return 0;
}
case WM_CREATE:
{
/*for(int ii=0;ii<19;ii++) //Тест на прочность
for(int n=0;n<25;n++)
map[n][ii]=2;
map[0][0]=0;*/
RECT wr;
TEXTMETRIC tm;
hdc=GetDC(hwnd); //Это дабы размер окна всегда
GetTextMetrics(hdc,&tm); //зависел от размера системного шрифта
D_U=tm.tmAveCharWidth/4;
ReleaseDC(hwnd,hdc);
GetWindowRect(hwnd,&wr);
MoveWindow(hwnd,wr.left,wr.top,600,370,TRUE);
border1=CreateWindow(
"static",NULL,
WS_CHILD|WS_VISIBLE|SS_GRAYFRAME|WS_DLGFRAME,
12,12,390,300,hwnd,(HMENU)IDS_1,hInst,NULL);
ShowWindow(border1,1);
UpdateWindow(border1);
border2=CreateWindow(
"static",NULL,
WS_CHILD|WS_VISIBLE|SS_GRAYFRAME|WS_DLGFRAME,
420,12,150,300,hwnd,(HMENU)IDS_1,hInst,NULL);
ShowWindow(border2,1);
UpdateWindow(border2);
return 0;
}
case WM_KEYDOWN:
return 0;
case WM_COMMAND: /*Messages from menu or buttons*/
{
//Если Win16, то switch(wParam)
//если Win32, то switch(LOWORD(wParam))
//А то не будут обрбатываться сообщения от
//акселераторов и (?) клавиатуры
switch(LOWORD(wParam))
{
case CM_GAME_NEW:
{
//MessageBox(hwnd,"Щазззз!","Гы-Гы-Гы-Гы...",MB_OK|MB_ICONINFORMATION);
for(int ii=0;ii<19;ii++)
for(int n=0;n<25;n++) {
map[n][ii]=Blocked[n][ii]=0;
player=1;
}
SearchZones(); //Заполняем Zones[]
//Обновляем окно полностью :
wr.left=0;
wr.top=0;
wr.right=600;
wr.bottom=500;
InvalidateRect(hwnd,&wr,true);
return 0;
}
case CM_GAME_EXIT:
{
DestroyWindow(hwnd);
return 0;
}
case CM_GAME_SAVE:
{
HFILE hf;
OFSTRUCT ofs;
hf=OpenFile("savegame.dat",&ofs,OF_CREATE);
_lwrite(hf,(const char *)map,25*19);
_lwrite(hf,(const char *)Blocked,25*19);
_lwrite(hf,(const char*)&player,sizeof(player));
_lclose(hf);
MessageBox(hwnd," Игра записана. ","Info",MB_OK|MB_ICONINFORMATION);
return 0;
}
case CM_GAME_SCORES:
{
MessageBox(hwnd,"Не работает ещё.","Scores",MB_OK|MB_ICONINFORMATION);
return 0;
}
case CM_GAME_RESTORE:
{
HFILE hf;
OFSTRUCT ofs;
hf=OpenFile("savegame.dat",&ofs,OF_READ);
_lread(hf,map,25*19);
_lread(hf,Blocked,25*19);
_lread(hf,&player,sizeof(player));
_lclose(hf);
SearchZones(); //Заполняем Zones[]
//Обновляем окно полностью :
wr.left=0;
wr.top=0;
wr.right=600;
wr.bottom=500;
InvalidateRect(hwnd,&wr,true);
return 0;
}
case CM_HLP:
{
MessageBox(hwnd,"Нету хелпа !\n\nЮзайте пункт About","Хелп",MB_OK|MB_ICONHAND);
return 0;
}
case CM_ABOUT:
{
MessageBox(hwnd,"Школьная игра \"Точки\" 1.10 \n\nCopyright (c) 2004 Kostromin I.A.\n","About...",MB_OK|MB_ICONINFORMATION);
return 0;
}
}
return 0;
}
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
case WM_RBUTTONUP: /* Отладочная процедура */
{
/* for(int i=0;i<18;i++)
for(int k=0;k<24;k++)
{
if(map[k][i])
{
char str[20];
wsprintf(str,"MAP[%u][%u] = %u\tnZones=%u",k+1,i+1,map[k][i],nZones);
MessageBox(hwnd,str,"Info",MB_OK|MB_ICONINFORMATION);
return 0;
}
} */
// player=!player;
return 0;
}
case WM_LBUTTONDOWN: //only for experiment!
//case WM_MOUSEMOVE:
{
hdc=GetDC(hwnd);
int X=(LOWORD(lParam)-14)/15;
int Y=(HIWORD(lParam)-14)/15;
int Xmod=(LOWORD(lParam)-13)%15;
int Ymod=(HIWORD(lParam)-13)%15;
if((LOWORD(lParam)<=14+25*15)&&(HIWORD(lParam)<=14+19*15))
if((LOWORD(lParam)>14+4)&&(HIWORD(lParam)>14+4))
if(((Xmod<4)&&(Ymod<4))||
((Xmod>9)&&(Ymod<4))||
((Xmod<4)&&(Ymod>9))||
((Xmod>9)&&(Ymod>9)) )
{
if((Xmod>9)&&(Ymod<4))
X++;
if((Xmod<4)&&(Ymod>9))
Y++;
if((Xmod>9)&&(Ymod>9))
{
Y++;
X++;
}
if(Xmod==0) X++; // Если Xmod=0, X на 1 меньше
if(Ymod==0) Y++; // -----^
char st[20];
wsprintf(st,"X = %u \nY = %u",X,Y);
//MessageBox(hwnd,st,"Current position : ",MB_OK|
// MB_ICONINFORMATION);
if((!map[X-1][Y-1])&&(!IsBlocked(X-1,Y-1))) // Занята ли позиция?
{
if(player) //Красная точка
map[X-1][Y-1]=1;
else
map[X-1][Y-1]=2; //Синяя точка
int x=(X)*15+13;
int y=(Y)*15+13;
player=!player;
SearchBlocked();
SearchZones();
//Обновляем окно
DrawZones();
DrawPoints();
wr.left=0; //Приходится обновлять всё окно...
wr.top=0;
wr.right=600;
wr.bottom=500;
InvalidateRect(hwnd,&wr,true);
}
}
ReleaseDC(hwnd,hdc);
return 0;
}
} //switch(msg)...
return DefWindowProc(hwnd,msg,wParam,lParam);
}
void DrawZones()
{
hpen=CreatePen(0,3,0);
int index=0;
unsigned char nPoints;
unsigned char oldX,oldY;
SelectObject(hdc,hpen);
for(int i=0;i<nZones;i++)
{
nPoints=Zones[index];
index++;
oldX=Zones[index];
oldY=Zones[index+1];
MoveToEx(hdc,Zones[index]*15+13,Zones[index+1]*15+13,NULL);
int k=0;
for(k;k<nPoints;k++)
{
unsigned char x,y; // <-- Приходится вводить дополнительные
x=Zones[index]; // переменные, дабы читать список
y=Zones[index+1]; // побайтно(тип int 16-разряден, и
index+=2; // получается МАЗА)
LineTo(hdc,x*15+13,y*15+13);
}
LineTo(hdc,oldX*15+13,oldY*15+13);
}
DeleteObject(hpen);
return;
}
void SearchZones()
{
nZones=0;
zIndex=0;
for(int ii=0;ii<19;ii++)
for(int n=0;n<25;n++)
Already[n][ii]=0;
j=0;
for(int i=0;i<19;i++)
for(int n=0;n<25;n++)
{
if((map[n][i]!=0)&&
(!IsAlready(n,i))&&
(!IsBlocked(n,i)))
FindZone(n,i);
}
return;
}
void FindZone(char n,char i) //Рекурсивная функция
{
Push(n,i);
signed char x,y;
bool zone=false;
signed long z=0;
while(z<(j-6))
{
if((sp[z]==n)&&(sp[z+1]==i))
{
Zones[zIndex]=(j-z)/2-1;
zIndex++;
for(int k=z;k<(j-2);k++)
{
Zones[zIndex]=sp[k]+1;
zIndex++;
}
nZones++;
zone=true;
}
z+=2;
}
if(!zone)
{
for(int k=0;k<8;k++)
{
x=NextX(n+1,k)-1;
y=NextY(i+1,k)-1;
if((x!=30)&&(y!=30))
{
char xx=sp[j-4]; //Эти 3 строчки нужны, чтобы
char yy=sp[j-3]; //выбирались зоны, а не просто
if((x!=xx)||(y!=yy)) //линии.
if((!IsBlocked(x,y))&&(map[x][y]==map[n][i])&&
(map[x][y]!=0)&&(!IsAlready(x,y)))
FindZone(x,y);
}
}
}
Pop();
if(!zone)Already[n][i]=1;
}
void SearchBlocked()
{
int i,n; //Локальные переменные-счётчики
for(i=0;i<19;i++) //Очистка основных структур данных :
for(n=0;n<25;n++)
{
if(IsBlocked(n,i))
{
Local[n][i]=Blocked[n][i];
Already[n][i]=1; //Уже блокированные не проверяются
}
else
{
Local[n][i]=1; //Локальный массив
//Если точка не заблокирована,
//флаг снимается, иначе
//точка остаётся заблокированой
//и её состояние записывается в глобальный массив Blocked[]
Already[n][i]=0;
}
}
for(i=0;i<19;i++) //Проверка непустых ячеек
for(n=0;n<25;n++)
{
if(!Already[n][i])
if(map[n][i]>0)
{
blocked=true;
PL=map[n][i];
for(int ii=0;ii<19;ii++)
for(int nn=0;nn<25;nn++)
{
LocalAlready[nn][ii]=0;
}
FindBlocked(n,i);
Already[n][i]=1;
}
}
for(i=0;i<19;i++) //Проверка пустых ячеек
for(n=0;n<25;n++)
{
if(map[n][i]==0)
{
if(!IsAlready(n,i))//Если ещё не проверено
{
for(int ii=0;ii<19;ii++)
for(int nn=0;nn<25;nn++)
{
LocalAlready[nn][ii]=0;
}
//Если есть путь, то не блокировано
if((IsWay(n,i)==0))
Local[n][i]=0;
Already[n][i]=1;
}
}
}
for(i=0;i<19;i++)
for(n=0;n<25;n++)
if(!IsBlocked(n,i)) //Точки не могут освобождаться
Blocked[n][i]=Local[n][i];
}
int IsWay(char n,char i)
{
blocked=true;
PL=1;
Find(n,i);
if(!blocked)
{
blocked=true;
PL=2;
Find(n,i);
if(!blocked)
return 0;
else
return 1; //у красных
}
else return 2; //У синих
}
int Search()
//Функция проверяет, есть ли в списке sp ненулевые точки
{
for(long z=0;z<j;z+=2)
{
char x=sp[z];
char y=sp[z+1];
if(map[x][y]!=0)
return 1;
}
return 0;
}
void Find(char n,char i)
{
Push(n,i);
if((n==0)||(i==0)||(n==24)||(i==18))
{
blocked=false;
}
if(blocked)
{
LocalAlready[n][i]=1;
for(int k=0;k<7;k+=2)
{
if(!blocked) break;
char x=NextX(n+1,k)-1;
char y=NextY(i+1,k)-1;
if(!LocalAlready[x][y])
{
if((Local[x][y]==0)&&(map[x][y]==0)) //Если Local[x][y]==0, то она уже точно проверена!
{
if(!Search())
{
blocked=false;
char x=sp[0];
char y=sp[1];
Local[x][y]=0;
Already[x][y]=1;
break;
}
}
if((IsAlready(x,y))&&(map[x][y]==PL)&&(!Local[x][y]))
{
if(!Search())
blocked=false;
break;
}
if(((map[x][y]==PL)||(map[x][y]==0))&&(!IsBlocked(x,y)))
Find(x,y);
if((map[x][y]!=PL)&&(IsBlocked(x,y)))
Find(x,y);
}
}
}
Pop();
}
void FindBlocked(char n,char i)
{
Push(n,i);
if((n==0)||(i==0)||(n==24)||(i==18))
{
for(long z=0;z<j;z+=2)
{
char x=sp[z];
char y=sp[z+1];
if(map[x][y]==PL)
{
Local[x][y]=0;
Already[x][y]=1;
}
}
blocked=false;
}
if(blocked)
{
LocalAlready[n][i]=1;
for(int k=0;k<7;k+=2)
{
if(!blocked) break;
char x=NextX(n+1,k)-1;
char y=NextY(i+1,k)-1;
if(!LocalAlready[x][y])
{
if(((map[x][y]==PL)||(map[x][y]==0))&&(!IsBlocked(x,y)))
FindBlocked(x,y);
//Если найденная точка уже заблокирована,
//но другого цвета, необходимо продолжить путь :
if((map[x][y]!=PL)&&(map[x][y]!=0)&&(IsBlocked(x,y)))
FindBlocked(x,y);
if((map[x][y]==0)&&(Local[x][y]>0))
FindBlocked(x,y);
}
}
}
Pop();
}
char NextX(char x,int k)
{
switch(k)
{
case 1:case 2:case 3:
{
x++;
break;
}
case 5:case 6:case 7:
x--;
}
if(x<1) return 31;
if(x>25) return 31;
return x;
}
char NextY(char y,int k)
{
switch(k)
{
case 7:case 0:case 1:
{
y--;
break;
}
case 3:case 4:case 5:
y++;
}
if(y<1) return 31;
if(y>19) return 31;
return y;
}
bool IsBlocked(char x,char y)
{
return Blocked[x][y];
}
char Player(char x,char y) //Чья точка?
{
return map[x][y];
}
bool IsAlready(char x,char y) //Уже проверили?
{
return Already[x][y];
}
void SetAlready(char x,char y)
{
Already[x][y]=1;
}
void Push(char x,char y)
{
sp[j]=x;
sp[j+1]=y;
j+=2;
}
void Pop(void)
{
j-=2; //Краткость-С.Т.
}
void DrawPoints(void) //Функция перерисовки точек
{
hpen=CreatePen(0,1,RGB(0,0,0)); //Сплошная линия
SelectObject(hdc,hpen);
if(player) //Чей ход?
hbrush=CreateSolidBrush(RGB(0xFF,0,0));
else
hbrush=CreateSolidBrush(RGB(0,0,0xFF));
SelectObject(hdc,hbrush);
Rectangle(hdc,500,42,515,57);
DeleteObject(hbrush);
DeleteObject(hpen);
//////////////////////////////////////
for(int i=0;i<=24;i++)
for(int k=0;k<=18;k++)
{
if(IsBlocked(i,k))
hpen=CreatePen(0,2,RGB(0x00,0xFF,0x00));
else
hpen=CreatePen(0,2,RGB(0x00,0x00,0x00));
SelectObject(hdc,hpen);
if(map[i][k]==1)
{
hbrush=CreateSolidBrush(RGB(0xFF,0x00,0x00));
}
if(map[i][k]==2)
{
hbrush=CreateSolidBrush(RGB(0x00,0x00,0xFF));
}
if(map[i][k])
{
SelectObject(hdc,hbrush);
Ellipse(hdc,14+(i+1)*15-5,14+(k+1)*15-5,14+(i+1)*15+5,14+(k+1)*15+5);
}
else
{
if(IsBlocked(i,k))
{
DeleteObject(hpen);
hpen=CreatePen(0,2,RGB(0x00,0x00,0x00));
SelectObject(hdc,hpen);
//Ellipse(hdc,14+(i+1)*15-3,14+(k+1)*15-3,14+(i+1)*15+2,14+(k+1)*15+2);
int x=14+(i+1)*15-1;
int y=14+(k+1)*15-1;
MoveToEx(hdc,x-3,y-3,NULL);
LineTo(hdc,x+3,y+3);
MoveToEx(hdc,x-3,y+3,NULL);
LineTo(hdc,x+3,y-3);
}
}
DeleteObject(hpen);
DeleteObject(hbrush);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment