user_232
New Coder
# Sudoku
This is a basic beginner Sudoku project made with the C language using Windows API.
# Features
# Notes
- What can I improve? What can I make more efficient and less time-consuming as am I am a rookie programmer and any extra suggestion you want to give me feel free?
GitHub repo: GitHub - reewdgh/sudoku
Include Directory
\
sudoku_game.h
sudoku_gui.c
Source Directory
sudoku_game.c
config.c
This is a basic beginner Sudoku project made with the C language using Windows API.
# Features
- Custom levels according to your capability
- click an empty cell then use keyboard or buttons on the screen to enter the number.
- The game features 3 hints for you to use when you get stuck.
- the GUI is super clean and modern with live score/mistakes/click tracking and cell highlighting.
# Notes
- What can I improve? What can I make more efficient and less time-consuming as am I am a rookie programmer and any extra suggestion you want to give me feel free?
GitHub repo: GitHub - reewdgh/sudoku
Include Directory
\
sudoku_game.h
Code:
#pragma once
#include <stdlib.h>
#include <stdbool.h>
int *shuffle();
int checkValidPlacement(int (*grid)[9], int num, int row, int col);
int solveSudoku(int (*grid)[9], int row, int col);
int copyMatrix(int (*grid1)[9], int (*grid2)[9]);
int countSolutions(int (*grid)[9]);
int checkRows(int (*grid)[9], int number, int row, int col);
int checkCols(int (*grid)[9], int number, int row, int col);
int checkSubGrid(int (*grid)[9], int number, int row, int col);
int generateValidSudoku(int (*grid)[9], int row, int col);
void fillWithZero(int (*grid1)[9], int (*grid2)[9], int level);
sudoku_gui.c
Code:
#pragma once
#include <stdio.h>
#include <windows.h>
#include <time.h>
#include "../src/config.h"
extern int i;
#define X 0
#define Y 1
#define I 2
#define J 3
extern int START_POINT;
extern int POINT_GAP;
typedef struct
{
int boardInfo[100][4];
int emptyCells;
int isEmptyCellClicked;
int userGrid[9][9];
int sudokuGrid[9][9];
int score;
int mistakes;
int isStart;
int unsolvedGrid[9][9];
int prevIndex;
int centerX;
int centerY;
int hintUsed;
} Sudoku;
#define CELL_I(index, ctx) ctx->boardInfo[index][I]
#define CELL_J(index, ctx) ctx->boardInfo[index][J]
#define CELL_X(index, ctx) ctx->boardInfo[index][X]
#define CELL_Y(index, ctx) ctx->boardInfo[index][Y]
void createNumberButtons(HWND hwnd);
void drawSudokuGrid(HDC hdc, Sudoku *ctx);
int fillEmptyCell(Sudoku *ctx, HWND hwnd);
void displayUserStats(HDC hdc, Sudoku *ctx);
int checkEmptyBoxClick(HWND hwnd, Sudoku *ctx);
void checkUserInput(HWND hwnd, int number, Sudoku *ctx);
void colorLevelButtons(int buttonID, LPDRAWITEMSTRUCT draw);
void drawImage(HDC hdc, char *imagePath, int x, int y, int width, int height);
int DeleteLevelButtons(HWND hwnd);
int createLevelButtons(Sudoku *ctx, HWND hwnd);
void colorNumberButtons(LPDRAWITEMSTRUCT draw, int buttonID);
void createHintButton(HWND hwnd);
void createStartScreen(HDC hdc, Sudoku *ctx);
void HandleKeyBoardInput(WPARAM wparm, Sudoku *ctx, HWND hwnd);
void isPointerNull(void *ptr);
Source Directory
sudoku_game.c
Code:
#include "../include/sudoku_game.h"
void fillWithZero(int (*grid1)[9], int (*grid2)[9], int level)
{
copyMatrix(grid1, grid2);
for (int i = 0; i < 9; i++)
{
int *numbers = shuffle();
for (int j = 0; j < level; j++)
{
grid1[i][numbers[j]] = 0;
if (countSolutions(grid1) == 0)
{
grid1[i][numbers[j]] = grid2[i][numbers[j]];
}
}
}
}
int countSolutions(int (*grid)[9])
{
int solveGrid1[9][9] = {0}, solvedGrid2[9][9] = {0};
copyMatrix(solveGrid1, grid);
solveSudoku(solveGrid1, 0, 0);
srand(4);
for (int i = 0; i < 9; i++)
{
copyMatrix(solvedGrid2, grid);
solveSudoku(solvedGrid2, 0, 0);
for (int i = 0; i < 9; i++)
{
for (int j = 0; j < 9; j++)
{
if (solvedGrid2[i][j] != solveGrid1[i][j])
{
return 0;
}
}
}
}
return 1;
}
int solveSudoku(int (*grid)[9], int row, int col)
{
if (row == 9)
{
return 1;
}
if (col == 9)
{
return solveSudoku(grid, row + 1, 0);
}
if (grid[row][col] != 0)
{
return solveSudoku(grid, row, col + 1);
}
int numbers[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
for (int i = 8; i > 0; i--)
{
int random = rand() % (i + 1);
int temp = numbers[i];
numbers[i] = numbers[random];
numbers[random] = temp;
}
for (int i = 0; i < 9; i++)
{
if (checkValidPlacement(grid, numbers[i], row, col))
{
grid[row][col] = numbers[i];
if (solveSudoku(grid, row, col + 1))
{
return 1;
}
grid[row][col] = 0;
}
}
return 0;
}
int copyMatrix(int (*grid1)[9], int (*grid2)[9])
{
for (int i = 0; i < 9; i++)
{
for (int j = 0; j < 9; j++)
{
grid1[i][j] = grid2[i][j];
}
}
return 0;
}
int *shuffle()
{
static int numbers[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
for (int i = 0; i < 9; i++)
{
int random = rand() % 9;
int temp = numbers[i];
numbers[i] = numbers[random];
numbers[random] = temp;
}
return numbers;
}
int checkValidPlacement(int (*grid)[9], int num, int row, int col)
{
return checkRows(grid, num, row, col) &&
checkCols(grid, num, row, col) &&
checkSubGrid(grid, num, row, col);
}
int generateValidSudoku(int (*grid)[9], int row, int col)
{
if (row == 9)
{
return 1;
}
if (col == 9)
{
return generateValidSudoku(grid, row + 1, 0);
}
int *numbers = shuffle();
for (int i = 0; i < 9; i++)
{
int num = numbers[i];
if (checkValidPlacement(grid, num, row, col))
{
grid[row][col] = num;
if (generateValidSudoku(grid, row, col + 1))
{
return 1;
}
grid[row][col] = 0;
}
}
return 0;
}
int checkRows(int (*grid)[9], int number, int row, int col)
{
for (int i = 0; i < 9; i++)
{
if (i != col && grid[row][i] == number)
{
return false;
}
}
return true;
}
int checkCols(int (*grid)[9], int number, int row, int col)
{
for (int i = 0; i < 9; i++)
{
if (i != row && grid[i][col] == number)
{
return false;
}
}
return true;
}
int checkSubGrid(int (*grid)[9], int number, int row, int col)
{
int first = (row / 3) * 3;
int second = (col / 3) * 3;
for (int i = first; i < first + 3; i++)
{
for (int j = second; j < second + 3; j++)
{
if ((i != row || j != col) && grid[i][j] == number)
{
return false;
}
}
}
return true;
}
Code:
#include "../include/sudoku_gui.h"
int i = 0;
#define X 0
#define Y 1
#define I 2
#define J 3
int START_POINT;
// Sudoku s1 = {};
void drawSudokuGrid(HDC hdc, Sudoku *ctx)
{
isPointerNull(ctx);
int y = START_POINT, x = START_POINT;
HPEN defaultPen = CreatePen(PS_SOLID, 1, BLACK);
HPEN boldPen = CreatePen(PS_SOLID, 2, BLACK);
for (int i = 0; i < LINES_TO_DRAW; i++)
{
if (i % 3 == 0)
{
SelectObject(hdc, boldPen);
}
MoveToEx(hdc, y, START_POINT, 0);
LineTo(hdc, y, END_POINT);
SelectObject(hdc, defaultPen);
y += START_POINT;
}
for (int j = 0; j < LINES_TO_DRAW; j++)
{
if (j % 3 == 0)
{
SelectObject(hdc, boldPen);
}
MoveToEx(hdc, START_POINT, x, 0);
LineTo(hdc, END_POINT, x);
SelectObject(hdc, defaultPen);
x += START_POINT;
}
DeleteObject(defaultPen);
DeleteObject(boldPen);
HFONT font = CreateFont(START_POINT - 10, 0, 0, 0, FW_MEDIUM, 0, 0, 0, 0, 0, 0, 0, 0, MAIN_FONT);
SelectObject(hdc, font);
int a = 0;
ctx->emptyCells = 0;
SetBkMode(hdc, TRANSPARENT);
for (int i = 0; i < 9; i++)
{
for (int j = 0; j < 9; j++)
{
ctx->boardInfo[a][X] = (START_POINT * (j + 1));
ctx->boardInfo[a][Y] = (START_POINT * (i + 1));
ctx->boardInfo[a][I] = i;
ctx->boardInfo[a][J] = j;
a++;
if (ctx->userGrid[i][j] == 0)
{
ctx->emptyCells++;
continue;
}
if (ctx->unsolvedGrid[i][j] == 0)
{
SetTextColor(hdc, BLUE);
}
char s[2];
sprintf(s, "%d", ctx->userGrid[i][j]);
RECT cellRect;
cellRect.left = START_POINT + (START_POINT * j);
cellRect.top = START_POINT + (START_POINT * i);
cellRect.right = cellRect.left + START_POINT;
cellRect.bottom = cellRect.top + START_POINT;
DrawText(hdc, s, 1, &cellRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
SetTextColor(hdc, BLACK);
}
}
DeleteObject(font);
}
void createNumberButtons(HWND hwnd)
{
HDC hdc = GetDC(hwnd);
HFONT font = CreateFont(START_POINT, 0, 0, 0, FW_MEDIUM, 0, 0, 0, 0, 0, 0, 0, 0, MAIN_FONT);
SelectObject(hdc, font);
int y = (START_POINT * 4), x = START_POINT * 11, j = 0, z = 0;
for (int i = 0; i < 9; i++)
{
if (i % 3 == 0 && i != 0)
{
y = y + START_POINT * 2;
z = 0;
x = START_POINT * (z + 11);
}
char s[10];
sprintf(s, "%d ", j + 1);
HWND button = CreateWindow("button", s, WS_CHILD | WS_VISIBLE | BS_OWNERDRAW, x, y,
START_POINT * 3 / 2, START_POINT * 3 / 2, hwnd, (HMENU)(INT_PTR)(j + 1), 0, 0);
SendMessage(button, WM_SETFONT, (WPARAM)font, TRUE);
x = (START_POINT * ((z + 1) + 11)) + START_POINT * (z + 1);
j++;
z++;
}
ReleaseDC(hwnd, hdc);
}
void checkUserInput(HWND hwnd, int number, Sudoku *ctx)
{
isPointerNull(ctx);
if (ctx->sudokuGrid[CELL_I(i, ctx)][CELL_J(i, ctx)] == number)
{
ctx->userGrid[CELL_I(i, ctx)][CELL_J(i, ctx)] = number;
ctx->score += MAX_INCREMENT_SCORE;
ctx->emptyCells--;
ctx->isEmptyCellClicked = 0;
}
else
{
PlaySound("fah.wav", NULL, SND_ASYNC);
MessageBox(hwnd, "Invalid placement, Try another number", "Error!", MB_OK | MB_ICONQUESTION);
ctx->mistakes++;
if (ctx->mistakes == 5)
{
MessageBox(hwnd, "Max limit of Mistakes Reached(5)!", "msg", MB_OK | MB_ICONASTERISK);
PostQuitMessage(0);
}
}
drawSudokuGrid(GetDC(hwnd), ctx);
displayUserStats(GetDC(hwnd), ctx);
if (!ctx->emptyCells)
{
MessageBox(hwnd, "Congratulations, You solved the Sudoku puzzle!", "Message ", MB_OK | MB_ICONINFORMATION);
PostQuitMessage(0);
}
}
int checkEmptyBoxClick(HWND hwnd, Sudoku *ctx)
{
isPointerNull(ctx);
POINT p = {.x = 0, .y = 0};
GetCursorPos(&p);
ScreenToClient(hwnd, &p);
if (p.x <= END_POINT && p.x >= START_POINT && p.y <= END_POINT && p.y >= START_POINT)
{
for (i = 0; i < 81; i++)
{
if ((p.x <= CELL_X(i, ctx) + START_POINT &&
p.y <= CELL_Y(i, ctx) + START_POINT) &&
(p.x >= CELL_X(i, ctx) &&
p.y >= CELL_Y(i, ctx)))
{
if (ctx->userGrid[CELL_I(i, ctx)][CELL_J(i, ctx)] == 0)
{
ctx->isEmptyCellClicked = 1;
return 1;
}
return 2;
}
}
}
ctx->isEmptyCellClicked = 0;
return 0;
}
int fillEmptyCell(Sudoku *ctx, HWND hwnd)
{
isPointerNull(ctx);
HBRUSH hBrush2 = CreateSolidBrush(RGB(176, 209, 232));
ctx->prevIndex = i;
HDC hdc = GetDC(hwnd);
if (checkEmptyBoxClick(hwnd, ctx) == 1)
{
RECT rect = {.left = CELL_X(i, ctx) + 1, .top = CELL_Y(i, ctx) + 1, .right = CELL_X(i, ctx) + START_POINT, .bottom = CELL_Y(i, ctx) + START_POINT};
FillRect(hdc, &rect, hBrush2);
ctx->isEmptyCellClicked = 1;
ReleaseDC(hwnd, hdc);
DeleteObject(hBrush2);
return 0;
}
if (checkEmptyBoxClick(hwnd, ctx) == 2)
{
for (int j = 0; j < 81; j++)
{
if (ctx->userGrid[CELL_I(j, ctx)][CELL_J(j, ctx)] == 0)
{
continue;
}
if (ctx->sudokuGrid[CELL_I(j, ctx)][CELL_J(j, ctx)] == ctx->sudokuGrid[CELL_I(i, ctx)][CELL_J(i, ctx)])
{
RECT rect1 = {.left = CELL_X(j, ctx) + 1, .top = CELL_Y(j, ctx) + 1, .right = CELL_X(j, ctx) + START_POINT, .bottom = CELL_Y(j, ctx) + START_POINT};
FillRect(hdc, &rect1, hBrush2);
}
}
drawSudokuGrid(hdc, ctx);
}
ctx->isEmptyCellClicked = 0;
DeleteObject(hBrush2);
return 0;
}
void displayUserStats(HDC hdc, Sudoku *ctx)
{
isPointerNull(ctx);
HFONT font = CreateFont(START_POINT / 2, 0, 0, 0, FW_SEMIBOLD, 0, 0, 0, 0, 0, 0, 0, 0, MAIN_FONT);
SelectObject(hdc, font);
char scoreMsg[20], mistakeMsg[20];
sprintf(scoreMsg, "Score : %d", ctx->score);
sprintf(mistakeMsg, "Mistakes: %d", ctx->mistakes);
SetTextColor(hdc, OFF_WHITE);
TextOut(hdc, END_POINT + START_POINT, END_POINT / 4, scoreMsg, strlen(scoreMsg));
TextOut(hdc, END_POINT + END_POINT / 2, END_POINT / 4, mistakeMsg, strlen(mistakeMsg));
DeleteObject(font);
}
void colorLevelButtons(int buttonID, LPDRAWITEMSTRUCT draw)
{
FillRect(draw->hDC, &draw->rcItem, CreateSolidBrush(DARK_BLUE));
SetBkMode(draw->hDC, TRANSPARENT);
SetTextColor(draw->hDC, WHITE);
HFONT font = CreateFont(START_POINT - 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, MAIN_FONT);
SelectObject(draw->hDC, font);
char *levels[3] = LEVELS;
int level[3] = LEVEL_IDS;
for (int i = 0; i < 3; i++)
{
if (buttonID == level[i])
{
DrawText(draw->hDC, levels[i], -1, &draw->rcItem, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
break;
}
}
}
void drawImage(HDC hdc, char *imagePath, int x, int y, int width, int height)
{
HBITMAP hbitmap = (HBITMAP)LoadImage(
NULL,
imagePath,
IMAGE_BITMAP,
0,
0,
LR_LOADFROMFILE);
if (hbitmap == NULL)
{
OutputDebugString("FILE NOT FOUND");
return;
}
BITMAP bmp;
GetObject(hbitmap, sizeof(bmp), &bmp);
HDC newHDC = CreateCompatibleDC(hdc);
HBITMAP oldbmp = SelectObject(newHDC, (HBITMAP)hbitmap);
StretchBlt(hdc, x, y, width, height, newHDC, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
SelectObject(newHDC, oldbmp);
DeleteDC(newHDC);
DeleteObject(&bmp);
}
int DeleteLevelButtons(HWND hwnd)
{
int id[3] = LEVEL_IDS;
for (int i = 0; i < 3; i++)
{
DestroyWindow(GetDlgItem(hwnd, id[i]));
}
InvalidateRect(hwnd, NULL, TRUE);
return 0;
}
int createLevelButtons(Sudoku *ctx, HWND hwnd)
{
isPointerNull(ctx);
int step = 5;
int id[] = LEVEL_IDS;
for (int i = 0; i < 3; i++)
{
CreateWindow("BUTTON", "", WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON | BS_OWNERDRAW, ctx->centerY + START_POINT * 2, START_POINT * step, START_POINT * 5, START_POINT, hwnd, (HMENU)(INT_PTR)id[i], 0, NULL);
step = step + 2;
}
return 0;
}
void colorNumberButtons(LPDRAWITEMSTRUCT draw, int buttonID)
{
char s[2];
sprintf(s, "%d", buttonID);
FillRect(draw->hDC, &draw->rcItem, CreateSolidBrush(LIGHT_BLUE));
SetTextColor(draw->hDC, BLUE);
SetBkColor(draw->hDC, LIGHT_BLUE);
DrawText(draw->hDC, s, -1, &draw->rcItem, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
}
void createHintButton(HWND hwnd)
{
CreateWindowEx(0, "button", "Hint", WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON | BS_OWNERDRAW, END_POINT + END_POINT / 3, START_POINT * 2,
START_POINT, START_POINT, hwnd, (HMENU)(INT_PTR)HINT_ID, 0, 0);
}
void createStartScreen(HDC hdc, Sudoku *ctx)
{
HFONT font = CreateFont(START_POINT - 10, 0, 0, 0, FW_MEDIUM, 0, 0, 0, 0, 0, 0, 0, 0, MAIN_FONT);
SelectObject(hdc, font);
SetTextAlign(hdc, TA_CENTER | TA_RIGHT);
TextOut(hdc, ctx->centerX - SUDOKU_DIMENSIONS * 2, ctx->centerY - START_POINT * 2, "Sudoku", strlen("Sudoku"));
drawImage(hdc, SUDOKU_BMP_PATH, ctx->centerX - START_POINT * 1.75, START_POINT / 4, START_POINT * 3, START_POINT * 3);
}
void HandleKeyBoardInput(WPARAM wparm, Sudoku *ctx, HWND hwnd)
{
isPointerNull(ctx);
int press = (int)wparm - '0';
if (press >= 1 && press <= 9)
{
if (ctx->isEmptyCellClicked)
{
checkUserInput(hwnd, press, ctx);
}
}
}
void isPointerNull(void *ptr)
{
if (ptr == NULL)
{
MessageBox(0, "Data passed is Null, Kindly check", "message", MB_OK | MB_ICONERROR);
PostQuitMessage(0);
}
}
Code:
#include <stdio.h>
#include <windows.h>
#include <time.h>
#include "../include/sudoku_gui.h"
#include "../include/sudoku_game.h"
LRESULT CALLBACK cb(HWND hwnd, UINT msg, WPARAM wparm, LPARAM lparm)
{
Sudoku *ctx = (Sudoku *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
int number_id[] = NUMBER_BUTTONS_ID;
int level_id[] = LEVEL_IDS;
switch (msg)
{
case WM_CLOSE:
{
PostQuitMessage(0);
return 0;
}
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
if (ctx->isStart)
{
createStartScreen(hdc, ctx);
break;
}
drawSudokuGrid(hdc, ctx);
displayUserStats(hdc, ctx);
EndPaint(hwnd, &ps);
break;
}
case WM_CREATE:
{
CREATESTRUCT *cs = (CREATESTRUCT *)lparm;
ctx = (Sudoku *)cs->lpCreateParams;
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)ctx);
HICON hicon;
hicon = (HICON)LoadImage(NULL, SUDOKU_ICON_PATH, IMAGE_ICON, 500, 500, LR_LOADFROMFILE);
SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)hicon);
if (ctx->isStart)
{
RECT rect;
GetClientRect(hwnd, &rect);
ctx->centerX = (rect.left + rect.right) / 2;
ctx->centerY = (rect.bottom + rect.top) / 2;
createLevelButtons(ctx, hwnd);
}
break;
}
case WM_DRAWITEM:
{
LPDRAWITEMSTRUCT draw = (LPDRAWITEMSTRUCT)lparm;
int buttonID = LOWORD(wparm);
if (buttonID == HINT_ID)
{
drawImage(draw->hDC, HINT_BMP_PATH, 0, 0, START_POINT, START_POINT);
}
else if (buttonID >= number_id[0] && buttonID <= number_id[SUDOKU_DIMENSIONS - 1])
{
colorNumberButtons(draw, buttonID);
}
else if (buttonID >= level_id[0] && buttonID <= level_id[LEVEL_COUNT - 1])
{
colorLevelButtons(buttonID, draw);
}
break;
}
case WM_COMMAND:
{
int buttonID = LOWORD(wparm);
if (ctx->isStart == 1 && buttonID >= level_id[0] && buttonID <= level_id[LEVEL_COUNT - 1])
{
DeleteLevelButtons(hwnd);
ctx->isStart = 0;
fillWithZero(ctx->userGrid, ctx->sudokuGrid, (buttonID - (level_id[0] - 1)) * 2);
copyMatrix(ctx->unsolvedGrid, ctx->userGrid);
createNumberButtons(hwnd);
createHintButton(hwnd);
break;
}
if (buttonID >= number_id[0] && buttonID <= number_id[SUDOKU_DIMENSIONS - 1] && ctx->isEmptyCellClicked)
{
checkUserInput(hwnd, buttonID, ctx);
}
if (buttonID == HINT_ID && ctx->isEmptyCellClicked)
{
if (ctx->hintUsed != MAX_HINT)
{
checkUserInput(hwnd, ctx->sudokuGrid[ctx->boardInfo[i][I]][ctx->boardInfo[i][J]], ctx);
ctx->hintUsed++;
}
else
{
MessageBox(hwnd, "Max Limit of Hint Used(3)", "Message", MB_OK | MB_ICONQUESTION);
}
}
SetFocus(hwnd);
break;
}
case WM_LBUTTONDOWN:
{
int check = checkEmptyBoxClick(hwnd, ctx);
if (check != 0)
{
if (i == ctx->prevIndex)
{
break;
}
for (int j = 0; j < 81; j++)
{
if (ctx->sudokuGrid[CELL_I(j, ctx)][CELL_J(j, ctx)] == ctx->sudokuGrid[CELL_I(ctx->prevIndex, ctx)][CELL_J(ctx->prevIndex, ctx)])
{
RECT rect = {.left = CELL_X(j, ctx) + 1, .top = CELL_Y(j, ctx) + 1, .right = CELL_X(j, ctx) + START_POINT, .bottom = CELL_Y(j, ctx) + START_POINT};
HRGN rgn = CreateRectRgn(rect.left, rect.top, rect.right, rect.bottom);
InvalidateRgn(hwnd, rgn, TRUE);
UpdateWindow(hwnd);
}
}
}
fillEmptyCell(ctx, hwnd);
break;
}
case WM_KEYDOWN:
{
if (ctx->isStart == 0)
{
HandleKeyBoardInput(wparm, ctx, hwnd);
}
break;
}
default:
return DefWindowProc(hwnd, msg, wparm, lparm);
}
return 0;
}
int main()
{
srand((unsigned int)time(NULL));
Sudoku ctx = {};
ctx.isStart = 1;
generateValidSudoku(ctx.sudokuGrid, 0, 0);
solveSudoku(ctx.sudokuGrid, 0, 0);
HINSTANCE hInstance = GetModuleHandle(0);
WNDCLASS class = {};
char classTitle[] = "my class";
class.lpszClassName = classTitle;
class.lpfnWndProc = cb;
class.hInstance = hInstance;
class.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
class.hCursor = LoadCursor(NULL, IDC_ARROW);
int width = GetSystemMetrics(SM_CXSCREEN);
float cal = ((float)100 / DEFAULT_WIDTH) * width;
START_POINT = (int)cal;
RegisterClass(&class);
HWND hwnd = CreateWindowEx(0, classTitle, "Sudoku",
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, 0, 0, 1000, 1000, NULL,
NULL, hInstance, &ctx);
if (hwnd == NULL)
{
MessageBox(NULL, "Something Went worng", "Error", MB_OK);
return 0;
}
ShowWindow(hwnd, SHOW_FULLSCREEN);
MSG msg;
RECT rect;
GetClientRect(hwnd, &rect);
ctx.centerX = (rect.left + rect.right) / 2;
ctx.centerY = (rect.bottom + rect.top) / 2;
while (GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
Code:
// config define
#define SUDOKU_DIMENSIONS 9
#define LINES_TO_DRAW 10
#define END_POINT (LINES_TO_DRAW * START_POINT)
#define DEFAULT_WIDTH 1920
#define DEFAULT_HEIGHT 1200
#define LEVEL_IDS {10, 11, 12}
#define NUMBER_BUTTONS_ID {1, 2, 3, 4, 5, 6, 7, 8, 9}
#define HINT_ID 40
#define BLACK RGB(0, 0, 0)
#define BLUE RGB(0, 102, 190)
#define MAIN_FONT "Segoe UI"
#define MAX_INCREMENT_SCORE 70
#define LEVEL_COUNT 3
#define LEVELS {"Easy", "Medium", "Hard"}
#define WHITE RGB(255, 255, 255)
#define DARK_BLUE RGB(71, 112, 202)
#define OFF_WHITE RGB(197, 203, 209)
#define LIGHT_BLUE RGB(234, 238, 244)
#define MAX_MISTAKES 5
#define MAX_HINT 3
#define SUDOKU_ICON_PATH "images/icon.ico"
#define SUDOKU_BMP_PATH "images/icon.bmp"
#define HINT_BMP_PATH "images/hint.bmp"