From 4c587ade77bcb200752de38521ebcad77b37fee8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20A=C3=9Fmus?= Date: Mon, 5 Apr 2010 10:46:08 +0000 Subject: [PATCH] Patch by Adam Smith. Extended the Pairs application to support arbitrary board sizes. Thanks a lot! Fixes ticket #5615. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@36032 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/apps/pairs/Pairs.cpp | 9 +- src/apps/pairs/Pairs.h | 7 +- src/apps/pairs/PairsGlobal.h | 5 +- src/apps/pairs/PairsTopButton.cpp | 3 +- src/apps/pairs/PairsTopButton.h | 7 +- src/apps/pairs/PairsView.cpp | 94 ++++++++++------- src/apps/pairs/PairsView.h | 21 ++-- src/apps/pairs/PairsWindow.cpp | 162 ++++++++++++++++++++++++------ src/apps/pairs/PairsWindow.h | 14 ++- 9 files changed, 230 insertions(+), 92 deletions(-) diff --git a/src/apps/pairs/Pairs.cpp b/src/apps/pairs/Pairs.cpp index dd8c7a4589..2bd2b9f334 100644 --- a/src/apps/pairs/Pairs.cpp +++ b/src/apps/pairs/Pairs.cpp @@ -1,6 +1,6 @@ /* - * Copyright 2008 Ralf Schülke, ralf.schuelke@googlemail.com. All rights reserved. - * Distributed under the terms of the MIT License. + * Copyright 2008 Ralf Schülke, ralf.schuelke@googlemail.com. + * All rights reserved. Distributed under the terms of the MIT License. */ #include @@ -16,8 +16,9 @@ const char* kSignature = "application/x-vnd.Haiku-Pairs"; Pairs::Pairs() - : BApplication(kSignature), - fWindow(NULL) + : + BApplication(kSignature), + fWindow(NULL) { be_locale->GetAppCatalog(&fCatalog); } diff --git a/src/apps/pairs/Pairs.h b/src/apps/pairs/Pairs.h index 14f2731052..9b10209a41 100644 --- a/src/apps/pairs/Pairs.h +++ b/src/apps/pairs/Pairs.h @@ -1,8 +1,7 @@ /* - * Copyright 2008 Ralf Schülke, ralf.schuelke@googlemail.com. All rights reserved. - * Distributed under the terms of the MIT License. + * Copyright 2008 Ralf Schülke, ralf.schuelke@googlemail.com. + * All rights reserved. Distributed under the terms of the MIT License. */ - #ifndef PAIRS_H #define PAIRS_H @@ -18,7 +17,7 @@ class Pairs : public BApplication { public: Pairs(); virtual ~Pairs(); - + virtual void ReadyToRun(); virtual void RefsReceived(BMessage* message); virtual void MessageReceived(BMessage* message); diff --git a/src/apps/pairs/PairsGlobal.h b/src/apps/pairs/PairsGlobal.h index 9080f98908..cce15aea62 100644 --- a/src/apps/pairs/PairsGlobal.h +++ b/src/apps/pairs/PairsGlobal.h @@ -1,6 +1,6 @@ /* - * Copyright 2008 Ralf Schülke, ralf.schuelke@googlemail.com. All rights reserved. - * Distributed under the terms of the MIT License. + * Copyright 2008 Ralf Schülke, ralf.schuelke@googlemail.com. + * All rights reserved. Distributed under the terms of the MIT License. */ #ifndef PAIRS_GLOBAL_H @@ -12,6 +12,7 @@ const uint32 kMsgCardButton = 'card'; const uint32 kMsgPairComparing = 'pcom'; const int kBitmapSize = 64; +const int kSpaceSize = 10; #endif // PAIRS_GLOBAL_H diff --git a/src/apps/pairs/PairsTopButton.cpp b/src/apps/pairs/PairsTopButton.cpp index 112c16b1c8..37ecb6002b 100644 --- a/src/apps/pairs/PairsTopButton.cpp +++ b/src/apps/pairs/PairsTopButton.cpp @@ -1,5 +1,6 @@ /* - * Copyright 2008 Ralf Schülke, ralf.schuelke@googlemail.com. All rights reserved. + * Copyright 2008 Ralf Schülke, ralf.schuelke@googlemail.com. + * All rights reserved. * Distributed under the terms of the MIT License. */ diff --git a/src/apps/pairs/PairsTopButton.h b/src/apps/pairs/PairsTopButton.h index 2eeabb19eb..dea5003aa6 100644 --- a/src/apps/pairs/PairsTopButton.h +++ b/src/apps/pairs/PairsTopButton.h @@ -1,12 +1,11 @@ /* - * Copyright 2008 Ralf Schülke, ralf.schuelke@googlemail.com. All rights reserved. - * Distributed under the terms of the MIT License. + * Copyright 2008 Ralf Schülke, ralf.schuelke@googlemail.com. + * All rights reserved. Distributed under the terms of the MIT License. */ - #ifndef PAIRS_TOP_BUTTON_H #define PAIRS_TOP_BUTTON_H -#include +#include class BButton; diff --git a/src/apps/pairs/PairsView.cpp b/src/apps/pairs/PairsView.cpp index d4bdb71bc8..fd183f6865 100644 --- a/src/apps/pairs/PairsView.cpp +++ b/src/apps/pairs/PairsView.cpp @@ -1,6 +1,7 @@ /* - * Copyright 2008 Ralf Schülke, ralf.schuelke@googlemail.com. All rights reserved. - * Distributed under the terms of the MIT License. + * Copyright 2008 Ralf Schülke, ralf.schuelke@googlemail.com. + * Copyright 2010 Adam Smith + * All rights reserved. Distributed under the terms of the MIT License. */ #include "PairsView.h" @@ -26,15 +27,17 @@ #include "PairsGlobal.h" #include "PairsTopButton.h" -// TODO: support custom board sizes - -PairsView::PairsView(BRect frame, const char* name, uint32 resizingMode) - : BView(frame, name, resizingMode, B_WILL_DRAW) +PairsView::PairsView(BRect frame, const char* name, int width, int height, + uint32 resizingMode) + : + BView(frame, name, resizingMode, B_WILL_DRAW), + fWidth(width), + fHeight(height), + fNumOfCards(width * height), + fRandPos(new int[fNumOfCards]), + fPosX(new int[fNumOfCards]), + fPosY(new int[fNumOfCards]) { - // init bitmap pointers - for (int i = 0; i < 8; i++) - fCard[i] = NULL; - CreateGameBoard(); _SetPairsBoard(); } @@ -55,11 +58,15 @@ PairsView::CreateGameBoard() PairsView::~PairsView() { - for (int i = 0; i < 8; i++) - delete fCard[i]; + for (int i = 0; i < fCardBitmaps.CountItems(); i++) + delete ((BBitmap*)fCardBitmaps.ItemAt(i)); - for (int i = 0; i < 16; i++) - delete fDeckCard[i]; + for (int i = 0; i < fDeckCard.CountItems(); i++) + delete ((TopButton*)fDeckCard.ItemAt(i)); + + delete fRandPos; + delete fPosX; + delete fPosY; } @@ -91,10 +98,10 @@ PairsView::_ReadRandomIcons() // TODO: maybe read the icons only once at startup // clean out any previous icons - for (int i = 0; i < 8; i++) { - delete fCard[i]; - fCard[i] = NULL; - } + for (int i = 0; i < fCardBitmaps.CountItems(); i++) + delete ((BBitmap*)fCardBitmaps.ItemAt(i)); + + fCardBitmaps.MakeEmpty(); BDirectory appsDirectory; BDirectory prefsDirectory; @@ -149,19 +156,23 @@ PairsView::_ReadRandomIcons() } } - // pick eight random bitmaps from the ones we got in the list + // pick random bitmaps from the ones we got in the list srand((unsigned)time(0)); - for (int i = 0; i < 8; i++) { + for (int i = 0; i < fNumOfCards / 2; i++) { int32 index = rand() % bitmaps.CountItems(); - fCard[i] = (BBitmap*)bitmaps.RemoveItem(index); - if (fCard[i] == NULL) { - BAlert* alert = new BAlert("fatal", "Pairs did not find enough " - "vector icons in the system, it needs at least eight.", + BBitmap* bitmap = ((BBitmap*)bitmaps.RemoveItem(index)); + if (bitmap == NULL) { + BString strErr; + strErr + << "Pairs did not find enough vector icons in the system; it " + << "needs at least " << fNumOfCards / 2; + BAlert* alert = new BAlert("fatal", strErr, "OK", NULL, NULL, B_WIDTH_FROM_WIDEST, B_STOP_ALERT); alert->Go(); exit(1); } + fCardBitmaps.AddItem(bitmap); } // delete the remaining bitmaps from the list @@ -173,15 +184,16 @@ PairsView::_ReadRandomIcons() void PairsView::_SetPairsBoard() { - for (int i = 0; i < 16; i++) { + for (int i = 0; i < fNumOfCards; i++) { fButtonMessage = new BMessage(kMsgCardButton); fButtonMessage->AddInt32("ButtonNum", i); - int x = i % 4 * (kBitmapSize + 10) + 10; - int y = i / 4 * (kBitmapSize + 10) + 10; + int x = i % fWidth * (kBitmapSize + kSpaceSize) + kSpaceSize; + int y = i / fHeight * (kBitmapSize + kSpaceSize) + kSpaceSize; - fDeckCard[i] = new TopButton(x, y, fButtonMessage); - AddChild(fDeckCard[i]); + TopButton* button = new TopButton(x, y, fButtonMessage); + fDeckCard.AddItem(button); + AddChild(button); } } @@ -193,23 +205,27 @@ PairsView::_GenerateCardPos() srand((unsigned)time(0)); - int positions[16]; - for (int i = 0; i < 16; i++) + int* positions = new int[fNumOfCards]; + for (int i = 0; i < fNumOfCards; i++) positions[i] = i; - for (int i = 16; i >= 1; i--) { + for (int i = fNumOfCards; i >= 1; i--) { int index = rand() % i; - fRandPos[16-i] = positions[index]; + fRandPos[fNumOfCards - i] = positions[index]; for (int j = index; j < i - 1; j++) positions[j] = positions[j + 1]; } - for (int i = 0; i < 16; i++) { - fPosX[i] = (fRandPos[i]) % 4 * (kBitmapSize + 10) + 10; - fPosY[i] = (fRandPos[i]) / 4 * (kBitmapSize + 10) + 10; + for (int i = 0; i < fNumOfCards; i++) { + fPosX[i] = (fRandPos[i]) % fWidth * (kBitmapSize + kSpaceSize) + + kSpaceSize; + fPosY[i] = (fRandPos[i]) / fHeight * (kBitmapSize + kSpaceSize) + + kSpaceSize; } + + delete [] positions; } @@ -219,8 +235,10 @@ PairsView::Draw(BRect updateRect) SetDrawingMode(B_OP_ALPHA); // draw rand pair 1 & 2 - for (int i = 0; i < 16; i++) - DrawBitmap(fCard[i % 8], BPoint(fPosX[i], fPosY[i])); + for (int i = 0; i < fNumOfCards; i++) { + BBitmap* bitmap = ((BBitmap*)fCardBitmaps.ItemAt(i % fNumOfCards / 2)); + DrawBitmap(bitmap, BPoint(fPosX[i], fPosY[i])); + } } diff --git a/src/apps/pairs/PairsView.h b/src/apps/pairs/PairsView.h index be9b892950..624ae229e5 100644 --- a/src/apps/pairs/PairsView.h +++ b/src/apps/pairs/PairsView.h @@ -1,8 +1,8 @@ /* - * Copyright 2008 Ralf Schülke, ralf.schuelke@googlemail.com. All rights reserved. - * Distributed under the terms of the MIT License. + * Copyright 2008 Ralf Schülke, ralf.schuelke@googlemail.com. + * Copyright 2010 Adam Smith + * All rights reserved. Distributed under the terms of the MIT License. */ - #ifndef PAIRS_VIEW_H #define PAIRS_VIEW_H @@ -15,6 +15,7 @@ class TopButton; class PairsView : public BView { public: PairsView(BRect frame, const char* name, + int width, int height, uint32 resizingMode); virtual ~PairsView(); @@ -22,7 +23,11 @@ public: virtual void Draw(BRect updateRect); virtual void CreateGameBoard(); - TopButton* fDeckCard[16]; + int fWidth; + int fHeight; + int fNumOfCards; + + BList fDeckCard; int GetIconFromPos(int pos); private: @@ -32,10 +37,10 @@ private: bool _HasBitmap(BList& bitmaps, BBitmap* bitmap); BMessage* fButtonMessage; - BBitmap* fCard[8]; - int fRandPos[16]; - int fPosX[16]; - int fPosY[16]; + BList fCardBitmaps; + int* fRandPos; + int* fPosX; + int* fPosY; }; diff --git a/src/apps/pairs/PairsWindow.cpp b/src/apps/pairs/PairsWindow.cpp index 4601196f4c..d86e1212a6 100644 --- a/src/apps/pairs/PairsWindow.cpp +++ b/src/apps/pairs/PairsWindow.cpp @@ -1,6 +1,7 @@ /* - * Copyright 2008 Ralf Schülke, ralf.schuelke@googlemail.com. All rights reserved. - * Distributed under the terms of the MIT License. + * Copyright 2008 Ralf Schülke, ralf.schuelke@googlemail.com. + * Copyright 2010 Adam Smith + * All rights reserved. Distributed under the terms of the MIT License. */ #include "PairsWindow.h" @@ -12,6 +13,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -21,28 +25,35 @@ #include "PairsView.h" #include "PairsTopButton.h" + // #pragma mark - PairsWindow + + #undef TR_CONTEXT #define TR_CONTEXT "PairsWindow" +const uint32 MENU_NEW = 'MGnw'; +const uint32 MENU_SIZE = 'MGsz'; +const uint32 MENU_QUIT = 'MGqu'; + + PairsWindow::PairsWindow() - : BWindow(BRect(100, 100, 405, 405), "Pairs", B_TITLED_WINDOW, + : + BWindow(BRect(100, 100, 405, 423), "Pairs", B_TITLED_WINDOW, B_ASYNCHRONOUS_CONTROLS | B_QUIT_ON_WINDOW_CLOSE | B_NOT_RESIZABLE | B_NOT_ZOOMABLE), - fPairComparing(NULL), - fIsFirstClick(true), - fIsPairsActive(true), - fPairCard(0), - fPairCardTmp(0), - fButtonTmp(0), - fButton(0), - fButtonClicks(0), - fFinishPairs(0) + fPairComparing(NULL), + fIsFirstClick(true), + fIsPairsActive(true), + fPairCard(0), + fPairCardTmp(0), + fButtonTmp(0), + fButton(0), + fButtonClicks(0), + fFinishPairs(0) { - fPairsView = new PairsView(Bounds().InsetByCopy(0, 0).OffsetToSelf(0, 0), - "PairsView", B_FOLLOW_NONE); - fPairsView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); - AddChild(fPairsView); + _MakeMenuBar(); + _MakeGameView(4, 4); CenterOnScreen(); } @@ -54,10 +65,107 @@ PairsWindow::~PairsWindow() } +void +PairsWindow::_MakeMenuBar() +{ + fMenuBar = new BMenuBar(BRect(0, 0, 0, 0), "menubar"); + AddChild(fMenuBar); + + BMenu* menu = new BMenu(TR("Game")); + fMenuBar->AddItem(menu); + + BMenuItem* menuItem; + menu->AddItem(menuItem = new BMenuItem(TR("New"), + new BMessage(MENU_NEW), 'N')); + + menu->AddSeparatorItem(); + + BMenu* sizeMenu = new BMenu(TR("Size")); + sizeMenu->SetRadioMode(true); + + BMessage* sizeMessage = new BMessage(MENU_SIZE); + sizeMessage->AddInt32("width", 4); + sizeMessage->AddInt32("height", 4); + sizeMenu->AddItem(menuItem = new BMenuItem(TR("Beginner (4x4)"), + sizeMessage)); + menuItem->SetMarked(true); + + sizeMessage = new BMessage(MENU_SIZE); + sizeMessage->AddInt32("width", 6); + sizeMessage->AddInt32("height", 6); + sizeMenu->AddItem(menuItem = new BMenuItem(TR("Intermediate (6x6)"), + sizeMessage)); + + sizeMessage = new BMessage(MENU_SIZE); + sizeMessage->AddInt32("width", 8); + sizeMessage->AddInt32("height", 8); + sizeMenu->AddItem(menuItem = new BMenuItem(TR("Expert (8x8)"), + sizeMessage)); + + menu->AddItem(sizeMenu); + + menu->AddSeparatorItem(); + + menu->AddItem(menuItem = new BMenuItem(TR("Quit"), + new BMessage(MENU_QUIT), 'Q')); +} + + +void +PairsWindow::_MakeGameView(int width, int height) +{ + BRect viewBounds = Bounds(); + viewBounds.top = fMenuBar->Bounds().Height() + 1; + + fPairsView = new PairsView(viewBounds, "PairsView", width, height, + B_FOLLOW_NONE); + fPairsView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + AddChild(fPairsView); +} + + +void +PairsWindow::NewGame() +{ + fButtonClicks = 0; + fFinishPairs = 0; + fPairsView->CreateGameBoard(); +} + + +void +PairsWindow::SetGameSize(int width, int height) +{ + ResizeTo((kBitmapSize + kSpaceSize) * width + kSpaceSize, + (kBitmapSize + kSpaceSize) * height + kSpaceSize + + fMenuBar->Bounds().Height()); + RemoveChild(fPairsView); + delete fPairsView; + _MakeGameView(width, height); + NewGame(); +} + + void PairsWindow::MessageReceived(BMessage* message) { switch (message->what) { + case MENU_NEW: + NewGame(); + break; + case MENU_SIZE: + { + int32 width; + int32 height; + if (message->FindInt32("width", &width) == B_OK + && message->FindInt32("height", &height) == B_OK) { + SetGameSize(width, height); + } + break; + } + case MENU_QUIT: + be_app->PostMessage(B_QUIT_REQUESTED); + break; case kMsgCardButton: if (fIsPairsActive) { fButtonClicks++; @@ -67,16 +175,16 @@ PairsWindow::MessageReceived(BMessage* message) break; // look what Icon is behind a button - for (int h = 0; h < 16; h++) { + for (int h = 0; h < fPairsView->fNumOfCards; h++) { if (fPairsView->GetIconFromPos(h) == num) { - fPairCard = (h % 8); + fPairCard = (h % fPairsView->fNumOfCards / 2); fButton = fPairsView->GetIconFromPos(h); break; } } // gameplay - fPairsView->fDeckCard[fButton]->Hide(); + ((TopButton*)fPairsView->fDeckCard.ItemAt(fButton))->Hide(); if (fIsFirstClick) { fPairCardTmp = fPairCard; @@ -102,20 +210,20 @@ PairsWindow::MessageReceived(BMessage* message) fIsPairsActive = true; - if (fPairCard == fPairCardTmp) { + if (fPairCard == fPairCardTmp) fFinishPairs++; - } else { - fPairsView->fDeckCard[fButton]->Show(); - fPairsView->fDeckCard[fButtonTmp]->Show(); + else { + ((TopButton*)fPairsView->fDeckCard.ItemAt(fButton))->Show(); + ((TopButton*)fPairsView->fDeckCard.ItemAt(fButtonTmp))->Show(); } // game end and results - if (fFinishPairs == 8) { + if (fFinishPairs == fPairsView->fNumOfCards / 2) { BString strAbout; strAbout << "Pairs\n" << "\twritten by Ralf Schülke\n" - << "\tCopyright 2008, Haiku Inc.\n" + << "\tCopyright 2008-2010, Haiku Inc.\n" << "\n" << "You completed the game in " << fButtonClicks << " clicks.\n"; @@ -136,9 +244,7 @@ PairsWindow::MessageReceived(BMessage* message) if (alert->Go() == 0) { // New game - fButtonClicks = 0; - fFinishPairs = 0; - fPairsView->CreateGameBoard(); + NewGame(); } else { // Quit game be_app->PostMessage(B_QUIT_REQUESTED); diff --git a/src/apps/pairs/PairsWindow.h b/src/apps/pairs/PairsWindow.h index 1badc7f250..ed7cb5f7b6 100644 --- a/src/apps/pairs/PairsWindow.h +++ b/src/apps/pairs/PairsWindow.h @@ -1,6 +1,7 @@ /* - * Copyright 2008 Ralf Schülke, ralf.schuelke@googlemail.com. All rights reserved. - * Distributed under the terms of the MIT License. + * Copyright 2008 Ralf Schülke, ralf.schuelke@googlemail.com. + * Copyright 2010 Adam Smith + * All rights reserved. Distributed under the terms of the MIT License. */ #ifndef PAIRS_WINDOW_H @@ -19,15 +20,22 @@ public: virtual void MessageReceived(BMessage* message); + void NewGame(); + void SetGameSize(int width, int height); + private: + void _MakeGameView(int width, int height); + void _MakeMenuBar(); + BView* fBackgroundView; PairsView* fPairsView; + BMenuBar* fMenuBar; BMessageRunner* fPairComparing; bool fIsFirstClick; bool fIsPairsActive; int fPairCard; int fPairCardTmp; - int fButtonTmp; + int fButtonTmp; int fButton; int fButtonClicks; int fFinishPairs;