-
Notifications
You must be signed in to change notification settings - Fork 0
/
queensmodel.py
127 lines (110 loc) · 4.29 KB
/
queensmodel.py
1
"""File: manyqueens.pyProject 6Author: Leigh StaufferDetermine all the solutions to the Many Queens problem for a chessboardof any size.1) There is a single input indicating the size of the board.2) Displays all solutions or indicates that there are none."""from grid import Gridfrom linkedstack import LinkedStackclass QueensModel(object): def __init__(self, size = 8): self.size = size self.newGame() def newGame(self): """Sets the data for the initial state.""" self.board = Grid(self.size, self.size, "-") self.stack = LinkedStack() self.row = 0 self.column = 0 self.placementCount = 0 self.squaresVisitedCount = 0 self.backtrackCount = 0 self.gameDone = False def __str__(self): """Return the string rep of the board.""" return str(self.board) def gameIsDone(self): """Return the game is done, or not.""" return self.gameDone def getPiece(self, row, column): """Return the string at row, column.""" return self.board[row][column] def getPlacementCount(self): """Returns the number of queen placements.""" return self.placementCount def getSquaresVisitedCount(self): """Returns the number of queen placements.""" return self.squaresVisitedCount def getBacktrackCount(self): """Returns the number of queen placements.""" return self.backtrackCount def move(self): """Tries to place a queen in a column.""" # Search for an unthreatened position in the current column, # starting with the current row. for row in range(self.row, self.board.getHeight()): self.squaresVisitedCount += 1 if not self.isThreatened(row, self.column): # Ok to place the queen in this column. self.board[row][self.column] = "Q" self.placementCount += 1 if self.column == self.board.getWidth() - 1: # Signal done if queen was placed in the last column. self.gameDone = True else: # Otherwise, remember the position of the successful placement, # and reset to advance to the next column. self.stack.push((row, self.column)) self.column += 1 self.row = 0 break elif row == self.board.getHeight() - 1: # Queen could not be placed in this column, so retreat to # previous column, erase the queen there, and start in the next row. (self.row, self.column) = self.stack.pop() self.backtrackCount += 1 if self.row == self.board.getHeight() - 1: # If the queen was in the bottom row, # erase her and move back one more column self.board[self.row][self.column] = "-" (self.row, self.column) = self.stack.pop() self.backtrackCount += 1 self.board[self.row][self.column] = "-" self.row += 1 def isThreatened(self, row, column): """Determine if the square at location (row, column) is under attack from any queen in columns 0 to column - 1. Returns True if square is threatened or False otherwise.""" r = row for c in range(column): if self.board[r][c] == "Q": return True r = row c = column while 0 <= min(r, c): if self.board[r][c] == "Q": return True r -= 1 c -= 1 r = row c = column while c >= 0 and r < self.board.getHeight(): if self.board[r][c] == "Q": return True r += 1 c -= 1 return Falsedef main(): """Starting point for terminal-based app.""" model = QueensModel() while not model.gameIsDone(): model.move() print(model) print("Total queen placements: " + str(model.getPlacementCount())) print("Total squares visited: " + str(model.getSquaresVisitedCount())) print("Total backtracks: " + str(model.getBacktrackCount()))if __name__ == "__main__": main()