20231319 2023-2024-2 《Python程序设计》实验4报告

20231319邓传山 2024-05-29 23:22:33

@

  • 20231319 2023-2024-2 《Python程序设计》实验4报告
  • 一、实验内容
  • 二、实验过程及结果
  • 1. 初始化 Pygame 画布界面
  • 2. 绘制棋盘
  • 3. 获取鼠标信息并显示落子位置
  • 4. 实现落子操作
  • 5. 判断胜利条件
  • 6.使用tkinter中的messagebox组件成功实现胜方显示。
  • 7. 完整代码
  • 三、 实验过程中遇到的问题和解决过程
  • 四、课程感悟与体会
  • 五、实验总结

20231319 2023-2024-2 《Python程序设计》实验4报告

课程:《Python程序设计》
班级: 2313
姓名: 邓传山
学号:20231319
实验教师:王志强
实验日期:2020年5月15日
必修/选修: 公选课

一、实验内容

使用pygame组件,实现双人五子棋游戏;

二、实验过程及结果

1. 初始化 Pygame 画布界面

首先,初始化 Pygame,并创建一个窗口界面。设置画布颜色为棕黄色。

import pygame
import sys
from pygame.locals import QUIT, KEYDOWN

# 初始化 Pygame
pygame.init()
# 创建窗口
screen = pygame.display.set_mode((670, 670))
screen_color = [238, 154, 73]  # 设置画布颜色

while True:
    for event in pygame.event.get():
        if event.type in (QUIT, KEYDOWN):
            sys.exit()
    screen.fill(screen_color)  # 清屏
    pygame.display.update()  # 刷新显示

2. 绘制棋盘

在画布上绘制五子棋的棋盘,包含 15x15 的网格线和中心点。

line_color = [0, 0, 0]  # 设置线条颜色

while True:
    for event in pygame.event.get():
        if event.type in (QUIT, KEYDOWN):
            sys.exit()
    screen.fill(screen_color)  # 清屏

    for i in range(27, 670, 44):
        # 画竖线
        if i == 27 or i == 670 - 27:
            pygame.draw.line(screen, line_color, [i, 27], [i, 670 - 27], 4)
        else:
            pygame.draw.line(screen, line_color, [i, 27], [i, 670 - 27], 2)
        # 画横线
        if i == 27 or i == 670 - 27:
            pygame.draw.line(screen, line_color, [27, i], [670 - 27, i], 4)
        else:
            pygame.draw.line(screen, line_color, [27, i], [670 - 27, i], 2)

    # 在棋盘中心画一个不透明的黑色小圆
    pygame.draw.circle(screen, line_color, [27 + 44 * 7, 27 + 44 * 7], 8, 0)
    pygame.display.update()  # 刷新显示

3. 获取鼠标信息并显示落子位置

获取鼠标位置,确定可以落子的具体位置,并实时显示在界面上。

def find_pos(x, y):
    for i in range(27, 670, 44):
        for j in range(27, 670, 44):
            if abs(x - i) < 22 and abs(y - j) < 22:
                return i, j
    return x, y

while True:
    for event in pygame.event.get():
        if event.type in (QUIT, KEYDOWN):
            sys.exit()
    screen.fill(screen_color)  # 清屏

    for i in range(27, 670, 44):
        # 画竖线
        if i == 27 or i == 670 - 27:
            pygame.draw.line(screen, line_color, [i, 27], [i, 670 - 27], 4)
        else:
            pygame.draw.line(screen, line_color, [i, 27], [i, 670 - 27], 2)
        # 画横线
        if i == 27或i == 670 - 27:
            pygame.draw.line(screen, line_color, [27, i], [670 - 27, i], 4)
        else:
            pygame.draw.line(screen, line_color, [27, i], [670 - 27, i], 2)

    # 在棋盘中心画一个小圆
    pygame.draw.circle(screen, line_color, [27 + 44 * 7, 27 + 44 * 7], 8, 0)

    # 获取鼠标坐标信息
    x, y = pygame.mouse.get_pos()
    x, y = find_pos(x, y)
    pygame.draw.rect(screen, [0, 229, 238], [x - 22, y - 22, 44, 44], 2, 1)

    pygame.display.update()  # 刷新显示

