Ncurses issue around functions which print to a window - c++

I'm currently making a simple ncurses menu for executing terminal commands more quickly while working on projects. I'm new to the library and keep having the same issue. I've read the documentation for the relevant functions but it seems to reveal nothing. I was hoping someone more experienced would know why there's an issue.
The function which performs "make main" has been the main one causing the problems
void makeMain( WINDOW *window ) {
wrefresh(window);
mvwprintw( window, 1, 1, "test" );
wrefresh(window);
std::system("make main");
wrefresh(window);
refresh();
wmove( window, 1, 1 );
refresh();
wrefresh( window );
}
the function is run from another function
void coordinateUserInput( int max, std::vector<command> commandslist, WINDOW *output ) {
cbreak();
noecho();
wrefresh(stdscr);
//prep work
char key_pressed;
bool can_go_up;
bool can_go_down;
int y;
int x;
const int &start_line = 3;
const int &finish_line = commandslist.size() + 2;
bool keep_going{1};
//
wmove( stdscr, 3, 2 );
refresh();
while(keep_going) {
getyx( stdscr, y, x );
can_go_up = (!(y == start_line));
can_go_down = (!(y == finish_line));
key_pressed = getch();
switch(key_pressed) {
case 'j':
if(can_go_down) {
wmove( stdscr, y + 1, 2 );
refresh();
}
break;
case 'k':
if(can_go_up) {
wmove( stdscr, y - 1, 2 );
refresh();
}
break;
case '\n':
((commandslist[y - 3]).fcnpointer)(output);
wmove( stdscr, 3, 2 );
refresh();
break;
case 'q':
keep_going = 0;
break;
default:
break;
}
}
return;
}
I'm fairly certain that these would be the problem functions. Running with -Wall and -Wextra doesn't yield errors.
int main() {
bool *is_set_up = new bool;
initscr();
refresh();
//set up command ouput window pointer
int maxx;
int *maxy = new int;
getmaxyx(stdscr, *maxy, maxx);
delete maxy;
static WINDOW *command_output = newwin( 3, maxx, 0, 0 );
box(command_output, 0, 0);
wrefresh(command_output);
//
std::vector<command> commands = {defineCommands()};
writeMenu(commands, commands.size(), is_set_up);
refresh();
coordinateUserInput(commands.size()-1, commands, command_output);
std::cout << "worked" << std::endl;
endwin();
delete is_set_up;
return 0;
}

Related

General SDL2 problems. MacOS, Xode

