William So

unread,
Apr 14, 2019, 6:07:28 AM4/14/19
to mitappinv...@googlegroups.com
Minesweeper
Or if you prefer, download the attached file.

Start
It started as a small project.
Originally, I was going to just make a simple, plain old Minesweeper.

Internal State Data Structure
First things first, I had to think of a way to represent the state of the game.
I decided to use a list of lists of numbers to represent the grid.
It works like this:
  • Assign states to numbers which are 2^n, where n can be any positive number (0-30 due to integer limit)
    as long as no state has the same number.
  • To assign a state to a cell, you do 
    bitwise_or(cell, state)
  • To toggle (turn off if on, turn on if off) a state in a cell, you do
    bitwise_xor(cell, state)
  • To see if a cell has a specific state, you do
    return bitwise_and(cell, state) != 0
  • To remove a state from a cell, you do
    if(bitwise_and(cell, state) != 0) then return bitwise_xor(cell, state) else return cell
By doing so, the number that represents the cell can have any combinations of the states you created. (this is guaranteed by Maths)
Now, since a cell represented like so can have multiple states, this is perfect for the game.

Dynamically Created Buttons
I wanted to allow people to customize the size of the grid.
As you know, you cannot create buttons in runtime, so after some thinking,
I realized that I have to use a canvas.
Of course, manually creating buttons is going to take a whole lot of blocks to do...
After creating countless procedures and 10 days working, it's finished.
By now, the game works like a charm.

I wish you can create buttons dynamically in AI2.

