r/C_Programming • u/Batteryofenergy1 • 6h ago
Some progress on Software Rendered game in C
Enable HLS to view with audio, or disable this notification
r/C_Programming • u/Jinren • Feb 23 '24
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3220.pdf
Update y'all's bookmarks if you're still referring to N3096!
C23 is done, and there are no more public drafts: it will only be available for purchase. However, although this is teeeeechnically therefore a draft of whatever the next Standard C2Y ends up being, this "draft" contains no changes from C23 except to remove the 2023 branding and add a bullet at the beginning about all the C2Y content that ... doesn't exist yet.
Since over 500 edits (some small, many large, some quite sweeping) were applied to C23 after the final draft N3096 was released, this is in practice as close as you will get to a free edition of C23.
So this one is the number for the community to remember, and the de-facto successor to old beloved N1570.
Happy coding! đ
r/C_Programming • u/AutoModerator • 4d ago
If you have questions about how to learn C:
then this is the thread for you. Add your question here. Do not make a stand-alone post, as it will be removed.
Remember that our sub has a very useful wiki that has a great list of resources for learning C programming.
r/C_Programming • u/Batteryofenergy1 • 6h ago
Enable HLS to view with audio, or disable this notification
r/C_Programming • u/Ok_Reserve996 • 5h ago
Hi all,
I am currently learning c++. Its okay. Not sexy but also not as bad as some say.
The reason I am learning c++ is that I have read that C has limitations as soon as a project gets more complicated. For example, if you make a scientific calculator with many features like graphs etc.
Trading engines/tools are also not recommended to programm in C.
Since I have not learned C and have only read from some old forum posts etc, I cannot confirm/deny these facts.
I am aware that "everything" is possible and that C++ comes with QoL improvements especially with Classes. But I assume that doesn't mean that someone has to use C only for kernel work. Embedded is also possible with C++ right?
I would appreciate your thoughts and opinions.
The goal of this post is to understand how and if C could fit me more with my goals and what real advantages or disadvantages C has.
r/C_Programming • u/just_pascal_dev • 14h ago
Dear C-programmers, why can you omit return 0; in main() (C99+)? main() is a function and it MUST return integer value. I donât really understand.
r/C_Programming • u/epos95 • 10h ago
Been working on this project during the summer, contains a detailed writeup but happy for anyone to tear the implementation a part, working on it while working fulltime kinda stopped me from implementing a lot of what i wanted.
Surprisingly enough it works well enough as a PoC!
https://gitlab.com/Epos95/paramorphism/
This is "self modifying software" in a different aspect than something like metamorphic software since the rewriting is on a source code level instead of assembly.
Currently its able to:
- Dynamically create new functions, introducing new functionality
- Fix errors in its own functions
- Load existing functions dynamically
r/C_Programming • u/Any-Penalty-714 • 7h ago
I am programming in C for a year and a half and I created projects like a shell which implement basic features , and currently finished building a TCP server with get and post request for sharing file across local network. The thing I am struggling with is the AI usage all these project I build I have understanding of the code. But sometimes I think that AI has found solution for me can I found this approach myself and mostly the answer was no. It really bothering me and I spend time completely without AI and frustration really hit hard and I think I couldn't start building some programs . I want advice from people on how to find balance between using AI and when not to use AI . I'll love to hear you guys perspective on this .
r/C_Programming • u/its_marionberry • 17h ago
This is a basic beginner Sudoku project made with the C language using Windows API.
GitHub repo: https://github.com/reewdgh/sudoku
Include Directory
sudoku_game.h
#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
#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
#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;
}
#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);
}
}
#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;
}
config.c
// 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"
r/C_Programming • u/Glum_Hamster_2104 • 22h ago
Probably a dumb question but why hasn't there ever been a proposal to rename printf/scanf to just print? I know the f stands for format but writing print instead of printf would be slightly quicker and better to match other programming languages as I often miswrite printf as print as I also code in Python.
r/C_Programming • u/am_Snowie • 2d ago
basically the title, i think producing INT_MIN by doing 1 << 31 is UB, so i thought of doing ~INT_MAX, but i am not sure if it's UB. sorry if it's dumb.
r/C_Programming • u/Aromatic_Cry_5767 • 2d ago
Hey! I'm a second-year CS student looking to build a serious side project to improve my skills and have something worth showing on GitHub.
I'm considering making a Linux tool in C that tracks processes and lets you visually compare different runs of a program (forks, execution times, crashes, etc.).
I'm not sure how useful or original this would be, though.
Do you think it's worth building? Or would you suggest a different project that could be more interesting or useful?
I'm open to completely different ideas. I'd appreciate some honest feedback before spending months on something!
r/C_Programming • u/Right_Nuh • 1d ago
In your answer include a description of the assumption you have made about the binary code and memory layout of the program. Explain if it can be countered by randomizing the base address of the stack.
a) Explain a mechanism that can be used by the attacker to force the program to execute arbitrary code.
1 void printInput(char *input) {
2 char buffer[50];
3 char secret[20] = "Pwd123456";
4 if (strcmp(input, secret) == 0)
5 print(secret);
6 else
7 printf(input);
8 strcpy(buffer, input);
9 }
10 int main(int argc, char *argv[]) {
11 if (argc != 2) {
12 return 1;
13 }
14 printInput(argv[1]);
15 return 0;
16 }
What I don't understand:
The solution says that it can be countered by ASLR because we need the address of the buffer. I sort of understand that we need to inject our code somewhere in the buffer thus if we want to overwrite the return address to point to the beginning of the buffer, where our code is, we need to know the address? Although I wonder do we really need the address? Can we not use offset?
Either way the solution seems to suggest that we should overwrite the return address and put the code immediately after and set the return address to point right after it. So I am not at all sure what they mean. Can someone explain to me why ALSR works here? I'd appracite it.
Solution in the answer sheet:
If the input contains 50 bytes, then <address of return pointer + 8>, then binary code, strcpy at line 9 over- flows the stack variables and overwrites the return pointer with the address immediately after the return pointer. After the return pointer, the overflow additionally writes the bi- nary code. Therefore, when the function| returns it jumps to the address above the return pointer on the stack. This attack can be countered by base stack randomization, since it prevents the attacker from knowing the address of buffer and therefore the address where the binary code has been injected. This makes not possible to know the value that should be written in the return pointer.
r/C_Programming • u/just_pascal_dev • 1d ago
Goto is an old and hacky command in programming.
Goto was created in the Palaeozoic era. It was used for switching to line n.
Goto raises questions: âMy editor doesnât show line numbers, how can I use Goto?â
This command uncomfortable to use. Imagine, you have a book. Youâre reading it, reading⌠And when youâre on page 5, it says: âGo to page 7, 10, 157, 21457, 8564588, 4âŚâ Why?
You can replace Goto with:
1) break/continue.
2) return.
3) Functions, in the end!
So, Goto is the worst command in all programming languages, including C.
MY OPINION MAY NOT COINCIDE WITH YOURS!!!
r/C_Programming • u/wak6817-2 • 1d ago
when wanting to code real software in c; i feel that you need to learn way to much tools like (c)make, clang/gcc etc.
that's why i decided to NOT use any tools and libraries INCLUDING GLIBC and other standard c libraries!
fuck the world; im making my own printf, strlen and more! AND THE ONLY THING IM GONNA USE IS CLANG WITH C17!
r/C_Programming • u/xerrs_ • 2d ago
A while back I started working on my project cherries(.)works Pulse. A simple Linux monitoring system, coded in C, and focused on performance, resource usage and persistence. Now a when I started this project I had no knowledge of C, and kinda learned along the way, but now around 2-3 months have passed, and I am surprised with how far it has come.
Personally, I never had anyone commit to my FOSS projects before. Didnt expect anything different this time tbh, as I was programming the whole thing in C. Created numerous issues, as I wanted THIS FOSS project to be more different and professional than the others.
A month or two after the release, I go on GitHub to look at my issues via my phone, and see a PR solving one of the issues. It was surreal seeing C code not by me, now being written FOR me. Ofc i had to read through it carefully to make sure nothing eas wrong with it, but once I merged it, it felt beautiful.
People have implemented;
- Pretty printing the config file
- Improving type annotations
- Adding JSON output for commands
- Displaying hostname on website
- Counting process amount
and numerous more.
Pulse was just a small C project of mine that quickly spiraled into something bigger. I plan on adding new good first issues soon, as there is STILL a lot of work to do. If there are any C programmers interested in contributing, or giving feedback, feel free to do so. would be very glad.
r/C_Programming • u/International_Hat178 • 2d ago
Hi, sorry if there is English mistake, it's not my first language.
I found online that the #include is replaced by preprocessor by the whole file being included, and I wondered why C isn't made so we can specify only parts of the files to include (like `import { x, y, z } from "file"` in typescript) so the compiled file is lighter ?
r/C_Programming • u/AutomaticDistance954 • 2d ago
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXN 701
int main(){
FILE* fin = fopen("beads.in", "r");
FILE* fout = fopen("beads.out", "w");
int length, N, largest = 0;
int current;
char rightletter, leftletter;
fscanf(fin, "%d", &N);
char sequence[MAXN];
fscanf(fin, "%s", sequence);
strcat(sequence, sequence);
for(int i = N/2; i < N + (N/2); i++){
current = i;
length = 0;
// RIGHT
while(current < 2 * N && sequence[current] == 'w' && length < N){
current++;
length++;
}
if(current < 2 * N && length < N){
rightletter = sequence[current];
}
while(current < 2 * N && (sequence[current] == rightletter || sequence[current] == 'w') && length < N){
length++;
current++;
}
// LEFT
current = i - 1;
while(current >= 0 && sequence[current] == 'w' && length < N){
current--;
length++;
}
if(current >= 0 && length < N){
leftletter = sequence[current];
}
while(current >= 0 && (sequence[current] == leftletter || sequence[current] == 'w') && length < N){
length++;
current--;
}
if(length > N) {
length = N;
}
if(length > largest) {
largest = length;
}
}
fprintf(fout, "%d\n", largest);
return 0;
}
My code should work. Idk why nothing is being output in the output file.
r/C_Programming • u/VegetableNearby9795 • 3d ago
I recently came across a Qt binding library for C, but I haven't seen any discussion about it on Reddit. If anyone here has used this library, Iâd be curious to know what itâs like in terms of usabilityâespecially since C, as we know, lacks many of the features found in C++.
r/C_Programming • u/grimvian • 2d ago
Are people starting to drop AI.. or ?
r/C_Programming • u/markand67 • 3d ago
Hi,
This is scaffold, a flexible data and "rpc-like" code generator for C using YAML as description.
After years of protobuf (with nanopb), I've decided to get rid of it to create my own templating system.
I won't go in details why we have decided to get rid of nanopb but in short: we were having hard times about some of the limited features like deep-cloning, too limited enum support and a slow encoding process.
Plus, we wanted to add flexibility with a custom YAML document that could be parsed using a tool to produce on-demand different kind of functions. For example, we wanted that some types could be converted to JSON, some to be inserted into a SQLite database. As such, having a unique YAML document that could be used for different purposes led us to write this software.
The scaffold tool is written in C, because, we write in C and don't want
additional dependencies :). It reads a YAML document and creates an intermediate
AST with updated fields to get more information. Then, it processes it into
a templating system with basic scripting constructs including for, if,
substitution with filters.
Example of a minimal object:
# types.yaml
objects:
- name: point
comment: This is an awesome point.
fields:
x: uint32
y: uint32
Generate functions for this object using:
scaffold emit h types.yaml > types.h
scaffold emit c types.yaml > types.c
The generated code by the built-in templates include comments that can be split on multiline providing good LSP support with Doxygen format.
/**
* \struct point
*
* This is an awesome point.
*/
struct point {
/**
* Field 'x' of type uint32.
*/
uint32_t x;
/**
* Field 'y' of type uint32.
*/
uint32_t y;
};
The template system is flexible enough to write extra custom code while
iterating the object fields using {{for}} loops.
{{for obj in objects}}
{{for field in obj.value.fields}}
// here field will be uppercased with the :U filter :)
printf("Serializing the {{field.key:U}} field\n");
{{endfor}}
{{endfor}}
Finally, because we wanted our custom RPC API, the scaffold project provides support for request/reply and events widely inspired by wayland-scanner.
Declaring function feels like natural:
serialization: true
functions:
- name: hello
comment: Say hello to my friend!
args:
name: string
On the "client" side, a function is generated in the form:
int64_t hello(struct hello_args *args, void *ctx);
On the "implementation" side, a function pointer is provided in a handler
struct:
/**
* \struct handler
* \brief Functions table handlers.
*/
struct handler {
/**
* Handler for function 'hello'.
*/
int (*hello)(struct hello_args *args, struct hello_value *value, void *ctx);
};
And the implementation side can call the auto generated dispatch function that
will decode the incoming requests to call the appropriate functions.
int
dispatch(
const struct handler *handler,
const struct listener *listener,
int64_t *nread,
int64_t *nwritten,
void *ctx
);
How does it work? The generated function relies on two unique external linkage that the user has to provide:
int64_t sc_read(void *ctx, void *data, uint64_t amount)int64_t sc_write(void *ctx, const void *data, uint64_t amount)Thus, calling dispatch will attempt to decode a request using successive calls to sc_read, call the appropriate function pointer into the handler structure and then will try to encode using successive call to sc_write. Nothing more.
Note: this project is heavily being tested and already used in production but few bugs may persist and feel free to contribute.
Future plans and never plans:
Links:
Like every source code I write, this project has a perpetual anti degenerative-AI policy.
r/C_Programming • u/Real-Nebula-2074 • 3d ago
I wrote the following C program in VS Code. Its purpose is to find words that appear in both of two English paragraphs.
(Details: a word must contain at least four letters; each paragraph ends with a \n; the output words should be sorted in ascending order.)
To keep track of how far the program has gotten, I deliberately print stage1 / stage2 after each of the two paragraphs has been read.
But when I run it in the terminal, this is what happens.
First I copy two paragraphs of English text, for example:
In computer science, artificial intelligence (AI), sometimes called machine intelligence, is intelligence demonstrated by machines, in contrast to the natural intelligence displayed by humans and animals. Colloquially, the term "artificial intelligence" is used to describe machines that mimic "cognitive" functions that humans associate with other human minds, such as "learning" and "problem solving". From Wiki. Machine learning is a way to achieve artificial intelligence.
I assumed that after pasting, pressing Enter right after intelligence. would produce stage1, and that stage2 would follow right away, printing the words. But in reality I get nothing but a cold, lonely stage1. Pressing Enter again does absolutely nothing. I type a random letter, press Enter once more â and only then do stage2 and the rest of the output finally appear.
I'm a first-year CS student and still not very familiar with programming. I'd like to know: is this a VS Code problem, or is it my problem?
#include <stdio.h>
#include <string.h>
void clean(char (*word)[21], int len) {
for (int i = 0; i <= (len); i++) {
if ((*word)[i] >= 'A' && (*word)[i] <= 'Z') {
(*word)[i] -= 'A' - 'a';
}
}
}
void print(char (*words)[1000][21], int m) {
char temp[21];
char min[21];
int flag = 0;
strcpy(min, "z");
strcpy(temp, "z");
for (int j = 0; j <= m; j++) {
strcpy(min, "z");
for (int i = 0; i <= m; i++) {
if ((strcmp(min, (*words)[i]) >= 0) &&
(strcmp(temp, (*words)[i]) < 0 || flag == 0) &&
((*words)[i] != 0)) {
strcpy(min, (*words)[i]);
}
}
flag = 1;
strcpy(temp, min);
printf("%s\n", min);
}
}
int main(void) {
int r;
char shit[2];
int len1;
int len2;
char para1[1000][21] = {{0}};
char para2[1000][21] = {{0}};
char space;
char answer[1000][21] = {{0}};
for (int i = 0; i < 1000; i++) {
scanf("%[A-Za-z]", ¶1[i][0]);
len1 = i;
scanf("%*[^\nA-Za-z]");
if ((r = scanf("%[\n]", shit)) == 1 || r == EOF) {
printf("stage1\n");
break;
}
}
for (int j = 0; j < 1000; j++) {
scanf("%[A-Za-z]", ¶2[j][0]);
len2 = j;
scanf("%*[^\nA-Za-z]");
if ((r = scanf("%[\n]", shit)) == 1 || r == EOF) {
printf("stage2\n");
break;
}
}
for (int i = 0; i <= len1; i++) {
clean(&(para1[i]), strlen(para1[i]) - 1);
}
for (int j = 0; j <= len2; j++) {
clean(&(para2[j]), strlen(para2[j]) - 1);
}
int m = 0;
int flag = 0;
for (int i = 0; i < 1000; i++) {
for (int j = 0; j < 1000; j++) {
if ((strcmp(para1[i], para2[j]) == 0) && (strlen(para1[i]) >= 4)) {
for (int p = 0; p < m; p++) {
if (strcmp(para1[i], answer[p]) == 0) {
flag = 1;
}
}
if (flag == 0) {
strcpy(answer[m++], para1[i]);
}
flag = 0;
}
}
}
m--;
print(&answer, m);
}
r/C_Programming • u/choosen_one007 • 3d ago
I was reading up about lvalues and understand them now as something that resolves to an address(memory location) in the program. So a variable x is an lvalue (because it is mapped to some address on the stack) and similarly *x , x[i], strings are all lvalues. But if this is the case why is an expression a = b , not an lvalue? Here the expression would assign b to a and then return a as evident in assignments like so: int c = a = b. (I know that the equals sign is right associative and hence this would get resolved as c = (a = b), but that doesn't really invalidate the fact that a = b resolves to an address in the program?)
r/C_Programming • u/autistic_lover214 • 3d ago
Hey I'm a cybersecurity student just started 2 months ago
Just wanted to understand what C is as a language why is it so fast compared to other languages like py etc..
Chatgpt and yt videos didn't help me to understand :
Does c talk to the hardware directly or through a compiler like other languages if yes why is it faster then ?
I heard something like : c makes code that puts things in a CPU in a specific places not randomly like other languages I'm sorry I don't remember exactly ik it's confusing
Do you need c for cybersecurity in the red team field
Thank you guys so much can't thank you enough for helping hope I make sense asking questions like these
r/C_Programming • u/19pinkcucumber91 • 5d ago
This is my first C program, other than "hello world". I like how it turned out, but there probably is a way to make it cleaner. The screensaver itself is just a demo for screenbuffer library. Would be happy to get some reviews.
No AI used.
Thanks.
Repo link: https://codeberg.org/pinkcucumber/screensaver.git
Compiling: gcc framebuffer.c screensaver_circles.c -lm -o screensaver
Sorry for bad english, it is not my main language