What I'm trying to do is make an SDL program that can write special symbols to a window I created. The keyboard can change between 4 layers each registering 32 keys. I just can't figure out how to actually make something appear on the screen and have no idea what I'm doing wrong.
#include <iostream>
#include <SDL2/SDL.h>
int main(int argc, const char * argv[])
{
//Setup
bool quit = false;
SDL_Event event;
int z = 0; //Layer
int x = 0;
int y = 0;
//Init
SDL_Init(SDL_INIT_VIDEO);
SDL_Window * window = SDL_CreateWindow("TPKB", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 960, 640, SDL_WINDOW_SHOWN);
SDL_Rect rect = {x, y, 32, 32};
SDL_Renderer * renderer = SDL_CreateRenderer(window, -1, 0);
SDL_Surface * A_srf = SDL_LoadBMP("A.bmp"); SDL_Texture * A = SDL_CreateTextureFromSurface(renderer, A_srf); SDL_FreeSurface(A_srf);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
//Events
while (!quit)
{
SDL_WaitEvent(&event);
switch (event.type)
{
case SDL_QUIT:
quit = true;
break;
case SDL_KEYUP:
{
if(z == 0)
{
switch(event.key.keysym.sym)
{
//case SDLK_1: SDL_BlitSurface(A_srf, NULL, surface, srfrect); break;
case SDLK_2: SDL_RenderCopy(renderer, A, NULL, &rect); if(x == 928){x = 0; y += 32;} else{x += 32;} rect.x = x; rect.y = y; SDL_RenderClear(renderer); SDL_RenderPresent(renderer); break;
case SDLK_LEFT: z = 1; std::cout << "1"; break;
}
}
if(z == 1)
{
switch(event.key.keysym.sym)
{
case SDLK_UP: z = 0; std::cout << "0"; break;
}
}
}
}
}
//Cleanup
SDL_DestroyRenderer(renderer);
SDL_DestroyTexture(A);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
I've tried moving the render clear render present stuff around but it hasn't seemed to be activating at all.

One of two instances not getting initialized

I am working with ncurses and i am trying to create a class that will print a box.
My class
class CMenu{
public:
CMenu( int x , int y){
this -> x = x;
this -> y = y;
createMenu();
}
void createMenu(){
start_color();
cbreak();
noecho();
keypad(stdscr, TRUE);
my_menu_win = newwin(30, 60, x, y);
keypad(my_menu_win, TRUE);
/* Print a border around the main window and print a title */
box(my_menu_win, 0, 0);
mvprintw(LINES - 2, 0, "F2 to exit");
refresh();
wrefresh(my_menu_win);
while(true){
switch(c = wgetch(my_menu_win)){
case KEY_F(2):
endwin();
exit(1);
case KEY_DOWN:
break;
case KEY_UP:
break;
case 10:
move(20, 0);
clrtoeol();
wrefresh(my_menu_win);
refresh();
break;
}
wrefresh(my_menu_win);
}
}
private:
int n_choices;
int i;
int index;
int c;
int x;
int y;
WINDOW *my_menu_win;
};
And class where I want to create instance of said class
class CUI{
public:
CUI(){
min_X = 200;
min_Y = 50;
}
void printBackground(){
start_color();
init_pair(1,COLOR_GREEN,COLOR_BLACK);
attron(COLOR_PAIR(1));
attroff(COLOR_PAIR(1));
attron(COLOR_PAIR(1));
mvhline( (y/5) - 1, (x/6), ACS_BOARD , 140);
mvhline( (y/5)*4, (x/6), ACS_BOARD , 140);
}
void initMenu(){
initscr();
printBackground();
left = new CMenu(10,35);
right = new CMenu(10,115);
refresh();
endwin();
}
private:
int min_X;
int min_Y;
int x;
int y;
CMenu *left;
CMenu *right;
};
And main
int main() {
CUI one;
one.initMenu();
return 0;
}
The problem is that only one of the box gets printed. I added cout to a constructor of a CMenu class to see if both of them gets invoked. Only one of the instance gets invoked the second one gets ingored. What is causing this? Why arent both instances being invoked?
After you created the first menu (left = new CMenu(10,35);), its constructor called createMenu()...and this one starts an infinite loop (while(true) statement) that will never end.
So the second menu won't be created. right = new CMenu(10,115); statement will never be reached...untill CMenu::createMenu() returns... and by reading your code there's apparently no action that will exit this loop. So your program will never create more than one CMenu instance...

Seg fault with Allegro bitmaps

I am using liballegro4.2-dev on Ubuntu 14.04 to (hopefully) write a simple game. My code compiles fine using the command g++ Picker.cpp -o out ``allegro-config --libs, but when I run the code I always get the error message Shutting down Allegro due to signal #11 Segmentation fault (core dumped). I suspect this has something to do with the line: masked_blit(face, screen, 0, 0, 0, 0, 64, 64);, but Internet searches turn nothing up and I am out of ideas. The full code is below:
#include <allegro.h>
void setUpAllegro()
{
//INIT
allegro_init();
install_keyboard();
install_timer();
install_mouse();
install_sound( DIGI_AUTODETECT, MIDI_AUTODETECT, 0 );
set_color_depth( 16 );
bool fullscreen = false;
if (fullscreen == true)
set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0);
else
set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0);
//END INIT
}
class Player
{
public:
int x;
int y;
void Move(int dir)
{
switch(dir)
{
case 1:
y += 5;
break;
case 2:
y -= 5;
break;
case 3:
x += 5;
break;
case 4:
x -= 5;
break;
default:
//exit(1);
break;
}
}
};
int main()
{
setUpAllegro();
Player player;
bool done = false;
BITMAP *buffer = create_bitmap( 640, 480 );
BITMAP *face;
face = load_bitmap("/home/alexander/Desktop/Pooper Picker/fake.BMP",NULL);
while (!done)
{
if( key[KEY_ESC] )
done = true;
if( key[KEY_UP])
player.Move(1);
else if( key[KEY_DOWN] )
player.Move(2);
if ( key[KEY_LEFT] )
player.Move(3);
else if( key[KEY_RIGHT] )
player.Move(4);
masked_blit(face, screen, 0, 0, 0, 0, 64, 64);
blit( buffer, screen, 0, 0, 5, 5, 640, 480 );
release_screen();
clear_bitmap( buffer );
}
//free memory
destroy_bitmap( buffer );
return 0;
}
END_OF_MAIN();
Thanks for the help!

SDL2.0 moving Sprite with keyboard

I have been working on this game using SDL2.0 and C++ and have hit a snag. I have created the move function and am calling the right rectangle. And have called the move function in the main loop and it just doesn't move.
Here is the code.
//
// Window.cpp
// Galaxy Shooter
//
// Created by Samrith on 02/03/14.
// Copyright (c) 2014 Sam Shankar. All rights reserved.
//
#include "Window.h"
void Window::create() {
Resources r;
SDL_Init(SDL_INIT_EVERYTHING);
window = SDL_CreateWindow("Galaxy Shooter", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
screen = SDL_GetWindowSurface(window);
if(window == NULL)
std::cout << " Window cannot be created. Error: " << SDL_GetError();
else {
r.load();
SDL_UpdateWindowSurface(window);
}
}
void Window::destroy() {
Resources r;
SDL_DestroyWindow(window);
r.free();
SDL_Quit();
}
void Window::run() {
bool done = false;
Resources r;
create();
while(!done)
{
while(SDL_PollEvent(&event) != 0)
{
if(event.type == SDL_QUIT)
{
done = true;
destroy();
}
r.move(event); //This is the move function
SDL_UpdateWindowSurface(window);
}
r.projectile();
SDL_UpdateWindowSurface(window);
}
}
SDL_Window * Window::getWindow() {
return window;
}
SDL_Surface * Window::getSurface() {
return screen;
}
And here is the resources source file which contains the move function:
//
// Resources.cpp
// Galaxy Shooter
//
// Created by Samrith on 06/03/14.
// Copyright (c) 2014 Sam Shankar. All rights reserved.
//
#include "Resources.h"
bool b[4] = {0, 0, 0, 0};
void Resources::load() {
background();
rocket();
//r.create();
}
void Resources::free() {
Sound s;
SDL_FreeSurface(bgimage);
SDL_FreeSurface(rimage);
//SDL_FreeSurface(screen);
s.destroy();
}
//void Resources::run() {
// Window w;
// w.run();
//}
void Resources::background() {
Window w;
Sound s;
//Load screen
screen = SDL_GetWindowSurface(w.getWindow());
if(screen == NULL)
std::cout << "Surface (background) error: " << SDL_GetError();
//Load image
bgimage = IMG_Load("bg2.jpg");
if(bgimage == NULL)
std::cout << "Image (background) error: " << SDL_GetError();
//Load rectangle and set values
bgrect.x = 0;
bgrect.y = 0;
bgrect.h = w.screenH();
bgrect.w = w.screenW();
//Blit image to screen
SDL_BlitScaled(bgimage, NULL, screen, &bgrect);
s.init(1);
}
void Resources::rocket() {
Window w;
Sound s;
//Load screen
screen = SDL_GetWindowSurface(w.getWindow());
if(screen == NULL)
std::cout << "Surface (rocket) error: " << SDL_GetError();
//Load image
rimage = IMG_Load("rocket.png");
if(rimage == NULL)
std::cout << "Image (rocket) error: " << SDL_GetError();
//Load rectangle and set values
rrect.x = 15;
rrect.y = w.screenH()/2;
rrect.h = 75;
rrect.w = 75;
//Blit image to screen
SDL_BlitScaled(rimage, NULL, screen, &rrect);
//s.init(2);
}
void Resources::move(SDL_Event event) {
//bool done = false;
Window w;
switch(event.type)
{
case SDL_KEYDOWN:
switch(event.key.keysym.sym)
{
case SDLK_UP:
b[0] = 1; break;
case SDLK_DOWN:
b[1] = 1; break;
case SDLK_RIGHT:
b[2] = 1; break;
case SDLK_LEFT:
b[3] = 1; break;
}
break;
case SDL_KEYUP:
switch(event.key.keysym.sym)
{
case SDLK_UP:
b[0] = 0; break;
case SDLK_DOWN:
b[1] = 0; break;
case SDLK_RIGHT:
b[2] = 0; break;
case SDLK_LEFT:
b[3] = 0; break;
}
break;
}
if(b[0]==true)
rrect.y += 10;
if(b[1]==true)
rrect.y -= 10;
if(b[2]==true)
rrect.x += 10;
if(b[3]==true)
rrect.x -= 10;
}
void Resources::projectile() {
Window w;
SDL_PumpEvents();
int x, y;
SDL_GetMouseState(&x, &y);
if(SDL_GetMouseState(&x, &y) & SDL_BUTTON(1))
{
rrect.x = x;
rrect.y = y;
SDL_BlitScaled(rimage, NULL, screen, &rrect);
for(int i=rrect.x; i<=w.screenW(); i++)
rrect.x+=2;
}
}
Also, I have Googled this problem and tried out various tutorials and docs. This is my last resort and not the first place I turned to for this problem. So please be kind. :)
by declaring Resource r in every function you create a new instance of the Resource class every time thus creating many different Resource objects.
The same goes for the Window w variable you declare in every function of the class Resource: each function call will create a new window.
I suggest you to read about Object Oriented Programming and variable scoping.
Also, C++ is not the most friendly language to start learning about Object Oriented Programming.
If you are starting out, I suggest you to switch to a simpler language such as Java or C#.
Good luck.