4. 实现落子操作

实现棋子的落子功能,包含判断当前位置是否已经落子和记录已落子的位置。

def check_over_pos(x, y, over_pos):
    for val in over_pos:
        if val[0] == [x, y]:
            return False
    return True

over_pos = []  # 已经落子的位置
white_color = [255, 255, 255]
black_color = [0, 0, 0]

while True:
    for event in pygame.event.get():
        if event.type in (QUIT, KEYDOWN):
            sys.exit()
    screen.fill(screen_color)  # 清屏

    for i in range(27, 670, 44):
        # 画竖线
        if i == 27 or i == 670 - 27:
            pygame.draw.line(screen, line_color, [i, 27], [i, 670 - 27], 4)
        else:
            pygame.draw.line(screen, line_color, [i, 27], [i, 670 - 27], 2)
        # 画横线
        if i == 27或i == 670 - 27:
            pygame.draw.line(screen, line_color, [27, i], [670 - 27, i], 4)
        else:
            pygame.draw.line(screen, line_color, [27, i], [670 - 27, i], 2)

    # 在棋盘中心画一个小圆
    pygame.draw.circle(screen, line_color, [27 + 44 * 7, 27 + 44 * 7], 8, 0)

    for val in over_pos:
        pygame.draw.circle(screen, val[1], val[0], 20, 0)

    # 获取鼠标坐标信息
    x, y = pygame.mouse.get_pos()
    x, y = find_pos(x, y)
    if check_over_pos(x, y, over_pos):
        pygame.draw.rect(screen, [0, 229, 238], [x - 22, y - 22, 44, 44], 2, 1)

    keys_pressed = pygame.mouse.get_pressed()
    if keys_pressed[0]:
        if check_over_pos(x, y, over_pos):
            if len(over_pos) % 2 == 0:
                over_pos.append([[x, y], black_color])
            else:
                over_pos.append([[x, y], white_color])

    for val in over_pos:
        pygame.draw.circle(screen, val[1], val[0], 20, 0)

    pygame.display.update()  # 刷新显示

5. 判断胜利条件

实现五子连心的胜利判断逻辑。

def check_win(board):
    for color in [1, 2]:
        for x in range(15):
            for y in range(15):
                if check_line(board, x, y, color, 1, 0) or \
                   check_line(board, x, y, color, 0, 1) or \
                   check_line(board, x, y, color, 1, 1) or \
                   check_line(board, x, y, color, 1, -1):
                    return color
    return 0

def check_line(board, x, y, color, dx, dy):
    count = 0
    for i in range(5):
        nx, ny = x + i * dx, y + i * dy
        if 0 <= nx < 15 and 0 <= ny < 15 and board[nx][ny] == color:
            count += 1
        else:
            break
    return count == 5

6.使用tkinter中的messagebox组件成功实现胜方显示。

7. 完整代码

import pygame
import sys
from pygame.locals import QUIT, KEYDOWN
import numpy as np
import tkinter as tk
from tkinter import messagebox

# 初始化 Pygame
pygame.init()
# 初始化 Tkinter
root = tk.Tk()
root.withdraw()  # 隐藏主窗口

# 获取对显示系统的访问,并创建一个窗口 screen
# 窗口大小为 670x670
screen = pygame.display.set_mode((670, 670))
screen_color = [238, 154, 73]  # 设置画布颜色
line_color = [0, 0, 0]  # 设置线条颜色

def check_win(board):
    for color in [1, 2]:
        for x in range(15):
            for y in range(15):
                if check_line(board, x, y, color, 1, 0) or \
                   check_line(board, x, y, color, 0, 1) or

 \
                   check_line(board, x, y, color, 1, 1) or \
                   check_line(board, x, y, color, 1, -1):
                    return color
    return 0

def check_line(board, x, y, color, dx, dy):
    count = 0
    for i in range(5):
        nx, ny = x + i * dx, y + i * dy
        if 0 <= nx < 15 and 0 <= ny < 15 and board[nx][ny] == color:
            count += 1
        else:
            break
    return count == 5

