此文章根据《父与子的编程之旅:与小卡特一起学Python 》Hangman例子进行详细学习,大牛路过勿喷,新手一个。
Hangman的PY代码:
1 import sys #导入系统标准库-SYS模块,此模块可以应用系统的一些配置。例如:sys.path就可以知道系统的环境变量 2 from PyQt4 import QtCore,QtGui,uic #通过PyQt4模块来导入QtCore和QtGui,uic。方便我们直接使用,命名空间 3 import random #导入random模块,用于取随机数 4 5 form_class = uic.loadUiType("hangman.ui")[0] #通过uic.loadUiType去加载我们通过Designer做好的UI界面从而获得返回的表单类和Qt积累,我们只需要表单类所以是[0] 6 #接下来将定义方法函数对字母进行检测 7 def find_letters(letter,a_string): #letter是引用该函数的时候传入猜的字母,a_string是传入的答案单词 8 locations = [] #建一个列表存储猜到的字母 9 start = 0 #寻找的启始位置 10 while a_string.find(letter,start,len(a_string)) != -1: #while循环,a_string.find 是字符串string 的一个方法,如果该方法放回的值等于-1的时候就是结束了。 11 location = a_string.find(letter,start,len(a_string)) #location 当我们find找到字母位置的时候定个位置, 12 locations.append(location) #把找到的字母位置添加进locations列表里 13 start = location + 1 #开始寻找的位置,从我们刚刚找到该字母的位置开始继续寻找是否还有该字母 14 return locations #返回locaitons列表 15 16 def replace_letters(string,locations,letter): #这是替换字母的方法,传入string我们的单词、locations是一个存储我们上个找到对应位置的数组,letter是字母 17 new_string = '' #创建一个空的新的字符串 18 for i in range(0,len(string)): #for循环长度是从0到字符串string单词的长度 19 if i in locations : #如果循环i位置存在locations列表里那么将执行下面语句,将在新的字符串上这个位置添加一个这个字母进去。 20 new_string = new_string + letter 21 else: #否则将添加单词原来的字符。 22 new_string = new_string + string[i] 23 return new_string #最后返回新的字符串单词。 24 25 def dashes(word): #传入随机选到的单词进去, 26 letters = "abcdefghijklmnopqrstuvwxyz" #定义一个lettere字符串 27 new_string = '' #定一个空的新的字符串 28 for i in word: # for循环单词把单词隐藏起来 29 if i in letters: 30 new_string += "-" 31 else: 32 new_string += i 33 return new_string #返回隐藏好后的单词 34 35 class MyWidget(QtGui.QMainWindow,form_class): #创建一个类,将刚过导出来的form_calss和一个主窗口传进去 36 def __init__(self,parent = None): #init是没有专门应用的方法的,他是在类创建新例的时候传入参数的同时会默认调用的方法。 37 QtGui.QMainWindow.__init__(self,parent) #引用主窗口的init方法并传入参数,调用主窗口 38 self.setupUi(self) #初始化UI界面 39 self.btn_guess.clicked.connect(self.btn_guess_clicked)#绑定UI界面中名称为btn_guess的按钮,括号中是对应的方法 40 self.actionExit.triggered.connect(self.menuExit_selected) #绑定UI界面中左上角菜单键对应的名称,对应括号中我们写的方法 41 self.pieces = [self.head,self.body,self.lefttarm,self.leftleg,self.righttarm,self.rightleg]#身体部分的数字,数组元素对应我们UI的身体躯干的名称 42 self.gallows = [self.line1,self.line2,self.line3,self.line4]#绞刑台的几条线对应UI界面中的名称 43 self.pieces_shown = 0 #身体部分显示的个数 44 self.currentword = "" #当前的单词 45 f = open("words.txt",'r') #打开单词文本,r是指read读取 46 self.lines = f.readlines() #一行一行读取的所有行并存在lines里 47 f.close() #关闭文本,必须要关闭。不然后面用到会打不开。 48 self.new_game() #开始游戏函数 49 def new_game(self): #定义开始游戏函数 50 self.guesses.setText("") #穿件guesses文本,暂时设置为空 51 self.currentword = random.choice(self.lines) #从我们读取到的单词lines中随机的选择一个单词存在currenword里 52 self.currentword = self.currentword.strip() #用字符串的strip方法去掉空格(没有指定字符的话默认是空格) 53 for i in self.pieces: #遍历循环我们上面的pieces数组里面的各个部分 54 i.setFrameShadow(QtGui.QFrame.Plain) #各个部分的阴影用默认的UI前景颜色绘制 55 i.setHidden(True) #然后在将其隐藏 56 for i in self.gallows: #遍历循环出绞刑台数组 57 i.setFrameShadow(QtGui.QFrame.Plain) #各个部分的阴影用默认的UI前景颜色绘制 58 self.word.setText(dashes(self.currentword)) #将word单词文本设置为我们用dashes方法处理后的字符 59 self.pieces_shown = 0 #部位露出的数量 60 def btn_guess_clicked(self): #穿件一个方法函数,是我们刚刚上面绑定的按钮对应的方法 61 guess = str(self.guessBox.text()) #格式化字符串我们获取到的用户输入的文本内容赋值给guess 62 if str(self.guesses.text()) != "": #判断一下格式化字符串guesses文本是否不为空 63 self.guesses.setText(str(self.guesses.text())+", "+guess) #不为空的话就将guesses赋值为guesses夹上guess 64 else: 65 self.guesses.setText(guess) #否则的话就直接吧guesses替换成guess 66 if len(guess) == 1: #判断一下guess的长度是否等于1 67 if guess in self.currentword: #如果是guess长度等于1的话 再判断一下 guess字母是否在我们的单词里面 68 locations = find_letters(guess,self.currentword) #如果在的话那么通过我们上面定义的方法传入字母和单词去寻找字母是否存在单词里,并且返回所有字母存在的位置 69 self.word.setText(replace_letters(str(self.word.text()),locations,guess)) #通过我们上面定义的替换方法,传入目前word文本内容,和字母位置列表,和字母,然后进行替换word文本内容。 70 if str(self.word.text()) == self.currentword: #再判断下 word的文本内容里的单词是不是跟我们的答案单词一样 71 self.win() #如果一样的话就调用win的方法函数。 72 else: 73 self.wrong() #否则guess的字母不存在我们的答案单词里面的话就调用wrond的方法函数。 74 else: 75 if guess == self.currentword: #如果guess长度不等于1那么判断一下guess的单词是否等于我们答案的单词 76 self.win() #如果是的话就调用win的方法函数 77 else: #否则的话 78 self.wrong() #就调用wrong的方法函数 79 self.guessBox.setText("") #然后就吧UI界面的guessBox的内容重新清空 80 def win(self): #创建win的方法函数 81 QtGui.QMessageBox.information(self,"Hangman","You win!") #弹出胜利信息框 82 self.new_game() #重新开始游戏 83 def wrong(self): #创建wrong方法函数 84 self.pieces_shown += 1 #当被调用时显示的不为加1 85 for i in range(self.pieces_shown): #for循环一下显示部位的数量 86 self.pieces[i].setHidden(False) #每一个部位被循环到的时候就显示 87 if self.pieces_shown == len(self.pieces): #如果身体显示部位的数量等于单词的长度 88 message = "You lose. The word was "+self.currentword #那么就先设置一个message的文本,内容+答案 89 QtGui.QMessageBox.warning(self,"Hangman",message) #引用QtGui里面的警告信息框,将刚刚的文本弹出来。 90 self.new_game() # 继续重新开始游戏 91 def menuExit_selected(self): #界面的菜单Exit按钮方法 92 self.close() #关闭程序 93 app = QtGui.QApplication(sys.argv) #每个程序都必须创建一个application对象,sys.argv是参数命令组中的一个参数 94 myapp = MyWidget(None) #创建一个窗口对象 95 myapp.show() #显示窗口对象, 96 app.exec_() #循环直到退出窗口方法,如果没有此语句将出现闪退现象
自己理解的大致意思 写为注释,有错的请指导更正。
Ui文件也贴上来吧
1 <?xml version="1.0" encoding="UTF-8"?> 2 <ui version="4.0"> 3 <class>MainWindow</class> 4 <widget class="QMainWindow" name="MainWindow"> 5 <property name="geometry"> 6 <rect> 7 <x>0</x> 8 <y>0</y> 9 <width>800</width> 10 <height>476</height> 11 </rect> 12 </property> 13 <property name="windowTitle"> 14 <string>MainWindow</string> 15 </property> 16 <widget class="QWidget" name="centralwidget"> 17 <widget class="Line" name="line3"> 18 <property name="enabled"> 19 <bool>true</bool> 20 </property> 21 <property name="geometry"> 22 <rect> 23 <x>90</x> 24 <y>30</y> 25 <width>104</width> 26 <height>21</height> 27 </rect> 28 </property> 29 <property name="font"> 30 <font> 31 <pointsize>13</pointsize> 32 <underline>true</underline> 33 </font> 34 </property> 35 <property name="autoFillBackground"> 36 <bool>false</bool> 37 </property> 38 <property name="frameShadow"> 39 <enum>QFrame::Plain</enum> 40 </property> 41 <property name="lineWidth"> 42 <number>7</number> 43 </property> 44 <property name="orientation"> 45 <enum>Qt::Horizontal</enum> 46 </property> 47 </widget> 48 <widget class="Line" name="line4"> 49 <property name="geometry"> 50 <rect> 51 <x>80</x> 52 <y>40</y> 53 <width>21</width> 54 <height>41</height> 55 </rect> 56 </property> 57 <property name="frameShadow"> 58 <enum>QFrame::Plain</enum> 59 </property> 60 <property name="lineWidth"> 61 <number>7</number> 62 </property> 63 <property name="orientation"> 64 <enum>Qt::Vertical</enum> 65 </property> 66 </widget> 67 <widget class="Line" name="line1"> 68 <property name="geometry"> 69 <rect> 70 <x>180</x> 71 <y>40</y> 72 <width>20</width> 73 <height>311</height> 74 </rect> 75 </property> 76 <property name="frameShadow"> 77 <enum>QFrame::Plain</enum> 78 </property> 79 <property name="lineWidth"> 80 <number>7</number> 81 </property> 82 <property name="orientation"> 83 <enum>Qt::Vertical</enum> 84 </property> 85 </widget> 86 <widget class="QLabel" name="head"> 87 <property name="geometry"> 88 <rect> 89 <x>60</x> 90 <y>80</y> 91 <width>51</width> 92 <height>71</height> 93 </rect> 94 </property> 95 <property name="font"> 96 <font> 97 <pointsize>88</pointsize> 98 </font> 99 </property> 100 <property name="text"> 101 <string>o</string> 102 </property> 103 </widget> 104 <widget class="Line" name="lefttarm"> 105 <property name="geometry"> 106 <rect> 107 <x>20</x> 108 <y>170</y> 109 <width>51</width> 110 <height>16</height> 111 </rect> 112 </property> 113 <property name="frameShadow"> 114 <enum>QFrame::Plain</enum> 115 </property> 116 <property name="lineWidth"> 117 <number>7</number> 118 </property> 119 <property name="orientation"> 120 <enum>Qt::Horizontal</enum> 121 </property> 122 </widget> 123 <widget class="Line" name="righttarm"> 124 <property name="geometry"> 125 <rect> 126 <x>90</x> 127 <y>170</y> 128 <width>51</width> 129 <height>16</height> 130 </rect> 131 </property> 132 <property name="frameShadow"> 133 <enum>QFrame::Plain</enum> 134 </property> 135 <property name="lineWidth"> 136 <number>7</number> 137 </property> 138 <property name="orientation"> 139 <enum>Qt::Horizontal</enum> 140 </property> 141 </widget> 142 <widget class="Line" name="body"> 143 <property name="geometry"> 144 <rect> 145 <x>70</x> 146 <y>140</y> 147 <width>21</width> 148 <height>91</height> 149 </rect> 150 </property> 151 <property name="frameShadow"> 152 <enum>QFrame::Plain</enum> 153 </property> 154 <property name="lineWidth"> 155 <number>7</number> 156 </property> 157 <property name="orientation"> 158 <enum>Qt::Vertical</enum> 159 </property> 160 </widget> 161 <widget class="QLabel" name="leftleg"> 162 <property name="geometry"> 163 <rect> 164 <x>40</x> 165 <y>210</y> 166 <width>71</width> 167 <height>91</height> 168 </rect> 169 </property> 170 <property name="font"> 171 <font> 172 <pointsize>60</pointsize> 173 </font> 174 </property> 175 <property name="text"> 176 <string>/</string> 177 </property> 178 </widget> 179 <widget class="QLabel" name="rightleg"> 180 <property name="geometry"> 181 <rect> 182 <x>60</x> 183 <y>220</y> 184 <width>71</width> 185 <height>91</height> 186 </rect> 187 </property> 188 <property name="font"> 189 <font> 190 <pointsize>70</pointsize> 191 <weight>50</weight> 192 <italic>false</italic> 193 <bold>false</bold> 194 </font> 195 </property> 196 <property name="text"> 197 <string> \</string> 198 </property> 199 </widget> 200 <widget class="Line" name="line2"> 201 <property name="enabled"> 202 <bool>true</bool> 203 </property> 204 <property name="geometry"> 205 <rect> 206 <x>0</x> 207 <y>340</y> 208 <width>331</width> 209 <height>21</height> 210 </rect> 211 </property> 212 <property name="font"> 213 <font> 214 <pointsize>13</pointsize> 215 <underline>true</underline> 216 </font> 217 </property> 218 <property name="autoFillBackground"> 219 <bool>false</bool> 220 </property> 221 <property name="frameShadow"> 222 <enum>QFrame::Plain</enum> 223 </property> 224 <property name="lineWidth"> 225 <number>7</number> 226 </property> 227 <property name="orientation"> 228 <enum>Qt::Horizontal</enum> 229 </property> 230 </widget> 231 <widget class="QLabel" name="word"> 232 <property name="geometry"> 233 <rect> 234 <x>260</x> 235 <y>70</y> 236 <width>191</width> 237 <height>81</height> 238 </rect> 239 </property> 240 <property name="font"> 241 <font> 242 <pointsize>60</pointsize> 243 </font> 244 </property> 245 <property name="text"> 246 <string>--------</string> 247 </property> 248 </widget> 249 <widget class="QLabel" name="label_5"> 250 <property name="geometry"> 251 <rect> 252 <x>270</x> 253 <y>300</y> 254 <width>131</width> 255 <height>16</height> 256 </rect> 257 </property> 258 <property name="text"> 259 <string>Previous guesses:</string> 260 </property> 261 </widget> 262 <widget class="QLabel" name="guesses"> 263 <property name="geometry"> 264 <rect> 265 <x>380</x> 266 <y>300</y> 267 <width>281</width> 268 <height>16</height> 269 </rect> 270 </property> 271 <property name="text"> 272 <string/> 273 </property> 274 </widget> 275 <widget class="QLabel" name="label_7"> 276 <property name="geometry"> 277 <rect> 278 <x>260</x> 279 <y>380</y> 280 <width>181</width> 281 <height>16</height> 282 </rect> 283 </property> 284 <property name="text"> 285 <string>Guess a letter or the word:</string> 286 </property> 287 </widget> 288 <widget class="QLineEdit" name="guessBox"> 289 <property name="geometry"> 290 <rect> 291 <x>260</x> 292 <y>400</y> 293 <width>221</width> 294 <height>31</height> 295 </rect> 296 </property> 297 </widget> 298 <widget class="QPushButton" name="btn_guess"> 299 <property name="geometry"> 300 <rect> 301 <x>480</x> 302 <y>400</y> 303 <width>110</width> 304 <height>32</height> 305 </rect> 306 </property> 307 <property name="text"> 308 <string>Guess</string> 309 </property> 310 </widget> 311 </widget> 312 <widget class="QMenuBar" name="menubar"> 313 <property name="geometry"> 314 <rect> 315 <x>0</x> 316 <y>0</y> 317 <width>800</width> 318 <height>22</height> 319 </rect> 320 </property> 321 <widget class="QMenu" name="menuFile"> 322 <property name="title"> 323 <string>File</string> 324 </property> 325 <addaction name="actionExit"/> 326 </widget> 327 <addaction name="menuFile"/> 328 </widget> 329 <widget class="QStatusBar" name="statusbar"/> 330 <action name="actionExit"> 331 <property name="text"> 332 <string>Exit</string> 333 </property> 334 </action> 335 </widget> 336 <resources/> 337 <connections/> 338 </ui>