Skip to content

Instantly share code, notes, and snippets.

@Ohjurot
Last active June 1, 2021 20:04
Show Gist options
  • Save Ohjurot/4956635e3e59f12163ff9c4836099349 to your computer and use it in GitHub Desktop.
Save Ohjurot/4956635e3e59f12163ff9c4836099349 to your computer and use it in GitHub Desktop.
Win32 Bad Snake | Just a very bad way to programm snake
#if defined(UNICODE) && !defined(_UNICODE)
#define _UNICODE
#elif defined(_UNICODE) && !defined(UNICODE)
#define UNICODE
#endif
#define _WIN32_WINNT 0x0A00
#define NOMINMAX
#include <windows.h>
#include <cmath>
#include <algorithm>
#include <cstdlib>
#include <ctime>
#define RECT_WIDTH(rc) (rc.right - rc.left)
#define RECT_HEIGHT(rc) (rc.bottom - rc.top)
volatile bool keepRunning = true;
volatile unsigned int playground[40][30] = {};
volatile int appleX = -1;
volatile int appleY = -1;
const unsigned playfieldX = 800;
const unsigned playfieldY = 600;
struct snakePosElement{
unsigned int x, y;
};
enum Direction{
LEFT,
RIGHT,
UP,
DOWN
};
volatile Direction moveDirection = DOWN;
LRESULT CALLBACK windowProc(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam){
switch(msg){
case WM_KEYDOWN:
switch(wParam){
case VK_UP:
if(moveDirection != DOWN) moveDirection = UP;
break;
case VK_DOWN:
if(moveDirection != UP) moveDirection = DOWN;
break;
case VK_LEFT:
if(moveDirection != RIGHT) moveDirection = LEFT;
break;
case VK_RIGHT:
if(moveDirection != LEFT) moveDirection = RIGHT;
break;
}
break;
case WM_CLOSE:
keepRunning = false;
break;
case WM_PAINT:
HBRUSH brYellow = CreateSolidBrush(RGB(200, 255, 0));
HBRUSH brSnakeHead = CreateSolidBrush(RGB(242, 185, 80));
HBRUSH brSnakeBody = CreateSolidBrush(RGB(242, 200, 148));
HBRUSH brSnakeFood = CreateSolidBrush(RGB(166, 30, 41));
// RECT
RECT cr;
GetClientRect(wnd, &cr);
// PAINT
PAINTSTRUCT ps;
HDC hdc = BeginPaint(wnd, &ps);
// PLAYFIELD
RECT playfield = {
(RECT_WIDTH(cr) - playfieldX) / 2,
(RECT_HEIGHT(cr) - playfieldY) / 2,
(RECT_WIDTH(cr) - playfieldX) / 2 + playfieldX,
(RECT_HEIGHT(cr) - playfieldY) / 2 + playfieldY
};
FillRect(hdc, &playfield, brYellow);
// Snake ground
for(unsigned int x = 0; x < 40; x++){
for(unsigned int y = 0; y < 30; y++){
RECT drawRect = {
playfield.left + (x * 20), playfield.top + (y * 20),
playfield.left + (x * 20) + 20, playfield.top + (y * 20) + 20
};
switch(playground[x][y]){
case 1:
FillRect(hdc, &drawRect, brSnakeBody);
break;
case 2:
FillRect(hdc, &drawRect, brSnakeHead);
break;
case 3:
FillRect(hdc, &drawRect, brSnakeFood);
break;
}
}
}
// END PAINT
EndPaint(wnd, &ps);
DeleteObject(brYellow);
DeleteObject(brSnakeHead);
DeleteObject(brSnakeBody);
DeleteObject(brSnakeFood);
break;
}
return DefWindowProc(wnd, msg, wParam, lParam);
}
const LPCSTR clsName = "SnakeWin";
bool moveSnake(snakePosElement* snakeArray, unsigned int* tail, unsigned int* length, Direction dir){
unsigned int snakeIndex = (*tail + *length) % 128;
snakePosElement head = snakeArray[snakeIndex];
switch(dir){
case LEFT:
head.x = (head.x == 0 ? 40 : (head.x - 1) % 40);
break;
case RIGHT:
head.x = (head.x + 1) % 40;
break;
case UP:
head.y = (head.y == 0 ? 30 : (head.y - 1) % 30);
break;
case DOWN:
head.y = (head.y + 1) % 30;
break;
}
unsigned int snakeIndexNext = (snakeIndex + 1)% 128;
// Check array
unsigned int checkIndex = *tail;
for(unsigned int i = 0; i < *length; i++){
if(snakeArray[checkIndex].x == head.x && snakeArray[checkIndex].y == head.y) return false;
checkIndex = (checkIndex + 1) % 128;
}
if(appleX == head.x && appleY == head.y){
appleX = (std::rand() / (float)RAND_MAX) * 40;
appleY = (std::rand() / (float)RAND_MAX) * 30;
if(*length != 128){
*length = *length +1;
}
}else{
*tail = (*tail + 1) % 128;
}
snakeArray[snakeIndexNext] = head;
return true;
}
int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow){
// CLS
WNDCLASSEX wcex;
ZeroMemory(&wcex, sizeof(WNDCLASSEX));
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hbrBackground = CreateSolidBrush(RGB(100, 200, 50));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hIcon = NULL;
wcex.hIconSm = NULL;
wcex.hInstance = hThisInstance;
wcex.lpfnWndProc = &windowProc;
wcex.lpszClassName = clsName;
wcex.lpszMenuName = NULL;
wcex.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
RegisterClassEx(&wcex);
// WND
HWND wnd = CreateWindowEx(
NULL,
clsName,
"Snake 1234",
WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_MAXIMIZE,
0, 0,
800, 600,
NULL,
NULL,
hThisInstance,
NULL
);
// MEM
snakePosElement snake[128] = {};
unsigned int tail = 0;
unsigned int length = 0;
// DBG
appleX = 10;
appleY = 10;
length = 1;
std::srand(std::time(0));
// Time
int ctr = 0;
// Loop
MSG msg = {};
while(keepRunning){
// MSG
while(PeekMessage(&msg, wnd, 0, 0, PM_REMOVE)){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// Game loop
if(ctr == 5){
ctr = 0;
// Clear array
ZeroMemory((void*)playground, 40 * 30 * sizeof(unsigned int));
// Fill array
for(unsigned int i = length; i > 0; i--){
snakePosElement pos = snake[(tail + i) % 128];
if(i == length){
playground[pos.x][pos.y] = 2;
}else{
playground[pos.x][pos.y] = 1;
}
}
// Apple
if(appleX >= 0 && appleY >= 0){
playground[appleX][appleY] = 3;
}
bool gameOk = moveSnake(snake, &tail, &length, moveDirection);
RedrawWindow(wnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
if(!gameOk){
MessageBox(wnd, "Game Over", "Game Over", MB_OK);
keepRunning = false;
}
}
ctr++;
Sleep(10);
}
// Cleanup
DestroyWindow(wnd);
UnregisterClass(clsName, hThisInstance);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment