×

Warning

JUser: :_load: Unable to load user with ID: 1175

Rock, Paper, Scissors - Full Tutorial

Who doesn't like a good old fashion game of Rock, Paper, Scissors? So here's an example app of it...  This tutorial is broken up into 3 parts:
Part 1 will focus on how to create the logic aspects (QML/JavaScript and C++).
Part 2 will create a user friendly user interface (UI) to liven up the app with graphics (QML).
Part 3 will combine the logic and UI, as well as add some additional features such animations and a help page.

Before getting into the explanations the full source code this app has been posted to github: https://github.com/bcs925/BrianScheirerOpenSource/tree/master/RockPaperScissors

And the app can be downloaded from App World (only available on BB10, Dev Alpha):  http://appworld.blackberry.com/webstore/content/135020/?model=Dev%20Alpha&lang=en

I like to do the logic first because I figure if you can't get the functionality working why bother making a pretty UI?  So without further ado... Let's get started!

Part 1: The Logic

Since this example uses both QML/JavaScript and C++ for the logic it is necessary to have some amount of UI.  As well as creating a barebones UI allows you to test that everything is working as it should. One thing to especially notice is that I chose identifiers for the id of each item to be representative of what the item is or does.  This will be especially true once the final UI is made in Part 2 and things won't be this close together in the code.

First part of the test UI will be 3 buttons: Rock, Paper, and Scissors.  These will act as the 3 signals that control the game.

        Container {
            Button {
                id: rockbutton
                objectName: "rockbutton"
                text: "ROCK!"
                onClicked: {
                }
            }
            Button {
                id: paperbutton
                objectName: "paperbutton"
                text: "PAPER!"
                onClicked: {
                }
            }
            Button {
                id: scissorsbutton
                objectName: "scissorsbutton"
                text: "SCISSORS!"
                onClicked: {
                }
            }
        }

Next is a Label that states what option the computer decided to pick:

            Label {
                id: computerpick
                text: "BlackBerry picks: ..."
            }

After that is the winner:

            Label {
                id: winnerlabel
                text: "Winner"
            }

Finally, there is a container that holds labels for your win/loss/tie record:

        Container {
            layout: StackLayout {
                layoutDirection: LayoutDirection.LeftToRight
            }
            Label {
                text: "Record: "
            }
            Label {
                id: win
                text: "0"
            }
            Label {
                text: "-"
            }
            Label {
                id: lose
                text: "0"
            }
            Label {
                text: "-"
            }
            Label {
                id: tie
                text: "0"
            }
        }