def find_pos(x, y):
    for i in range(27, 670, 44):
        for j in range(27, 670, 44):
            if abs(x - i) < 22 and abs(y - j) < 22:
                return i, j
    return x, y

def check_over_pos(x, y, over_pos):
    for val in over_pos:
        if val[0] == [x, y]:
            return False
    return True

def draw_board(screen):
    screen.fill(screen_color)
    for i in range(27, 670, 44):
        if i == 27 or i == 670 - 27:
            pygame.draw.line(screen, line_color, [i, 27], [i, 670 - 27], 4)
        else:
            pygame.draw.line(screen, line_color, [i, 27], [i, 670 - 27], 2)
        if i == 27 or i == 670 - 27:
            pygame.draw.line(screen, line_color, [27, i], [670 - 27, i], 4)
        else:
            pygame.draw.line(screen, line_color, [27, i], [670 - 27, i], 2)
    pygame.draw.circle(screen, line_color, [27 + 44 * 7, 27 + 44 * 7], 8, 0)

board = [[0]*15 for _ in range(15)]
over_pos = []
white_color = [255, 255, 255]
black_color = [0, 0, 0]
flag = False
tim = 0

while True:
    for event in pygame.event.get():
        if event.type in (QUIT, KEYDOWN):
            pygame.quit()
            sys.exit()
    draw_board(screen)

    for val in over_pos:
        pygame.draw.circle(screen, val[1], val[0], 20, 0)

    res = check_win(board)
    if res != 0:
        winner_color = "Black" if res == 1 else "White"
        messagebox.showinfo("Game Over", f"{winner_color} wins!")
        pygame.quit()
        sys.exit()

    x, y = pygame.mouse.get_pos()
    x, y = find_pos(x, y)
    if check_over_pos(x, y, over_pos):
        pygame.draw.rect(screen, [0, 229, 238], [x - 22, y - 22, 44, 44], 2, 1)

    keys_pressed = pygame.mouse.get_pressed()
    if keys_pressed[0] and tim == 0:
        flag = True
        if check_over_pos(x, y, over_pos):
            pos = ((x - 27) // 44, (y - 27) // 44)
            if len(over_pos) % 2 == 0:
                over_pos.append([[x, y], black_color])
                board[pos[0]][pos[1]] = 1
            else:
                over_pos.append([[x, y], white_color])
                board[pos[0]][pos[1]] = 2

    if flag:
        tim += 1
    if tim % 50 == 0:
        flag = False
        tim = 0

    pygame.display.update()

三、 实验过程中遇到的问题和解决过程

  • 问题1:Tkinter消息框导入问题

  • 具体描述:程序打包为 .exe 文件后报错 tkinter 没有 attribute 'messagebox'

  • 问题1解决方案:在尝试多种导入方式后,正确导入 tkinter 模块,并使用 root.withdraw() 隐藏主窗口。

  • 问题2:落子判断逻辑错误

  • 具体描述:无法正确判断五子连心。

  • 问题2解决方案:检查并改进 check_wincheck_line 函数,确保能够正确检测到所有可能的五子连线。

  • ...

四、课程感悟与体会

  1. 人生苦短,我用 Python
  2. 学习 Python 通过编写小型项目或解决实际问题,可以帮助我更好地理解 Python 的各种概念和用法,同时提升编程技能。
  3. 老师风趣幽默的授课方式非常吸引人,希望老师明年面对新生时,也能保持时不时抽查提问的风格。

    五、实验总结

    通过这次实验,我进一步熟悉了 Pygame 和 Tkinter 的使用,理解了如何在 Python 中实现一个简单的图形用户界面和交互逻辑。实现五子棋游戏不仅提高了我的编程能力,也增强了我解决问题的能力。整个过程中,我学到了很多宝贵的经验,对 Python 语言的认识也更加深入。
...全文
105 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

108

社区成员

发帖
与我相关
我的任务
社区描述
人生苦短,我用Python!
python3.11 高校
社区管理员
  • blackwall0321
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