Welcome to a new month. Its been a while since my last post and with this post, we are on our 8th post. Work has been busy with the school calendar ending, we are focussed on preparing for summer.
No course on Android development would be complete without covering game development. There is an abundance of materials covering this online and I decided that rather than rehash this materials, I would add my voice to the mix.
The above game is called Ise. It is played by my people who are from Edo state in Nigeria. The Ghanaian version is called Oware.
The wikipedia page is somewhat detailed on how to play the game. The key to creating this game is the design of its algorithm.
Game play starts by picking a pot and moving anti clockwise in your seed distribution. The pots on the lower side of the board will belong to one player and the other one to the next player. We will be creating a two player version of this game.
Following the NICE methodology, all that remains is to create our user interface. In my case, I used images I could find online for figures. I named them with the image value for example an image that would display zero would be named 0.jpg because it would allow us map the changes to the pots easier.
To represent the board, I decided to use a list. Lists have already been introduced to you so I thought it would be a nice way to extend your knowledge. Our list would represent the internal state of the board.
A key component of programming is our ability to model the real world in a way that makes the computer understand it. Doing this successfully requires an understanding of how to represent objects in the real world to a computer.
For our board, this representation is made using the list. It is simple and easy enough to represent reality and can be tweaked to work for our purposes.
The algorithm to create the entire game starts with what actions must be carried out when a pot is clicked by the user and it is given below:
- Check if the pot is empty or has seeds inside it
- If the pot has seeds inside it, check the number of seeds it has
- Pick the seeds from the pot the user selected
- Distribute the seeds picked from the pot to its neighbouring pots in ascending order one pot at a time until all the seeds are finished. Cycle back from pots 12 to 1. Drop a seed into each pot.
- If the last seed is placed on a pot with no seed, stop the seed distribution.
- Else if the last seed is placed in a pot with 3 seeds in it, capture the seeds, assign it to the player's score and end the distribution.
- Else pick the seeds from the pot and repeat step 4.
- Assign seeds that reach up to 4 during distribution to the player who owns the pot the belong to and capture them.
The above steps will not be implemented all at once. We will cover steps 1 to 4 in this blog post and the remaining steps in part II.
Since we know the name of our game, our first step would be to create our user interface for our board. The way to go about this is to use the first 2 components which can be found under the Drawing and Animation components of your Palette drawer. These is shown below:
Drag the Canvas component from the Palette drawer and set its Width and Height to fill parent. When creating games in App Inventor, your Canvas component is your drawing surface.
Next drag out 14 ImageSprites and name them in the following order:
The user pots containing 0 would be named for the players scores. The one on your right should be called player1Pot as it will keep track of the score for player 1 while the one on your right should be called player2Pot. The picture properties of the ImageSprite is used to change the image displayed by the ImageSprite components that we are using.
Extra components would include a Notifier component and a Clock. The Notifier component would be used to display a message to the user while our Clock would be used to slow down the distribution process and make it visible to the eye. For our Clock we disable its TimerAlwaysFires and TimerEnabled properties by unchecking them.
The first thing we want to program would be our list the code to do this is shown below:
Once we are done with our list, we need 4 variables to get our program working. Our variables are shown below:
When a pot is clicked, our first task is to get its potID which is also the index of the pot in the list we created. This will help us have a reference for the pot that was clicked by the user. To do this, we will use a procedure which will get the potID of the pot that was clicked by the user and assign it to the currentPot variable that we have created. Create a shell procedure with potID as an input parameter and use it for this purpose. Do this for all 12 of your pots. For my first 3 pots, the code is shown below:
If the seeds held by the selected pot is 0 (meaning that the pot is empty), we notify the user to select another pot. Otherwise, we pick the seed in that pot and distribute our seeds. The code for the setPotID procedure is shown below. Ensure to use skeleton blocks for the procedures or functions not yet covered.
Our seedsHeld function works by returning the value of the element at the index. The difference between functions and procedures is that functions return a value while procedures carry out an action. The code for this function is shown below:
Our pickSeeds procedure works on the model of the board to the computer and its visual representation to the user. This procedure is designed to pick the seeds in the pot selected by the user so that distribution of the seeds can start. To do this, it must replace the value of seeds held by the pot in the list to 0 and change the image displayed for the seeds held by the pot in the list.
The changeImage procedure is used by the pick seeds method to change the image for a pot. It works matching the imageValue to the picture in our media library. We use the trim function to prevent any surprises. The changeImage procedure is shown below:
The distributeSeeds procedure is a simple procedure that activates your Clock component. All it does is set the TimerEnabled property of your Clock component to True so that your clock can start. Since your TimeInterval property is 1000 or 1 second, it means that your clock will fire every second. The code for the procedure is given below:
Once your Clock is activated, it will fire every second and continue seed distribution until the number of seeds held is 0. In a way, our clock acts like a loop but it is a timed loop. Once the seeds held is 0, the Clock will be disabled and the user will be notified the the distribution of seeds has stopped.
As long as the number of seeds held is greater than 0, we will have to get the next pot for us to distribute our seed to. This is important because the limit of our board is 12 and we must ensure that the distribution loops back to 1 once we get to 12. For our next pot, we add a seed to it and then we subtract 1 from the number of seeds held. Finally, we set our nextPot to our currentPot and continue until our seeds held is 0.
Our getNextPot function uses the modulus operator. The modulus operator is an operator that returns the remainder of the division of two numbers. For example 10 modulus 3 returns 1. A modulus of 0 means that the first number is divisible by the second number. We use this in our program to make our pot distribution cycle back from 12 to 1. The code for this is shown below:
The addSeeds procedure gets the number of seeds in our pot and adds 1 to it. For now we are not implementing the capture part but next week, we will complete the program and this procedure will help us implement capture. The code to do this is shown below:
This week we implemented a simple game using App Inventor. The game Ise belongs to the Mancala family of games.
We have created the basic code covering steps 1 to 4 of our algorithm, next week we will conclude this game.
By now, I expect that you would have completed your first Android application. If you haven't you could create an Android program that tests if a number is even or odd.
When we come back next week, we will be concluding this game and rounding up this series. Do have a great weekend.