BlackJack Algorithm

What is the general alogirthm for a BlackJack game ?
I'm writing one in c++ and end up having WAY too many if statements which ruin the whole thing.
The project is a win32 GUI application, and Im posting the message loop as well as the part of the program that checks the game's status
Posting the complete code will make it humongous, so here are the links to all the files:
Full Source Code
Message Loop
LRESULT CALLBACK WndProc( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam ){
switch(Msg)
{
case WM_PAINT:
{
PAINTSTRUCT PS;
HDC hDC = BeginPaint(hWnd, &PS);
You.Draw(hDC);
Dealer.Draw(hDC);
EndPaint(hWnd, &PS);
if(Bet.Enabled){
Bet.GetFocus();
Bet.Select(0,Bet.Length());
}
}
return 0;
case WM_CTLCOLORSTATIC:
{
SetBkMode((HDC)wParam, TRANSPARENT);
}
return (INT_PTR)(HBRUSH)GetStockObject(NULL_BRUSH);
case WM_CREATE:
{
//Create edit control
Bet.Create(hWnd, 10, 550, 100, 25, "0");
//Create labels
char Buffer[30];
sprintf(Buffer, "%d", You.HandValue());
BetLabel.Create(hWnd, 10, 500, 100, 40, "Enter Bet Amount");
GameControls.Create(hWnd, 10, 375, 100, 40, "Game Controls");
PlayerLabels.Create(hWnd, 10, 10, 100, 20, "You:");
PlayerLabels.Create(hWnd, 10, 150, 100, 20, "Dealer:");
HandValueLabel.Create(hWnd, (int)You.x[You.cards] + 85, (int)You.y[You.cards] + 25, 100, 20, Buffer);
YourMoney.Create(hWnd, 125, 500, 100, 40, "Your money: ");
sprintf(Buffer, "%d", You.money);
MoneyValue.Create(hWnd, 125, 525, 100, 40, Buffer);
//Create buttons
Ok.Create(hWnd, 10, 600, 100, 50, "Ok");
Hit.Create(hWnd, 10, 425, 100, 50, "Hit");
Stand.Create(hWnd, 120, 425, 100, 50, "Stand");
//Select Text
Bet.Select(0,3);
}
return 0;
case WM_CLOSE:
exit(0);
break;
case WM_COMMAND:
{
switch(HIWORD(wParam))
{
case BN_CLICKED:
{
switch(LOWORD(wParam))
{
case ID_OK:
{
//Place bet
int bet = 0;
bet = StringToNumber(Bet.Text());
You.money -= bet;
char Buffer[30];
sprintf(Buffer, "%d", You.money);
MoneyValue.SetText(Buffer);
//Update the window
InvalidateRect(hWnd, 0, TRUE);
You.Bet = YES;
Ok.Disable();
Bet.Disable();
You.DealCard();
You.DealCard();
Dealer.DealCard();
Dealer.DealCard();
You.win = false;
You.bust = false;
You.playing = YES;
Dealer.win = NO;
Dealer.bust = NO;
Dealer.playing = YES;
}
break;
case ID_HIT:
{
if(You.HandValue() < 21 && You.playing && !You.bust){
//Deal a card to the player, if he hasn't won or lost
You.DealCard();
}
if((Dealer.HandValue() <= 17 || Dealer.HandValue() < You.HandValue()) && Dealer.playing)
{
Dealer.DealCard();
}
//Update Hand Value
char Buffer[30];
sprintf(Buffer, "%d", You.HandValue());
HandValueLabel.SetText(Buffer);
InvalidateRect(hWnd,0,TRUE);
MoveWindow(HandValueLabel.Handle, (int)You.x[You.cards] + 80, (int)You.y[You.cards] + 25, 100, 20, TRUE);
RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_INTERNALPAINT);
}
break;
case ID_STAND:
if(Hit.Enabled){
//Don't deal more cards
Hit.Disable();
You.playing = false;
}
if((Dealer.HandValue() <= 17 || Dealer.HandValue() < You.HandValue()) && Dealer.playing){
//Deal a card to the dealer
Dealer.DealCard();
}
}
StatusChecker
void ProcessStatus(HWND hWnd){
if(Dealer.HandValue() > 17){
if(Dealer.HandValue() > You.HandValue() && Dealer.playing){
Dealer.playing = false;
}
else if(!You.playing && Dealer.HandValue() <= You.HandValue() && Dealer.playing){
Dealer.DealCard();
}
}
else if(Dealer.HandValue() <= 17 && Dealer.HandValue() <= You.HandValue() && !You.playing && Dealer.playing){
Dealer.DealCard();
}
if(EvaluateStatus() != 0){
status = OVER;
}
if(EvaluateStatus() == -1){
switch(MessageBoxA(hWnd, "You Lost! \n Keep Playing ?", "You Lost!", MB_YESNO | MB_ICONQUESTION))
{
case IDYES:
Reset();
break;
case IDNO:
exit(0);
break;
}
}
else if(EvaluateStatus() == 1){
switch(MessageBoxA(hWnd, "You Won! \n Keep Playing ?", "You Won!", MB_YESNO | MB_ICONQUESTION))
{
case IDYES:
Reset();
break;
case IDNO:
exit(0);
break;
}
}
}
int EvaluateStatus()
{
if(You.HandValue() > 21 && You.playing)
{
You.bust = true;
Dealer.win = true;
You.playing = NO;
return -1;
}
if(You.HandValue() == 21)
{
You.win = true;
return 1;
}
if(Dealer.HandValue() > 21)
{
Dealer.bust = true;
You.win = true;
return 1;
}
if(Dealer.HandValue() == 21)
{
Dealer.win = true;
return -1;
}
if(!You.playing && Dealer.HandValue() > You.HandValue() &&!Dealer.bust)
{
Dealer.win = true;
return -1;
}
if(You.HandValue() > Dealer.HandValue() && (!You.playing && (!Dealer.playing || Dealer.bust)))
{
You.win = true;
return 1;
}
if(You.HandValue() == Dealer.HandValue() && (!You.playing || !Dealer.playing))
{
You.win = true;
return 1;
}
As a first step: I probably wouldn't mix game logic and your GUI logic.. separate them into different modules.
And if you only have two players, you only need a bool to decide which one won. You don't need for both of the players Bust and Won variables.
A google search revealed this PDF paper on BlackJack algorithms. I'm sure if you did some more research using Google, you could find things too.
To figure out how to work out the actual steps needing to be done to play the game, work out on paper the different steps of the game, then decide how you can create classes that represent parts of the game and functions in these classes to execute the different steps of the game.'
This could be an iterative thing, where you go through it, then create some classes, functions, etc, now you can go back and see if what you've done makes sense, improve on the design etc.
Perhaps also play the game and see what is done, how that could be translated into code.
I have modified the way the program handles messages, and am posting it as a seperate answer.
It is still broken because of a minor hiccup, but i think the general idea is solid. comments would be appreciated
cards.h
/*
* cards.h
*
* Created on: Aug 31, 2011
* Author: Viraj
*/
#ifndef CARDS_H_
#define CARDS_H_
#include <iostream>
#include <algorithm>
#define STARTED true
#define OVER false
#define YES true
#define NO false
using namespace std;
HINSTANCE hApplication;
HBITMAP Bitmap;
char Buffer[30];
class Deck{
public:
int deck[53];
Deck(){
for(int suit = 1; suit <= 4; suit++){
for(int card = 1; card <= 13; card++){
deck[((suit-1)*13)+card] = card;
}
}
deck[0] = 0;
}
};
Deck deck;
class Cards{
private:
int card_seed;
int suit_seed;
public:
int card[11];
int cards;
int value[11];
Cards(){
fill(card, card + 10, 0);
fill(value, value + 10, 0);
cards = 0;
}
void DealCard()
{
cards++;
while(!deck.deck[card[cards]]){
card_seed = rand()%13 + 1;
suit_seed = rand()%4 + 1;
card[cards] = (suit_seed - 1)*13 + card_seed;
}
deck.deck[card[cards]] = 0;
if(card_seed > 1 && card_seed < 11){
value[cards] = card_seed;
}
else if(card_seed >= 11 && card_seed <= 13){
value[cards] = 10;
}
else if(card_seed == 1){
value[cards] = 11;
}
}
};
class Player : public Cards {
public:
float x[11];
float y[11];
bool playing;
bool bust;
bool win;
int money;
Player(const char* Type){
srand(time(NULL));
playing = true;
if(Type == "Dealer"){
for(int card = 1; card <= 10; card++){
x[card] = 10 + (card-1)*75;
y[card] = 200;
}
}
else{
for(int card = 1; card <= 10; card++){
x[card] = 10 + (card-1)*75;
y[card] = 35;
money = 1000;
}
}
}
void Reset(){
cards = 0;
fill(card, card + 10, 0);
fill(value, value + 10, 0);
playing = true;
}
int HandValue(){
int sum = 0;
for(int current_card = 1; current_card <= cards; current_card++){
sum += value[current_card];
}
if(sum > 21){
for(int current_card = 1; current_card <= cards; current_card++){
if(value[current_card] == 11 && sum > 21){
value[current_card] = 1;
sum = HandValue();
break;
}
}
}
return sum;
}
void Draw(HDC hDC){
HDC MemoryDevice;
for(int CardToLoad = 1; CardToLoad <= cards; CardToLoad++){
Bitmap = LoadBitmap(hApplication, MAKEINTRESOURCE(card[CardToLoad]));
MemoryDevice = CreateCompatibleDC(hDC);
SelectObject(MemoryDevice, Bitmap);
BitBlt(hDC, (int)x[CardToLoad], (int)y[CardToLoad], 75, 100, MemoryDevice, 0, 0, SRCCOPY);
}
DeleteDC(MemoryDevice);
}
};
class CONTROL{
public:
HWND Handle;
char* ClassName;
char* Caption;
DWORD ClassStyle;
DWORD ExtendedStyle;
int x;
int y;
int Width;
int Height;
int ID;
bool Enabled;
void Create(HWND ParentHandle, int x, int y, int Width, int Height, char* Caption){
Handle = CreateWindowExA(ExtendedStyle, ClassName, Caption, ClassStyle, x, y, Width, Height, ParentHandle, (HMENU)ID, NULL, NULL);
Enabled = true;
CONTROL::Caption = Caption;
CONTROL::x = x;
CONTROL::y = y;
CONTROL::Width = Width;
CONTROL::Height = Height;
}
void GetFocus(){
SetFocus(Handle);
}
void Disable(){
EnableWindow(Handle, FALSE);
Enabled = false;
}
void Enable(){
EnableWindow(Handle, TRUE);
Enabled = true;
}
void SetText(char* String){
SetWindowTextA(Handle, String);
}
};
class BUTTON : public CONTROL {
public:
BUTTON(int Identifier){
ClassStyle = BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD;
ID = Identifier;
ClassName = "BUTTON";
ExtendedStyle = 0;
}
};
class EDIT : public CONTROL {
public:
EDIT(int Identifier){
ClassStyle = ES_NUMBER | WS_VISIBLE | ES_CENTER | WS_CHILD | ES_NOHIDESEL;
ExtendedStyle = WS_EX_CLIENTEDGE;
ID = Identifier;
ClassName = "EDIT";
}
void Select(int first, int last){
Edit_SetSel(Handle, first, last);
}
int Length(){
return Edit_GetTextLength(Handle);
}
const char* Text(){
char Buffer[Length() + 1];
Edit_GetText(Handle, (LPTSTR)&Buffer, Length() + 1);
string String = Buffer;
return String.c_str();
}
};
class STATIC : public CONTROL {
public:
STATIC() {
ClassStyle = WS_VISIBLE | SS_CENTER | WS_CHILD;
ID = 0;
ClassName = "STATIC";
ExtendedStyle = 0;
}
};
Player You("You"), Dealer("Dealer");
BUTTON Ok(ID_OK), Hit(ID_HIT), Stand(ID_STAND);
EDIT Bet(ID_BET);
STATIC BetLabel, GameControls, PlayerLabels, HandValueLabel, YourMoney, MoneyValue, Bust;
class Game{
public:
bool started;
Game(){
started = false;
}
void Stop(){
started = false;
}
void ResetGame(HWND hWnd){
//Reset Players
You.Reset();
Dealer.Reset();
//Reset Controls
Ok.Enable();
Bet.Enable();
Hit.Enable();
//Reset Hand value
sprintf(Buffer, "%d", You.HandValue());
HandValueLabel.SetText(Buffer);
//Reset deck
deck = Deck();
//Stop the game
started = false;
//Update the Display
InvalidateRect(hWnd, 0, TRUE);
RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_INTERNALPAINT);
}
int SendMessage(HWND hWnd, int ButtonID, unsigned int MESSAGE, int Information, char* _Information){
return ProcessMessage(hWnd, ButtonID, MESSAGE, Information, _Information);
}
int ProcessMessage(HWND hWnd, int ButtonID, unsigned int MESSAGE, int Information, char* _Information){
switch(MESSAGE)
{
case START_GAME:
//Place Bet
You.money -= Information;
started = YES;
sprintf(Buffer, "%d", You.money);
//Update Controls
MoneyValue.SetText(Buffer);
Ok.Disable();
Bet.Disable();
//Deal two cards to player and dealer
You.DealCard();
You.DealCard();
Dealer.DealCard();
Dealer.DealCard();
//Update the Hand Value Label
sprintf(Buffer, "%d", You.HandValue());
HandValueLabel.SetText(Buffer);
//Move the label
MoveWindow(HandValueLabel.Handle, (int)You.x[You.cards] + 80, (int)You.y[You.cards] + 25, 100, 20, TRUE);
//Send PAINT message
InvalidateRect(hWnd,0, TRUE);
RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_INTERNALPAINT);
//Check for BlackJacks
if(You.HandValue() == 21){
SendMessage(hWnd, 0, INTERNAL, YOU_WIN, "");
}
else if(Dealer.HandValue() == 21){
SendMessage(hWnd, 0, INTERNAL, DEALER_WIN, "");
}
break;
case STAND:
if(started){
Hit.Disable();
You.playing = false;
}
break;
case INTERNAL:
switch(Information)
{
case DEALER_WIN:
return MessageBoxA(hWnd, "You Loose! \n Play Again ?", "Game Over", MB_YESNO | MB_ICONINFORMATION);
case YOU_WIN:
return MessageBoxA(hWnd, "You Win! \n Keep Playing ?", "Game Over", MB_YESNO | MB_ICONINFORMATION);
}
break;
case IDLE:
if(started){
//Check for BlackJacks
if(Dealer.HandValue() == 21){
started = false;
switch(SendMessage(hWnd, 0, INTERNAL, DEALER_WIN, ""))
{
case IDYES:
ResetGame(hWnd);
return 0;
case IDNO:
exit(0);
return 0;
}
}
if(!You.playing && Dealer.playing && Dealer.HandValue() < You.HandValue())
Dealer.DealCard();
//Update the Window
InvalidateRect(hWnd,0, TRUE);
RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_INTERNALPAINT);
//Check for a Bust
if(Dealer.HandValue() > 21){
switch(SendMessage(hWnd, 0, INTERNAL, YOU_WIN, ""))
{
case IDYES:
ResetGame(hWnd);
return 0;
case IDNO:
exit(0);
return 0;
}
}
if(Dealer.HandValue() == 21){
switch(SendMessage(hWnd, 0, INTERNAL, YOU_WIN, ""))
{
case IDYES:
ResetGame(hWnd);
return 0;
case IDNO:
exit(0);
return 0;
}
}
}
break;
case HIT:
//Check to see who's still playing and deal a card to them
if(started){
if(You.playing){
You.DealCard();
//Update the Hand Value Label
sprintf(Buffer, "%d", You.HandValue());
HandValueLabel.SetText(Buffer);
//Move the label and update the screen
MoveWindow(HandValueLabel.Handle, (int)You.x[You.cards] + 80, (int)You.y[You.cards] + 25, 100, 20, TRUE);
InvalidateRect(hWnd, 0, TRUE);
RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_INTERNALPAINT);
//Check for a BlackJack
if(You.HandValue() == 21){
started = false;
switch(SendMessage(hWnd, 0, INTERNAL, YOU_WIN, ""))
{
case IDYES:
ResetGame(hWnd);
return 0;
case IDNO:
exit(0);
return 0;
}
}
//Check for a bust
if(You.HandValue() > 21){
started = false;
switch(SendMessage(hWnd, 0, INTERNAL, YOU_WIN, ""))
{
case IDYES:
ResetGame(hWnd);
return 0;
case IDNO:
exit(0);
return 0;
}
}
}
if(Dealer.playing){
Dealer.DealCard();
InvalidateRect(hWnd, 0, TRUE);
RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_INTERNALPAINT);
//Check for BlackJack
if(Dealer.HandValue() == 21){
started = false;
switch(SendMessage(hWnd, 0, INTERNAL, DEALER_WIN, ""))
{
case IDYES:
ResetGame(hWnd);
return 0;
case IDNO:
exit(0);
return 0;
}
}
//Check for Bust
if(Dealer.HandValue() > 21){
started = false;
switch(SendMessage(hWnd, 0, INTERNAL, YOU_WIN, ""))
{
case IDYES:
ResetGame(hWnd);
return 0;
case IDNO:
exit(0);
return 0;
}
}
}
}
break;
}
return 0;
}
};
Game game;
#endif
Message Loop
switch(Msg)
{
case WM_PAINT:
{
PAINTSTRUCT PS;
HDC hDC = BeginPaint(hWnd, &PS);
You.Draw(hDC);
Dealer.Draw(hDC);
EndPaint(hWnd, &PS);
if(Bet.Enabled){
Bet.GetFocus();
Bet.Select(0,Bet.Length());
}
}
return 0;
case WM_CTLCOLORSTATIC:
{
SetBkMode((HDC)wParam, TRANSPARENT);
}
return (INT_PTR)(HBRUSH)GetStockObject(NULL_BRUSH);
case WM_CREATE:
{
//Create edit control
Bet.Create(hWnd, 10, 550, 100, 25, "0");
//Create labels
char Buffer[30];
sprintf(Buffer, "%d", You.HandValue());
BetLabel.Create(hWnd, 10, 500, 100, 40, "Enter Bet Amount");
GameControls.Create(hWnd, 10, 375, 100, 40, "Game Controls");
PlayerLabels.Create(hWnd, 10, 10, 100, 20, "You:");
PlayerLabels.Create(hWnd, 10, 175, 100, 20, "Dealer:");
HandValueLabel.Create(hWnd, (int)You.x[You.cards] + 85, 60, 100, 20, Buffer);
YourMoney.Create(hWnd, 125, 500, 100, 40, "Your money: ");
sprintf(Buffer, "%d", You.money);
MoneyValue.Create(hWnd, 125, 525, 100, 40, Buffer);
//Create buttons
Ok.Create(hWnd, 10, 600, 100, 50, "Ok");
Hit.Create(hWnd, 10, 425, 100, 50, "Hit");
Stand.Create(hWnd, 120, 425, 100, 50, "Stand");
//Select Text
Bet.Select(0,3);
}
return 0;
case WM_CLOSE:
exit(0);
break;
case WM_COMMAND:
{
switch(HIWORD(wParam))
{
case BN_CLICKED:
{
switch(LOWORD(wParam))
{
case ID_OK:
{
//Place bet
int bet = 0;
bet = StringToNumber(Bet.Text());
game.SendMessage(hWnd, ID_OK, START_GAME, bet, "");
}
break;
case ID_HIT:
{
//Tell the game that the player wants another card
game.SendMessage(hWnd, ID_HIT, HIT, 0, "");
}
break;
case ID_STAND:
game.SendMessage(hWnd, ID_STAND, STAND, 0, "");
}
}
break;
}
}
break;
default:
//Default:
game.SendMessage(hWnd, 0, IDLE, 0, "");
return DefWindowProcA(hWnd, Msg, wParam, lParam);
}
return 0;
}