Now it is time to create the logic within the buttons and C++ functions.  The way it made sense for me to do it was to let QML/JavaScript handle the setup for each choice then pass those choices to C++ for it to return the winner.  So for instance for the "rockbutton" onClicked signal it generates a "var = number" of 1-3 for the computer's choice and takes "1" as the user's choice for Rock. (For Scissors it is "2" and for Paper it is "3" for the user's choice.)  Then passes those two numbers into clickedRock() C++ function to find out the winner.  I am not going to go through each line individually but as you see below in the full code it is just a bunch of if/else statements for deciding who wins/loses/ties based off the rules of Rock, Paper, Scissors. 

Lastly, for the win/loss/tie record keeping, this is accomplished by looking at the outcome of the game and the previous total for either win/loss/tie. Based on the outcome the codeWinning() C++ function adds 1 to the appropriate value.

And that's it for logic.  See below for full code of main.qml, app.cpp, and app.hpp.  Since I didn't go too in depth, feel free to ask questions in the comments field about any aspect of the logic.

main.qml

import bb.cascades 1.0

Page {
    content: Container {
        Container {
            Button {
                id: rockbutton
                objectName: "rockbutton"
                text: "ROCK!"
                onClicked: {
                    var winning = win.text;
                    var losing = lose.text;
                    var ties = tie.text;
                    var number = Math.floor((Math.random() * 3) + 1);
                    var gameoutcome = app.clickedRock(1, number);
                    if (number == 1) {
                        computerpick.text = "BlackBerry picks: Rock";
                    } else if (number == 2) {
                        computerpick.text = "BlackBerry picks: Paper";
                    } else {
                        computerpick.text = "BlackBerry picks: Scissors";
                    }
                    if (gameoutcome == 1) {
                        winnerlabel.text = "You WIN!";
                    } else if (gameoutcome == 2) {
                        winnerlabel.text = "BlackBerry WINS!";
                    } else {
                        winnerlabel.text = "Draw";
                    }
                    if (gameoutcome == 1) {
                        win.text = app.codeWinning(winning);
                    } else if (gameoutcome == 2) {
                        lose.text = app.codeWinning(losing);
                    } else {
                        tie.text = app.codeWinning(ties);
                    }
                }
            }
            Button {
                id: paperbutton
                objectName: "paperbutton"
                text: "PAPER!"
                onClicked: {
                    var winning = win.text;
                    var losing = lose.text;
                    var ties = tie.text;
                    var number = Math.floor((Math.random() * 3) + 1);
                    var gameoutcome = app.clickedPaper(2, number);
                    if (number == 1) {
                        computerpick.text = "BlackBerry picks: Rock";
                    } else if (number == 2) {
                        computerpick.text = "BlackBerry picks: Paper";
                    } else {
                        computerpick.text = "BlackBerry picks: Scissors";
                    }
                    if (gameoutcome == 1) {
                        winnerlabel.text = "You WIN!";
                    } else if (gameoutcome == 2) {
                        winnerlabel.text = "BlackBerry WINS!";
                    } else {
                        winnerlabel.text = "Draw";
                    }
                    if (gameoutcome == 1) {
                        win.text = app.codeWinning(winning);
                    } else if (gameoutcome == 2) {
                        lose.text = app.codeWinning(losing);
                    } else {
                        tie.text = app.codeWinning(ties);
                    }
                }
            }
            Button {
                id: scissorsbutton
                objectName: "scissorsbutton"
                text: "SCISSORS!"
                onClicked: {
                    var winning = win.text;
                    var losing = lose.text;
                    var ties = tie.text;
                    var number = Math.floor((Math.random() * 3) + 1);
                    var gameoutcome = app.clickedScissors(3, number);
                    if (number == 1) {
                        computerpick.text = "BlackBerry picks: Rock";
                    } else if (number == 2) {
                        computerpick.text = "BlackBerry picks: Paper";
                    } else {
                        computerpick.text = "BlackBerry picks: Scissors";
                    }
                    if (gameoutcome == 1) {
                        winnerlabel.text = "You WIN!";
                    } else if (gameoutcome == 2) {
                        winnerlabel.text = "BlackBerry WINS!";
                    } else {
                        winnerlabel.text = "Draw";
                    }
                    if (gameoutcome == 1) {
                        win.text = app.codeWinning(winning);
                    } else if (gameoutcome == 2) {
                        lose.text = app.codeWinning(losing);
                    } else {
                        tie.text = app.codeWinning(ties);
                    }
                }
            }
        }
        Container {
            topMargin: 50.0
            Label {
                id: computerpick
                text: "BlackBerry picks: ..."
            }
            Label {
                id: winnerlabel
                text: "Winner"
            }
        }
        Container {
            layout: StackLayout {
                layoutDirection: LayoutDirection.LeftToRight
            }
            Label {
                text: "Record: "
            }
            Label {
                id: win
                text: "0"
            }
            Label {
                text: "-"
            }
            Label {
                id: lose
                text: "0"
            }
            Label {
                text: "-"
            }
            Label {
                id: tie
                text: "0"
            }
        }
    }
}

app.cpp

#include "app.hpp"

#include <bb/cascades/Application>
#include <bb/cascades/QmlDocument>
#include <bb/cascades/AbstractPane>

using namespace bb::cascades;

App::App()
{
    QmlDocument *qml = QmlDocument::create("main.qml");
    qml->setContextProperty("app", this);
    
    AbstractPane *root = qml->createRootNode<AbstractPane>();
    Application::setScene(root);
}

int App::clickedRock(int user1, int user2)
{
    int winner;

    if((user1 == 1) && (user2 == 2))
    winner=2;
    else if ((user1 == 1) && (user2 == 3))
    winner=1;
    else if ((user1 == 1) && (user2 == 1))
    winner=0;

    return (winner);

}

int App::clickedPaper(int user1, int user2)
{
    int winner;

    if((user1 == 2) && (user2 == 2))
    winner=0;
    else if ((user1 == 2) && (user2 == 3))
    winner=2;
    else if ((user1 == 2) && (user2 == 1))
    winner=1;

    return (winner);

}

int App::clickedScissors(int user1, int user2)
{
    int winner;

    if((user1 == 3) && (user2 == 2))
    winner=1;
    else if ((user1 == 3) && (user2 == 3))
    winner=0;
    else if ((user1 == 3) && (user2 == 1))
    winner=2;

    return (winner);

}

int App::codeWinning(int record)
{
    int add1;
    add1 = record+1;
    return add1;
}

app.hpp

#ifndef APP_H
#define APP_H

#include <QObject>


class App : public QObject
{
    Q_OBJECT

public:
    App();

Q_INVOKABLE int clickedRock(int user1, int user2);
Q_INVOKABLE int clickedPaper(int user1, int user2);
Q_INVOKABLE int clickedScissors(int user1, int user2);
Q_INVOKABLE int codeWinning(int record);


};

#endif // ifndef APP_H

Leave your comments

Post comment as a guest

0

People in this conversation

  • Guest (Mark)

    You have posted a very informative tutorial which i like reading. I must say it has provided me with quality information which i did not know before. I will share this post with my friends.
    cafe racer jeans

    Like 0 Short URL:
Subscribe to the official OSBB BBM Channel!

osbbchannelQR

C00013E89

Back to top