基于flask实现五子棋小游戏

下面我就来详细讲解“基于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/路由接收前端发送的请求,调用gobang.fill函数进行逻辑处理,返回JSON格式的数据。

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技术站

(0)
上一篇 2023年5月15日
下一篇 2023年5月15日

相关文章

  • Flask框架运用Ajax实现数据交互的示例代码

    下面是关于“Flask框架运用Ajax实现数据交互的示例代码”的完整攻略,其中包含两个示例说明。 示例一:通过Ajax获取服务器数据 我们假设前端页面上有一个按钮,点击后会向服务器发送一个请求,获取服务器返回的数据,然后将数据展示在页面上。具体实现步骤如下: 在前端页面中,使用jQuery库的$.ajax()函数向服务器发送GET请求,请求数据的URL为服务…

    Flask 2023年5月16日
    00
  • Python Flask框架扩展操作示例

    接下来我将为您详细讲解“Python Flask框架扩展操作示例”的完整攻略,该攻略包含两条示例说明。 示例一:Flask插件Flask-Cache 什么是Flask-Cache? Flask-Cache是Flask框架的一个插件,它提供了对缓存的支持。 如何安装Flask-Cache? 使用pip工具即可,命令如下: $ pip install Flask…

    Flask 2023年5月15日
    00
  • 基于go-cqhttp与Flask搭建定制机器人项目实战示例

    下面我将详细讲解“基于go-cqhttp与Flask搭建定制机器人项目实战示例”的完整攻略,这个过程中包含两条示例的说明。 简介 本攻略将介绍使用go-cqhttp和Flask两个工具搭建一个定制的QQ机器人项目。其中第一条示例将展示如何使用go-cqhttp和Flask来实现一个抢购机器人,而第二条则将介绍如何使用这两个工具来实现一个天气查询机器人。 环境…

    Flask 2023年5月16日
    00
  • python 5个顶级异步框架推荐

    Python 5个顶级异步框架推荐 异步编程已经在Python编程中变得越来越常见。Python发展出了许多不同的异步框架来帮助编程者简化异步编程的过程。这里是Python 5个顶级异步框架推荐: 1. asyncio asyncio 是官方内置的异步库,可以用于编写单线程的并发代码。它提供coroutine、asynchronous function、fu…

    Flask 2023年5月16日
    00
  • python文件路径操作方法总结

    基于”python文件路径操作方法总结”这个主题,我会给出完整的攻略,包括以下几个部分的讲解: 什么是文件路径? Python中的文件路径表示方式 文件路径的操作方式(包括绝对路径和相对路径) 示例说明 1. 什么是文件路径? 文件路径是标识文件在计算机上存储位置的一串字符,一般包括文件所在驱动器、目录、文件名和文件扩展名等内容。 在Windows上,文件路…

    Flask 2023年5月16日
    00
  • flask框架路由常用定义方式总结

    让我为你详细讲解一下“flask框架路由常用定义方式总结”的完整攻略。 什么是flask框架? Flask是一个基于 Python 语言的轻量级 Web 开发框架,使用 Werkzeug 作为 Web 服务器网关接口,使用 Jinja2 模板引擎,这两个库也都是 Flask 标配。它设计精简,易于扩展,使它成为很多 Web 开发者喜欢使用的框架之一。 什么是…

    Flask 2023年5月15日
    00
  • Flask如何接收前端ajax传来的表单(包含文件)

    要让Flask能够接收前端Ajax传来的表单数据(包括文件),需要注意以下几个步骤: 在前端使用ajax请求时,需要将请求内容以FormData的形式打包,以支持传输文件。 在Flask后端,需要使用request.form和request.files两个对象分别获取表单字段和文件数据。 某些情况下,上传文件时需要设置Flask应用程序的配置,以支持文件上传…

    Flask 2023年5月16日
    00
  • python中的信号通信 blinker的使用小结

    标题:Python中的信号通信 blinker的使用小结 什么是blinker? blinker 是一个简单的 Python 库,作用是用于处理事件的发布和订阅。它提供了一个 Signal 类型,用于将函数连接到一个事件源上,并在该事件源发布事件时自动触发对应的函数。 安装blinker 首先需要安装 blinker 库,在命令行中使用 pip 命令进行安装…

    Flask 2023年5月16日
    00
合作推广
合作推广
分享本页
返回顶部