Last active
August 29, 2015 14:25
-
-
Save zelark/44c708a6a7d8433c19b5 to your computer and use it in GitHub Desktop.
All you need to play with it is Python 3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from random import sample | |
class Cell: | |
BOMB = 'B' | |
FLAG = 'F' | |
def __init__(self): | |
self.status = 0 | |
self.content = 0 | |
def __str__(self): | |
if self.isOpened(): | |
ret = str(self.content) | |
elif self.isFlagged(): | |
ret = Cell.FLAG | |
else: | |
ret = '#' | |
return ret | |
def __repr__(self): | |
return str(self.content) | |
def open(self): | |
self.status = 1 | |
def mark(self): | |
self.status = 2 | |
def setBomb(self): | |
self.content = Cell.BOMB | |
def incCounterOfBombs(self): | |
self.content += 1 | |
def isClosed(self): | |
return True if self.status == 0 else False | |
def isOpened(self): | |
return True if self.status == 1 else False | |
def isFlagged(self): | |
return True if self.status == 2 else False | |
def isQuestioned(self): | |
return True if self.status == 3 else False | |
def hasBomb(self): | |
return True if self.content == Cell.BOMB else False | |
def hasZero(self): | |
return True if self.content == 0 else False | |
def hasNonZero(self): | |
return True if self.content in range(1,9) else False | |
class SocialCell(Cell): | |
def __init__(self): | |
self.neighbors = [] | |
super().__init__() | |
def addNeighbor(self, cell): | |
self.neighbors.append(cell) | |
def getNeighbors(self): | |
return self.neighbors | |
def incNeighbors(self): | |
for neighbor in self.neighbors: | |
neighbor.content += 1 | |
class Game: | |
boards = { | |
'small': (9, 9, 10), | |
'medium': (16, 16, 40), | |
'large': (16, 30, 81), | |
'test': (9, 9, 50)} | |
shifts = ( | |
(0, -1), (1, -1), (1, 0), (1, 1), | |
(0, 1), (-1, 1), (-1, 0), (-1, -1)) | |
def __init__(self, board): | |
self.gameOver = False | |
self.height, self.width, self.bombCount = self.boards[board] | |
self.size = self.width * self.height | |
self.gameBoard = [] | |
for i in range(self.size): | |
self.gameBoard.append(SocialCell()) | |
def showBoard(self, godMode=False): | |
for offset, cell in enumerate(self.gameBoard): | |
if offset % self.width == 0: | |
print("\n{:>2} | ".format(offset // self.width), end=' ') | |
if not godMode: | |
print("{}".format(cell), end=' ') | |
else: | |
print("{}".format(cell.__repr__()), end=' ') | |
print() | |
def showGameInfo(self): | |
print("height: {}\nwidth: {}\nbombs count: {}" | |
.format(self.height, self.width, self.bombCount)) | |
def checkWin(self): | |
counterOfOpened = 0 | |
for cell in self.gameBoard: | |
if cell.isOpened() and not cell.hasBomb(): | |
counterOfOpened += 1 | |
return True if self.size - self.bombCount == counterOfOpened else False | |
def checkGameOver(self): | |
return self.gameOver | |
def checkInBoard(self, x, y): | |
if x in range(self.width) and y in range(self.height): | |
return True | |
else: | |
return False | |
def getCell(self, x, y): | |
offset = self.getOffsetByLocation(x, y) | |
return self.gameBoard[offset] | |
def openCell(self, x, y): | |
if self.checkInBoard(x, y): | |
cell = self.getCell(x, y).open() | |
if cell.hasZero(): | |
self.openArea(cell) | |
elif cell.hasBomb(): | |
self.gameOver = True | |
def markCell(self, x, y): | |
if self.checkInBoard(x, y): | |
self.getCell(x, y).mark() | |
def getOffsetByLocation(self, x, y): | |
return y * self.width + x | |
def getLocationByOffset(self, offset): | |
return (offset % self.width, offset // self.width) | |
def setBombs(self): | |
for offset in sample(range(0, self.size-1), self.bombCount): | |
self.gameBoard[offset].setBomb() | |
def calcBoards(self): | |
for cell in self.gameBoard: | |
if cell.hasBomb(): | |
cell.incNeighbors() | |
def makeFriends(self): | |
for offset, cell in enumerate(self.gameBoard): | |
x, y = self.getLocationByOffset(offset) | |
self.findNeighbors(cell, x, y) | |
def findNeighbors(self, cell, x, y): | |
for dx, dy in self.shifts: | |
offset = self.getOffsetByLocation(x+dx, y+dy) | |
if (self.checkInBoard(x+dx, y+dy) | |
and not self.gameBoard[offset].hasBomb()): | |
cell.addNeighbor(self.gameBoard[offset]) | |
def openArea(self, cell): | |
if cell.hasNonZero(): | |
return | |
for neighbor in cell.getNeighbors(): | |
if not neighbor.isOpened(): | |
neighbor.open() | |
self.openArea(neighbor) | |
def main(): | |
game = Game('small') | |
game.showGameInfo() | |
game.setBombs() | |
game.makeFriends() | |
game.calcBoards() | |
game.showBoard() | |
while True: | |
try: | |
text = input('>> ') | |
except (EOFError, KeyboardInterrupt): | |
print() | |
break | |
if not text: | |
continue | |
try: | |
mode, y, x = text.split() | |
except ValueError: | |
mode, y, x = text, '', '' | |
if x.isdigit() and y.isdigit(): | |
x = int(x) | |
y = int(y) | |
elif mode == 'i' or mode == 'info': | |
game.showGameInfo() | |
continue | |
elif mode == 'b' or mode == 'board': | |
game.showBoard() | |
continue | |
elif mode == 'gm': | |
game.showBoard(godMode=True) | |
continue | |
elif mode == 'h' or mode == 'help': | |
print( | |
"\nh, help - this help" | |
"\ni, info - the info about the game" | |
"\nb, board - show the board" | |
"\no, open y x - open a cell with y and x" | |
"\nm, mark y x - mark a cell with y and x as a bomb") | |
else: | |
continue | |
if mode == 'o' or mode == 'open': | |
game.openCell(x, y) | |
game.showBoard() | |
if game.checkWin(): | |
print("[GameBot]: You win!") | |
if game.checkGameOver(): | |
print("[GameBot]: You lose.") | |
elif mode == 'm' or mode == 'mark': | |
game.markCell(x, y) | |
game.showBoard() | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment