#include <windows.h>
#include "sudoku.h"
#include "resource.h"
//#include <afxwin.h>
//using namespace std;
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);//窗口过程
LRESULT CALLBACK NumberProc(HWND,UINT,WPARAM,LPARAM);//子窗口过程
BOOL CALLBACK DialogProc(HWND,UINT,WPARAM,LPARAM);//对话框过程
static int iPastID;//上一次点击的子窗口ID
static HBITMAP hbitmapStatic,hbitmapPrint,hbitmapWrong;//分别用于填充生成数独的已有数字和玩家输入数字
static int sudokuMap[9][9];//记录原始数独
BOOL bFlagWrong;
CSudoku sudoku;//数独类对象
TCHAR szChildClass[]=TEXT("Sudoku_Child");//子窗口名
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR szCmdLine,int iCmdShow)
{
static TCHAR szAppName[]=TEXT("Sudoku");
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
wndclass.style=NULL;
wndclass.lpfnWndProc=WndProc;
wndclass.cbClsExtra=0;
wndclass.cbWndExtra=0;
wndclass.hInstance=hInstance;
wndclass.hIcon=LoadIcon(hInstance,MAKEINTRESOURCE(IDI_ICON1));
wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);
wndclass.hbrBackground=(HBRUSH)GetStockObject(LTGRAY_BRUSH);
wndclass.lpszMenuName=MAKEINTRESOURCE(IDR_MENU1);
wndclass.lpszClassName=szAppName;
RegisterClass(&wndclass);
//子窗口类
wndclass.lpfnWndProc=NumberProc;
wndclass.hIcon=NULL;
wndclass.lpszClassName=szChildClass;
RegisterClass(&wndclass);
hwnd=CreateWindow(
szAppName,
TEXT("Sudoku Game"),
WS_OVERLAPPEDWINDOW&~WS_MAXIMIZEBOX&~WS_THICKFRAME,
460,
140,
170,
260,
NULL,
NULL,
hInstance,
NULL);
ShowWindow(hwnd,iCmdShow);
UpdateWindow(hwnd);
while (GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
//窗口过程
{
static HINSTANCE hInstance;
static HWND hSinglewnd[9][9],hMouseWnd[10],hButtonwnd;
HWND hWrongwnd;
HDC hdc;
int x,y;
RECT rect;
int iWidth;
int mark[10];
static int newSudokuHardness;
switch(message)
{
case WM_CREATE:
sudoku.createSudoku(3);//构造初始数独,难度初级
//记录原始数独
for(x=0;x<9;++x)
for(y=0;y<9;++y)
sudokuMap[x][y]=sudoku.map[x][y];
hInstance=((LPCREATESTRUCT)lParam)->hInstance;
hbitmapStatic=LoadBitmap(hInstance,MAKEINTRESOURCE(IDB_BITMAP1));
hbitmapPrint=LoadBitmap(hInstance,MAKEINTRESOURCE(IDB_BITMAP2));
hbitmapWrong=LoadBitmap(hInstance,MAKEINTRESOURCE(IDB_BITMAP3));
hButtonwnd=CreateWindow(TEXT("button"),TEXT("完成"),
WS_CHILDWINDOW|WS_VISIBLE,
0,0,0,0,
hwnd,(HMENU)(110),
(HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),
NULL);
//构造81个子窗口
//ID为:行值×10+列值
for(x=0;x<9;++x)
for (y=0;y<9;++y)
{
hSinglewnd[x][y]=CreateWindow(szChildClass,NULL,
WS_CHILDWINDOW|WS_VISIBLE,
0,0,0,0,
hwnd,(HMENU)(x*10+y),
(HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),
NULL);
}
//构造10个子窗口用于鼠标接口的输入
//ID为:100+数字
for (x=0;x<10;++x)
{
hMouseWnd[x]=CreateWindow(szChildClass,NULL,
WS_CHILDWINDOW|WS_VISIBLE,
0,0,0,0,
hwnd,(HMENU)(100+x),
(HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),
NULL);
}
return 0;
case WM_SIZE:
GetClientRect(hwnd,&rect);
iWidth=(rect.right-rect.left-5)/9;
MoveWindow(hButtonwnd,rect.right-5-2*iWidth,rect.top+5,2*iWidth,2*iWidth,TRUE);
//各子窗口就位
for (x=0;x<9;++x)
for (y=0;y<9;++y)
{
MoveWindow(hSinglewnd[x][y],5+x*iWidth,rect.bottom-iWidth-5-y*iWidth,
iWidth,iWidth,TRUE);
}
for(x=0;x<5;++x)
{
MoveWindow(hMouseWnd[x],5+x*iWidth,rect.top+5,
iWidth,iWidth,TRUE);
}
for(x=5;x<10;++x)
{
MoveWindow(hMouseWnd[x],5+(x-5)*iWidth,rect.top+5+iWidth,
iWidth,iWidth,TRUE);
}
return 0;
case WM_LBUTTONDOWN:
//清除上次点击的子窗口的标志红色框
x=iPastID/10;
y=iPastID%10;
hdc=GetDC(hwnd);
SelectObject(hdc,GetStockObject(NULL_BRUSH));
SelectObject(hdc,(HPEN)GetStockObject(BLACK_PEN));
GetClientRect(hwnd,&rect);
iWidth=(rect.right-rect.left-5)/9;
Rectangle(hdc,5+x*iWidth,rect.bottom-iWidth-5-y*iWidth,
5+x*iWidth+iWidth,rect.bottom-5-y*iWidth);
ReleaseDC(hwnd,hdc);
return 0;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDM_NEW:
break;
case IDM_BASIC:
newSudokuHardness=10;;
break;
case IDM_MIDDLE:
newSudokuHardness=30;
break;
case IDM_PROFFEOR:
newSudokuHardness=50;
break;
case IDM_QUIT:
SendMessage(hwnd,WM_CLOSE,0,0);
break;
case IDM_ABOUT:
DialogBox(hInstance,MAKEINTRESOURCE(IDD_DIALOG1),hwnd,DialogProc);
break;
case 110:
for(x=0;x<9;++x)
{
for(y=0;y<9;++y)
{
if (sudokuMap[x][y]==0)
if(int i=sudoku.check(x,y,mark))
{
bFlagWrong=1;
hWrongwnd=GetDlgItem(hwnd,x*10+y);
GetClientRect(hWrongwnd,&rect);
InvalidateRect(hWrongwnd,&rect,TRUE);
}
}
}
if(!bFlagWrong)
MessageBox(hwnd,"Congratulations!","Win",MB_OK);
break;
}
if(LOWORD(wParam)>=IDM_NEW&&LOWORD(wParam)<=IDM_PROFFEOR)
{
sudoku.createSudoku(newSudokuHardness);
GetClientRect(hwnd,&rect);
for(x=0;x<9;++x)
for(y=0;y<9;++y)
sudokuMap[x][y]=sudoku.map[x][y];
InvalidateRect(hwnd,&rect,TRUE);
}
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd,message,wParam,lParam);
}
LRESULT CALLBACK NumberProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
HDC hdc,hdcMem;
PAINTSTRUCT ps;
RECT rect;
HPEN hpen;
static HWND hPastWnd;
int id=GetWindowLong(hwnd,GWL_ID);
int i,j;
int iChar=0;
switch(message)
{
case WM_PAINT:
hdc=BeginPaint(hwnd,&ps);
GetClientRect(hwnd,&rect);
Rectangle(hdc,0,0,rect.right,rect.bottom);//绘制每个子窗口的黑色框
hdcMem=CreateCompatibleDC(hdc);
//用位图填充子窗口
if(!bFlagWrong||sudokuMap[id/10][id%10]!=0)
{
if (sudokuMap[id/10][id%10]==0&&id<100)
{
SelectObject(hdcMem,hbitmapPrint);
}
else
SelectObject(hdcMem,hbitmapStatic);
}
else
SelectObject(hdcMem,hbitmapWrong);
if(id>=100)
BitBlt(hdc,0,0,17,17,hdcMem,0,(109-id)*16,SRCCOPY);
else
BitBlt(hdc,0,0,17,17,hdcMem,0,(9-sudoku.map[id/10][id%10])*16,SRCCOPY);
DeleteDC(hdcMem);
EndPaint(hwnd,&ps);
return 0;
case WM_LBUTTONDOWN:
bFlagWrong=0;
if(id<100)
{
if(sudokuMap[id/10][id%10]==0)
//如果原始数独该位置为0,则执行
{
SetFocus(hwnd);
if(iPastID!=id)
SendMessage(GetParent(hwnd),message,wParam,lParam);
hdc=GetDC(hwnd);
hpen=CreatePen(PS_SOLID,1,RGB(255,0,0));
SelectObject(hdc,GetStockObject(NULL_BRUSH));
SelectObject(hdc,hpen);
GetClientRect(hwnd,&rect);
Rectangle(hdc,0,0,rect.right,rect.bottom);//画红色标志框
DeleteObject(hpen);
iPastID=GetDlgCtrlID(hwnd);//记录此次点击位置,作为下次点击的先导
hPastWnd=hwnd;
ReleaseDC(hwnd,hdc);
}
return 0;
}
else
SendMessage(hPastWnd,WM_CHAR,id-100+'0',lParam);//若为键盘接口子窗口则调用上一个窗口的WM_CHAR消息
return 0;
case WM_CHAR:
bFlagWrong=0;
//键盘接口
switch((char)wParam)
//对不同按键进行处理
{
case '0':
iChar=9;
sudoku.map[id/10][id%10]=0;
break;
case '1':
iChar=8;
sudoku.map[id/10][id%10]=1;
break;
case '2':
iChar=7;
sudoku.map[id/10][id%10]=2;
break;
case '3':
iChar=6;
sudoku.map[id/10][id%10]=3;
break;
case '4':
iChar=5;
sudoku.map[id/10][id%10]=4;
break;
case '5':
iChar=4;
sudoku.map[id/10][id%10]=5;
break;
case '6':
iChar=3;
sudoku.map[id/10][id%10]=6;
break;
case '7':
iChar=2;
sudoku.map[id/10][id%10]=7;
break;
case '8':
iChar=1;
sudoku.map[id/10][