Commits

Dinesh Manajipet committed d59406b

The First Commit : Incomplete Bits of minesweeper i was about to make for my conf.kde.in

Comments (0)

Files changed (6)

+from PySide.QtGui import *
+from MineFieldWidget import *
+from Overlay import *
+
+class MainWindow(QMainWindow):
+  def __init__(self, parent = None):
+    QMainWindow.__init__(self,parent)
+    self._rows = 10
+    self._columns = 10
+    self._mines = 10
+    self._overlay = Overlay ("start")
+    self.setCentralWidget(self._overlay)
+    self._overlay.clicked.connect(self.newGame)
+    
+  def newGame(self):
+    print "new Game!"
+    self._mineFieldWidget = MineFieldWidget(self._rows ,self._columns, self._mines)
+    self._mineFieldWidget.gameWon.connect(self.gameWon)
+    self._mineFieldWidget.gameLost.connect(self.gameLost)
+    self.setCentralWidget(self._mineFieldWidget)
+  
+  def gameWon(self):
+    self._overlay = Overlay ("won")
+    self._overlay.clicked.connect(self.newGame)
+    self.setCentralWidget (self._overlay)
+    
+  def gameLost(self):
+    self._overlay = Overlay ("lost")
+    self._overlay.clicked.connect(self.newGame)
+    self.setCentralWidget (Overlay ("lost"))
+#-----------------------------------------------------------------------------------------------------------------------------
+# Clicking the Mine means uncovering it in the MineField
+# RightClicking the Mine means cycling through { unknown -> flagmine -> doubtmine }
+# 
+# 
+#--------------------------------------------------------------------------------------------------------------------------
+
+
+from PySide.QtGui import *
+from PySide.QtCore import *
+from MineField import MineField
+
+class Mine(QPushButton):
+  uncovered = Signal(int, int , int)
+  def __init__( self, row , column , mineField , parent = None ):
+    QPushButton.__init__(self,parent)
+    self._row = row
+    self._column = column
+    self._mineField = mineField
+    
+
+  def sizeHint(self):
+    return QSize(30,30)
+
+  def mousePressEvent (self, event):
+    if (event.button() == Qt.LeftButton):
+      self.uncover()
+    elif (event.button() == Qt.RightButton):
+      self.nextState()
+  
+  def uncover( self ):
+    # Only uncover it, if the status is unknown
+    if not self._mineField.status(self._row ,self._column) == self._mineField.blockState["unknown"]:
+      return
+    self.setEnabled(False)
+    #uncover
+    status = self._mineField.uncover(self._row,self._column)
+    #print self._row, self._column, ":" , status
+    self.uncovered.emit(self._row,self._column , status)
+    
+    #Don't display value even for zero surrounding Mines
+    if (status == 0):
+      return
+    self.setStatus( status )
+    
+  def setStatus(self, status):
+    if (status > 0 ):
+      self.setText(str(status))      
+    elif (status == self._mineField.blockState["mine"]):
+      self.explodeMe()
+    elif (status == self._mineField.blockState["flag"]):
+      self.flagMe()
+      
+  def reveal(self):
+    '''if there is a Mine in a block, show it as a mine'''
+    if (self._mineField.reveal(self._row, self._column)):
+    #If already exploded, do nothing , cuz we already have a shiny image for the Explosion in place
+      if (self._mineField.status(self._row, self._column) == self._mineField.blockState["mine"]):
+        return
+      self.clearMe()
+      self.setIcon(QPixmap("./Artwork/Mine.png"))
+      
+  def explodeMe(self):
+    self.clearMe()
+    self.setIcon(QPixmap("./Artwork/Explosion1.png"))
+    
+  def flagMe(self):
+    self.clearMe()
+    self.setIcon(QPixmap("./Artwork/Flag.png"))
+  
+  def doubtMe(self):
+    self.clearMe()
+    self.setText("?")
+    #self.setIcon(QPixmap("./Artwork/Flag.png"))
+  
+  def clearMe(self):
+    self.setText("")
+    self.setIcon(QPixmap(""))
+        
+  def nextState( self ):
+    status = self._mineField.status(self._row, self._column)
+    if (status == self._mineField.blockState["unknown"]):
+      if(self._mineField.flagMine(self._row, self._column)):
+        self.flagMe()
+      
+    elif (status == self._mineField.blockState["flag"]):
+      if(self._mineField.doubtMine(self._row, self._column)):
+        self.doubtMe()
+      
+    else :
+      if (self._mineField.unmarkMine(self._row, self._column)):
+        self.clearMe()
+#-----------------------------------------------------------------------------------------------------------------------------
+# For simplicity, We shall use 2 matrices, 1 for representing the state of mines and the other for representing 
+# status of mines. 
+# Rules
+# =====
+# The User can either Mark a block as a mine , or doubt it for later, or uncover it.
+# The User dies when there is a mine in the block he uncovers
+# The User wins when he uncovers all the free blocks (only way to prove right??)
+#--------------------------------------------------------------------------------------------------------------------------
+from random import randint
+
+class MineField:
+  blockState = { "mine" : -1 ,"unknown" : -2 , "flag" : -3 , "doubtful" : -4 }
+  def __init__(self, rows = 10, columns = 10, mines = 10):
+    self._rows = rows
+    self._columns = columns
+    self._mines = mines
+    self._flags = 0
+    self._blocksUncovered = 0
+    
+    self._mineMatrix = []
+    self._statusMatrix = []
+
+    self.initializeMatrices()
+    
+  
+  def initializeMatrices(self):
+    #create a Blank MineField first
+    for i in range(self._rows):
+      mineColumn = []
+      statusColumn = []
+      for j in range(self._columns):
+        mineColumn.append (False)
+        statusColumn.append(self.blockState["unknown"])
+      self._mineMatrix.append(mineColumn)
+      self._statusMatrix.append(statusColumn)
+      
+    #Then randomly put the mines in the blocks without mines
+    for i in range (self._mines):
+      row = randint (0,self._rows - 1)
+      column = randint (0, self._columns - 1)
+      while (self._mineMatrix[row][column]):
+        row = randint (0,self._rows - 1)
+        column = randint (0, self._columns - 1)
+      self._mineMatrix[row][column] = True
+        
+    
+  def uncover(self, row, column):
+    '''The Main Function which does all the magic! '''    
+    #if Mine underneath, GameOver
+    if (self._mineMatrix[row][column]):
+      self._statusMatrix[row][column] = self.blockState["mine"]
+      return self.blockState["mine"]
+    else:
+      #else compute the value of the block
+      self._blocksUncovered += 1
+      status = 0
+      for i in range(-1,2):
+        for j in range(-1,2):
+	  #no need to worry about self._mineMatrix[row][column] cuz it obviously is 0
+          if(row + i >= 0 and column + j >= 0 and\
+	  row + i < self._rows and column + j < self._columns):
+            status += int (self._mineMatrix[row+i][column+j])
+            
+    self._statusMatrix[row][column] = status
+    return status
+  
+  
+  def flagMine (self, row, column):
+    ''' Mark the block as mine , if enough flags are left '''
+    if (self._flags == self._mines):
+      return False
+    self._flags += 1
+    self._statusMatrix[row][column] = self.blockState["flag"]    
+    return True
+  
+  
+  def doubtMine(self,row,column):
+    ''' Doubt the block as a Mine'''
+    if (self._statusMatrix[row][column] == self.blockState["flag"]):
+      self._flags -= 1
+    self._statusMatrix[row][column] = self.blockState["doubtful"]
+    return True
+  
+  
+  def unmarkMine (self, row, column):
+    ''' Unmark a doubtful block '''
+    self._statusMatrix[row][column] = self.blockState["unknown"]
+    return True
+  
+  
+  def status(self,row,column):
+    ''' Show the current marked status of a block '''
+    return self._statusMatrix[row][column]
+    
+  def reveal(self, row, column):
+    ''' Show if there is a Mine or not'''
+    return self._mineMatrix[row][column]
+  
+  def __str__(self):
+    mineString = ''
+    for i in range(self._rows):
+      mineString += str(self._statusMatrix[i]) + "\n"
+    return mineString

