基于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日

相关文章

  • python学习开发mock接口

    Python学习开发Mock接口 在进行前后端项目开发中,前后端联调过程中可能会出现前后端开发进度不一致或者依赖的接口尚未完成等问题,导致耗费大量时间等问题。这时可以使用Mock接口的技术手段,在后端接口未完成的情况下,模拟数据返回从而达到开发目的。 本篇攻略将介绍Python Mock接口的开发,并包含两个示例说明。 准备工作 安装Python开发环境 本…

    Flask 2023年5月16日
    00
  • Flask深入了解Jinja2引擎的用法

    首先介绍一下Jinja2引擎,它是一个基于Python的模板引擎,常用于web开发中生成HTML页面。 一、Jinja2引擎的基本用法 在Flask中,可以通过实例化Jinja2对象,将其与app关联,来使用Jinja2引擎。示例代码如下: from flask import Flask, render_template from jinja2 import…

    Flask 2023年5月15日
    00
  • Flask实现图片的上传、下载及展示示例代码

    本篇回答将介绍如何在Flask中实现图片上传、下载及展示,并提供两个完整的示例代码。 示例1:图片上传 前置要求 在进行图片上传之前,需要安装Flask及Flask-Uploads库: pip install Flask Flask-Uploads Step1:创建Flask应用 from flask import Flask app = Flask(__n…

    Flask 2023年5月15日
    00
  • Flask 上传自定义头像的实例详解

    我们来详细讲解一下“Flask 上传自定义头像的实例详解”的完整攻略。 1. 确定需求 首先,我们需要明确我们的需求,即用户能够上传自己的头像,并在用户页面中显示。这个功能可以分为两个部分: 用户头像上传:用户需要有一个页面来上传头像,并把上传的头像保存在服务器上。 用户头像显示:用户上传了头像后,在用户页面中可以显示出来。 2. 创建Flask应用 在开始…

    Flask 2023年5月16日
    00
  • Python flask与fastapi性能测试方法介绍

    下面我将为你详细讲解“Python flask与fastapi性能测试方法介绍”的完整攻略,包括性能测试的基本概念、测试工具的选择、性能测试的流程以及示例说明。 基本概念 在进行性能测试之前,我们需要先了解一些基本概念。 性能测试 性能测试是用来测试应用程序在特定负载下的性能表现。其目的是找出应用程序处理高负载时的瓶颈,评估应用程序的稳定性和可靠性,以及为性…

    Flask 2023年5月15日
    00
  • 公众号接入chatGPT的详细教程 附Python源码

    公众号接入chatGPT的详细教程,下面我会讲解相关步骤。 准备工作 在开始整个接入chatGPT的流程之前,需要准备以下的相关工作: 注册微信公众号并获取appid和appsecret,并在后台配置好服务器地址。 获取chatGPT的API Key。 接入流程 1. 获取用户openid 首先需要获取用户的openid,用于在后面请求chatGPT时进行身…

    Flask 2023年5月15日
    00
  • flask/django 动态查询表结构相同表名不同数据的Model实现方法

    Flask/Django是目前非常流行的Python Web框架,可以用于开发各种规模的Web应用程序。在开发Web应用程序时,经常需要动态地查询不同数据表中结构相同的数据。本文将介绍如何实现动态查询表结构相同、表名不同的数据表。 方法一:使用Django的多数据库 在Django应用程序中,可以使用多个数据库连接(Multi-database)来连接多个数…

    Flask 2023年5月16日
    00
  • 详解python执行shell脚本创建用户及相关操作

    下面我将详细讲解如何使用Python执行Shell脚本并创建用户及相关操作,并提供两个示例作为说明。 进行前的准备工作 在开始之前,我们需要确认Python和Shell都已经安装好并且可用。同时,我们需要明确本次操作需要使用到的Python模块和Shell命令。具体的准备工作如下: Python模块 本次操作需要使用到的Python模块有: os: 用于执行…

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