diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..43ae0e2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +__pycache__/ +*.py[cod] diff --git a/UI/app.js b/UI/app.js index 19d2553..c75b44d 100644 --- a/UI/app.js +++ b/UI/app.js @@ -9,6 +9,7 @@ function startNew(mode) { // hard -> 18X32=576 -> 100 bombs | 24 -> 100 bombs // extreme-> 26X50=1300 -> 220 bombs | 30 -> 200 bombs // const mode = element.value; + isOpen = document.getElementById('isOpen').checked; if (mode === "easy") { size = 10; bombs = 15; @@ -32,7 +33,7 @@ function startNew(mode) { document.getElementById("h1").classList.remove("won"); document.getElementById("h1").classList.remove("lost"); document.getElementById("h1").innerHTML = `Minesweeper`; - eel.makeBoard(size, bombs)(); //size, bombs + eel.makeBoard(size, bombs, isOpen)(); //size, bombs drawFirst(); } diff --git a/UI/index.html b/UI/index.html index a7d8222..dcad8c1 100644 --- a/UI/index.html +++ b/UI/index.html @@ -11,6 +11,8 @@

Minesweeper

+ Show Open +
2: + raise ValueError(f"Only one or two dimensions supported, got {dim}") + + self.dim = dim + self.numMines = m_numMines + + self.values = np.zeros(self.shape, dtype=int) + self.selected = np.zeros(shape=self.values.shape, dtype=bool) + + mine_indices = np.array(np.unravel_index(np.random.choice(self.values.size, size=m_numMines, replace=False), self.values.shape)) + self.values[*mine_indices] = -1 + + for m in range(mine_indices.shape[-1]): + mine_index = mine_indices[:, m] + current_index = mine_index.copy() + for k in range(dim): + for a in [-1, 0, 1]: + if mine_index[k] + a >= self.values.shape[k] or mine_index[k] + a < 0: + continue + current_index[k] = mine_index[k] + a + for j in range(k): + for b in [-1, 0, 1]: + if mine_index[j] + b >= self.values.shape[j] or mine_index[j] + b < 0: + continue + current_index[j] = mine_index[j] + b + self.values[*current_index] += 1 if self.values[*current_index] >= 0 else 0 + + + self.selectableSpots = self.values.size - m_numMines + + @property + def boardSize(self): + return self.values.shape[0] # TODO generalize + def __str__(self): + if self.dim > 2: + raise ValueError(f"Only one or two dimensions supported, got {self.dim}") returnString = " " divider = "\n---" - for i in range(0, self.boardSize): - returnString += " | " + str(i) - divider += "----" - divider += "\n" + if len(self.values.shape > 1): + + for i in range(0, self.values.shape[0]): + returnString += " | " + str(i) + divider += "----" + divider += "\n" returnString += divider for y in range(0, self.boardSize): returnString += str(y) for x in range(0, self.boardSize): - if self.board[x][y].mine and self.board[x][y].selected: - returnString += " |" + str(self.board[x][y].value) - elif self.board[x][y].selected: - returnString += " | " + str(self.board[x][y].value) + if self.values[x, y] < 0 and self.selected[x, y]: + returnString += " |" + str(self.values[x, y]) + elif self.selected[x, y]: + returnString += " | " + str(self.values[x, y]) else: returnString += " | " returnString += " |" returnString += divider return returnString - def addMine(self, x, y): - self.board[x][y].value = -1 - self.board[x][y].mine = True - for i in range(x-1, x+2): - if i >= 0 and i < self.boardSize: - if y-1 >= 0 and not self.board[i][y-1].mine: - self.board[i][y-1].value += 1 - if y+1 < self.boardSize and not self.board[i][y+1].mine: - self.board[i][y+1].value += 1 - if x-1 >= 0 and not self.board[x-1][y].mine: - self.board[x-1][y].value += 1 - if x+1 < self.boardSize and not self.board[x+1][y].mine: - self.board[x+1][y].value += 1 - def makeMove(self, x, y): - self.board[x][y].selected = True + self.selected[x, y] = True self.selectableSpots -= 1 - if self.board[x][y].value == -1: + if self.values[x, y] == -1: return False - if self.board[x][y].value == 0: + if self.values[x, y] == 0: for i in range(x-1, x+2): if i >= 0 and i < self.boardSize: - if y-1 >= 0 and not self.board[i][y-1].selected: + if y-1 >= 0 and not self.selected[i, y-1]: self.makeMove(i, y-1) - if y+1 < self.boardSize and not self.board[i][y+1].selected: + if y+1 < self.boardSize and not self.selected[i, y+1]: self.makeMove(i, y+1) - if x-1 >= 0 and not self.board[x-1][y].selected: + if x-1 >= 0 and not self.selected[x-1,y]: self.makeMove(x-1, y) - if x+1 < self.boardSize and not self.board[x+1][y].selected: + if x+1 < self.boardSize and not self.selected[x+1, y]: self.makeMove(x+1, y) return True else: return True def hitMine(self, x, y): - return self.board[x][y].value == -1 + return self.values[x, y] == -1 def isWinner(self): return self.selectableSpots == 0 +def increment_tuple(t: tuple, index: int = 0, value: int = 1) -> tuple: + if not t or index < 0 or index >= len(t): + return t # Return original tuple if empty or index is out of range + + t_list = list(t) + t_list[index] += value + return tuple(t_list) #play game def playGame(): boardSize = int(input("Choose the Width of the board: ")) numMines = int(input("Choose the number of mines: ")) + dim = int(input("Choose dimensions of board: ")) gameOver = False winner = False - Board = boardClass(boardSize, numMines) + Board = boardClass(boardSize, numMines, dim=dim) while not gameOver: print(Board) print("Make your move:") @@ -112,7 +118,7 @@ def playGame(): y = int(input("y: ")) Board.makeMove(x, y) gameOver = Board.hitMine(x, y) - if Board.isWinner() and gameOver == False: + if Board.isWinner() and gameOver is False: gameOver = True winner = True @@ -122,4 +128,5 @@ def playGame(): else: print("You hit a mine, Game Over!") -playGame() +if __name__ == "__main__": + playGame() diff --git a/minesweeperGUI.py b/minesweeperGUI.py index 4b2f546..c1c160c 100644 --- a/minesweeperGUI.py +++ b/minesweeperGUI.py @@ -1,95 +1,36 @@ -import random import eel +from minesweeper import boardClass -class boardSpot(object): - value = 0 - selected = False - mine = False - - def __init__(self): - self.selected = False - - def __str__(self): - return str(boardSpot.value) - - def isMine(self): - if boardSpot.value == -1: - return True - return False - - -class boardClass(object): - def __init__(self, m_boardSize, m_numMines): - self.board = [[boardSpot() for i in range(m_boardSize)] - for j in range(m_boardSize)] - self.boardSize = m_boardSize - self.numMines = m_numMines - self.selectableSpots = m_boardSize * m_boardSize - m_numMines - i = 0 - while i < m_numMines: - x = random.randint(0, self.boardSize-1) - y = random.randint(0, self.boardSize-1) - if not self.board[x][y].mine: - self.addMine(x, y) - i += 1 - else: - i -= 1 +class GUIBoardClass(boardClass): def __str__(self): returnString = "" for y in range(0, self.boardSize): # returnString += str(y) for x in range(0, self.boardSize): - if self.board[x][y].mine and self.board[x][y].selected: + if self.values[x, y] == -1 and self.selected[x, y]: returnString += 'B' # returnString += str(self.board[x][y].value) - elif self.board[x][y].selected: - returnString += str(self.board[x][y].value) + elif self.selected[x, y]: + returnString += str(self.values[x, y]) else: # empthy cell returnString += "E" return returnString - def addMine(self, x, y): - self.board[x][y].value = -1 - self.board[x][y].mine = True - for i in range(x-1, x+2): - if i >= 0 and i < self.boardSize: - if y-1 >= 0 and not self.board[i][y-1].mine: - self.board[i][y-1].value += 1 - if y+1 < self.boardSize and not self.board[i][y+1].mine: - self.board[i][y+1].value += 1 - if x-1 >= 0 and not self.board[x-1][y].mine: - self.board[x-1][y].value += 1 - if x+1 < self.boardSize and not self.board[x+1][y].mine: - self.board[x+1][y].value += 1 - - def makeMove(self, x, y): - self.board[x][y].selected = True - self.selectableSpots -= 1 - if self.board[x][y].value == -1: - return False - if self.board[x][y].value == 0: - for i in range(x-1, x+2): - if i >= 0 and i < self.boardSize: - if y-1 >= 0 and not self.board[i][y-1].selected: - self.makeMove(i, y-1) - if y+1 < self.boardSize and not self.board[i][y+1].selected: - self.makeMove(i, y+1) - if x-1 >= 0 and not self.board[x-1][y].selected: - self.makeMove(x-1, y) - if x+1 < self.boardSize and not self.board[x+1][y].selected: - self.makeMove(x+1, y) - return True - else: - return True - - def hitMine(self, x, y): - return self.board[x][y].value == -1 - - def isWinner(self): - return self.selectableSpots == 0 + +class OpenGUIBoardClass(boardClass): + def __str__(self): + returnString = "" + for y in range(0, self.boardSize): + # returnString += str(y) + for x in range(0, self.boardSize): + if self.values[x, y] == -1: + returnString += str(0) + else: + returnString += str(self.values[x, y]) + return returnString #### For UI #### @@ -109,7 +50,7 @@ def clickedOnTheCell(x, y): if GO_IN: BOARD.makeMove(x, y) GAME_OVER = BOARD.hitMine(x, y) - if BOARD.isWinner() and GAME_OVER == False: + if BOARD.isWinner() and GAME_OVER is False: GAME_OVER = True WINNER = True print("Won") @@ -121,10 +62,13 @@ def clickedOnTheCell(x, y): @eel.expose -def makeBoard(boardSize, numMines): +def makeBoard(boardSize, numMines, isOpen=False): global BOARD del BOARD - BOARD = boardClass(boardSize, numMines) + if isOpen: + BOARD = OpenGUIBoardClass(boardSize, numMines) + else: + BOARD = GUIBoardClass(boardSize, numMines) # noqa: F841 web_app_options = { diff --git a/requirements.txt b/requirements.txt index b81a462..2abcaf0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,2 @@ -eel==0.14.0 \ No newline at end of file +eel==0.14.0 +numpy==2.2.4 \ No newline at end of file