DEV Community

Andrés Álvarez Iglesias
Andrés Álvarez Iglesias

Posted on

Django 8: Implementing the game in Player vs Player

NOTE: This article was initially posted on my Substack, at https://andresalvareziglesias.substack.com/

Hi all!

In the first seven chapters of this series, we explored the power of the Django framework by building a basic application with functionalities like session management and database access. We've also learned how to create the infrastructure for this sample program using Docker, another powerful tool.

That was our primary goal: to learn Django and Docker. However, there's one thing remaining in our little demo project...

Articles in this series

Image description

Programming TicTacToe in Python

The TicTacToe is a very simple game, ideal for beginners. A possible implementation can be:

class TicTacToe:
   def __init__(self, board):
       self.board = board
       self.winner = ""

   def checkMove(self, position):
       if self.board[position] == "E":
           return True

       return False

   def makeMove(self, symbol, position):
       if self.checkMove(position):
           self.board = self.board[:position]+symbol+self.board[position+1:]
           print(f"The player {symbol} makes a move at position {position}. Current board: [{self.board}]")
           return True

       print(f"Invalid movement! The position {position} is already occupied. Current board: [{self.board}]")
       return False

   def checkGameOver(self):
       for i in range(0, 3):
           # Vertical line
           if self.board[i] != "E" and self.board[i] == self.board[i+3] and self.board[i] == self.board[i+6]:
               self.winner = self.board[i]
               print(f"Win condition reached (vertical line)! Winner: {self.winner} | Current board: [{self.board}]")
               return True

           # Horizontal line
           if self.board[i*3] != "E" and self.board[i*3] == self.board[i*3+1] and self.board[i*3] == self.board[i*3+2]:
               self.winner = self.board[i*3]
               print(f"Win condition reached (horizontal line)! Winner: {self.winner} | Current board: [{self.board}]")
               return True

       # Diagonal lines
       if self.board[0] != "E" and self.board[0] == self.board[4] and self.board[0] == self.board[8]:
           self.winner = self.board[0]
           print(f"Win condition reached (diagonal \\ line)! Winner: {self.winner} | Current board: [{self.board}]")
           return True

       elif self.board[2] != "E" and self.board[2] == self.board[4] and self.board[2] == self.board[6]:
           self.winner = self.board[2]
           print(f"Win condition reached (diagonal / line)! Winner: {self.winner} | Current board: [{self.board}]")
           return True

       # No more spaces to play
       for i in range(0, 9):
           if self.board[i] == "E":
               return False

       self.winner = "D"
       print(f"No more spaces to play, draw! Winner: {self.winner} | Current board: [{self.board}]")
       return True
Enter fullscreen mode Exit fullscreen mode

Key features of this implementation:

  • 3x3 Grid: The game board will always be a 3x3 grid with 9 positions.
  • Two Players, Three Outcomes: The game allows two players and has three possible endings: victory for player O, victory for player X, or a draw.
  • Winning Conditions: Any horizontal, vertical, or diagonal row of three tiles with the same symbol will result in a victory.
  • Initial Board State: The class will maintain the current state of the board at the start of the game.
  • Movement Tracking: Storing each movement in a database might be relevant for a more complex game like TicMagicalLine. This class allows to initialize the board with any initial state.

Can be easier, isn't it?

Playing Tic-Tac-Toe Against a Human Opponent

Now, let's explore a simple code example to test our class in Player-vs-Player (PvP) mode:

import os
from tictactoe import TicTacToe

def playerPlay(game, symbol):
   validMove = False
   while not validMove:
       x, y = map(int, input(f'Player {symbol}: Make your move (x,y from 1 to 3): ').split(","))
       position = ((x-1)*3)+(y-1)

       validMove = game.makeMove(symbol, position)
       if validMove:
           print(f"Player {symbol}: Plays {symbol} at position {position} | State: {game.board}")
           game.dumpBoard()

       else:
           print(f"Player {symbol}: Invalid move at position {position}! | State: {game.board}")

   return game.checkGameOver()

emptyBoard = "EEEEEEEEE"
game = TicTacToe(emptyBoard)

player = 'O'
while not game.checkGameOver():
   position = playerPlay(game, player)

   if game.checkGameOver():
       print(f"Player {player} wins!")
       break

   player = ('O' if player == 'X' else 'X')
Enter fullscreen mode Exit fullscreen mode

The code will handle the following:

  • Game Board Initialization: It will set up the initial empty game board.
  • Turn Management: It will facilitate each player's turn until a winner is declared or the game reaches a draw.

Training the AI to Play Tic-Tac-Toe

Now, let's take things a step further and explore how to train our program to play Tic-Tac-Toe using machine learning. We'll be implementing a reward/punishment algorithm with TensorFlow and a small neural network.

While this approach might seem like overkill for a simple game like Tic-Tac-Toe, it serves as a fun introduction to the concepts of machine learning!

About the list

Among the Python and Docker posts, I will also write about other related topics (always tech and programming topics, I promise... with the fingers crossed), like:

  • Software architecture
  • Programming environments
  • Linux operating system
  • Etc.

If you found some interesting technology, programming language or whatever, please, let me know! I'm always open to learning something new!

About the author

I'm Andrés, a full-stack software developer based in Palma, on a personal journey to improve my coding skills. I'm also a self-published fantasy writer with four published novels to my name. Feel free to ask me anything!

Top comments (0)