from random import randint import curses class Game: COVERED = 0 UNCOVERED = 1 FLAG = 2 PLAYING = 0 WON = 1 LOST = 2 def __init__(self,width,height,bombs): self.width = width self.height = height self.bombs = bombs if self.bombs > self.width*self.height: raise ValueError("Too much bombs") self.running = True self.cursorx = 0 self.cursory = 0 self.state = self.PLAYING self.__generate() def mapdone(self): for y in range(self.height): for x in range(self.width): if self.discovered[y][x] == self.COVERED: return False if self.discovered[y][x] == self.FLAG and not self.bombmap[y][x]: return False return True def __generate(self): self.bombmap = [ [False for x in range(self.width) ] for y in range(self.height) ] self.discovered = [ [0 for x in range(self.width) ] for y in range(self.height) ] for i in range(self.bombs): x,y = randint(0,self.width-1),randint(0,self.height-1) while self.bombmap[y][x]: x,y = randint(0,self.width-1),randint(0,self.height-1) self.bombmap[y][x] = True def countbomb(self,y,x): n = 0 for dy in range(-1,2): for dx in range(-1,2): if y+dy < 0 or y+dy >= self.height: continue if x+dx < 0 or x+dx >= self.width: continue if self.bombmap[y+dy][x+dx]: n+=1 return n def uncover(self,y,x): if y < 0 or y >= self.height: return if x < 0 or x >= self.width: return if self.discovered[y][x] != self.UNCOVERED and not self.bombmap[y][x]: self.discovered[y][x] = self.UNCOVERED if self.countbomb(y,x) == 0: self.uncover(y+1,x) self.uncover(y+1,x+1) self.uncover(y,x+1) self.uncover(y-1,x+1) self.uncover(y-1,x) self.uncover(y-1,x-1) self.uncover(y,x-1) self.uncover(y+1,x-1) def update(self,key): if self.state == self.PLAYING: if key == ord('f'): #Set a flag if self.discovered[self.cursory][self.cursorx] == self.COVERED: self.discovered[self.cursory][self.cursorx] = self.FLAG if self.mapdone(): self.state = self.WON elif self.discovered[self.cursory][self.cursorx] == self.FLAG: self.discovered[self.cursory][self.cursorx] = self.COVERED elif key == ord(' '): if self.bombmap[self.cursory][self.cursorx]: self.state = self.LOST else: self.uncover(self.cursory,self.cursorx) if self.mapdone(): self.state = self.WON elif key == curses.KEY_DOWN: if self.cursory+1 < self.height: self.cursory+=1 elif key == curses.KEY_UP: if self.cursory-1 >= 0: self.cursory-=1 elif key == curses.KEY_RIGHT: if self.cursorx+1 < self.width: self.cursorx+=1 elif key == curses.KEY_LEFT: if self.cursorx-1 >= 0: self.cursorx-=1 if key == ord('q'): self.running = False def draw(self,screen): for y in range(self.height): for x in range(self.width): if self.discovered[y][x] == self.COVERED: char = "-" attr = curses.A_NORMAL elif self.discovered[y][x] == self.UNCOVERED: if self.bombmap[y][x]: char = "*" attr = curses.A_BOLD else: n = self.countbomb(y,x) if n == 0: char = " " else: char = str(n) attr = curses.A_NORMAL elif self.discovered[y][x] == self.FLAG: char = "F" attr = curses.A_BOLD screen.addch(y,x,ord(char),attr) if self.state == self.PLAYING: screen.addstr(self.height,0,"f - Set Flag, Space - Uncover, q - Quit") elif self.state == self.LOST: screen.addstr(self.height,0,"--- LOST (q to quit) ---") screen.clrtoeol() elif self.state == self.WON: screen.addstr(self.height,0,"--- WON (q to quit) ---") screen.clrtoeol() def run(self, screen): sh, sw = screen.getmaxyx() #l = (sw-self.width)//2 l = t = 0 #t = (sh-self.height)//2 #window = curses.newwin(self.height,self.width,t,l) while self.running: self.draw(screen) screen.move(t+self.cursory,l+self.cursorx) k = screen.getch() self.update(k) if __name__ == '__main__': s = curses.initscr() curses.savetty() curses.noecho() s.keypad(1) #curses.curs_set(2) Game(40,20,70).run(s) curses.resetty() curses.endwin()