Overview
Examples
Screenshots
Comparisons
Applications
Download
Documentation
Bazaar
Status & Roadmap
FAQ
Authors & License
Forums
Funding Ultimate++
Search on this site













SourceForge.net Logo

Puzzle

 

Puzzle game

 

      

 

 

 

 

Puzzle.cpp

 

#include "CtrlLib/CtrlLib.h"

 

using namespace Upp;

 

#define LAYOUTFILE <Puzzle/Puzzle.lay>

#include <CtrlCore/lay.h>

 

#define IMAGEFILE  <Puzzle/Puzzle.iml>

#define IMAGECLASS PuzzleImg

#include <Draw/iml.h>

 

#define TFILE <Puzzle/Puzzle.t>

#include <Core/t.h>

 

class Puzzle : public TopWindow {

public:

    virtual void Paint(Draw& w);

    virtual void LeftDown(Point p, dword);

 

private:

    Buffer<int>            box;

    Size                   size;

    Point                  hole;

    int                    moves;

    int                    lang;

    VectorMap<String, int> score;

 

    int& Get(int x, int y)           { return box[size.cx * y + x]; }

 

    bool Move(int x, int y);

    void ShowStatus();

    void Init();

 

    void About();

    void Scores();

    void Setup();

    void New();

 

    void GameMenu(Bar& bar);

    void MainMenu(Bar& bar);

 

    MenuBar   menu;

    StatusBar status;

 

    typedef Puzzle CLASSNAME;

 

public:

    void Xmlize(XmlIO xml);

    void Generate();

 

    Puzzle();

};

 

bool Puzzle::Move(int x, int y)

{

    if(x >= 0 && x < size.cx && y >= 0 && y < size.cy &&

       (y == hole.y && abs(x - hole.x) == 1 || x == hole.x && abs(y - hole.y) == 1)) {

           Swap(Get(x, y), Get(hole.x, hole.y));

        hole = Point(x, y);

        Refresh();

        return true;

    }

    return false;

}

 

void Puzzle::ShowStatus()

{

    String txt = t_("Moves: ");

    txt << moves;

    status = txt;

}

 

void Puzzle::Generate()

{

    int n = size.cx * size.cy;

    box.Alloc(n);

    n--;

    for(int i = 0; i < n; i++)

        box[i] = i + 1;

    box[n] = 0;

    hole = size - 1;

    n = 20 * size.cx * size.cy;

    while(n > 0)

        n -= Move(hole.x + (rand() % 3) - 1, hole.y + (rand() % 3) - 1);

    moves = 0;

    ShowStatus();

    SetRect(GetWorkArea().CenterRect(AddFrameSize(size * 32)));

}

 

void Puzzle::Paint(Draw& w)

{

    w.DrawRect(GetSize(), WhiteGray);

    for(int y = 0; y < size.cy; y++)

        for(int x = 0; x < size.cx; x++) {

            int b = Get(x, y);

            Point p(x * 32, y * 32);

            if(b) {

                w.DrawImage(p.x, p.y, PuzzleImg::BoxImg());

                String txt = AsString(b);

                Size sz = GetTextSize(txt, Arial(20).Bold());

                w.DrawText(p.x + (32 - sz.cx) / 2, p.y + (32 - sz.cy) / 2, txt,

                           Arial(20).Bold(), SLtBlue);

            }

        }

}

 

void Puzzle::LeftDown(Point p, dword)

{

    if(Move(p.x / 32, p.y / 32)) {

        moves++;

        ShowStatus();

        int n = size.cx * size.cy - 1;

        for(int i = 0; i < n; i++)

            if(box[i] != i + 1)

                return;

        String dim;

        int& sm = score.GetAdd(String().Cat() << size.cx << "x" << size.cy);

        if(moves < sm) {

            sm = moves;

            PromptOK(t_("You win with the new best score!"));

        }

        else

            PromptOK(t_("You win!"));

        Generate();

    }

    else

        BeepExclamation();

}

 

void Puzzle::About()

{

    PromptOK("[A5 Puzzle]&Using [*^http://www.ultimatepp.org^ Ultimate`+`+] technology.");

}

 

void Puzzle::Scores()

