AI-based 2048 logo

Programming an AI-based 2048 game (Part 3: User Interface)

This third blog post presents the User Interface that I designed for my 2048 video game (you can check the first blog post of this series out if you haven’t read it yet).

I chose to rely on the very good tkinter package, which is the standard Python interface to the Tk GUI toolkit. Both Tk and tkinter are available on most Unix platforms, as well as on Windows systems. More details are available on the official documentation website.

This third post will mainly describe the TkConstants and Window classes. If you want more details, the source code of the project is also available on Github.

TkConstants class

This class is actually pretty simple and only contains the required text options (font types, police sizes) and the required colors for the tile backgrounds/borders.

Each tile number has been associated to a tuple (background color, foreground color) where foreground color is the color of the text:

colors = {
   '0':("#cdc0b4", "#cdc0b4"),
   '2':("#eee4da", "#776e65"),
   '4':("#ede0c8", "#776e65"),
   '8':("#f2b179", "#f9f6f2"),
   '16':("#f59563", "#f9f6f2"),
   '32':("#f67c5f", "#f9f6f2"),
   '64':("#f65e3b", "#f9f6f2"),
   '128':("#edcf72", "#f9f6f2"),
   '256':("#edcc61", "#f9f6f2"),
   '512': ("#edc850", "#f9f6f2"),
   '1024':("#edc53f", "#f9f6f2"),
   '2048':("#edc22e", "#f9f6f2")
}

Window class

The Window class contains 5 main methods, that have quite self-explanatory names:

def start_new_game(self)
def replay_game(self)
def display_grid(self)
def update_grid(self)
def update(self, event)

The update method is the general callback for any key release event:

self.window.bind('<KeyRelease>', self.update)

The update_grid method is called by the update method when a grid displayed need to be re-drawn:

if event.keysym in [v.value for v in Directions]:
    if not self.game.ended_game:
        # ...
        self.update_grid()

Finally, the start_new_game and replay_game methods are called in response to the click event on options of the File menu. The final rendering is shown below:

Finally, from a main entry-point file (e.g., Application.py), the GUI is created and started as follow:

# No need to create grid or game objects when we launch GUI
app = Window(nb_rows_columns=Constants.GRID_NB_ROWS_COLUMNS, base_path=replay_dir)
app.start_new_game()

As a reminder, I do not guarantee that my solution is the best or the most optimized one. Feel free to propose yours or any suggestion you may have by commenting this series of blog posts.

I hope you enjoyed reading this blog post and that you are impatient for the next blog posts. 🙂