(P) Yatzy¶
Goal: I will learn to design and implement a graphical user interface with Qt. I will learn to use Qt documentation. I will practice modularity and especially how to separate user interface from the action logic of the program.
Instructions:
Code for a working path game is given in templates/12/yatzy/
.
The program has no graphical user interface, but it works with ASCII prints,
which enables you to test playing the game.
Your task is to implement a graphical user interface on the existing game.
Create a new project: student/12/yatzy_gui/
(note the
name different from the template code).
Add the class GameEngine
in the Qt project, and copy
code to it from the corresponding class in the template code
(in the same way as in total grade exercise (11.6.2)).
Similarly, add also the module Functions
.
Besides the actual code files, templates
folder provides you
the following files:
1.png
,2.png
,3.png
,4.png
,5.png
,6.png
, andempty.png
diceresource.qrc
qrc_diceresource.cpp
.
These files enable you to put the following kind of figures into your program:
From the subsection Using dice figures in a correct way, you can look at how to add figures into a Qt project. However, it is not mandatory to use these figures, but you can print the corresponding number in the place of each dice figure.
Using template code is mandatory (except for the aforementioned figures). Note especially that you shall not implement again things given in the template code, but use existing operations and data.
Important
Before starting to write code, read carefully the whole assignment, especially the point Special requirements. Remember also to use version control with a sufficient number of commits.
Recall the section 12.1 Introduction. Based on it you can decide what are the most important examples of this round when you are selecting the properties you are going to implement in the project.
Note
This project will be done independently. Working in pairs is not allowed, but it will be considered as plagiarism.
The task is to implement a graphical user interface for the given yatzy game. You can find rules for the game from the subsection Game rules below, and they have also been coded in the given template code (so you need not know the rules in detail).
In this assignment, you will write a document describing those features you have implemented, the structure of your program, and design decisions.
The section Minimal requirements tells which features there at least must be in your implementation.
Header comment and feedback language¶
In the same way as earlier, the header comment is again required. You can use the first project’s assignment as an example (see 4.5 (P) Checkers). It is sufficient to add header comments in the files you modify.
As in the previous projects, the feedback language will be chosen in the submission box (at the very end of this page). We will only use the language you have given in the submission box of the final submission.
Game rules¶
Game rules are described here such that they will be implemented in this project (or have been implemented in the template code). They can differ from the real yatzy game.
Yatzy game has five dices that are thrown by the players in desired order. At start, each player has three turns to roll up dices, but it is not mandatory to use them all. Moreover, it is not required to use the turns alternately, but a player can, for example, take all their turns one after the other (without giving turn to other players between one’s rolls).
A player can lock part of the dices such that only unlocked dices will be rolled in the next roll.
After all turns of all players have been used or after dropping out the game, the program tells who was the winner or between which players the result is tie.
The series of five dices have the following rank order (from the best one to the worst one):
- yatzy, i.e. all five dices have the same face
- four of a kind, i.e. exactly four dices have the same face
- full house, i.e. exactly three dices have the same face and also the rest two dices have the same face
- straigth, i.e. either the faces 1, 2, 3, 4, and 5, or the faces 2, 3, 4, 5, and 6
- three of a kind, i.e. exactly three dices have the same face
- two pairs, i.e. exactly two dices have the same face and also exactly two other dices have the same face
- pair, i.e. exactly two dices have the same face
- nothing of above.
There is no rank order inside the above classes. For example, the pair of 1’s is as good as the pair of 6’s.
You need not care about the above rank order, since it is implemented in
the functions of the module Functions
.
Assignment¶
Your task is to implement a graphical user interface in the yatzy game, the action logic of which is given in the template code. You shall now implement the user interface functionality graphically, i.e.:
- displaying the faces of the rolled dices
- possibility to roll again or to give turn to the next player
- displaying the game status (e.g. which player is in turn and how many rolls they have used or how many rolls there are left).
Besides the functionalities listed above, the game must include:
- possibility to lock dices
- possibility to start the game again (reset)
- timer telling the time used so far.
You can implement the user interface (game window) in a way you like.
(Game window means the main window, i.e. one window is enough.)
Dices can be implemented e.g. as labels (QLabel
) or push
buttons (QPushButton
), or you can use QGraphicsScene
.
The template code provides you dice pictures (as png files). You can use them in the way similar to that done in the fruit example.
Note
When implementing graphical user interface, do not reimplement those things that can be found from the template code.
An exception on this is the roll
method.
You can implement a new roll
method in MainWindow
class,
even if there is already one in GameEngine
class.
In evaluating the project, a special attention will be paid to how well
you have separated user interface code from the action logic of the game.
The action logic is (mainly) already implemented in the template code, and thus,
it is principally enough to write all user interface code in the
MainWindow
class.
However, most probably you will need more functions in other classes, too.
If the functions you add are not related to user interface at all,
you should place them in the GameEngine
class.
Note that the code should be as close as possible to the data it deals
with.
When following this principle, it is easily possible that an implementation
of a property requires a new method in both of the aforementioned classes.
If necessary, you can move methods in the GameEngine
class from the
private part to the public one, or you can modify a void
method to return a value of a suitable type.
You can also add new methods and attributes or any other variables.
Anyway, take care that the non-graphical game still works in the same
way as earlier.
However, graphical game is not required to work exactly in the same way as the non-graphical one. This would not even be possible, since the non-graphical version does not have a locking feature but the graphical one has such.
Important
Take especially care about that the ready-made code should know nothing about the user interface. Instead, the user interface code must (of course) know the given code, i.e. the action logic of the game.
Minimal requirements¶
By implementing the minimum functionality of the project, you can earn 50 points at maximum. At least, you must implement the following features:
- To play the game, the game window and faces of the rolled dices are
shown for the user.
- These elements must be graphical user interface components (e.g. push buttons/rectangles/squares/labels), not just text.
- It is enough to show the faces of the dices as numbers. Using the dice figures given in the template code is not required (but using them gives you extra points, see Extra features).
- It must be possible to change the number of player, but it is enough to do this by changing the value of a constant in the program code. Remember to mention in the document, what is the name of this constant and where it can be found.
- It must be possible to select a new roll or to give turn for the next player.
- This can be done e.g. with clicking a button, or with a key command, or such.
- It must be possible to lock dices.
- The game status must be shown for the user (which player is in turn, how many rolls they have done or how many rolls they have left).
- It is possible to start the game again (reset). This must be possible after the game is over, as well as in the middle of the game.
- The game tells the time used and the winner or the players, between which the result was tie.
- You must document the functionality of the game. The document must include instructions to play the game, for example, which dependences the actions have. It must tell what happens and what can happen in different situations. The document must also describe the program structure and the design decisions you have made.
You must implement the points above in such a way that they work. The better your implementation is and the better programming style you have followed, the more points you will get.
To get more points, pay attention also to the user-friendliness of the game.
You can, for example, control the push buttons or other widgets to make
them either enabled or disabled.
For this purpose, the class QWidget
has the slots setEnabled
and setDisabled
.
It is especially important to pay attention to the robustness of the game. This means that the program works in a sensible way (and do not, for example, crash), even if the user does something stupid. For example, in the case of push buttons, you can disable those ones that cannot be used in a sensible way at the moment. In any case, try to think beforehand, which kind of use cases there can be. Test your program by imaging that you are an evil enemy, whose purpose is to make the program crash. If you succeed in this, fix your code to prevent such situations.
In general, we will pay attention to the naming convention used in your code.
However, the names generated by Qt do not always follow a good programming
style.
For example, if you automatically generate a slot, the name can be
as on_pushButton_clicked
.
This can be considered as a bad style, since it uses both underscores and
CamelCase style in dividing the name into parts.
However, you should keep the names given by yourself consistent in their style.
Extra features¶
As told earlier, by implementing the minimum functionality of the game, you can earn 50 points at maximum. By implementing extra features for the game, you can earn another 50 points at maximum. You can get points only from working and documented extra features, i.e. also the extra features must be documented.
Assistants will add bonus points into the later section in Plussa while reviewing the projects. Besides the functionality of extra features, assistants take into account how clean your solution is.
Examples of extra features are listed below (approximate maximum points given in parenthesis):
- Dices have been implemented with the png figures given in the template code.
(10 p.)
- Here you can look at the fruits example.
- Be careful in taking figures in a correct way, since otherwise you will get no points from this feature. It is not enough to make the figures to work locally in your own computer, but they must work also in assistant’s computer. You can ensure this by following the instructions given in the next subsection Using dice figures in a correct way.
- Drawn dices not just appear, but their rolling has been animated.
(20 p.)
- You can implement this feature by using a timer, e.g. such that the dices are drawn, say ten times (and the last one remains valid). Now the method drawing dice pictures (again after several draws) is called ten times. With the timer you can slow down these method calls, to make it possible to notice dice changes (rolls). (This is a different timer from that mentioned in minimal requirements.)
- The user can set the number of players in the user interface. (5 p.)
- It is possible to give names for the players. (5 p.)
- The players can collect points in a way you can invent by yourself. Remember to document your rules. (15 p.)
- The game includes a score board for storing the results (points) the players have earned. The stored data is preserved between games (i.e. the data is stored into a file). (10 p.)
- The background color of the user interface changes, when the game is over. Resetting the game sets the original color. (5 p.)
- The game has a pause button, from which the user can pause the timer. This is possible only when the game is on. Pause has e.g. the effect that the game does not response to key commands any more. The game informs about the pause for the user. (10 p.)
In addition you can suggest an additional feature of your own. The suggestions must be made at least a week before the deadline. Suggestions can be made after the exercise classes or by sending e-mail to the course’s e-mail address. The course staff has the right to accept/reject the suggestions, and define the maximum points for the feature.
Note that by successfully implementing all the features listed above, you seem to get more than 50 points. However, the maximum amount of points is 50, so if you get more of them, they are decreased to 50. It is still worth trying to implement as much extra features as you can, since you might not get the maximum points from each implemented feature. (Note that the evaluation criteria of the projects at the end of the course is stricter than at the beginning.)
Using dice figures in a correct way¶
To use dice figures in a correct way (i.e. to get points from the corresponding extra feature), follow the steps below:
- Click the name of the project (
yatzy_gui
) with the right mouse button. From the opening menu, select Add New … -> Qt -> Qt Resource File. - Add Prefix (give a name e.g. pictures)
- Press Add Files.
Instructions as figures:
Testing your program and user instructions¶
In this project, you are the main responsible person for testing the program with sufficient coverage. However, you must still submit your work in Plussa to get it evaluated. Note that the program must work on Linux desktop.
From a Plussa submission, it will be checked if the program can be compiled. In such case, it earns one point. A submission with zero points will not end up to assistant’s evaluation.
Create the file instructions.txt
and write in it short
instructions on how to use the program, what are the rules of your game,
and which functionalities you have implemented.
The instructions must be clear and exact enough to enable the assistant
to test and evaluate your program.
Check from the minimal requirements all the points, the document must contain.
Remember to push also this file in version control.
If you use version control from command line, you can push the document
file as any other file.
If you use version control from Qt, you can add the document file into
Qt project as follows.
On the left from the edit window of Qt, you can a list of the files
included in the project.
On top of this list, you can see the project name.
Click it with the right button of the mouse and from the opening menu,
select Add Existing Files ...
(if the file instructions.txt
already exists) or Add New ...
(if you are about to begin to write
the file).
If you have implemented an additional feature, but you have not documented
it in the file instructions.txt
, you will not get points
from the additional feature.
Valgrind + External errors
The Qt program code may cause valgrind errors, which you have no influence on. Valgrind reports these errors in the category External errors. They are counted in the total amount of errors, but by default the error messages are not visible in the valgrind report.
You don’t need care about such external erros, but of course you need to fix all other errors.
General tips¶
To be able to roll only unlocked dices, you can implement a new
roll
method inMainWindow
class, even if there is already one inGameEngine
class.It is recommended to study the examples of the current round. In their code, you can find points that are useful in implementing the project.
When you add new widgets in the file
mainwindow.ui
, their relative position to widgets created in the code, might not be correct. Try to set the widgets such that final user interface is visually as good as possible.Although you add widgets in Qt Designer (
mainwindow.ui
), adjust their properties in code. The adjustments done in Qt Designer will not necessarily shown correctly in the running program.Implementing the game will most probably require you to read Qt documentation. There you can find useful functions for implementing different features.
You can exploit version control also in your experiments. After pushing the latest working version in Git, you can do even large modifications safely, since you know that you can return to the earlier version if needed. You can do as follows (for each modified file):
- In Qt: Tools -> Git -> Current File -> Undo Unstaged Changes/Undo Uncommitted Changes
- In command line: git checkout – <filename>
See Git course on Plussa for more details.
Special requirements¶
If you want your assignment to pass the evaluation, you must meet these requirements:
- The program must not have errors related to memory management.
Therefore executing valgrind is recommended.
- If you allocate memory with
new
, you must deallocate it withdelete
, unless deallocation happens via the parent-child mechanism (see round 11 at About widgets).
- If you allocate memory with
- The given code template must be used, i.e. the program must be based on it.
- Containers only from STL library are allowed, not e.g. from Boost.
Evaluation¶
To end up to assistants’ evaluation, you must submit your work in Plussa, and it must pass the automated tests. (In this case, automated tests check only, if the program can be compiled.) If the automated tests give 0 points for your work, also your final points will be 0, and your work will not be evaluated by an assistant.
The assistant evaluates the latest Plussa submission that has passed the automated testing (= 1 p) and fulfilled the special requirements of the assignment before the deadline, according to the following criteria:
- The functionality and user instructions of the program: 0-10 points
- All the features mentioned in the list of minimal requirements have been implemented, and they are working.
- The program does not crash.
- The instructions inform how to use the game, and which additional features have been implemented. The instructions have been written clearly enough to enable assistants to understand them easily.
- The game works as said in the instructions.
- The overall principle of the solution: 0-30 points:
- The learning goals of the exercise have been achieved.
- The program code has been split into logical, suitably long segments using functions, classes, and/or methods.
- If the program uses classes and objects, these have been implemented according to the basics of object-oriented programming (see from round 4 the section About programming style at Object-oriented programming). User interface is separated from the action logic of the game.
- The data structure does not include repetitive data nor unnecessary parts. The chosen data structures have been used in a reasonable way.
- The program code does not include unnecessary repetitions nor other unnecessary parts.
- The program code does not include unnecessary limitations or assumptions or other forced solutions.
- The implementations of the program’s structures are easy to understand.
- Global variables have not been used in the program code (global constants are OK).
- The program does not terminate with the
exit
function. - The program has no errors related to memory management (use valgrind).
- Programming style: -20-0 points:
- Variables and functions are named clearly and appropriately. These items have named by using only one language, not e.g. Finnish and English mixed.
- The program uses named constants instead of magic numbers.
- The program code is neatly formatted.
- Each program line has at most 80 characters.
- At the beginning of each file written/edited by yourself, there is a comment explaining the purpose of the file, your name and student number and other necessary information. (see the assignment of the first project).
- At the beginning of each function/method (in the header file if such exists), there is a comment describing its working, return value, and parameters.
- There are comments in the code where necessary.
- Comments are related to the current version of the program, not to an older one.
- All comments have written in the same language (fi/en), but comments can be written in a language different from that used in naming variables and such.
- All the variables have been initialized.
- The compiler does not give warnings while compiling.
- Using the version control: 0-10 points:
- There are enough commits.
- The content of commit messages is clear and relevant.
From the above list, please note that in this phase of the course it is assumed that the student follows good programming style. Therefore, you will not get points from following the style guidelines, but if you do not follow them, your points will be decreased. So, it is recommended to revisit the material about programming style on rounds 4 and 10.
Final note
After the final submission, check from the web user interface of GitLab that the submission is really in your central repository. Assistants will evaluate the version of your program that corresponds to the latest Plussa submission made before the deadline.
If you get one point from your Plussa submission, your program will be evaluated by an assistant. The assistant gives 0-50 points to your submission after completing their evaluation. The maximum amount of points is 50 (it is not possible to get 51 points).
Bonus points will be added in the later section on this round.
A+ presents the exercise submission form here.