调整了目录结构
This commit is contained in:
parent
36ffd6c281
commit
6a7f860227
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
### for-in循环
|
### for-in循环
|
||||||
|
|
||||||
如果明确的知道循环执行的次数或者是要对一个容器进行迭代(后面会讲到),那么我们推荐使用`for-in`循环,例如下面代码中计算。
|
如果明确的知道循环执行的次数或者是要对一个容器进行迭代(后面会讲到),那么我们推荐使用`for-in`循环,例如下面代码中计算。
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
"""
|
"""
|
||||||
|
|
@ -2,11 +2,11 @@
|
||||||
|
|
||||||
在讲解本章节的内容之前,我们先来研究一道数学题,请说出下面的方程有多少组正整数解。
|
在讲解本章节的内容之前,我们先来研究一道数学题,请说出下面的方程有多少组正整数解。
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
事实上,上面的问题等同于将8个苹果分成四组每组至少一个苹果有多少种方案。想到这一点问题的答案就呼之欲出了。
|
事实上,上面的问题等同于将8个苹果分成四组每组至少一个苹果有多少种方案。想到这一点问题的答案就呼之欲出了。
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
可以用Python的程序来计算出这个值,代码如下所示。
|
可以用Python的程序来计算出这个值,代码如下所示。
|
||||||
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
### 使用字符串
|
### 使用字符串
|
||||||
|
|
||||||
第二次世界大战促使了现代电子计算机的诞生,当初的想法很简单,就是用计算机来计算导弹的弹道,因此在计算机刚刚诞生的那个年代,计算机处理的信息主要是数值,而世界上的第一台电子计算机ENIAC每秒钟能够完成约5000次浮点运算。随着时间的推移,虽然对数值运算仍然是计算机日常工作中最为重要的事情之一,但是今天的计算机处理得更多的数据都是以文本信息的方式存在的,而Python表示文本信息的方式我们在很早以前就说过了,那就是字符串类型。所谓**字符串**,就是由零个或多个字符组成的有限序列,一般记为。
|
第二次世界大战促使了现代电子计算机的诞生,当初的想法很简单,就是用计算机来计算导弹的弹道,因此在计算机刚刚诞生的那个年代,计算机处理的信息主要是数值,而世界上的第一台电子计算机ENIAC每秒钟能够完成约5000次浮点运算。随着时间的推移,虽然对数值运算仍然是计算机日常工作中最为重要的事情之一,但是今天的计算机处理得更多的数据都是以文本信息的方式存在的,而Python表示文本信息的方式我们在很早以前就说过了,那就是字符串类型。所谓**字符串**,就是由零个或多个字符组成的有限序列,一般记为。
|
||||||
|
|
||||||
我们可以通过下面的代码来了解字符串的使用。
|
我们可以通过下面的代码来了解字符串的使用。
|
||||||
|
|
||||||
|
|
@ -183,11 +183,11 @@ if __name__ == '__main__':
|
||||||
|
|
||||||
除了上面提到的生成器语法,Python中还有另外一种定义生成器的方式,就是通过`yield`关键字将一个普通函数改造成生成器函数。下面的代码演示了如何实现一个生成[斐波拉切数列](https://zh.wikipedia.org/wiki/%E6%96%90%E6%B3%A2%E9%82%A3%E5%A5%91%E6%95%B0%E5%88%97)的生成器。所谓斐波拉切数列可以通过下面[递归](https://zh.wikipedia.org/wiki/%E9%80%92%E5%BD%92)的方法来进行定义:
|
除了上面提到的生成器语法,Python中还有另外一种定义生成器的方式,就是通过`yield`关键字将一个普通函数改造成生成器函数。下面的代码演示了如何实现一个生成[斐波拉切数列](https://zh.wikipedia.org/wiki/%E6%96%90%E6%B3%A2%E9%82%A3%E5%A5%91%E6%95%B0%E5%88%97)的生成器。所谓斐波拉切数列可以通过下面[递归](https://zh.wikipedia.org/wiki/%E9%80%92%E5%BD%92)的方法来进行定义:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||

|

|
||||||
|
|
||||||

|

|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|
@ -297,3 +297,123 @@ if __name__ == '__main__':
|
||||||
|
|
||||||
传输层除了有可靠的传输协议TCP之外,还有一种非常轻便的传输协议叫做用户数据报协议,简称UDP。TCP和UDP都是提供端到端传输服务的协议,二者的差别就如同打电话和发短信的区别,后者不对传输的可靠性和可达性做出任何承诺从而避免了TCP中握手和重传的开销,所以在强调性能和而不是数据完整性的场景中(例如传输网络音视频数据),UDP可能是更好的选择。可能大家会注意到一个现象,就是在观看网络视频时,有时会出现卡顿,有时会出现花屏,这无非就是部分数据传丢或传错造成的。在Python中也可以使用UDP套接字来创建网络应用,对此我们不进行赘述,有兴趣的读者可以自行研究。
|
传输层除了有可靠的传输协议TCP之外,还有一种非常轻便的传输协议叫做用户数据报协议,简称UDP。TCP和UDP都是提供端到端传输服务的协议,二者的差别就如同打电话和发短信的区别,后者不对传输的可靠性和可达性做出任何承诺从而避免了TCP中握手和重传的开销,所以在强调性能和而不是数据完整性的场景中(例如传输网络音视频数据),UDP可能是更好的选择。可能大家会注意到一个现象,就是在观看网络视频时,有时会出现卡顿,有时会出现花屏,这无非就是部分数据传丢或传错造成的。在Python中也可以使用UDP套接字来创建网络应用,对此我们不进行赘述,有兴趣的读者可以自行研究。
|
||||||
|
|
||||||
|
### 网络应用开发
|
||||||
|
|
||||||
|
#### 发送电子邮件
|
||||||
|
|
||||||
|
在即时通信软件如此发达的今天,电子邮件仍然是互联网上使用最为广泛的应用之一,公司向应聘者发出录用通知、网站向用户发送一个激活账号的链接、银行向客户推广它们的理财产品等几乎都是通过电子邮件来完成的,而这些任务应该都是由程序自动完成的。
|
||||||
|
|
||||||
|
就像我们可以用HTTP(超文本传输协议)来访问一个网站一样,发送邮件要使用SMTP(简单邮件传输协议),SMTP也是一个建立在TCP(传输控制协议)提供的可靠数据传输服务的基础上的应用级协议,它规定了邮件的发送者如何跟发送邮件的服务器进行通信的细节,而Python中的smtplib模块将这些操作简化成了几个简单的函数。
|
||||||
|
|
||||||
|
下面的代码演示了如何在Python发送邮件。
|
||||||
|
|
||||||
|
```Python
|
||||||
|
from smtplib import SMTP
|
||||||
|
from email.header import Header
|
||||||
|
from email.mime.text import MIMEText
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
# 请自行修改下面的邮件发送者和接收者
|
||||||
|
sender = 'abcdefg@126.com'
|
||||||
|
receivers = ['uvwxyz@qq.com', 'uvwxyz@126.com']
|
||||||
|
message = MIMEText('用Python发送邮件的示例代码.', 'plain', 'utf-8')
|
||||||
|
message['From'] = Header('王大锤', 'utf-8')
|
||||||
|
message['To'] = Header('骆昊', 'utf-8')
|
||||||
|
message['Subject'] = Header('示例代码实验邮件', 'utf-8')
|
||||||
|
smtper = SMTP('smtp.126.com')
|
||||||
|
# 请自行修改下面的登录口令
|
||||||
|
smtper.login(sender, 'secretpass')
|
||||||
|
smtper.sendmail(sender, receivers, message.as_string())
|
||||||
|
print('邮件发送完成!')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
|
```
|
||||||
|
|
||||||
|
如果要发送带有附件的邮件,那么可以按照下面的方式进行操作。
|
||||||
|
|
||||||
|
```Python
|
||||||
|
from smtplib import SMTP
|
||||||
|
from email.header import Header
|
||||||
|
from email.mime.text import MIMEText
|
||||||
|
from email.mime.image import MIMEImage
|
||||||
|
from email.mime.multipart import MIMEMultipart
|
||||||
|
|
||||||
|
import urllib
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
# 创建一个带附件的邮件消息对象
|
||||||
|
message = MIMEMultipart()
|
||||||
|
|
||||||
|
# 创建文本内容
|
||||||
|
text_content = MIMEText('附件中有本月数据请查收', 'plain', 'utf-8')
|
||||||
|
message['Subject'] = Header('本月数据', 'utf-8')
|
||||||
|
# 将文本内容添加到邮件消息对象中
|
||||||
|
message.attach(text_content)
|
||||||
|
|
||||||
|
# 读取文件并将文件作为附件添加到邮件消息对象中
|
||||||
|
with open('/Users/Hao/Desktop/hello.txt', 'rb') as f:
|
||||||
|
txt = MIMEText(f.read(), 'base64', 'utf-8')
|
||||||
|
txt['Content-Type'] = 'text/plain'
|
||||||
|
txt['Content-Disposition'] = 'attachment; filename=hello.txt'
|
||||||
|
message.attach(txt)
|
||||||
|
# 读取文件并将文件作为附件添加到邮件消息对象中
|
||||||
|
with open('/Users/Hao/Desktop/汇总数据.xlsx', 'rb') as f:
|
||||||
|
xls = MIMEText(f.read(), 'base64', 'utf-8')
|
||||||
|
xls['Content-Type'] = 'application/vnd.ms-excel'
|
||||||
|
xls['Content-Disposition'] = 'attachment; filename=month-data.xlsx'
|
||||||
|
message.attach(xls)
|
||||||
|
|
||||||
|
# 创建SMTP对象
|
||||||
|
smtper = SMTP('smtp.126.com')
|
||||||
|
# 开启安全连接
|
||||||
|
# smtper.starttls()
|
||||||
|
sender = 'abcdefg@126.com'
|
||||||
|
receivers = ['uvwxyz@qq.com']
|
||||||
|
# 登录到SMTP服务器
|
||||||
|
# 请注意此处不是使用密码而是邮件客户端授权码进行登录
|
||||||
|
# 对此有疑问的读者可以联系自己使用的邮件服务器客服
|
||||||
|
smtper.login(sender, 'secretpass')
|
||||||
|
# 发送邮件
|
||||||
|
smtper.sendmail(sender, receivers, message.as_string())
|
||||||
|
# 与邮件服务器断开连接
|
||||||
|
smtper.quit()
|
||||||
|
print('发送完成!')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 发送短信
|
||||||
|
|
||||||
|
发送短信也是项目中常见的功能,网站的注册码、验证码、营销信息基本上都是通过短信来发送给用户的。在下面的代码中我们使用了[互亿无线](http://www.ihuyi.com/)短信平台(该平台为注册用户提供了50条免费短信以及常用开发语言发送短信的demo,可以登录该网站并在用户自服务页面中对短信进行配置)提供的API接口实现了发送短信的服务,当然国内的短信平台很多,读者可以根据自己的需要进行选择(通常会考虑费用预算、短信达到率、使用的难易程度等指标),如果需要在商业项目中使用短信服务建议购买短信平台提供的套餐服务。
|
||||||
|
|
||||||
|
```Python
|
||||||
|
import urllib.parse
|
||||||
|
import http.client
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
host = "106.ihuyi.com"
|
||||||
|
sms_send_uri = "/webservice/sms.php?method=Submit"
|
||||||
|
# 下面的参数需要填入自己注册的账号和对应的密码
|
||||||
|
params = urllib.parse.urlencode({'account': '你自己的账号', 'password' : '你自己的密码', 'content': '您的验证码是:147258。请不要把验证码泄露给其他人。', 'mobile': '接收者的手机号', 'format':'json' })
|
||||||
|
print(params)
|
||||||
|
headers = {'Content-type': 'application/x-www-form-urlencoded', 'Accept': 'text/plain'}
|
||||||
|
conn = http.client.HTTPConnection(host, port=80, timeout=30)
|
||||||
|
conn.request('POST', sms_send_uri, params, headers)
|
||||||
|
response = conn.getresponse()
|
||||||
|
response_str = response.read()
|
||||||
|
jsonstr = response_str.decode('utf-8')
|
||||||
|
print(json.loads(jsonstr))
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
|
```
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -1,121 +0,0 @@
|
||||||
## 网络应用开发
|
|
||||||
|
|
||||||
### 发送电子邮件
|
|
||||||
|
|
||||||
在即时通信软件如此发达的今天,电子邮件仍然是互联网上使用最为广泛的应用之一,公司向应聘者发出录用通知、网站向用户发送一个激活账号的链接、银行向客户推广它们的理财产品等几乎都是通过电子邮件来完成的,而这些任务应该都是由程序自动完成的。
|
|
||||||
|
|
||||||
就像我们可以用HTTP(超文本传输协议)来访问一个网站一样,发送邮件要使用SMTP(简单邮件传输协议),SMTP也是一个建立在TCP(传输控制协议)提供的可靠数据传输服务的基础上的应用级协议,它规定了邮件的发送者如何跟发送邮件的服务器进行通信的细节,而Python中的smtplib模块将这些操作简化成了几个简单的函数。
|
|
||||||
|
|
||||||
下面的代码演示了如何在Python发送邮件。
|
|
||||||
|
|
||||||
```Python
|
|
||||||
from smtplib import SMTP
|
|
||||||
from email.header import Header
|
|
||||||
from email.mime.text import MIMEText
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
# 请自行修改下面的邮件发送者和接收者
|
|
||||||
sender = 'abcdefg@126.com'
|
|
||||||
receivers = ['uvwxyz@qq.com', 'uvwxyz@126.com']
|
|
||||||
message = MIMEText('用Python发送邮件的示例代码.', 'plain', 'utf-8')
|
|
||||||
message['From'] = Header('王大锤', 'utf-8')
|
|
||||||
message['To'] = Header('骆昊', 'utf-8')
|
|
||||||
message['Subject'] = Header('示例代码实验邮件', 'utf-8')
|
|
||||||
smtper = SMTP('smtp.126.com')
|
|
||||||
# 请自行修改下面的登录口令
|
|
||||||
smtper.login(sender, 'secretpass')
|
|
||||||
smtper.sendmail(sender, receivers, message.as_string())
|
|
||||||
print('邮件发送完成!')
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
||||||
```
|
|
||||||
|
|
||||||
如果要发送带有附件的邮件,那么可以按照下面的方式进行操作。
|
|
||||||
|
|
||||||
```Python
|
|
||||||
from smtplib import SMTP
|
|
||||||
from email.header import Header
|
|
||||||
from email.mime.text import MIMEText
|
|
||||||
from email.mime.image import MIMEImage
|
|
||||||
from email.mime.multipart import MIMEMultipart
|
|
||||||
|
|
||||||
import urllib
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
# 创建一个带附件的邮件消息对象
|
|
||||||
message = MIMEMultipart()
|
|
||||||
|
|
||||||
# 创建文本内容
|
|
||||||
text_content = MIMEText('附件中有本月数据请查收', 'plain', 'utf-8')
|
|
||||||
message['Subject'] = Header('本月数据', 'utf-8')
|
|
||||||
# 将文本内容添加到邮件消息对象中
|
|
||||||
message.attach(text_content)
|
|
||||||
|
|
||||||
# 读取文件并将文件作为附件添加到邮件消息对象中
|
|
||||||
with open('/Users/Hao/Desktop/hello.txt', 'rb') as f:
|
|
||||||
txt = MIMEText(f.read(), 'base64', 'utf-8')
|
|
||||||
txt['Content-Type'] = 'text/plain'
|
|
||||||
txt['Content-Disposition'] = 'attachment; filename=hello.txt'
|
|
||||||
message.attach(txt)
|
|
||||||
# 读取文件并将文件作为附件添加到邮件消息对象中
|
|
||||||
with open('/Users/Hao/Desktop/汇总数据.xlsx', 'rb') as f:
|
|
||||||
xls = MIMEText(f.read(), 'base64', 'utf-8')
|
|
||||||
xls['Content-Type'] = 'application/vnd.ms-excel'
|
|
||||||
xls['Content-Disposition'] = 'attachment; filename=month-data.xlsx'
|
|
||||||
message.attach(xls)
|
|
||||||
|
|
||||||
# 创建SMTP对象
|
|
||||||
smtper = SMTP('smtp.126.com')
|
|
||||||
# 开启安全连接
|
|
||||||
# smtper.starttls()
|
|
||||||
sender = 'abcdefg@126.com'
|
|
||||||
receivers = ['uvwxyz@qq.com']
|
|
||||||
# 登录到SMTP服务器
|
|
||||||
# 请注意此处不是使用密码而是邮件客户端授权码进行登录
|
|
||||||
# 对此有疑问的读者可以联系自己使用的邮件服务器客服
|
|
||||||
smtper.login(sender, 'secretpass')
|
|
||||||
# 发送邮件
|
|
||||||
smtper.sendmail(sender, receivers, message.as_string())
|
|
||||||
# 与邮件服务器断开连接
|
|
||||||
smtper.quit()
|
|
||||||
print('发送完成!')
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
||||||
```
|
|
||||||
|
|
||||||
### 发送短信
|
|
||||||
|
|
||||||
发送短信也是项目中常见的功能,网站的注册码、验证码、营销信息基本上都是通过短信来发送给用户的。在下面的代码中我们使用了[互亿无线](http://www.ihuyi.com/)短信平台(该平台为注册用户提供了50条免费短信以及常用开发语言发送短信的demo,可以登录该网站并在用户自服务页面中对短信进行配置)提供的API接口实现了发送短信的服务,当然国内的短信平台很多,读者可以根据自己的需要进行选择(通常会考虑费用预算、短信达到率、使用的难易程度等指标),如果需要在商业项目中使用短信服务建议购买短信平台提供的套餐服务。
|
|
||||||
|
|
||||||
```Python
|
|
||||||
import urllib.parse
|
|
||||||
import http.client
|
|
||||||
import json
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
host = "106.ihuyi.com"
|
|
||||||
sms_send_uri = "/webservice/sms.php?method=Submit"
|
|
||||||
# 下面的参数需要填入自己注册的账号和对应的密码
|
|
||||||
params = urllib.parse.urlencode({'account': '你自己的账号', 'password' : '你自己的密码', 'content': '您的验证码是:147258。请不要把验证码泄露给其他人。', 'mobile': '接收者的手机号', 'format':'json' })
|
|
||||||
print(params)
|
|
||||||
headers = {'Content-type': 'application/x-www-form-urlencoded', 'Accept': 'text/plain'}
|
|
||||||
conn = http.client.HTTPConnection(host, port=80, timeout=30)
|
|
||||||
conn.request('POST', sms_send_uri, params, headers)
|
|
||||||
response = conn.getresponse()
|
|
||||||
response_str = response.read()
|
|
||||||
jsonstr = response_str.decode('utf-8')
|
|
||||||
print(json.loads(jsonstr))
|
|
||||||
conn.close()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
@ -1,78 +1,78 @@
|
||||||
import pygame
|
import pygame
|
||||||
|
|
||||||
EMPTY = 0
|
EMPTY = 0
|
||||||
BLACK = 1
|
BLACK = 1
|
||||||
WHITE = 2
|
WHITE = 2
|
||||||
|
|
||||||
black_color = [0, 0, 0]
|
black_color = [0, 0, 0]
|
||||||
white_color = [255, 255, 255]
|
white_color = [255, 255, 255]
|
||||||
|
|
||||||
|
|
||||||
class RenjuBoard(object):
|
class RenjuBoard(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._board = [[]] * 15
|
self._board = [[]] * 15
|
||||||
self.reset()
|
self.reset()
|
||||||
|
|
||||||
def reset(self):
|
def reset(self):
|
||||||
for row in range(len(self._board)):
|
for row in range(len(self._board)):
|
||||||
self._board[row] = [EMPTY] * 15
|
self._board[row] = [EMPTY] * 15
|
||||||
|
|
||||||
def move(self, row, col, is_black):
|
def move(self, row, col, is_black):
|
||||||
if self._board[row][col] == EMPTY:
|
if self._board[row][col] == EMPTY:
|
||||||
self._board[row][col] = BLACK if is_black else WHITE
|
self._board[row][col] = BLACK if is_black else WHITE
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def draw(self, screen):
|
def draw(self, screen):
|
||||||
for index in range(1, 16):
|
for index in range(1, 16):
|
||||||
pygame.draw.line(screen, black_color,
|
pygame.draw.line(screen, black_color,
|
||||||
[40, 40 * index], [600, 40 * index], 1)
|
[40, 40 * index], [600, 40 * index], 1)
|
||||||
pygame.draw.line(screen, black_color,
|
pygame.draw.line(screen, black_color,
|
||||||
[40 * index, 40], [40 * index, 600], 1)
|
[40 * index, 40], [40 * index, 600], 1)
|
||||||
pygame.draw.rect(screen, black_color, [36, 36, 568, 568], 4)
|
pygame.draw.rect(screen, black_color, [36, 36, 568, 568], 4)
|
||||||
pygame.draw.circle(screen, black_color, [320, 320], 5, 0)
|
pygame.draw.circle(screen, black_color, [320, 320], 5, 0)
|
||||||
pygame.draw.circle(screen, black_color, [160, 160], 5, 0)
|
pygame.draw.circle(screen, black_color, [160, 160], 5, 0)
|
||||||
pygame.draw.circle(screen, black_color, [480, 480], 5, 0)
|
pygame.draw.circle(screen, black_color, [480, 480], 5, 0)
|
||||||
pygame.draw.circle(screen, black_color, [480, 160], 5, 0)
|
pygame.draw.circle(screen, black_color, [480, 160], 5, 0)
|
||||||
pygame.draw.circle(screen, black_color, [160, 480], 5, 0)
|
pygame.draw.circle(screen, black_color, [160, 480], 5, 0)
|
||||||
for row in range(len(self._board)):
|
for row in range(len(self._board)):
|
||||||
for col in range(len(self._board[row])):
|
for col in range(len(self._board[row])):
|
||||||
if self._board[row][col] != EMPTY:
|
if self._board[row][col] != EMPTY:
|
||||||
ccolor = black_color \
|
ccolor = black_color \
|
||||||
if self._board[row][col] == BLACK else white_color
|
if self._board[row][col] == BLACK else white_color
|
||||||
pos = [40 * (col + 1), 40 * (row + 1)]
|
pos = [40 * (col + 1), 40 * (row + 1)]
|
||||||
pygame.draw.circle(screen, ccolor, pos, 20, 0)
|
pygame.draw.circle(screen, ccolor, pos, 20, 0)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
board = RenjuBoard()
|
board = RenjuBoard()
|
||||||
is_black = True
|
is_black = True
|
||||||
pygame.init()
|
pygame.init()
|
||||||
pygame.display.set_caption('五子棋')
|
pygame.display.set_caption('五子棋')
|
||||||
screen = pygame.display.set_mode([640, 640])
|
screen = pygame.display.set_mode([640, 640])
|
||||||
screen.fill([255, 255, 0])
|
screen.fill([255, 255, 0])
|
||||||
board.draw(screen)
|
board.draw(screen)
|
||||||
pygame.display.flip()
|
pygame.display.flip()
|
||||||
running = True
|
running = True
|
||||||
while running:
|
while running:
|
||||||
for event in pygame.event.get():
|
for event in pygame.event.get():
|
||||||
if event.type == pygame.QUIT:
|
if event.type == pygame.QUIT:
|
||||||
running = False
|
running = False
|
||||||
elif event.type == pygame.KEYUP:
|
elif event.type == pygame.KEYUP:
|
||||||
pass
|
pass
|
||||||
elif event.type == pygame.MOUSEBUTTONDOWN\
|
elif event.type == pygame.MOUSEBUTTONDOWN\
|
||||||
and event.button == 1:
|
and event.button == 1:
|
||||||
x, y = event.pos
|
x, y = event.pos
|
||||||
row = round((y - 40) / 40)
|
row = round((y - 40) / 40)
|
||||||
col = round((x - 40) / 40)
|
col = round((x - 40) / 40)
|
||||||
if board.move(row, col, is_black):
|
if board.move(row, col, is_black):
|
||||||
is_black = not is_black
|
is_black = not is_black
|
||||||
screen.fill([255, 255, 0])
|
screen.fill([255, 255, 0])
|
||||||
board.draw(screen)
|
board.draw(screen)
|
||||||
pygame.display.flip()
|
pygame.display.flip()
|
||||||
pygame.quit()
|
pygame.quit()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
@ -1,334 +1,334 @@
|
||||||
from abc import ABCMeta, abstractmethod
|
from abc import ABCMeta, abstractmethod
|
||||||
from enum import Enum, unique
|
from enum import Enum, unique
|
||||||
from random import randrange
|
from random import randrange
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
|
|
||||||
import pygame
|
import pygame
|
||||||
|
|
||||||
|
|
||||||
class Color(object):
|
class Color(object):
|
||||||
"""颜色"""
|
"""颜色"""
|
||||||
|
|
||||||
GRAY = (242, 242, 242)
|
GRAY = (242, 242, 242)
|
||||||
BLACK = (0, 0, 0)
|
BLACK = (0, 0, 0)
|
||||||
GREEN = (0, 255, 0)
|
GREEN = (0, 255, 0)
|
||||||
PINK = (255, 20, 147)
|
PINK = (255, 20, 147)
|
||||||
|
|
||||||
|
|
||||||
@unique
|
@unique
|
||||||
class Direction(Enum):
|
class Direction(Enum):
|
||||||
"""方向"""
|
"""方向"""
|
||||||
|
|
||||||
UP = 0
|
UP = 0
|
||||||
RIGHT = 1
|
RIGHT = 1
|
||||||
DOWN = 2
|
DOWN = 2
|
||||||
LEFT = 3
|
LEFT = 3
|
||||||
|
|
||||||
|
|
||||||
class GameObject(object, metaclass=ABCMeta):
|
class GameObject(object, metaclass=ABCMeta):
|
||||||
"""游戏中的对象"""
|
"""游戏中的对象"""
|
||||||
|
|
||||||
def __init__(self, x=0, y=0, color=Color.BLACK):
|
def __init__(self, x=0, y=0, color=Color.BLACK):
|
||||||
"""
|
"""
|
||||||
初始化方法
|
初始化方法
|
||||||
|
|
||||||
:param x: 横坐标
|
:param x: 横坐标
|
||||||
:param y: 纵坐标
|
:param y: 纵坐标
|
||||||
:param color: 颜色
|
:param color: 颜色
|
||||||
"""
|
"""
|
||||||
self._x = x
|
self._x = x
|
||||||
self._y = y
|
self._y = y
|
||||||
self._color = color
|
self._color = color
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def x(self):
|
def x(self):
|
||||||
return self._x
|
return self._x
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def y(self):
|
def y(self):
|
||||||
return self._y
|
return self._y
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def draw(self, screen):
|
def draw(self, screen):
|
||||||
"""
|
"""
|
||||||
绘制
|
绘制
|
||||||
|
|
||||||
:param screen: 屏幕
|
:param screen: 屏幕
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Wall(GameObject):
|
class Wall(GameObject):
|
||||||
"""围墙"""
|
"""围墙"""
|
||||||
|
|
||||||
def __init__(self, x, y, width, height, color=Color.BLACK):
|
def __init__(self, x, y, width, height, color=Color.BLACK):
|
||||||
"""
|
"""
|
||||||
初始化方法
|
初始化方法
|
||||||
|
|
||||||
:param x: 横坐标
|
:param x: 横坐标
|
||||||
:param y: 纵坐标
|
:param y: 纵坐标
|
||||||
:param width: 宽度
|
:param width: 宽度
|
||||||
:param height: 高度
|
:param height: 高度
|
||||||
:param color: 颜色
|
:param color: 颜色
|
||||||
"""
|
"""
|
||||||
super().__init__(x, y, color)
|
super().__init__(x, y, color)
|
||||||
self._width = width
|
self._width = width
|
||||||
self._height = height
|
self._height = height
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def width(self):
|
def width(self):
|
||||||
return self._width
|
return self._width
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def height(self):
|
def height(self):
|
||||||
return self._height
|
return self._height
|
||||||
|
|
||||||
def draw(self, screen):
|
def draw(self, screen):
|
||||||
pygame.draw.rect(screen, self._color,
|
pygame.draw.rect(screen, self._color,
|
||||||
(self._x, self._y, self._width, self._height), 4)
|
(self._x, self._y, self._width, self._height), 4)
|
||||||
|
|
||||||
|
|
||||||
class Food(GameObject):
|
class Food(GameObject):
|
||||||
"""食物"""
|
"""食物"""
|
||||||
|
|
||||||
def __init__(self, x, y, size, color=Color.PINK):
|
def __init__(self, x, y, size, color=Color.PINK):
|
||||||
"""
|
"""
|
||||||
初始化方法
|
初始化方法
|
||||||
|
|
||||||
:param x: 横坐标
|
:param x: 横坐标
|
||||||
:param y: 纵坐标
|
:param y: 纵坐标
|
||||||
:param size: 大小
|
:param size: 大小
|
||||||
:param color: 颜色
|
:param color: 颜色
|
||||||
"""
|
"""
|
||||||
super().__init__(x, y, color)
|
super().__init__(x, y, color)
|
||||||
self._size = size
|
self._size = size
|
||||||
self._hidden = False
|
self._hidden = False
|
||||||
|
|
||||||
def draw(self, screen):
|
def draw(self, screen):
|
||||||
if not self._hidden:
|
if not self._hidden:
|
||||||
pygame.draw.circle(screen, self._color,
|
pygame.draw.circle(screen, self._color,
|
||||||
(self._x + self._size // 2, self._y + self._size // 2),
|
(self._x + self._size // 2, self._y + self._size // 2),
|
||||||
self._size // 2, 0)
|
self._size // 2, 0)
|
||||||
self._hidden = not self._hidden
|
self._hidden = not self._hidden
|
||||||
|
|
||||||
|
|
||||||
class SnakeNode(GameObject):
|
class SnakeNode(GameObject):
|
||||||
"""蛇身上的节点"""
|
"""蛇身上的节点"""
|
||||||
|
|
||||||
def __init__(self, x, y, size, color=Color.GREEN):
|
def __init__(self, x, y, size, color=Color.GREEN):
|
||||||
"""
|
"""
|
||||||
初始化方法
|
初始化方法
|
||||||
|
|
||||||
:param x: 横坐标
|
:param x: 横坐标
|
||||||
:param y: 纵坐标
|
:param y: 纵坐标
|
||||||
:param size: 大小
|
:param size: 大小
|
||||||
:param color: 颜色
|
:param color: 颜色
|
||||||
"""
|
"""
|
||||||
super().__init__(x, y, color)
|
super().__init__(x, y, color)
|
||||||
self._size = size
|
self._size = size
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def size(self):
|
def size(self):
|
||||||
return self._size
|
return self._size
|
||||||
|
|
||||||
def draw(self, screen):
|
def draw(self, screen):
|
||||||
pygame.draw.rect(screen, self._color,
|
pygame.draw.rect(screen, self._color,
|
||||||
(self._x, self._y, self._size, self._size), 0)
|
(self._x, self._y, self._size, self._size), 0)
|
||||||
pygame.draw.rect(screen, Color.BLACK,
|
pygame.draw.rect(screen, Color.BLACK,
|
||||||
(self._x, self._y, self._size, self._size), 1)
|
(self._x, self._y, self._size, self._size), 1)
|
||||||
|
|
||||||
|
|
||||||
class Snake(GameObject):
|
class Snake(GameObject):
|
||||||
"""蛇"""
|
"""蛇"""
|
||||||
|
|
||||||
def __init__(self, x, y, size=20, length=5):
|
def __init__(self, x, y, size=20, length=5):
|
||||||
"""
|
"""
|
||||||
初始化方法
|
初始化方法
|
||||||
|
|
||||||
:param x: 横坐标
|
:param x: 横坐标
|
||||||
:param y: 纵坐标
|
:param y: 纵坐标
|
||||||
:param size: 大小
|
:param size: 大小
|
||||||
:param length: 初始长度
|
:param length: 初始长度
|
||||||
"""
|
"""
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self._dir = Direction.LEFT
|
self._dir = Direction.LEFT
|
||||||
self._nodes = []
|
self._nodes = []
|
||||||
self._alive = True
|
self._alive = True
|
||||||
self._new_dir = None
|
self._new_dir = None
|
||||||
for index in range(length):
|
for index in range(length):
|
||||||
node = SnakeNode(x + index * size, y, size)
|
node = SnakeNode(x + index * size, y, size)
|
||||||
self._nodes.append(node)
|
self._nodes.append(node)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def dir(self):
|
def dir(self):
|
||||||
return self._dir
|
return self._dir
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def alive(self):
|
def alive(self):
|
||||||
return self._alive
|
return self._alive
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def head(self):
|
def head(self):
|
||||||
return self._nodes[0]
|
return self._nodes[0]
|
||||||
|
|
||||||
def change_dir(self, new_dir):
|
def change_dir(self, new_dir):
|
||||||
"""
|
"""
|
||||||
改变方向
|
改变方向
|
||||||
|
|
||||||
:param new_dir: 新方向
|
:param new_dir: 新方向
|
||||||
"""
|
"""
|
||||||
if new_dir != self._dir and \
|
if new_dir != self._dir and \
|
||||||
(self._dir.value + new_dir.value) % 2 != 0:
|
(self._dir.value + new_dir.value) % 2 != 0:
|
||||||
self._new_dir = new_dir
|
self._new_dir = new_dir
|
||||||
|
|
||||||
def move(self):
|
def move(self):
|
||||||
"""移动"""
|
"""移动"""
|
||||||
if self._new_dir:
|
if self._new_dir:
|
||||||
self._dir, self._new_dir = self._new_dir, None
|
self._dir, self._new_dir = self._new_dir, None
|
||||||
snake_dir = self._dir
|
snake_dir = self._dir
|
||||||
x, y, size = self.head.x, self.head.y, self.head.size
|
x, y, size = self.head.x, self.head.y, self.head.size
|
||||||
if snake_dir == Direction.UP:
|
if snake_dir == Direction.UP:
|
||||||
y -= size
|
y -= size
|
||||||
elif snake_dir == Direction.RIGHT:
|
elif snake_dir == Direction.RIGHT:
|
||||||
x += size
|
x += size
|
||||||
elif snake_dir == Direction.DOWN:
|
elif snake_dir == Direction.DOWN:
|
||||||
y += size
|
y += size
|
||||||
else:
|
else:
|
||||||
x -= size
|
x -= size
|
||||||
new_head = SnakeNode(x, y, size)
|
new_head = SnakeNode(x, y, size)
|
||||||
self._nodes.insert(0, new_head)
|
self._nodes.insert(0, new_head)
|
||||||
self._nodes.pop()
|
self._nodes.pop()
|
||||||
|
|
||||||
def collide(self, wall):
|
def collide(self, wall):
|
||||||
"""
|
"""
|
||||||
撞墙
|
撞墙
|
||||||
|
|
||||||
:param wall: 围墙
|
:param wall: 围墙
|
||||||
"""
|
"""
|
||||||
head = self.head
|
head = self.head
|
||||||
if head.x < wall.x or head.x + head.size > wall.x + wall.width \
|
if head.x < wall.x or head.x + head.size > wall.x + wall.width \
|
||||||
or head.y < wall.y or head.y + head.size > wall.y + wall.height:
|
or head.y < wall.y or head.y + head.size > wall.y + wall.height:
|
||||||
self._alive = False
|
self._alive = False
|
||||||
|
|
||||||
def eat_food(self, food):
|
def eat_food(self, food):
|
||||||
"""
|
"""
|
||||||
吃食物
|
吃食物
|
||||||
|
|
||||||
:param food: 食物
|
:param food: 食物
|
||||||
|
|
||||||
:return: 吃到食物返回True否则返回False
|
:return: 吃到食物返回True否则返回False
|
||||||
"""
|
"""
|
||||||
if self.head.x == food.x and self.head.y == food.y:
|
if self.head.x == food.x and self.head.y == food.y:
|
||||||
tail = self._nodes[-1]
|
tail = self._nodes[-1]
|
||||||
self._nodes.append(tail)
|
self._nodes.append(tail)
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def eat_self(self):
|
def eat_self(self):
|
||||||
"""咬自己"""
|
"""咬自己"""
|
||||||
for index in range(4, len(self._nodes)):
|
for index in range(4, len(self._nodes)):
|
||||||
node = self._nodes[index]
|
node = self._nodes[index]
|
||||||
if node.x == self.head.x and node.y == self.head.y:
|
if node.x == self.head.x and node.y == self.head.y:
|
||||||
self._alive = False
|
self._alive = False
|
||||||
|
|
||||||
def draw(self, screen):
|
def draw(self, screen):
|
||||||
for node in self._nodes:
|
for node in self._nodes:
|
||||||
node.draw(screen)
|
node.draw(screen)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
||||||
def refresh():
|
def refresh():
|
||||||
"""刷新游戏窗口"""
|
"""刷新游戏窗口"""
|
||||||
screen.fill(Color.GRAY)
|
screen.fill(Color.GRAY)
|
||||||
wall.draw(screen)
|
wall.draw(screen)
|
||||||
food.draw(screen)
|
food.draw(screen)
|
||||||
snake.draw(screen)
|
snake.draw(screen)
|
||||||
pygame.display.flip()
|
pygame.display.flip()
|
||||||
|
|
||||||
def handle_key_event(key_event):
|
def handle_key_event(key_event):
|
||||||
"""处理按键事件"""
|
"""处理按键事件"""
|
||||||
key = key_event.key
|
key = key_event.key
|
||||||
if key == pygame.K_F2:
|
if key == pygame.K_F2:
|
||||||
reset_game()
|
reset_game()
|
||||||
elif key in (pygame.K_a, pygame.K_w, pygame.K_d, pygame.K_s):
|
elif key in (pygame.K_a, pygame.K_w, pygame.K_d, pygame.K_s):
|
||||||
if snake.alive:
|
if snake.alive:
|
||||||
if key == pygame.K_w:
|
if key == pygame.K_w:
|
||||||
new_dir = Direction.UP
|
new_dir = Direction.UP
|
||||||
elif key == pygame.K_d:
|
elif key == pygame.K_d:
|
||||||
new_dir = Direction.RIGHT
|
new_dir = Direction.RIGHT
|
||||||
elif key == pygame.K_s:
|
elif key == pygame.K_s:
|
||||||
new_dir = Direction.DOWN
|
new_dir = Direction.DOWN
|
||||||
else:
|
else:
|
||||||
new_dir = Direction.LEFT
|
new_dir = Direction.LEFT
|
||||||
snake.change_dir(new_dir)
|
snake.change_dir(new_dir)
|
||||||
|
|
||||||
def create_food():
|
def create_food():
|
||||||
"""创建食物"""
|
"""创建食物"""
|
||||||
unit_size = snake.head.size
|
unit_size = snake.head.size
|
||||||
max_row = wall.height // unit_size
|
max_row = wall.height // unit_size
|
||||||
max_col = wall.width // unit_size
|
max_col = wall.width // unit_size
|
||||||
row = randrange(0, max_row)
|
row = randrange(0, max_row)
|
||||||
col = randrange(0, max_col)
|
col = randrange(0, max_col)
|
||||||
return Food(wall.x + unit_size * col, wall.y + unit_size * row, unit_size)
|
return Food(wall.x + unit_size * col, wall.y + unit_size * row, unit_size)
|
||||||
|
|
||||||
def reset_game():
|
def reset_game():
|
||||||
"""重置游戏"""
|
"""重置游戏"""
|
||||||
nonlocal food, snake
|
nonlocal food, snake
|
||||||
food = create_food()
|
food = create_food()
|
||||||
snake = Snake(250, 290)
|
snake = Snake(250, 290)
|
||||||
|
|
||||||
def background_task():
|
def background_task():
|
||||||
nonlocal running, food
|
nonlocal running, food
|
||||||
while running:
|
while running:
|
||||||
if snake.alive:
|
if snake.alive:
|
||||||
refresh()
|
refresh()
|
||||||
clock.tick(10)
|
clock.tick(10)
|
||||||
if snake.alive:
|
if snake.alive:
|
||||||
snake.move()
|
snake.move()
|
||||||
snake.collide(wall)
|
snake.collide(wall)
|
||||||
if snake.eat_food(food):
|
if snake.eat_food(food):
|
||||||
food = create_food()
|
food = create_food()
|
||||||
snake.eat_self()
|
snake.eat_self()
|
||||||
|
|
||||||
"""
|
"""
|
||||||
class BackgroundTask(Thread):
|
class BackgroundTask(Thread):
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
nonlocal running, food
|
nonlocal running, food
|
||||||
while running:
|
while running:
|
||||||
if snake.alive:
|
if snake.alive:
|
||||||
refresh()
|
refresh()
|
||||||
clock.tick(10)
|
clock.tick(10)
|
||||||
if snake.alive:
|
if snake.alive:
|
||||||
snake.move()
|
snake.move()
|
||||||
snake.collide(wall)
|
snake.collide(wall)
|
||||||
if snake.eat_food(food):
|
if snake.eat_food(food):
|
||||||
food = create_food()
|
food = create_food()
|
||||||
snake.eat_self()
|
snake.eat_self()
|
||||||
"""
|
"""
|
||||||
|
|
||||||
wall = Wall(10, 10, 600, 600)
|
wall = Wall(10, 10, 600, 600)
|
||||||
snake = Snake(250, 290)
|
snake = Snake(250, 290)
|
||||||
food = create_food()
|
food = create_food()
|
||||||
pygame.init()
|
pygame.init()
|
||||||
screen = pygame.display.set_mode((620, 620))
|
screen = pygame.display.set_mode((620, 620))
|
||||||
pygame.display.set_caption('贪吃蛇')
|
pygame.display.set_caption('贪吃蛇')
|
||||||
# 创建控制游戏每秒帧数的时钟
|
# 创建控制游戏每秒帧数的时钟
|
||||||
clock = pygame.time.Clock()
|
clock = pygame.time.Clock()
|
||||||
running = True
|
running = True
|
||||||
# 启动后台线程负责刷新窗口和让蛇移动
|
# 启动后台线程负责刷新窗口和让蛇移动
|
||||||
# BackgroundTask().start()
|
# BackgroundTask().start()
|
||||||
Thread(target=background_task).start()
|
Thread(target=background_task).start()
|
||||||
# 处理事件的消息循环
|
# 处理事件的消息循环
|
||||||
while running:
|
while running:
|
||||||
for event in pygame.event.get():
|
for event in pygame.event.get():
|
||||||
if event.type == pygame.QUIT:
|
if event.type == pygame.QUIT:
|
||||||
running = False
|
running = False
|
||||||
elif event.type == pygame.KEYDOWN:
|
elif event.type == pygame.KEYDOWN:
|
||||||
handle_key_event(event)
|
handle_key_event(event)
|
||||||
pygame.quit()
|
pygame.quit()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue