Hi
I have a memory leak somewhere in this code but I have no idea where. Can anybody help me out ?
#include <windows.h>
#include <mmsystem.h>
#pragma comment(lib, "winmm.lib")
#include <fstream>
#include <time.h>
#include <cstring>
#include "resource.h"
using namespace std;
const char cn[] = "SameGame"; // ClassName
HBITMAP BLUEBMP = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BLUE1));
HBITMAP GREENBMP = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_GREEN1));
HBITMAP REDBMP = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_RED1));
HBITMAP YELLOWBMP = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_YELLOW1));
HBITMAP BLUEBMP_S = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BLUE2));
HBITMAP GREENBMP_S = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_GREEN2));
HBITMAP REDBMP_S = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_RED2));
HBITMAP YELLOWBMP_S = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_YELLOW2));
#define EMPTY 0
#define IS_SELECTED(B) (B > 4)
#define IS_EMPTY(B) (B == EMPTY)
#define SELECTED 8 // 1000
#define BLUE 1 // 0001
#define GREEN 2 // 0010
#define RED 3 // 0011
#define YELLOW 4 // 0100
int width = 15; // Grid Width
int height = 15; // Grid Height
#define ballSize 30 // Ball Diameter
#define ID_DELAY 1
#define ID_DELAY2 2
int score = 0;
int tempScore = 0;
bool MEGASHIFT = 0;
unsigned char grid[100][100];
HPEN pen = CreatePen(PS_SOLID , 0 , RGB(255,255,255));
HPEN panel = CreatePen(PS_SOLID , 0 , RGB(0,0,0));
HDC hdc;
HBITMAP bmp;
BITMAP bm;
PAINTSTRUCT ps;
HDC _hdc;
HDC _hdcMem;
HBITMAP hbmOld;
int randNum;
int RandomNumber(int high, int low) {
return ((rand() % high - low) + low + 1);
}
int bi; // Ball Index
int bc; // Ball count
int TB; // SHIFTING TOP BALL
int BB; // SHIFTING BOTTOM BALL
int RB; // SHIFTING RIGHT BALL
int LB; // SHIFTING LEFT BALL
UINT _w = width;
UINT _h = height;
char *_score = new char();
char *_tempscore = new char();
bool idg = 0;
void (*delayFunction)(HWND);
int GETINTLENGTH(int num) {
int curMax = 10;
int noOfChs = 1;
while (num > curMax) {
curMax *= 10;
noOfChs++;
}
return noOfChs;
}
char *INTTOCHARP(int num) {
char *val = new char();
_itoa_s(num, val, GETINTLENGTH(num)+1, 10);
return val;
}
int GET_TRUE_COL(int ball) {
return ball ^ SELECTED;
}
void REMOVEALLSELECTED() {
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
if (IS_SELECTED(grid[y][x])) {
grid[y][x] = EMPTY;
}
}
}
}
void UNSELECTALL() {
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
if (IS_SELECTED(grid[y][x])) {
grid[y][x] ^= SELECTED;
}
}
}
}
void REPAINT(HWND hwnd) {
InvalidateRect(hwnd, NULL, 1);
}
void NEWGAME(HWND hwnd) {
srand((int)time(NULL));
score = 0;
tempScore = 0;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
randNum = RandomNumber(4,0);
grid[y][x] = randNum;
}
}
REPAINT(hwnd);
}
void FLOOD(int x, int y, int col) {
grid[y][x] |= SELECTED;
bc++;
if (x >= 1) if (col == (int) grid[y][x-1] && int( grid[y][x-1] ) ^ (int) col == SELECTED) FLOOD(x-1, y, col);
if (x <= width-2) if (col == (int) grid[y][x+1] && int( grid[y][x+1] ) ^ (int) col == SELECTED) FLOOD(x+1, y, col);
if (y >= 1) if (col == (int) grid[y-1][x] && int( grid[y-1][x] ) ^ (int) col == SELECTED) FLOOD(x, y-1, col);
if (y <= height-2) if (col == (int) grid[y+1][x] && int( grid[y+1][x] ) ^ (int) col == SELECTED) FLOOD(x, y+1, col);
}
void SHIFTALLDOWN() {
for (int y = height - 2; y >= 0; y--) {
for (int x = 0; x < width; x++) {
TB = grid[y][x];
BB = grid[y+1][x];
if (IS_EMPTY(BB) && (!IS_EMPTY(TB))) {
grid[y+1][x] = grid[y][x];
grid[y][x] = EMPTY;
x--;
if (y+1 != height-1) y++;
else y = height-2;
}
}
}
}
void SHIFTALLRIGHT() {
for (int y = 0; y < height; y++) {
for (int x = width - 2; x >= 0; x--) {
LB = grid[y][x];
RB = grid[y][x+1];
if (IS_EMPTY(RB) && (!IS_EMPTY(LB))) {
grid[y][x+1] = grid[y][x];
grid[y][x] = EMPTY;
y--;
x = width - 2;
}
}
}
}
bool ADDNEWCOLUMNS() {
bool anyNew = 0;
for (int x = 0; x < width; x++) {
if (IS_EMPTY(grid[height-1][x])) {
anyNew = 1;
int rand = RandomNumber(height + 1, 1);
int rand2;
for (int y = height - 1; y >= height - (rand - 1); y--) {
rand2 = RandomNumber(4, 0);
grid[y][x] = rand2;
}
}
}
return anyNew;
}
bool CHECKFORFINISH() {
bool fin = 1;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
if (IS_EMPTY(grid[y][x])) continue;
if (!IS_EMPTY(grid[y][x+1]) && x < width - 2) if (grid[y][x] == grid[y][x+1]) return 0;
if (!IS_EMPTY(grid[y][x-1]) && x > 1) if (grid[y][x] == grid[y][x-1]) return 0;
if (!IS_EMPTY(grid[y+1][x]) && y < height - 2) if (grid[y][x] == grid[y+1][x]) return 0;
if (!IS_EMPTY(grid[y-1][x]) && y > 1) if (grid[y][x] == grid[y-1][x]) return 0;
}
}
return 1;
}
void COUNTBALLS(HWND hwnd) {
int ballcount[4]; // Red, Green, Blue, Yellow
for (int i = 0; i < 4; i++) ballcount[i] = 0;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
switch (grid[y][x]) {
case RED: ballcount[0]++; break;
case GREEN: ballcount[1]++; break;
case BLUE: ballcount[2]++; break;
case YELLOW: ballcount[3]++; break;
}
}
}
string txt;
txt = "Reds:\t\t";
txt += INTTOCHARP(ballcount[0]);
txt += "\nGreens:\t\t";
txt += INTTOCHARP(ballcount[1]);
txt += "\nBlues:\t\t";
txt += INTTOCHARP(ballcount[2]);
txt += "\nYellows:\t\t";
txt += INTTOCHARP(ballcount[3]);
MessageBox(hwnd, (char *) txt.c_str(), "Ball count", MB_OK);
}
HBITMAP GETBALLBMP(UINT ball) {
switch (ball) {
case IDB_BLUE1: return BLUEBMP; break;
case IDB_GREEN1: return GREENBMP; break;
case IDB_RED1: return REDBMP; break;
case IDB_YELLOW1: return YELLOWBMP; break;
case IDB_BLUE2: return BLUEBMP_S; break;
case IDB_GREEN2: return GREENBMP_S; break;
case IDB_RED2: return REDBMP_S; break;
case IDB_YELLOW2: return YELLOWBMP_S; break;
}
return NULL;
}
UINT GETBALLINDEX(int ball, bool selected) { // Retrieves Ball ID
bi = ball ^ (selected ? SELECTED : 0);
switch (bi) {
case BLUE: return IDB_BLUE1; break;
case GREEN: return IDB_GREEN1; break;
case RED: return IDB_RED1; break;
case YELLOW: return IDB_YELLOW1; break;
case BLUE | SELECTED: return IDB_BLUE2; break;
case GREEN | SELECTED: return IDB_GREEN2; break;
case RED | SELECTED: return IDB_RED2; break;
case YELLOW | SELECTED: return IDB_YELLOW2; break;
}
return EMPTY;
}
void CLIENTRESIZE(HWND hWnd, int nWidth, int nHeight) {
RECT rcClient, rcWindow;
POINT ptDiff;
GetClientRect(hWnd, &rcClient);
GetWindowRect(hWnd, &rcWindow);
ptDiff.x = (rcWindow.right - rcWindow.left) - rcClient.right;
ptDiff.y = (rcWindow.bottom - rcWindow.top) - rcClient.bottom;
MoveWindow(hWnd,rcWindow.left, rcWindow.top, nWidth + ptDiff.x, nHeight + ptDiff.y, TRUE);
}
void DRAWSTATUS(HDC hdc) {
_itoa_s(score, _score, 10, 10);
TextOut(hdc, 10, 3 + ballSize * height, "Score:", 6);
TextOut(hdc, 70, 3 + ballSize * height, _score, GETINTLENGTH(score));
if (width < 11) return;
_itoa_s(tempScore, _tempscore, 10, 10);
TextOut(hdc, 150, 3 + ballSize * height, "Selection value:", 16);
TextOut(hdc, 270, 3 + ballSize * height, _tempscore, GETINTLENGTH(tempScore));
}
void StartDelay(HWND hwnd, int dur, int id) {
idg = 1;
SetTimer(hwnd, id, dur, NULL);
}
void EndDelay(HWND hwnd, int id) {
KillTimer(hwnd, id);
}
void FuncAfterDelay(HWND hwnd, void (*f)(HWND), int dur, int id) {
delayFunction = f;
StartDelay(hwnd, dur, id);
}
//
int CALLBACK Dimensions(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {
UNREFERENCED_PARAMETER(lParam);
switch (message) {
case WM_INITDIALOG:
{
SetDlgItemText(hDlg, IDC_WIDTH, INTTOCHARP(width));
SetDlgItemText(hDlg, IDC_HEIGHT, INTTOCHARP(height));
return (INT_PTR)TRUE;
}
case WM_COMMAND:
{
switch (LOWORD(wParam)) {
case IDOK:
{
_w = GetDlgItemInt(hDlg, IDC_WIDTH, 0, 0);
_h = GetDlgItemInt(hDlg, IDC_HEIGHT, 0, 0);
_w = _w > 40 ? 40 : _w < 5 ? 5 : _w;
_h = _h > 30 ? 30 : _h < 5 ? 5 : _h;
EndDialog(hDlg, LOWORD(wParam));
return IDOK;
}
break;
case IDCANCEL:
{
EndDialog(hDlg, LOWORD(wParam));
return IDCANCEL;
}
break;
}
}
break;
}
return (INT_PTR)FALSE;
}
void SHIFTR(HWND hwnd) {
SHIFTALLRIGHT();
REPAINT(hwnd);
EndDelay(hwnd, ID_DELAY2);
if (CHECKFORFINISH()) {
MessageBox(hwnd, "Finished!", "End", MB_OK);
if (MessageBox(hwnd, "Do you want to start a new game?",
(char*) L"", MB_YESNO | MB_ICONWARNING) == IDYES) {
CLIENTRESIZE(hwnd, width * ballSize, 23 + (height * ballSize));
NEWGAME(hwnd);
}
}
idg = 0;
}
void SHIFT(HWND hwnd) {
SHIFTALLDOWN();
if (MEGASHIFT) {
while (ADDNEWCOLUMNS());
REPAINT(hwnd);
FuncAfterDelay(hwnd, SHIFTR, 100, ID_DELAY2);
}
REPAINT(hwnd);
score += tempScore;
tempScore = 0;
if (!MEGASHIFT) idg = 0;
EndDelay(hwnd, ID_DELAY);
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_TIMER:
{
delayFunction(hwnd);
}
break;
case WM_COMMAND:
{
switch (LOWORD(wParam)) {
case ID_OPTIONS_DIMENSIONS:
{
int ret = (int) DialogBox(NULL, MAKEINTRESOURCE(IDD_DIMENSIONS), hwnd, Dimensions);
if (ret == IDOK) {
if (MessageBox(hwnd, "Do you want to start a new game?",
"Warning", MB_YESNO | MB_ICONWARNING) == IDYES) {
CLIENTRESIZE(hwnd, _w * ballSize, 23 + (_h * ballSize));
width = _w;
height = _h;
NEWGAME(hwnd);
}
}
}
break;
case ID_OPTIONS_MEGASHIFT:
{
if (MessageBox(hwnd, "Do you want to start a new game?",
"Warning", MB_YESNO | MB_ICONWARNING) == IDYES) {
NEWGAME(hwnd);
if (!MEGASHIFT) {
SetWindowText(hwnd, "SameGame - Megashift");
MEGASHIFT = 1;
} else {
SetWindowText(hwnd, "SameGame");
MEGASHIFT = 0;
}
}
}
break;
case ID_GAME_NEWGAME:
{
NEWGAME(hwnd);
}
break;
case ID_GAME_EXIT:
{
DestroyWindow(hwnd);
}
break;
case ID_HELP_ABOUT:
{
MessageBox(hwnd, "William Hemsworth\n2008 March 7",
"About", MB_OK | MB_ICONINFORMATION);
}
break;
case ID_HELP_RULES:
{
MessageBox(hwnd,
" Same Game\n\n\
The aim of the game is to try and get the\n\
highest score possible and to do that you\n\
need to try and gather as many same coloured balls\n\
together to retrieve the highest amounts of\n\
points once clicked.", "Rules", MB_OK);
}
break;
case ID_TOOLS_COUNTCOLOURS:
{
COUNTBALLS(hwnd);
}
break;
}
}
break;
case WM_KEYDOWN:
{
switch (LOWORD(wParam)) {
case 112:
{
try {
COUNTBALLS(hwnd);
} catch (void *v) {
}
}
break;
case 113:
NEWGAME(hwnd);
break;
case 27:
DestroyWindow(hwnd);
break;
}
}
break;
case WM_LBUTTONDOWN:
{
if (idg) break; // If in a delay
bc = 0;
POINT pt;
GetCursorPos(&pt);
ScreenToClient(hwnd, &pt);
int x = pt.x / ballSize;
int y = pt.y / ballSize;
if (IS_EMPTY(grid[y][x])) {
tempScore = 0;
UNSELECTALL();
REPAINT(hwnd);
break;
}
bool alreadySelected = IS_SELECTED((int)grid[y][x]);
if (!alreadySelected) {
UNSELECTALL();
FLOOD(x,y,(int)grid[y][x]);
tempScore = ((bc*bc)+(3*bc)+4);
if (bc==1) {
UNSELECTALL();
tempScore = 0;
REPAINT(hwnd);
break;
}
REPAINT(hwnd);
}
else {
REMOVEALLSELECTED();
PlaySound((char*)IDR_POP,NULL,SND_RESOURCE|SND_ASYNC);
REPAINT(hwnd);
FuncAfterDelay(hwnd, SHIFT, 100, ID_DELAY);
}
}
break;
case WM_CLOSE:
{
DeleteObject(BLUEBMP);
DeleteObject(GREENBMP);
DeleteObject(REDBMP);
DeleteObject(YELLOWBMP);
DeleteObject(BLUEBMP_S);
DeleteObject(GREENBMP_S);
DeleteObject(REDBMP_S);
DeleteObject(YELLOWBMP_S);
DeleteObject(pen);
DeleteObject(panel);
DeleteObject(hdc);
DeleteObject(bmp);
DeleteObject(_hdc);
DeleteObject(_hdcMem);
DeleteObject(hbmOld);
DestroyWindow(hwnd);
}
break;
case WM_ERASEBKGND:
{
hdc = GetDC(hwnd);
SelectObject(hdc , pen);
for (unsigned int y = 0; y < (unsigned int) height; y++) {
for (unsigned int x = 0; x < (unsigned int) width; x++) {
if (!IS_EMPTY(grid[y][x])) continue;
Rectangle(hdc, x * ballSize, y * ballSize,
(x * ballSize) + ballSize, (y * ballSize) + ballSize);
}
}
SelectObject(hdc , panel);
Rectangle(hdc, 0, height * ballSize, width * ballSize, 23 + (height * ballSize));
MoveToEx(hdc, 0, height * ballSize, NULL);
LineTo(hdc, ballSize * width, ballSize * height);
DRAWSTATUS(hdc);
}
break;
case WM_PAINT:
{
_hdc = BeginPaint(hwnd, &ps);
_hdcMem = CreateCompatibleDC(_hdc);
for (unsigned int y = 0; y < (unsigned int) height; y++) {
for (unsigned int x = 0; x < (unsigned int) width; x++) {
if (IS_EMPTY(grid[y][x])) continue;
bmp = GETBALLBMP(GETBALLINDEX(grid[y][x], 0));
hbmOld = (HBITMAP) SelectObject(_hdcMem, bmp);
GetObject(bmp, sizeof(bm), &bm);
BitBlt(_hdc, x * ballSize, y * ballSize, bm.bmWidth, bm.bmHeight, _hdcMem,0, 0, SRCCOPY);
}
}
SelectObject(_hdcMem, hbmOld);
DeleteDC(_hdcMem);
EndPaint(hwnd, &ps);
}
break;
case WM_CREATE:
{
CLIENTRESIZE(hwnd, width * ballSize, 23 + (height * ballSize));
NEWGAME(hwnd);
}
break;
case WM_DESTROY:
{
PostQuitMessage(0);
}
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrev, char *cmdl, int nShowCmd) {
WNDCLASSEX wc;
HWND hwnd;
MSG msg;
wc.cbClsExtra = 0;
wc.cbSize = sizeof(WNDCLASSEX);
wc.cbWndExtra = 0;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH) CreateSolidBrush(RGB(255,255,255));
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(wc.hInstance, MAKEINTRESOURCE(IDI_ICON2));
wc.hIconSm = LoadIcon(wc.hInstance, MAKEINTRESOURCE(IDI_ICON2));
wc.lpfnWndProc = WndProc;
wc.lpszClassName = cn;
wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);
wc.style = 0;
if (!RegisterClassEx(&wc)) {
MessageBox(NULL, (char*)L"Error, coulden't register window class", (char*)L"Error", MB_OK);
return 1;
}
hwnd = CreateWindowEx(WS_EX_APPWINDOW,
cn,
"SameGame",
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
300, 200, width * ballSize, height * ballSize,
NULL, NULL, hInstance, NULL);
if (hwnd == NULL) {
MessageBox(NULL, (char*)L"Error, coulden't create the window", (char*)L"Error", MB_OK);
return 1;
}
ShowWindow(hwnd, nShowCmd);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0) > 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
Here is the link to download the poject.
http://www.2shared.com/file/3022171/f34d7237/SameGame.html