Programming: Arduino

Check out my other articles:


Farkle

Farkle is a simple dice game that pits players against each other and themselves. I already have a version of this game on the Apple Store but I wanted to convert it to the run on the Arduino. To test the capabilities of the platform and the SmatGPU2, I tried to maintain all of the original features of the iPhone version.


Overview

The instructions of the game are detailed in the following screen shots which have been lifted straight from my iPhone version.



Game Play

My version of Farkle allows up to four players to compete against each other. After an initial splash screen is shown, the number of players can be selected by pressing the plus and minus buttons at the bottom of the screen. Adding an additional player highlights there face allowing you to customise their image and name.

Clicking on the players face reveals a selection of male and female faces to choose from. The graphics have been supplied with permission by www.deleket.com, thanks again! Finally, users can click on the player's name and type in their own name using a variation of the keyboard code supplied by Vizic Technologies the makers of the SmartGPU2 display.

Δ Top

Players take turns throwing the dice and accumulating their score but risk losing 500 points if they throw a Farkle (a non-point scoring hand). Dice are selected from the current throw in the upper section of the screen with those selected grey out to indicate this. Users can roll again or take the score if they have achieved a score of 300 or more and pass play to the next player. As play moves from one player to the next, a history of the player's previous rolls are shown at the bottom of the screen.

Throwing a Farkle is a costly mistake and results in a loss of 500 points. The next player in a multi-player game is displayed in the lower corner of the screen. After ten rounds, an awards screen shows the final scores for each player.

Δ Top


Code Fragments

The following code highlights areas of interest in the application. It is not intended to be a tutorial or a complete solution. I have provided the complete code for download and you may use or modify it as required.

Inner Classes

Inner classes are supported in C, C++ and pretty much every other object-oriented language. I originally thought that the Arduino could handle inner classes but developing Farkle taught me that although it is possible to declare and use inner classes, they do not behave exactly as I would have liked.

The inner class below describes a single player with properties such as their display name, image name and current scores. To save code and memory, the properties are declared public rather than wrapping them within getters and setters. A series of arrays store the history of the user's last ten rolls and these are maintained using a method called addThrowHistory which accepts the details of the current roll and 'pushes' them onto FIFO stack.

A second method, reset clears the stack and all other variables and is used at the start of each game.

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
class Player {
 
  public:

  boolean enabled; 
  char* playerName;
  char* imageName;
  char playerNameLength;
  int runningScore;
  int grandScore;
  int throwNumber;
  int playerNumber;
  
  char die1[10]; 
  char die2[10]; 
  char die3[10]; 
  char die4[10];
  char die5[10];
  char die6[10];
  char throwNo[10];
  int thisScore[10];
  int totalScore[10];
  boolean divider[10];

  void addThrowHistory(int throwNoValue, int dValue1, int dValue2, 
                       int dValue3, int dValue4, int dValue5, int dValue6, 
                       int thisScoreValue, int totalScoreValue, 
                       boolean dividerValue) {
    
    for (int x = 8; x >= 0; x--) {
      
      die1[x + 1] = die1[x];
      die2[x + 1] = die2[x];
      die3[x + 1] = die3[x];
      die4[x + 1] = die4[x];
      die5[x + 1] = die5[x];
      die6[x + 1] = die6[x];
      throwNo[x + 1] = throwNo[x];
      thisScore[x + 1] = thisScore[x];
      totalScore[x + 1] = totalScore[x];
      divider[x + 1] = divider[x];
  
    }

    die1[0] = dValue1;
    die2[0] = dValue2;
    die3[0] = dValue3;
    die4[0] = dValue4;
    die5[0] = dValue5;
    die6[0] = dValue6;
    throwNo[0] = throwNoValue;
    thisScore[0] = thisScoreValue;
    totalScore[0] = totalScoreValue;
    divider[0] = dividerValue;

  }
  
  void reset(int playerNo) {
    
    runningScore = 0;
    grandScore = 0;
    throwNumber = 1;
    playerNumber = playerNo;

    for (int i=0; i<=10; i++) {
      
      die1[i] = 0;
      die2[i] = 0;
      die3[i] = 0;
      die4[i] = 0;
      die5[i] = 0;
      die6[i] = 0;
      throwNo[i] = 0;
      thisScore[i] = 0;
      totalScore[i] = 0;
      divider[i] = false;
      
    }
    
  }

};

Wrapping the logic of a player in a single class allows it to be passed to functions as a parameter, right? Wrong. This is the first thing I discovered about inner classes in Arduino - the compiler is simply not smart enough to compile the following piece of code ..

001
002
003
void someFunction(Player *thePlayer) {
  
}

The compiler spits out the following errors:

001
002
003
farkle:126: error: variable or field 'someFunction' declared void
farkle:126: error: 'Player' was not declared in this scope
farkle:126: error: 'thePlayer' was not declared in this scope

A search of the forums reveals the following post http://forum.arduino.cc/index.php/topic,41848.0.html which seems to describe the problem.

The Arduino IDE automatically generates prototypes for your functions. Unfortunately, this doesn't work for functions whose arguments or return value are types defined in the sketch, since the prototypes get inserted above the type definitions. I'm not sure there's really a good workaround for this.

I finally gave up and simply declared four instances of my class for the four possible players and a 'spare' reference (lines 001 - 005) that I assign to the current player (line 020 in the Setup routine starts the game with referencing the first player. All of the functions in the program refer to the global variable player.

A function called setNetUser() is called at the end of a player's turn to determine who the next player is based on the number of players in the game. For example, if the current player is the second player (line 040) and there are more than two players in the game (line 041) then the current player reference is updated to the third player (line 042). If there were only two players in the game, then the current player reference is updated to the first player (lines 044 - 046).

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
Player *player1;
Player *player2;
Player *player3;
Player *player4;
Player *player;

...

void setup() { 

   ...
  
  player1 = new Player(); 
  player2 = new Player(); 
  player3 = new Player(); 
  player4 = new Player(); 

  ...
  
  player = player1;
  
}

...

void setNextUser() {
    
    switch (player->playerNumber) {
            
        case 1:
            if (numberOfPlayers > 1) {
                player = player2;
            }
            else {
                player = player1;
            }
            break;

            
        case 2:
            if (numberOfPlayers > 2) {
                player = player3;
            }
            else {
                player = player1;
            }
            break;
            
        case 3:
            if (numberOfPlayers > 3) {
                player = player4;
            }
            else {
                player = player1;
            }
            break;
            
        case 4:
            player = player1;
            break;
            
    }
    
}
Δ Top

Wiring Diagram

The diagram below show the wiring diagram when using a standard Arduino Uno (or compatible) and the SmartGPU2. Click on the images to see a detailed drawing.


Δ Top

Downloads

Feel free to download, modify and adapt this code to your needs. Please credit me if you use some or all of this code in your own project. If you alter the code to fix bugs or add functionality, please submit them back to me and I will add them to the download.

   Arduino Source Code
Δ Top

Comments?

 Anything to say?
Name :
Email :
Comments :
Confirmation: