Project Details
What is the idea behind our Project?
- The Idea
- The Frontend
- The Backend
- CHALLENGE 1: OOP
- CHALLENGE 2: Enumerated types
- CHALLENGE 3: Recursive algorithm
- CHALLENGE 4: Yet to be implemented
- CHALLENGE 5: JSON communication
- Current Game Implementation
The Idea
Our team wishes to build a minesweeper game with a python backend that could consistently communicate with our front-end website to bring a new degree of sophistication and aesthetic to this classic Game. This project would be split into two main portions each with it's own challenge. The first portion would be making the game engine in python, while the latter portion would be to design and create an aesthetically pleasing and functional frontend to display the Game Status
The Frontend
The frontend aspect of this project should preferably display a grid of the game and incorporate some aspect of user input. Preliminary testing and experimentation could be done through textbox inputs of coordinate values, while prospective functions could include individual buttons on the Grid itself to provide a GUI for the user to interact with. In both cases, the frontend should be able to communicate with the python backend through JSON data to send and receive data.
More aspects about the Frontend aspects will be added with additional planning in the future.
The Backend
Arguably the more challenging half of this project, the backend would primarily serve to be the game engine of the minesweeper game. Additionally, the backend would also control and organize the various pages and menus on the website. In this writeup, we will only be focusing on the main goals and challenges faced by the Backend team.
- Using Object Oriented Programming to create individual objects for the game. Some aspects that could be represented by such objects would be the gameboard and also the individual cells and nodes present within the game board.
- Doing so would simplify the algorithmic aspect of the game, as the board itself could have methods and attributes to help control the game logic.
- Morever, using an object to represent an individual cell in the board would provide greater functionalities than just using a single variable
-
Use Enumerated types with the python
enum
module to create different values for the type and status of each node. Each of these types could then be bound to a constant value which could then be printed on the screen -
Use Recursion to create an algorithm to recursively detect adjacent cells that are safe (AKA not mines). This algorithm would work in the following format
- Maintain a list of current cells already determined to be safe
- Verify if the four adjacent (up, down, left, right) cells next to the selected cell are safe or not, if safe, store the coordinate point in the list, if not, record the cell as a "border cell", terminate the recursive process, and run another helper function to determine the precise number of mines surrounding the cell
- Re-call the function for each of the surrounding adjacent cells to identify other consecutive cells who are safe.
- Return a list of the coordinates of a contiguous block of safe cells
- Mark the cells to be safe and calculate number of surrounding mines for border cells.
-
Verify the Game status, Game is won if:
- All mines are flagged
- All safe cells are cleared Game is lost if:
- A mine was dug by the user
-
Return the final result back to the front end. If a safe cell was dug, send out a JSON containing an array of the coordinates of the cell and it's safe neighbors. If a mine was dug, send a JSON containing a boolean value to signify the end of the game.
from enum import Enum
from random import randint
class MType(Enum):
SAFE = 1
MINE = 2
class MStatus(Enum):
UNKNOWN = 1
DUG = 2
FLAG = 3
class Node:
def __init__(self):
self.type = MType.SAFE
self.status = MStatus.UNKNOWN
self.value = "-"
def setInitialValue(self):
if self.type == MType.MINE:
self.value="M"
Here is the Code for the Minesweeper gameboard and its methods.
class NotInBoard(Exception):
pass
class Minesweeper:
# Class constructor, containing game data
def __init__(self):
self.mine_coords = []
self.board = []
self.rows = 0
self.cols = 0
self.gameWin = False
self.gameOver = False
# Create the gameboard on a given input of rows and columns
def generateBoard(self,r,c):
self.rows = r
self.cols = c
self.board = [[Node() for i in range(self.rows)] for i in range(self.cols)]
return self.board
# Print the current board
def printBoard(self):
res = ""
for row in self.board:
concat = ""
for column in row:
concat = concat + column.value + " "
concat = concat.strip() + "\n"
res = res+concat
print(res)
return 0
# Generate the coordinates of the mines AFTER the first user input
# THE FIRST ACTION ON A CELL WOULD NEVER BE A MINE!
def setMines(self):
num_of_mines = (self.rows * self.cols)//4
counter = 0
while counter <= num_of_mines:
mine_coord = (randint(0,self.rows-1),randint(0,self.cols-1))
print("Mine coord: ", mine_coord)
if mine_coord in self.mine_coords:
continue
self.board[mine_coord[0]][mine_coord[1]].type = MType.MINE
self.mine_coords.append(mine_coord)
counter +=1
for i in range(self.rows):
for j in range(self.cols):
self.board[i][j].setInitialValue()
return 0
# The first click of the game
def firstClick(self):
self.printBoard()
try:
ipt = input("What row and column? (format in row,column): ")
row, col = int(ipt.split(",")[0]), int(ipt.split(",")[1])
if row not in range(1,self.rows+1) or col not in range(1,self.cols+1):
print("Values not in bound, try again")
raise NotInBoard
self.setMines()
except NotInBoard:
self.firstClick()
# Following actions after the first-dig
# checkAdkacent function will be created soon
def digMine(self, r ,c):
if self.board[r][c].type == MType.MINE:
self.gameOver = True
else:
safe_mines = self.checkAdjacent(r,c)
from enum import Enum
class MType(Enum):
SAFE = 1
MINE = 2
class MStatus(Enum):
UNKNOWN = 1
DUG = 2
FLAG = 3
def main():
MS = Minesweeper()
rows = int(input("How many rows do you want? "))
cols = int(input("How many columns do you want? "))
MS.generateBoard(cols, rows)
MS.firstClick()
MS.printBoard()
# Define a while lop here to loop game.
print("List of generated mine coordinates: ", MS.mine_coords)
main()