MineFieldWidget.py

+#-----------------------------------------------------------------------------------------------------------------------------
+# The Main Frame, holding all the Mines
+# 
+# 
+#--------------------------------------------------------------------------------------------------------------------------
+from PySide.QtGui import *
+from PySide.QtCore import *
+import MineField
+import Mine
+
+class MineFieldWidget(QWidget):
+  gameLost = Signal()
+  gameWon = Signal()
+  def __init__( self , rows = 10 , columns = 10 , mines = 10  , parent = None ):
+    QWidget.__init__(self,parent)
+    self._rows = rows
+    self._columns = columns
+    self._mines = mines
+    self._minesLeft = rows*columns - mines
+    self._mineField = MineField.MineField( rows, columns , mines )
+    self.initializeGui()
+    
+  def initializeGui(self):
+    self._mineLayout = QGridLayout()
+    self._mineLayout.setSizeConstraint(QLayout.SetMinimumSize)
+    self._mineLayout.setSpacing(0)
+    self.setLayout(self._mineLayout)
+    
+    #Now the mines!
+    for i in range(self._rows):
+      for j in range(self._columns):
+        mine = Mine.Mine(i,j,self._mineField)
+        mine.uncovered.connect(self.blockUncovered)
+        self._mineLayout.addWidget(mine,i,j)
+        
+  def boom(self):
+    ''' If the user tripped on a single Mine, then reveal all the Mines'''
+    
+    for row in range (0, self._rows):
+      for column in range (0 , self._columns):
+        self._mineLayout.itemAtPosition(row , column).widget().reveal()
+        
+    msgBox = QMessageBox(self)
+    msgBox.setText("That Was a mine!! You lost :(")
+    msgBox.exec_()
+    
+    self.gameLost.emit()
+        
+  def phew(self):
+    ''' If the user uncovered all the free blocks, then game is Won '''
+    
+    # additional things like score etc... ?
+            
+    msgBox = QMessageBox(self)
+    msgBox.setText("Yayy! You Won :D")
+    msgBox.exec_()
+    
+    self.gameWon.emit()
+    
+        
+  @Slot(int , int , int)
+  def blockUncovered(self, row, column , status):
+    #if the uncovered block is a mine, BOOM!
+    if (status == self._mineField.blockState["mine"]):
+      self.boom()
+    #if the uncovered mine has no mines in it's neighbours, uncover them too :)
+    if (status == 0):
+      for i in range (-1,2):
+        for j in range ( -1,2 ):
+          if ( row + i >= 0 and row + i < self._rows and \
+               column + j >= 0 and column + j < self._columns):
+                 if (not (i == j and i == 0) ):
+                   self._mineLayout.itemAtPosition(row + i ,column + j).widget().uncover()
+    if (status >= 0):
+      self._minesLeft -= 1
+      if (self._minesLeft == 0 ):
+        self.phew()
+    
+from PySide.QtGui import *
+
+class Overlay(QPushButton):
+  def __init__( self , state , parent = None ):
+    QPushButton.__init__( self, parent )
+    self._smile = QPixmap("./Artwork/Smiley.png")
+    self._frown = QPixmap("./Artwork/Frown.png")
+    self._pause = QPixmap("./Artwork/Pause.png")
+    self.setState(state)
+
+  def setState(self, state):
+    self._state = state
+    if(state == "won"):
+      self.setIcon(self._smile)
+      self.setText("Yayy!! You ve WON!!!")
+    elif(state == "lost"):
+      self.setIcon(self._frown)
+      self.setText("Oops! that wasn't a mine!!")
+    elif (state == "start"):
+      self.setIcon(self._pause)
+      self.setText( "Click Me to go on with the game!!")
+#! /usr/bin/python
+from PySide.QtCore import *
+from PySide.QtGui import *
+import sys
+
+from MineFieldWidget import *
+
+def newGame():
+  global myMainWindow
+  myMainWindow = MineFieldWidget(10,10,10)
+  myMainWindow.gameWon.connect(newGame)
+  myMainWindow.gameLost.connect(newGame)
+  myMainWindow.show()
+
+app = QApplication(sys.argv)
+myMainWindow = MineFieldWidget(10,10,10)
+newGame()
+app.exec_()
+
+