Theme
The game is supposed to be completed, but when I tested it on an emulator, the labels cannot be seen.
It is dark-themed, so it requires the change of color of the background of the screen to black.
However, in the emulator (very old version, I think it's API 6 or 7), you can't change it,
so the labels and the background are both white.
That causes me to add a new setting - theme.
The way I do so is
  1. Assign components that need to be changed to a list in
    Screen.Initialize
    There is a separate list for each type of components.
  2. A procedure is created for each type of components.
  3. A procedure that uses the above procedures is created for each theme.
  4. A procedure is created that calls the theme-specific procedures.
  5. When the theme is changed, the above procedure is called.
It did take some time, as I had to manually create those lists.
At this point, I consider the game to be completed.

Leaderboard
I showcased the app to my friends.
One of them suggested that I should add a leaderboard. And so I did.
After thinking of a way to calculate a score, which is
(((if (mines < max(grid - 2, grid / 2)) then mines else grid - mines) + 1) ^ 2) * grid / (time + 1)
The above algorithm prevents
  • games that have mines set to (grid - 2) or (grid - 1) from getting a high score (one click win)
  • division by 0 when the time is 0 (if you just configure the settings just right, which is easy)
Alright, we are still missing a sort function for lists, and apparently, AI2 doesn't have one!
After looking up in Wikipedia, I decided to use merge sort - it isn't too hard to implement, and it's quite fast.
Still take quite a while though, especially when pulling blocks is slow compared to typing.

I wish AI2 has a sort function. It would save me all those troubles.

There is still one more thing though, and that is AI2 doesn't have a table (not TableArrangement) that works like ListView!
I decided to approach it by splitting each column with |.
I tested it and oh... it looks very ugly. The columns are not aligned and after some searching around,
there seems to be no way of aligning them without the use of extensions.
And I want to avoid extensions.
At last, I decided that this is okay - it still shows information clearly.

Localization
This is where the fun begins.
This is suggested by another friend.
I chose to make the localization extremely robust.
Well, this comes at the cost of increased complexity, and I do mean it.
It takes ~500 blocks per screen to make the localization system.
Errors are hard to debug, and the block editor is extremely slow, which means it took a lot of time.
After using 12 hours, it's finally done.

Well, I wish AI2 has built-in localization.

Now
I don't think I will be developing this app for some time now after creating the time-consuming localization system,
but if you have any suggestions, you can reply to me.
Feel free to copy or understand any part of my code. Maybe that localization system is useful to you?
That's all and happy playing!

Typing this is also time-consuming...
Minesweeper.aia

catsniff

unread,
Apr 14, 2019, 9:55:34 AM4/14/19
to MIT App Inventor Forum
Holy cow. I would never have the patience to do something like this - so many blocks! When I try to run it, however, it keeps stopping. Why is this?

Taifun

unread,
Apr 14, 2019, 11:21:07 AM4/14/19
to MIT App Inventor Forum
Alright, we are still missing a sort function for lists, and apparently, AI2 doesn't have one!
use the List Utils Extension by Appybuilder

and that is AI2 doesn't have a table (not TableArrangement) that works like ListView!
use one of the table extensions, you can find them here https://puravidaapps.com/extensions.php

I decided to approach it by splitting each column with |.
I tested it and oh... it looks very ugly. The columns are not aligned and after some searching around,
there seems to be no way of aligning them without the use of extensions.
And I want to avoid extensions.
in this case there also is this solution 

Dynamic table layout with any number of rows and columns including table listpicker


Taifun


Trying to push the limits of App Inventor! Snippets, Tutorials and Extensions from Pura Vida Apps by Taifun. 


ABG

unread,
Apr 14, 2019, 1:49:14 PM4/14/19
to MIT App Inventor Forum
Well done!

But how do you signal a mine?

ABG

Capture.PNG

William So

unread,
Apr 14, 2019, 11:44:55 PM4/14/19
to mitappinv...@googlegroups.com
catsniff,

It seems to be related to permissions.
The documentation on Screen.PermissionDenied and Screen.PermissionGranted is a bit brief.

I designed the app so that when you deny permission for storage, it will exit.
And when you grant the app permission for storage for the first time, it will exit.
You will need to reopen the app after granting permission for the app to work.

Now, you may wonder why the app has to exit when you grant storage for the first time.
It's because if you don't, the localization system won't work properly as it cannot load the localization CSVs, that is, it doesn't translate at all.
A restart is required for it to work.

Now, on some phones, it works perfectly.
However, on other phones, the dialog that asks you for permission does not up, and it will automatically exit.
Even if you grant it permission in the settings, the app exit still.

I might have to do some research on Screen.PermissionDenied and Screen.PermissionGranted,
but if anyone has any ideas why this happens, please tell me.

William So

unread,
Apr 14, 2019, 11:48:32 PM4/14/19
to mitappinv...@googlegroups.com
Taifun,

I am trying to avoid extensions as much as possible for this app,
but in the future, I will definitely consider using some of them.

And also thanks for the last link, using HTML and JavaScript for the leaderboard is brilliant!
I will research how I should adopt it into my app...

Edit: I found several tutorials that provide the code. I think I will try to find the most suitable one and maybe also edit the file to my liking.

William So

unread,
Apr 15, 2019, 1:59:22 AM4/15/19
to mitappinv...@googlegroups.com
ABG,

Do you mean putting a flag on a cell?
If so, just click that "Mode" button and it should change to "Flag" mode.
Clicking on any unswept cell should put a flag on it.

William So

unread,
Apr 15, 2019, 6:17:31 AM4/15/19
to mitappinv...@googlegroups.com
One more thing.

Having a lot of blocks (especially Screen1, which has 2000+ blocks) in code editor is not a very good idea as it runs painfully slow in my PC. It drops to like 0.25 FPS when I try to do anything...
Collapsing the blocks seem to help, but it's still slow.

Is there any way to speed up the code editor and reduce the amount of blocks?

Ghica

unread,
Apr 15, 2019, 10:02:25 AM4/15/19
to MIT App Inventor Forum
Mine (pun intended) does not run: 
The operation select list item cannot accept the arguments: , [5], [1]
Note: You will not see another error reported for 5 seconds.

Therefore, I do not know where to start giving recommendations. I just noticed this:

Snap30.png

It seems duplicate to me. Cheers, Ghica.

ABG

unread,
Apr 15, 2019, 10:24:37 AM4/15/19
to MIT App Inventor Forum
I am told Firefox is faster than Chrome.

For my large apps, I like to do an Expand All,
then frequent Cleanup Blocks to get a vertical linear 
arrangement I can scroll through.

I am guessing this reduces the complexity of
the work the Blocks Editor has to do to
search for potential block hookups.

I suggest first doing a Project->SaveAs to 
allow safe testing of this idea.

ABG

ABG

unread,
Apr 15, 2019, 10:30:59 AM4/15/19
to MIT App Inventor Forum
Regarding the Internationalization,
you are doing a lot of work for little benefit.

If you remember the original Windows Mine Sweeper,
it relied on a little sun icon to signal a win, adding sun glasses.

If you use emojis  instead of text, you can avoid a lot of
problems.

Alternatively, prepare Media folder files of instructions
for your major target languages.  That should eliminate the need
for Web access or file permissions (I assume.)

ABG

William So

unread,
Apr 15, 2019, 7:48:43 PM4/15/19
to mitappinv...@googlegroups.com
Ghica,

The preinitialize is called only once in Screen.Initialize.

However, initialize is called in Screen.Initialize and Screen.OtherScreenClosed.

The TinyDB reading block in preinitialize is for LoadLocalization, while the one in initialize is for the three blocks below it.

One last thing, when did you get that error?

William So

unread,
Apr 15, 2019, 10:23:13 PM4/15/19
to MIT App Inventor Forum
ABG,

I will try Firefox and see how it goes.
And also try using cleanup blocks.

Regarding internationalization,
since I already completed it, there's not really any reasons to remove it now.
You said that I can use pictures to replace text so that I can eliminate internationalization.
There are some text that are difficult to be replaced by text, and it's likely that quite some people won't understand the picture even if I replace it, such as "theme".
Besides, I will still need storage access for TinyDB.
Reply all
Reply to author
Forward
0 new messages