#include <windows.h>
#include <time.h>
#include <vector>
using namespace std;
#define STATIC_OUTSIDE 0 // 0 - 2
#define STATIC_MESSAGE 3 // Định danh cửa sổ thông báo điểm
enum { TC_FREE = 0, TC_LARGE, TC_SMALL, TC_ROAD };
typedef struct
{
short Style; // Kiểu ép từ CCell qua chỉ có 2 giá trị : TC_LARGE, TC_FREE
short PrevIndex; // Chỉ mục nốt trước
} TEMP;
class CWindow;
class CMess
{
private:
HWND m_hWnd; // Thẻ cửa sổ Cell
int m_nMark = 0; // Điểm số cộng dồn
COLORREF m_crFore = RGB(255, 255, 0); // Màu chữ
COLORREF m_crBack = RGB(0, 0, 255); // Màu nền
public:
// Các thuộc tính
__declspec(property(get = getHwnd)) HWND Hwnd;
__declspec(property(get = getForeColor, put = setForeColor)) COLORREF ForeColor;
__declspec(property(get = getBackColor, put = setBackColor)) COLORREF BackColor;
__declspec(property(get = getMark, put = setMark)) int Mark;
__declspec(property(get = getParent, put = setParent)) CWindow * Parent;
// Các cài đặt thuộc tính
HWND getHwnd() { return m_hWnd; }
COLORREF getForeColor() { return m_crFore; }
void setForeColor(COLORREF crFore) { m_crFore = crFore; }
COLORREF getBackColor() { return m_crBack; }
void setBackColor(COLORREF crBack) { m_crBack = crBack; }
int getMark() { return m_nMark; }
void setMark(int nMark) { m_nMark = nMark; }
// Các hàm công cộng
HWND Create(HINSTANCE hInst, HWND hParent, UINT id);
void Move();
void Draw();
};
class CDrop
{
private:
HWND m_hWnd; // Thẻ cửa sổ Cell
UINT m_uIndex; // Chỉ mục Cell này
COLORREF m_crFore; // Màu bi
COLORREF m_crBack; // Màu nền
CWindow * m_pWindow; // Cửa sổ cha
public:
// Các thuộc tính
__declspec(property(get = getHwnd)) HWND Hwnd;
__declspec(property(get = getIndex, put = setIndex)) UINT Index;
__declspec(property(get = getForeColor, put = setForeColor)) COLORREF ForeColor;
__declspec(property(get = getBackColor, put = setBackColor)) COLORREF BackColor;
__declspec(property(get = getParent, put = setParent)) CWindow * Parent;
// Các cài đặt thuộc tính
HWND getHwnd() { return m_hWnd; }
UINT getIndex() { return m_uIndex; }
void setIndex(UINT uIndex) { m_uIndex = uIndex; }
COLORREF getForeColor() { return m_crFore; }
void setForeColor(COLORREF crFore) { m_crFore = crFore; }
COLORREF getBackColor() { return m_crBack; }
void setBackColor(COLORREF crBack) { m_crBack = crBack; }
CWindow * getParent() { return m_pWindow; }
void setParent(CWindow * pWindow) { m_pWindow = pWindow; }
// Các hàm công cộng
HWND Create(HINSTANCE hInst, HWND hParent, UINT id);
void Move();
void Draw();
};
class CCell
{
private:
HWND m_hWnd; // Thẻ cửa sổ Cell
UINT m_uIndex; // Chỉ mục Cell này
UINT m_uStyle; // Kiểu Cell
BOOL m_bSelected; // Cell này đang chọn ?
COLORREF m_crBack; // Màu nền
COLORREF m_crFore; // Màu bi
CWindow * m_pWindow; // Cửa sổ cha
// Thủ tục window
static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wparam, LPARAM lparam);
// Các bộ xử lý thông điệp
LRESULT OnCreate(HINSTANCE hInst, HWND hWnd);
LRESULT OnPaint();
LRESULT OnLButtonDown(LPARAM lparam);
public:
// Các thuộc tính
__declspec(property(get = getHwnd)) HWND Hwnd;
__declspec(property(get = getIndex, put = setIndex)) UINT Index;
__declspec(property(get = getStyle, put = setStyle)) UINT Style;
__declspec(property(get = getSelected, put = setSelected)) BOOL Selected;
__declspec(property(get = getBackColor, put = setBackColor)) COLORREF BackColor;
__declspec(property(get = getForeColor, put = setForeColor)) COLORREF ForeColor;
__declspec(property(get = getParent, put = setParent)) CWindow * Parent;
// Các cài đặt thuộc tính
HWND getHwnd() { return m_hWnd; }
UINT getIndex() { return m_uIndex; }
void setIndex(UINT uIndex) { m_uIndex = uIndex; }
UINT getStyle() { return m_uStyle; }
void setStyle(UINT uStyle) { m_uStyle = uStyle; }
BOOL getSelected() { return m_bSelected; }
void setSelected(BOOL bSelected) { m_bSelected = bSelected; }
COLORREF getBackColor() { return m_crBack; }
void setBackColor(COLORREF crBack) { m_crBack = crBack; }
COLORREF getForeColor() { return m_crFore; }
void setForeColor(COLORREF crFore) { m_crFore = crFore; }
CWindow * getParent() { return m_pWindow; }
void setParent(CWindow * pWindow) { m_pWindow = pWindow; }
// Các hàm công cộng
HWND Create(HINSTANCE hInst, HWND hParent);
void Move();
void Draw();
};
class CWindow
{
private:
HINSTANCE m_hInst; // Thể hiện chương trình
HWND m_hWnd; // Thẻ cửa sổ chính
CCell m_Cell[81]; // Các đối tượng Cell
CDrop m_Drop[3];
CMess m_Mess;
COLORREF m_crTable[7] =
{ RGB(255,255,0), RGB(255,0,255), RGB(0,255,255), RGB(255,0,0), RGB(0,255,0), RGB(0,0,255), RGB(128,128,128) };
// Thủ tục window
static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wparam, LPARAM lparam);
// Các bộ xử lý thông điệp
LRESULT OnCreate(HINSTANCE hInst, HWND hWnd);
LRESULT OnSize(LPARAM lparam);
LRESULT OnDrawItem(LPDRAWITEMSTRUCT pd);
LRESULT OnClose();
LRESULT OnDestroy();
void LoopRoad(TEMP temp[81], vector<short> & prev, short end, vector<short> & road);
void DrawRoad(vector<short> & road);
void StepRoad(vector<short> & road);
short EnumStyleCell(short style, vector<short> & result);
short BonusFromCell(short node, vector<short> & bonus);
public:
// Các thuộc tính
__declspec(property(get = getSelectedCell)) CCell * SelectedCell;
__declspec(property(get = getCell)) CCell * Cell[];
// Các cài đặt thuộc tính
CCell * getSelectedCell();
CCell * getCell(int index) { return &m_Cell[index]; }
// Các phương thức
BOOL Create(HINSTANCE hInst);
int LoopMessage();
void HandleAll(short start, short end);
};
HWND CMess::Create(HINSTANCE hInst, HWND hParent, UINT id)
{
m_hWnd = CreateWindowEx(WS_EX_DLGMODALFRAME, TEXT("static"), NULL, WS_CHILD | WS_VISIBLE | SS_OWNERDRAW, 0, 0, 0, 0, hParent, (HMENU)id, hInst, NULL);
return m_hWnd;
}
void CMess::Move()
{
MoveWindow(m_hWnd, 130, 545, 395, 30, TRUE);
}
void CMess::Draw()
{
RECT r;
HDC hdc = GetDC(m_hWnd);
HBRUSH hbrBack = CreateSolidBrush(m_crBack);
GetClientRect(m_hWnd, &r);
FillRect(hdc, &r, hbrBack);
DeleteObject(hbrBack);
SetTextColor(hdc, m_crFore);
SetBkMode(hdc, TRANSPARENT);
TCHAR szText[MAX_PATH];
wsprintf(szText, TEXT("Marks : %u"), m_nMark);
DrawText(hdc, szText, -1, &r, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
ReleaseDC(m_hWnd, hdc);
}
HWND CDrop::Create(HINSTANCE hInst, HWND hParent, UINT id)
{
m_uIndex = id;
m_hWnd = CreateWindowEx(WS_EX_DLGMODALFRAME, TEXT("static"), NULL, WS_CHILD | WS_VISIBLE | SS_OWNERDRAW, 0, 0, 0, 0, hParent, (HMENU)id, hInst, NULL);
return m_hWnd;
}
void CDrop::Move()
{
MoveWindow(m_hWnd, m_uIndex * 30 + 30, 545, 30, 30, TRUE);
}
void CDrop::Draw()
{
RECT r;
HDC hdc = GetDC(m_hWnd);
HBRUSH hbrBack = CreateSolidBrush(m_crBack);
GetClientRect(m_hWnd, &r);
FillRect(hdc, &r, hbrBack);
DeleteObject(hbrBack);
HBRUSH hbrFore = CreateSolidBrush(m_crFore);
SelectObject(hdc, hbrFore);
Ellipse(hdc, 2, 2, r.right - 2, r.bottom - 2);
DeleteObject(hbrFore);
ReleaseDC(m_hWnd, hdc);
}
LRESULT CCell::WndProc(HWND hWnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
if (msg == WM_CREATE)
{
LPCREATESTRUCT pcs = reinterpret_cast<LPCREATESTRUCT>(lparam);
CCell * pCell = reinterpret_cast<CCell*>(pcs->lpCreateParams);
SetWindowLongPtr(hWnd, GWLP_USERDATA, PtrToUlong(pCell));
return pCell->OnCreate(pcs->hInstance, hWnd);
}
CCell * pCell = reinterpret_cast<CCell*>(static_cast<LONG_PTR>(GetWindowLongPtr(hWnd, GWLP_USERDATA)));
switch (msg)
{
case WM_PAINT: return pCell->OnPaint();
case WM_LBUTTONDOWN: return pCell->OnLButtonDown(lparam);
}
return DefWindowProc(hWnd, msg, wparam, lparam);
}
LRESULT CCell::OnCreate(HINSTANCE hInst, HWND hWnd)
{
m_hWnd = hWnd;
return 0;
}
LRESULT CCell::OnPaint()
{
PAINTSTRUCT ps;
BeginPaint(m_hWnd, &ps);
EndPaint(m_hWnd, &ps);
Draw();
return 0;
}
LRESULT CCell::OnLButtonDown(LPARAM lparam)
{
if (m_uStyle == TC_LARGE)
{
if (this->Selected) // Click ngay cell đã chọn trước đó
{
this->Selected ^= 1; // Bỏ chọn
this->Draw();
}
else // Cell này chưa được chọn
{
CCell * pCell = m_pWindow->SelectedCell;
if (pCell) // Nếu có chọn trước một cell
{
pCell->Selected ^= 1; // Bỏ chọn cell trước
pCell->Draw();
}
this->Selected ^= 1; // Chọn cell này
this->Draw();
}
}
else
{
CCell * pCell;
if (pCell = m_pWindow->SelectedCell)
m_pWindow->HandleAll(pCell->Index, this->Index);
}
return 0;
}
HWND CCell::Create(HINSTANCE hInst, HWND hParent)
{
static BOOL bRegistered = 0; // Sử dụng biến tĩnh để tránh đăng ký nhiều lần
WNDCLASS w;
w.lpszClassName = TEXT("Cell");
if (!bRegistered)
{
w.cbClsExtra = 0;
w.cbWndExtra = 0;
w.hbrBackground = NULL;
w.hCursor = LoadCursor(NULL, IDC_ARROW);
w.hIcon = NULL;
w.hInstance = hInst;
w.lpfnWndProc = WndProc;
w.lpszMenuName = NULL;
w.style = CS_HREDRAW | CS_VREDRAW;
if (!RegisterClass(&w))
return FALSE;
bRegistered = true;
}
return CreateWindowEx(WS_EX_DLGMODALFRAME, w.lpszClassName, NULL, WS_CHILD | WS_VISIBLE, 0, 0, 0, 0, hParent, NULL, hInst, this);
}
void CCell::Move()
{
UINT row = m_uIndex / 9;
UINT col = m_uIndex % 9;
MoveWindow(m_hWnd, 30 + col * 55, 30 + row * 55, 55, 55, TRUE);
}
void CCell::Draw()
{
RECT r;
HDC hdc = GetDC(m_hWnd);
HBRUSH hbrBack = (m_bSelected) ? CreateSolidBrush(RGB(0, 128, 255)) : CreateSolidBrush(m_crBack);
GetClientRect(m_hWnd, &r);
FillRect(hdc, &r, hbrBack);
DeleteObject(hbrBack);
if (m_uStyle != TC_FREE)
{
HBRUSH hbrFore = CreateSolidBrush(m_crFore);
SelectObject(hdc, hbrFore);
switch (m_uStyle)
{
case TC_LARGE: Ellipse(hdc, 3, 3, r.right - 3, r.bottom - 3); break;
case TC_SMALL: Ellipse(hdc, 13, 13, r.right - 13, r.bottom - 13); break;
}
DeleteObject(hbrFore);
}
ReleaseDC(m_hWnd, hdc);
}
LRESULT CWindow::WndProc(HWND hWnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
if (msg == WM_CREATE)
{
LPCREATESTRUCT pcs = reinterpret_cast<LPCREATESTRUCT>(lparam);
CWindow * pWindow = reinterpret_cast<CWindow*>(pcs->lpCreateParams);
SetWindowLongPtr(hWnd, GWLP_USERDATA, PtrToUlong(pWindow));
return pWindow->OnCreate(pcs->hInstance, hWnd);
}
CWindow * pWindow = reinterpret_cast<CWindow*>(static_cast<LONG_PTR>(GetWindowLongPtr(hWnd, GWLP_USERDATA)));
switch (msg)
{
case WM_SIZE: return pWindow->OnSize(lparam);
case WM_DRAWITEM: return pWindow->OnDrawItem((LPDRAWITEMSTRUCT)lparam);
case WM_CLOSE: return pWindow->OnClose();
case WM_DESTROY: return pWindow->OnDestroy();
}
return DefWindowProc(hWnd, msg, wparam, lparam);
}
LRESULT CWindow::OnCreate(HINSTANCE hInst, HWND hWnd)
{
m_hInst = hInst;
m_hWnd = hWnd;
// Tính toán kích thước cho cửa sổ chính
RECT r = { 0, 0, 555 , 595 };
AdjustWindowRect(&r, WS_CAPTION, FALSE);
int cxWindow = r.right - r.left;
int cyWindow = r.bottom - r.top;
GetWindowRect(hWnd, &r);
r.right = r.left + cxWindow;
r.bottom = r.top + cyWindow;
MoveWindow(hWnd, r.left, r.top, cxWindow, cyWindow, TRUE);
// Khởi tạo
srand((UINT)time(NULL));
for (int i = 0; i < 81; i++)
{
m_Cell[i].Index = i;
m_Cell[i].Style = TC_FREE;
m_Cell[i].Selected = FALSE;
m_Cell[i].BackColor = RGB(255, 128, 0);
m_Cell[i].ForeColor = 0;
m_Cell[i].Parent = this;
if (!m_Cell[i].Create(hInst, hWnd))
return -1;
}
for (int i = 0; i < 6; i++) // Khởi tạo 3 bi lớn và nhỏ đầu tiên trên Board
{
int index;
do
{
index = rand() % 81;
} while (m_Cell[index].Style != TC_FREE);
m_Cell[index].Style = (i < 3) ? TC_LARGE : TC_SMALL;
m_Cell[index].ForeColor = m_crTable[rand() % 7];
}
for (int i = 0; i < 3; i++)
{
m_Drop[i].Create(hInst, hWnd, STATIC_OUTSIDE + i);
m_Drop[i].ForeColor = m_crTable[rand() % 7];
m_Drop[i].BackColor = RGB(255, 128, 0);
m_Drop[i].Parent = this;
}
m_Mess.Create(hInst, hWnd, STATIC_MESSAGE);
return 0;
}
LRESULT CWindow::OnSize(LPARAM lparam)
{
// Di chuyển các điều khiển tới vị trí mới
for (int i = 0; i < 81; i++)
m_Cell[i].Move();
for (int i = 0; i < 9; i++)
m_Drop[i].Move();
m_Mess.Move();
return 0;
}
LRESULT CWindow::OnDrawItem(LPDRAWITEMSTRUCT pd)
{
if (pd->CtlID == STATIC_MESSAGE)
m_Mess.Draw();
if (pd->CtlID < STATIC_MESSAGE)
m_Drop[pd->CtlID].Draw();
return 0;
}
LRESULT CWindow::OnClose()
{
DestroyWindow(m_hWnd);
return 0;
}
LRESULT CWindow::OnDestroy()
{
PostQuitMessage(0);
return 0;
}
CCell * CWindow::getSelectedCell()
{
for (int i = 0; i < 81; i++)
if (m_Cell[i].Selected)
return &m_Cell[i];
return NULL;
}
BOOL CWindow::Create(HINSTANCE hInst)
{
WNDCLASS w;
w.cbClsExtra = 0;
w.cbWndExtra = 0;
w.hbrBackground = (HBRUSH)GetStockObject(DKGRAY_BRUSH);
w.hCursor = LoadCursor(NULL, IDC_ARROW);
w.hIcon = LoadIcon(NULL, IDI_APPLICATION);
w.hInstance = hInst;
w.lpfnWndProc = WndProc;
w.lpszClassName = TEXT("Lines98");
w.lpszMenuName = NULL;
w.style = CS_HREDRAW | CS_VREDRAW;
if (!RegisterClass(&w))
return FALSE;
HWND hwnd = CreateWindow(w.lpszClassName, w.lpszClassName, WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInst, this);
if (!hwnd)
return FALSE;
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
return TRUE;
}
int CWindow::LoopMessage()
{
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
void CWindow::HandleAll(short start, short end)
{
TEMP temp[81];
for (short i = 0; i < 81; i++) // Sao chép sang mảng tạm chỉ 2 giá trị : TC_LARGE, TC_FREE
{
temp[i].Style = (m_Cell[i].Style == TC_LARGE) ? TC_LARGE : TC_FREE;
temp[i].PrevIndex = -1;
}
temp[start].Style = TC_FREE;
temp[end].Style = TC_LARGE;
vector<short> prev(1, end);
vector<short> road;
LoopRoad(temp, prev, start, road);
if (road.empty())
{
MessageBox(m_hWnd, TEXT("No Roads !!!"), TEXT("Lines98"), MB_OK | MB_ICONINFORMATION);
return;
}
DrawRoad(road);
StepRoad(road);
vector<short> bonus(0);
if (BonusFromCell(end, bonus)) // Nếu có nhận những ô sẽ ăn
{
m_Mess.Mark += bonus.size();
m_Mess.Draw();
for (short j = 0; j < 3; j++)
{
for (short i = (short)bonus.size() - 1; i >= 0; i--)
{
m_Cell[bonus[i]].Style = TC_LARGE;
m_Cell[bonus[i]].Draw();
}
Sleep(200);
for (short i = (short)bonus.size() - 1; i >= 0; i--)
{
m_Cell[bonus[i]].Style = TC_FREE;
m_Cell[bonus[i]].Draw();
}
Sleep(200);
}
return;
}
vector<short> smallcell;
if (EnumStyleCell(TC_SMALL, smallcell)) // Từ nhỏ -> lớn
{
short count = (short)smallcell.size();
for (short i = 0; i < count; i++)
{
m_Cell[smallcell[i]].Style = TC_LARGE; // Chuyển sang lớn
m_Cell[smallcell[i]].Draw();
}
for (short i = 0; i < count; i++) // Ăn bi thụ động
{
vector<short> bonus(0);
if (BonusFromCell(smallcell[i], bonus))
{
m_Mess.Mark += bonus.size();
m_Mess.Draw();
for (short j = 0; j < 3; j++)
{
for (short i = (short)bonus.size() - 1; i >= 0; i--)
{
m_Cell[bonus[i]].Style = TC_LARGE;
m_Cell[bonus[i]].Draw();
}
Sleep(200);
for (short i = (short)bonus.size() - 1; i >= 0; i--)
{
m_Cell[bonus[i]].Style = TC_FREE;
m_Cell[bonus[i]].Draw();
}
Sleep(200);
}
}
}
}
vector<short> freecell;
if (EnumStyleCell(TC_FREE, freecell)) // Chuẩn bị chuyển các ô bên ngoài vào board chính
{
short count = (short)freecell.size();
for (int i = 0; i < min(count, 3); i++) // Chuyển vào Board dưới dạng ô nhỏ
{
short index;
do
{
index = rand() % count;
} while (m_Cell[freecell[index]].Style != TC_FREE);
m_Cell[freecell[index]].Style = TC_SMALL;
m_Cell[freecell[index]].ForeColor = m_Drop[i].ForeColor;
m_Cell[freecell[index]].Draw();
}
for (int i = 0; i < 3; i++)
{
m_Drop[i].ForeColor = m_crTable[rand() % 7];
m_Drop[i].Draw();
}
}
else
{
if (IDNO == MessageBox(m_hWnd, TEXT("YOU LOST !!!\n<Yes> : Replay\n<No> : Exit"), TEXT("Lines98"), MB_YESNO | MB_ICONQUESTION))
SendMessage(m_hWnd, WM_CLOSE, 0, 0);
else
{
for (int i = 0; i < 81; i++)
{
m_Cell[i].Style = TC_FREE;
m_Cell[i].Selected = FALSE;
m_Cell[i].ForeColor = 0;
m_Cell[i].Draw();
}
for (int i = 0; i < 6; i++) // Khởi tạo 3 bi lớn và nhỏ đầu tiên trên Board
{
int index;
do
{
index = rand() % 81;
} while (m_Cell[index].Style != TC_FREE);
m_Cell[index].Style = (i < 3) ? TC_LARGE : TC_SMALL;
m_Cell[index].ForeColor = m_crTable[rand() % 7];
m_Cell[index].Draw();
}
for (int i = 0; i < 3; i++)
{
m_Drop[i].ForeColor = m_crTable[rand() % 7];
m_Drop[i].Draw();
}
m_Mess.Mark = 0;
m_Mess.Draw();
}
}
}
void CWindow::LoopRoad(TEMP temp[81], vector<short> & prev, short end, vector<short> & road)
{
vector<short> next; // Vector sẽ chứa các chỉ mục cho lần duyệt kế tiếp
for (short i = (short)prev.size() - 1; i >= 0; i--) // Duyệt các chỉ mục được cho từ lần duyệt trước
{
short preIndex;
short index = prev[i];
short row = index / 9;
short col = index % 9;
if (index == end) // Gặp đích - đẩy đường đi vào ngăn xếp
{
road.push_back(index);
while (temp[index].PrevIndex != -1)
{
index = temp[index].PrevIndex; // Lấy chỉ mục ô trước đó
road.push_back(index); // Đẩy vào ngăn xếp
}
return;
}
preIndex = row * 9 + col - 1; // Xét ô bên trái
if (col > 0 && temp[preIndex].Style == TC_FREE)
{
temp[preIndex].Style = TC_ROAD; // Đánh dấu ô này là đường đi
temp[preIndex].PrevIndex = index; // Thiết lập chỉ mục cha
next.push_back(preIndex); // Nối thêm vào mảng duyệt lần sau
}
preIndex = (row - 1) * 9 + col; // Xét ô phía trên
if (row > 0 && temp[preIndex].Style == TC_FREE)
{
temp[preIndex].Style = TC_ROAD;
temp[preIndex].PrevIndex = index;
next.push_back(preIndex);
}
preIndex = row * 9 + col + 1; // Xét ô bên phải
if (col < 8 && temp[preIndex].Style == TC_FREE)
{
temp[preIndex].Style = TC_ROAD;
temp[preIndex].PrevIndex = index;
next.push_back(preIndex);
}
preIndex = (row + 1) * 9 + col; // Xét ô phía dưới
if (row < 8 && temp[preIndex].Style == TC_FREE)
{
temp[preIndex].Style = TC_ROAD;
temp[preIndex].PrevIndex = index;
next.push_back(preIndex);
}
}
if (!next.empty()) // Nếu có một tập hợp ô mới cần xét...
LoopRoad(temp, next, end, road); // ... thì cho đệ quy tiếp tục
}
void CWindow::DrawRoad(vector<short> & road)
{
HBRUSH hbrFore = CreateSolidBrush(m_Cell[road[0]].ForeColor);
HBRUSH hbrBack = CreateSolidBrush(m_Cell[road[1]].BackColor);
for (short i = (short)road.size() - 1; i > 0; i--)
{
HWND hWnd = m_Cell[road[i]].Hwnd;
HDC hdc = GetDC(hWnd);
RECT r;
GetClientRect(hWnd, &r);
FillRect(hdc, &r, hbrBack);
SelectObject(hdc, hbrFore);
if (m_Cell[road[i]].Style == TC_SMALL)
{
HBRUSH hbr = CreateSolidBrush(m_Cell[road[i]].ForeColor);
SelectObject(hdc, hbr);
Ellipse(hdc, 13, 13, r.right - 13, r.bottom - 13);
DeleteObject(hbr);
}
else
Ellipse(hdc, 18, 18, r.right - 18, r.bottom - 18);
ReleaseDC(hWnd, hdc);
}
DeleteObject(hbrFore);
DeleteObject(hbrBack);
}
void CWindow::StepRoad(vector<short> & road)
{
m_Cell[road[0]].Selected ^= 1;
m_Cell[road[0]].Draw();
m_Cell[road[0]].Style = TC_FREE;
HBRUSH hbrFore = CreateSolidBrush(m_Cell[road[0]].ForeColor);
HBRUSH hbrBack = CreateSolidBrush(m_Cell[road[0]].BackColor);
short count = (short)road.size();
for (short i = 0; i < count - 1; i++)
{
HWND hWnd = m_Cell[road[i + 1]].Hwnd;
HDC hdc = GetDC(hWnd);
RECT r;
GetClientRect(hWnd, &r);
FillRect(hdc, &r, hbrBack);
SelectObject(hdc, hbrFore);
Ellipse(hdc, 3, 3, r.right - 3, r.bottom - 3);
ReleaseDC(hWnd, hdc);
hWnd = m_Cell[road[i]].Hwnd;
hdc = GetDC(hWnd);
GetClientRect(hWnd, &r);
FillRect(hdc, &r, hbrBack);
if (m_Cell[road[i]].Style == TC_SMALL)
{
HBRUSH hbr = CreateSolidBrush(m_Cell[road[i]].ForeColor);
SelectObject(hdc, hbr);
Ellipse(hdc, 13, 13, r.right - 13, r.bottom - 13);
DeleteObject(hbr);
}
ReleaseDC(hWnd, hdc);
Sleep(50);
}
DeleteObject(hbrFore);
DeleteObject(hbrBack);
BOOL bOver = FALSE;
COLORREF crOver = 0;
if (m_Cell[road[count - 1]].Style == TC_SMALL)
{
bOver = TRUE;
crOver = m_Cell[road[count - 1]].ForeColor;
}
m_Cell[road[count - 1]].Style = TC_LARGE;
m_Cell[road[count - 1]].ForeColor = m_Cell[road[0]].ForeColor;
if (bOver)
{
vector<short> freecell;
short count = EnumStyleCell(TC_FREE, freecell);
short index = rand() % count; // Tìm 1 ô trống ngẫu nhiên
m_Cell[freecell[index]].Style = TC_SMALL; // để chuyển ô bị đè tới đó
m_Cell[freecell[index]].ForeColor = crOver;
m_Cell[freecell[index]].Draw();
}
}
short CWindow::EnumStyleCell(short style, vector<short> & result)
{
short count = 0;
result.resize(0);
for (short i = 0; i < 81; i++)
if (m_Cell[i].Style == style)
{
result.push_back(i);
count++;
}
return count;
}
short CWindow::BonusFromCell(short node, vector<short> & bonus)
{
short r, c, count;
COLORREF color = m_Cell[node].ForeColor;
// ngang
count = 1;
bonus.resize(1, node);
r = node / 9; c = node % 9;
while (--c >= 0 && m_Cell[r * 9 + c].Style == TC_LARGE && m_Cell[r * 9 + c].ForeColor == color) // left
{
bonus.push_back(r * 9 + c); count++;
}
r = node / 9; c = node % 9;
while (++c <= 8 && m_Cell[r * 9 + c].Style == TC_LARGE && m_Cell[r * 9 + c].ForeColor == color) // right
{
bonus.push_back(r * 9 + c); count++;
}
if (count >= 5)
return count;
// dọc
count = 1;
bonus.resize(1, node);
r = node / 9; c = node % 9;
while (--r >= 0 && m_Cell[r * 9 + c].Style == TC_LARGE && m_Cell[r * 9 + c].ForeColor == color) // up
{
bonus.push_back(r * 9 + c); count++;
}
r = node / 9; c = node % 9;
while (++r <= 8 && m_Cell[r * 9 + c].Style == TC_LARGE && m_Cell[r * 9 + c].ForeColor == color) // down
{
bonus.push_back(r * 9 + c); count++;
}
if (count >= 5)
return count;
// chéo thuận
count = 1;
bonus.resize(1, node);
r = node / 9; c = node % 9;
while (--r >= 0 && --c >= 0 && m_Cell[r * 9 + c].Style == TC_LARGE && m_Cell[r * 9 + c].ForeColor == color) // tây bắc
{
bonus.push_back(r * 9 + c); count++;
}
r = node / 9; c = node % 9;
while (++r <= 8 && ++c <= 8 && m_Cell[r * 9 + c].Style == TC_LARGE && m_Cell[r * 9 + c].ForeColor == color) // đông nam
{
bonus.push_back(r * 9 + c); count++;
}
if (count >= 5)
return count;
// chéo nghịch
count = 1;
bonus.resize(1, node);
r = node / 9; c = node % 9;
while (--r >= 0 && ++c <= 8 && m_Cell[r * 9 + c].Style == TC_LARGE && m_Cell[r * 9 + c].ForeColor == color) // đông bắc
{
bonus.push_back(r * 9 + c); count++;
}
r = node / 9; c = node % 9;
while (++r <= 8 && --c >= 0 && m_Cell[r * 9 + c].Style == TC_LARGE && m_Cell[r * 9 + c].ForeColor == color) // tây nam
{
bonus.push_back(r * 9 + c); count++;
}
if (count >= 5)
return count;
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrev, PSTR pCmd, int nShow)
{
CWindow MainWnd;
if (!MainWnd.Create(hInstance))
return 0;
return MainWnd.LoopMessage();
}