{

    WithScoreLayout<TopWindow> d;

    CtrlLayoutOK(d, t_("Best scores"));

    d.score.AddColumn(t_("Dimension"));

    d.score.AddColumn(t_("Moves"));

    d.score.ColumnWidths("71 48");

    d.score.NoCursor().NoGrid();

    Vector<int> o = GetSortOrder(score.GetKeys());

    for(int i = 0; i < o.GetCount(); i++)

        d.score.Add(score.GetKey(o[i]), score[o[i]]);

    d.Run();

}

 

void Puzzle::Setup()

{

    WithSetupLayout<TopWindow> d;

    CtrlLayoutOKCancel(d, t_("Puzzle setup"));

    CtrlRetriever r;

    Size sz = size;

    r

        (d.cx, size.cx)

        (d.cy, size.cy)

        (d.lang, lang)

    ;

    if(d.Run() == IDOK) {

        r.Retrieve();

        Init();

        if(sz != size)

            Generate();

    }

}

 

void Puzzle::New()

{

    if(PromptYesNo(t_("Start a new game?")))

        Generate();

}

 

void Puzzle::GameMenu(Bar& bar)

{

    bar.Add(t_("New game"), THISBACK(New));

    bar.Add(t_("Setup.."), THISBACK(Setup));

    bar.Add(t_("Best scores.."), THISBACK(Scores));

    bar.Separator();

    bar.Add(t_("Exit"), Breaker());

}

 

void Puzzle::MainMenu(Bar& bar)

{

    bar.Add(t_("Game"), THISBACK(GameMenu));

    bar.Add(t_("About"), THISBACK(About));

}

 

void Puzzle::Init()

{

    SetLanguage(lang);

    SetDefaultCharset(CHARSET_UTF8);

    menu.Set(THISBACK(MainMenu));

    ShowStatus();

}

 

void Puzzle::Xmlize(XmlIO xml)

{

    XmlizeLangAttr(xml, lang);

    xml("Scores", score)

       ("Dimension", size);

    Init();

}

 

Puzzle::Puzzle()

{

    size = Size(4, 4);

    AddFrame(menu);

    AddFrame(status);

    lang = LNG_ENGLISH;

    Init();

    BackPaint();

}

 

GUI_APP_MAIN

{

    Puzzle p;

    LoadFromXMLFile(p);

    p.Generate();

    p.Run();

    StoreAsXMLFile(p);

}

 

 

 

Puzzle.lay

 

LAYOUT(SetupLayout, 152, 160)

    ITEM(LabelBox, dv___0, SetLabel(t_("Dimension:")).LeftPosZ(8, 136).TopPosZ(4, 60))

    ITEM(Label, dv___1, SetLabel(t_("Height:")).SetAlign(ALIGN_CENTER).LeftPosZ(80, 48).TopPosZ(20, 13))

    ITEM(EditIntSpin, cx, Min(3).Max(15).NotNull(true).SetFrame(ThinInsetFrame()).LeftPosZ(16, 56).TopPosZ(36, 19))

    ITEM(Label, dv___3, SetLabel(t_("Width:")).SetAlign(ALIGN_CENTER).LeftPosZ(16, 48).TopPosZ(20, 13))

    ITEM(EditIntSpin, cy, Min(3).Max(15).NotNull(true).SetFrame(ThinInsetFrame()).LeftPosZ(80, 56).TopPosZ(36, 19))

    ITEM(LabelBox, dv___5, SetLabel(t_("Language:")).LeftPosZ(8, 136).TopPosZ(72, 52))

    ITEM(LNGCtrl, lang, LeftPosZ(32, 88).TopPosZ(92, 20))

    ITEM(Button, ok, SetLabel(t_("OK")).HSizePosZ(80, 8).TopPosZ(132, 20))

    ITEM(Button, cancel, SetLabel(t_("Cancel")).HSizePosZ(8, 80).TopPosZ(132, 20))

END_LAYOUT

 

LAYOUT(ScoreLayout, 156, 260)

    ITEM(ArrayCtrl, score, LeftPosZ(8, 140).TopPosZ(44, 180))

    ITEM(Button, ok, SetLabel(t_("OK")).LeftPosZ(84, 64).TopPosZ(232, 20))

    ITEM(Label, dv___2, SetLabel(t_("Best scores")).SetAlign(ALIGN_CENTER).SetFont(Arial(20)).SetInk(Blue).LeftPosZ(8, 140).TopPosZ(8, 32))

END_LAYOUT

 

 

 

 

Do you want to contribute?