下面我就来详细讲解“基于flask实现五子棋小游戏”的完整攻略。
1. 确定游戏规则
在开发五子棋小游戏之前,需要明确游戏规则。五子棋规则简述:两人轮流在棋盘上落子,黑方先行。当一方先在横、竖或斜行连续放置五个棋子时,游戏结束,该方胜利。
2. 创建项目及相关文件
在命令行下进入项目文件夹,执行以下命令创建项目:
mkdir flask_gobang
cd flask_gobang
python -m venv venv
source venv/bin/activate
pip install Flask
新建一个app.py文件,作为入口文件。如下所示:
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
if __name__ == '__main__':
app.run(debug=True)
同时,在项目文件夹中创建templates文件夹,新建index.html文件,用于渲染网页:
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<title>Gobang Game</title>
</head>
<body>
<h1>Gobang Game</h1>
</body>
</html>
3. 实现页面布局
五子棋棋盘由16行16列共256个小格组成。我们需要先在index.html文件中添加一个table元素,来呈现五子棋的棋盘:
<table>
<tbody>
{% for i in range(16) %}
<tr>
{% for j in range(16) %}
<td></td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
以上代码是使用flask-templates引擎的语法,for循环来生成16*16的棋盘格子。
4. 实现落子交互
接下来,需要实现落子交互功能,即用户点击空格子,会在这个格子上出现相应的棋子。
在index.html文件中添加JavaScript代码:
<script>
function fillCell(ele, row, col) {
var xhr = new XMLHttpRequest();
xhr.open('GET', '/fill/' + row + '-' + col, true);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
var json = JSON.parse(xhr.responseText);
if (json.result) {
ele.style.backgroundImage = 'url(' + json.src + ')';
} else {
alert(json.msg);
}
}
};
xhr.send();
}
document.querySelector('table').addEventListener('click', function(e) {
var ele = e.target;
if (ele.nodeName === 'TD' && !ele.style.backgroundImage) {
var row = ele.parentNode.rowIndex;
var col = ele.cellIndex;
fillCell(ele, row, col);
}
});
</script>
以上代码中,fillCell函数会发送GET请求,请求URL为/fill/+行-列,获得后端响应后,将图片链接填充到相应的格子中。
同时,还需要在app.py中添加路由处理:
@app.route('/fill/<string:pos>')
def fill(pos):
row, col = [int(i) for i in pos.split('-')]
status, msg, filename = gobang.fill(row, col)
return jsonify({'result': status, 'msg': msg, 'src': url_for('static', filename=filename)})
以上代码中,/fill/
5. 实现游戏逻辑
游戏的核心逻辑在gobang.py中实现。可以调用Python面向对象思想,实现类的编写。如下所示:
import os
import uuid
from PIL import Image, ImageDraw, ImageFont
UP, DOWN, LEFT, RIGHT, LEFT_UP, LEFT_DOWN, RIGHT_UP, RIGHT_DOWN = range(8)
class Gobang:
...
以上代码定义了一个Gobang类,用于实现游戏逻辑。可以看到,这个类的变量和函数还没有定义,下面我们进行逐个定义。
5.1 初始化函数
需要首先定义类的初始化函数,完成游戏的初始化:
def __init__(self, size=16, win=5):
self.size = size # 棋盘大小
self.win = win # 需要连成的棋子数
self.turn = 0 # 当前轮到哪一方落子
# 初始化棋盘
self.board = []
for i in range(size):
self.board.append(['' for j in range(size)])
# 初始化和配置字体
self.font = ImageFont.truetype(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'static', 'DroidSans-Bold.ttf'), 64)
# 创建存储棋子的文件夹
self.img_folder = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'static', 'img')
if not os.path.exists(self.img_folder):
os.makedirs(self.img_folder)
# 初始化连续棋子的数量
self.count = [[0 for j in range(size)] for i in range(size)]
以上变量的说明:
- size:棋盘大小。
- win:需要连成的棋子数。
- turn:轮到哪一方落子。0代表黑子,1代表白子。
- board:数组,表示棋盘状态。
- font:字体对象,用于绘制棋子编号。
- img_folder:字符串,表示存储棋子的文件夹路径。
- count:二维数组,表示每个点上已连续的棋子数。
5.2 其他函数
除了初始化函数之外,还需要定义其他函数,用于实现游戏的各种功能。这里我们分别介绍这些函数。
5.2.1 get_next_pos函数
get_next_pos函数用于实现AI的落子。我们可以通过枚举棋子周围的空格子,计算每个空格子对应的得分,并选取得分最高的空格子作为AI的落子点。如下所示:
def get_next_pos(self):
scores = []
for i in range(self.size):
for j in range(self.size):
if self.board[i][j] == '':
score = 0
for direction in range(8):
score += self.get_score(i, j, direction)
scores.append(((i, j), score))
scores.sort(key=lambda x: x[1], reverse=True)
return scores[0][0]
以上代码中,计算得分的代码是使用get_score函数来实现的,我们将在后面介绍这个函数。
5.2.2 get_score函数
get_score函数用于计算当前空格子在棋盘上连续棋子数的得分。具体实现如下:
def get_score(self, row, col, direction):
score = 0
# 按照给定的方向进行遍历
for delt_row, delt_col in self.get_directions(direction):
cur_row, cur_col = row + delt_row, col + delt_col
if cur_row >= self.size or cur_col >= self.size or cur_row < 0 or cur_col < 0 or self.board[cur_row][cur_col] != self.get_turn():
continue
score += 1
while True:
cur_row, cur_col = cur_row + delt_row, cur_col + delt_col
if cur_row >= self.size or cur_col >= self.size or cur_row < 0 or cur_col < 0 or self.board[cur_row][cur_col] != self.get_turn():
break
score += 1
if cur_row >= self.size or cur_col >= self.size or cur_row < 0 or cur_col < 0 or self.board[cur_row][cur_col] != '':
continue
if score + 1 >= self.win:
return (10 ** score + 1) * (10 ** (self.win - score))
score = 0
return score
以上代码中,get_turn函数用于获取当前轮到哪一方落子。get_directions函数返回横、竖、斜向八个方向的偏移量。
5.2.3 fill函数
fill函数用于获取玩家的落子,同时也会调用AI的落子函数。具体实现如下:
def fill(self, row, col):
if self.board[row][col] != '':
return False, '此处已经有棋子了!', ''
filename = str(uuid.uuid4().hex) + '.png'
if self.turn == 0:
self.board[row][col] = 'B'
self.draw_chessman('BLACK', os.path.join(self.img_folder, filename))
else:
self.board[row][col] = 'W'
self.draw_chessman('WHITE', os.path.join(self.img_folder, filename))
self.count[row][col] = 1
if self.check_win(row, col):
return True, '你赢了!', filename
self.turn = 1 - self.turn
if self.turn == 1:
next_pos = self.get_next_pos()
self.fill(*next_pos)
return True, '', filename
以上代码中,在玩家落子的时候,会根据当前轮到哪一方落子,记录下棋子的类型,并保存棋子图片到本地文件夹。之后检查该次落子是否导致获胜,如果是,则返回胜利信息和图片链接;否则,切换轮到哪一方,并调用AI落子函数。
5.2.4 check_win函数
check_win函数用于检测当前棋盘上是否已经有一方胜利。实现方式即枚举当前落子位置周围的八个方向,计算连串棋子的数量。如果数量>=win,那么返回True,代表已经有一方胜利;否则返回False,代表游戏未结束。具体实现如下:
def check_win(self, row, col):
for direction in range(8):
if self.get_score(row, col, direction) >= self.win:
return True
return False
以上就是实现五子棋小游戏的全部代码了。
6. 运行游戏
除了上述介绍的代码之外,还需要在运行前添加部分参数和代码。需要在app.py文件中添加如下代码:
from gobang import Gobang
gobang = Gobang(size=16, win=5)
同时,需要在app.run之前添加如下一行:
app.config['SEND_FILE_MAX_AGE_DEFAULT'] = 0
这是为了防止静态资源缓存。代码添加完成后,运行命令如下:
python app.py
最后在浏览器中输入localhost:5000即可进入五子棋小游戏页面。
示例1:玩家落子
当玩家落子时,会在该处显示相应的棋子,并标注棋子编号信息。当玩家连成5个棋子时,页面会提示玩家获胜,并弹出相关对话框。
示例2:AI落子
当AI落子时,页面会出现相应的棋子,并标注棋子编号。如果AI连成5个棋子,则页面会提示AI获胜,并弹出相关对话框。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:基于flask实现五子棋小游戏 - Python技术站