python小游戏五子棋小游戏设计与实现(代码片段)

WEB_DC WEB_DC     2023-03-31     253

关键词:

文章目录


0 项目简介

🔥 Hi,各位同学好呀,这里是L学长!

🥇今天向大家分享一个今年(2022)最新完成的毕业设计项目作品

python小游戏毕设 五子棋小游戏设计与实现 (源码)

🥇 学长根据实现的难度和等级对项目进行评分(最低0分,满分5分)

  • 难度系数:3分

  • 工作量:3分

  • 创新点:4分

1 游戏介绍

基于python实现的支持局域网联机对战的五子棋小游戏。

游戏规则:

五子棋起源于中国,是全国智力运动会竞技项目之一,是一种两人对弈的纯策略型棋类游戏。双方分别使用黑白两色的棋子,下在棋盘直线与横线的交叉点上,先形成五子连珠者获胜。

2 实现效果


3 开发工具

3.1 环境配置

  • Python版本:3.6.4

  • 相关模块:

  • pygame模块;

  • 以及一些Python自带的模块。

3.2 Pygame介绍

简介

Pygame是一系列专门为编写电子游戏而设计的Python模块(modules)。Pygame在已经非常优秀的SDL库的基础上增加了许多功能。这让你能够用Python语言编写出丰富多彩的游戏程序。

Pygame可移植性高,几乎能在任何平台和操作系统上运行。

Pygame已经被下载过数百万次。

Pygame免费开源。它在LGPL许可证(Lesser General Public License,GNU宽通用公共许可证)下发行。使用Pygame,你可以创造出免费开源,可共享,或者商业化的游戏。详情请见LGPL许可证。

优点

  • 能够轻松使用多核CPU(multi core CPUs) :如今双核CPU很常用,8核CPU在桌面系统中也很便宜,而利用好多核系统,能让你在你的游戏中实现更多东西。特定的pygame函数能够释放令人生畏的python GIL(全局解释器锁),这几乎是你用C语言才能做的事。

  • 核心函数用最优化的C语言或汇编语言编写:C语言代码通常比Python代码运行速度快10-20倍。而汇编语言编写的代码(assembly code)比Python甚至快到100多倍。

  • 安装便捷:一般仅需包管理程序或二进制系统程序便能安装。

  • 真正地可移植:支持Linux (主要发行版), Windows (95, 98, ME, 2000, XP, Vista, 64-bit Windows,), Windows CE, BeOS, MacOS, Mac OS X, FreeBSD, NetBSD, OpenBSD, BSD/OS, Solaris, IRIX, and QNX等操作系统.也能支持AmigaOS, Dreamcast, Atari, AIX, OSF/Tru64, RISC OS, SymbianOS and OS/2,但是还没有受到官方认可。你也可以在手持设备,游戏控制台, One Laptop Per Child (OLPC) computer项目的电脑等设备中使用pygame.

  • 用法简单:无论是小孩子还是大人都能学会用pygame来制作射击类游戏。

  • 很多Pygame游戏已发行:其中包括很多游戏大赛入围作品、非常受欢迎的开源可分享的游戏。

  • 由你来控制主循环:由你来调用pygame的函数,pygame的函数并不需要调用你的函数。当你同时还在使用其他库来编写各种各种的程序时,这能够为你提供极大的掌控权。

  • 不需要GUI就能使用所有函数:仅在命令行中,你就可以使用pygame的某些函数来处理图片,获取游戏杆输入,播放音乐……

  • 对bug反应迅速:很多bug在被上报的1小时内就能被我们修复。虽然有时候我们确实会卡在某一个bug上很久,但大多数时候我们都是很不错的bug修复者。如今bug的上报已经很少了,因为许多bug早已被我们修复。

  • 代码量少:pygame并没有数以万计的也许你永远用不到的冗杂代码。pygame的核心代码一直保持着简洁特点,其他附加物诸如GUI库等,都是在核心代码之外单独设计研发的。

  • 模块化:你可以单独使用pygame的某个模块。想要换着使用一个别的声音处理库?没问题。pygame的很多核心模块支持独立初始化与使用。

最小开发框架

import pygame,sys #sys是python的标准库,提供Python运行时环境变量的操控

pygame.init()  #内部各功能模块进行初始化创建及变量设置,默认调用
size = width,height = 800,600  #设置游戏窗口大小,分别是宽度和高度
screen = pygame.display.set_mode(size)  #初始化显示窗口
pygame.display.set_caption("小游戏程序")  #设置显示窗口的标题内容,是一个字符串类型
while True:  #无限循环,直到Python运行时退出结束
    for event in pygame.event.get():  #从Pygame的事件队列中取出事件,并从队列中删除该事件
        if event.type == pygame.QUIT:  #获得事件类型,并逐类响应
            sys.exit()   #用于退出结束游戏并退出          
    pygame.display.update()  #对显示窗口进行更新,默认窗口全部重绘

代码执行流程

4 具体实现

这里简单介绍下原理吧,代码主要用PyQt5写的,pygame只用来播放一些音效。首先,设计并实现个游戏主界面:


代码实现如下:


'''游戏开始界面'''
class gameStartUI(QWidget):
  def __init__(self, parent=None, **kwargs):
    super(gameStartUI, self).__init__(parent)
    self.setFixedSize(760, 650)
    self.setWindowTitle('五子棋-微信公众号: Charles的皮卡丘')
    self.setWindowIcon(QIcon(cfg.ICON_FILEPATH))
    # 背景图片
    palette = QPalette()
    palette.setBrush(self.backgroundRole(), QBrush(QPixmap(cfg.BACKGROUND_IMAGEPATHS.get('bg_start'))))
    self.setPalette(palette)
    # 按钮
    # --人机对战
    self.ai_button = PushButton(cfg.BUTTON_IMAGEPATHS.get('ai'), self)
    self.ai_button.move(250, 200)
    self.ai_button.show()
    self.ai_button.click_signal.connect(self.playWithAI)
    # --联机对战
    self.online_button = PushButton(cfg.BUTTON_IMAGEPATHS.get('online'), self)
    self.online_button.move(250, 350)
    self.online_button.show()
    self.online_button.click_signal.connect(self.playOnline)
  '''人机对战'''
  def playWithAI(self):
    self.close()
    self.gaming_ui = playWithAIUI(cfg)
    self.gaming_ui.exit_signal.connect(lambda: sys.exit())
    self.gaming_ui.back_signal.connect(self.show)
    self.gaming_ui.show()
  '''联机对战'''
  def playOnline(self):
    self.close()
    self.gaming_ui = playOnlineUI(cfg, self)
    self.gaming_ui.show()

会pyqt5的应该都可以写出这样的界面,没啥特别的,记得把人机对战和联机对战两个按钮触发后的信号分别绑定到人机对战和联机对战的函数上就行。

然后分别来实现人机对战和联机对战就行了。这里人机对战的算法抄的公众号之前发的那篇AI五子棋的文章里用的算法,所以只要花点心思用PyQt5重新写个游戏界面就行了,效果大概是这样的:


主要的代码实现如下:


'''人机对战'''
class playWithAIUI(QWidget):
    back_signal = pyqtSignal()
    exit_signal = pyqtSignal()
    send_back_signal = False
    def __init__(self, cfg, parent=None, **kwargs):
        super(playWithAIUI, self).__init__(parent)
        self.cfg = cfg
        self.setFixedSize(760, 650)
        self.setWindowTitle('五子棋-微信公众号: Charles的皮卡丘')
        self.setWindowIcon(QIcon(cfg.ICON_FILEPATH))
        # 背景图片
        palette = QPalette()
        palette.setBrush(self.backgroundRole(), QBrush(QPixmap(cfg.BACKGROUND_IMAGEPATHS.get('bg_game'))))
        self.setPalette(palette)
        # 按钮
        self.home_button = PushButton(cfg.BUTTON_IMAGEPATHS.get('home'), self)
        self.home_button.click_signal.connect(self.goHome)
        self.home_button.move(680, 10)
        self.startgame_button = PushButton(cfg.BUTTON_IMAGEPATHS.get('startgame'), self)
        self.startgame_button.click_signal.connect(self.startgame)
        self.startgame_button.move(640, 240)
        self.regret_button = PushButton(cfg.BUTTON_IMAGEPATHS.get('regret'), self)
        self.regret_button.click_signal.connect(self.regret)
        self.regret_button.move(640, 310)
        self.givein_button = PushButton(cfg.BUTTON_IMAGEPATHS.get('givein'), self)
        self.givein_button.click_signal.connect(self.givein)
        self.givein_button.move(640, 380)
        # 落子标志
        self.chessman_sign = QLabel(self)
        sign = QPixmap(cfg.CHESSMAN_IMAGEPATHS.get('sign'))
        self.chessman_sign.setPixmap(sign)
        self.chessman_sign.setFixedSize(sign.size())
        self.chessman_sign.show()
        self.chessman_sign.hide()
        # 棋盘(19*19矩阵)
        self.chessboard = [[None for i in range(19)] for _ in range(19)]
        # 历史记录(悔棋用)
        self.history_record = []
        # 是否在游戏中
        self.is_gaming = True
        # 胜利方
        self.winner = None
        self.winner_info_label = None
        # 颜色分配and目前轮到谁落子
        self.player_color = 'white'
        self.ai_color = 'black'
        self.whoseround = self.player_color
        # 实例化ai
        self.ai_player = aiGobang(self.ai_color, self.player_color)
        # 落子声音加载
        pygame.mixer.init()
        self.drop_sound = pygame.mixer.Sound(cfg.SOUNDS_PATHS.get('drop'))
    '''鼠标左键点击事件-玩家回合'''
    def mousePressEvent(self, event):
        if (event.buttons() != QtCore.Qt.LeftButton) or (self.winner is not None) or (self.whoseround != self.player_color) or (not self.is_gaming):
            return
        # 保证只在棋盘范围内响应
        if event.x() >= 50 and event.x() <= 50 + 30 * 18 + 14 and event.y() >= 50 and event.y() <= 50 + 30 * 18 + 14:
            pos = Pixel2Chesspos(event)
            # 保证落子的地方本来没有人落子
            if self.chessboard[pos[0]][pos[1]]:
                return
            # 实例化一个棋子并显示
            c = Chessman(self.cfg.CHESSMAN_IMAGEPATHS.get(self.whoseround), self)
            c.move(event.pos())
            c.show()
            self.chessboard[pos[0]][pos[1]] = c
            # 落子声音响起
            self.drop_sound.play()
            # 最后落子位置标志对落子位置进行跟随
            self.chessman_sign.show()
            self.chessman_sign.move(c.pos())
            self.chessman_sign.raise_()
            # 记录这次落子
            self.history_record.append([*pos, self.whoseround])
            # 是否胜利了
            self.winner = checkWin(self.chessboard)
            if self.winner:
                self.showGameEndInfo()
                return
            # 切换回合方(其实就是改颜色)
            self.nextRound()
    '''鼠标左键释放操作-调用电脑回合'''
    def mouseReleaseEvent(self, event):
        if (self.winner is not None) or (self.whoseround != self.ai_color) or (not self.is_gaming):
            return
        self.aiAct()
    '''电脑自动下-AI回合'''
    def aiAct(self):
        if (self.winner is not None) or (self.whoseround == self.player_color) or (not self.is_gaming):
            return
        next_pos = self.ai_player.act(self.history_record)
        # 实例化一个棋子并显示
        c = Chessman(self.cfg.CHESSMAN_IMAGEPATHS.get(self.whoseround), self)
        c.move(QPoint(*Chesspos2Pixel(next_pos)))
        c.show()
        self.chessboard[next_pos[0]][next_pos[1]] = c
        # 落子声音响起
        self.drop_sound.play()
        # 最后落子位置标志对落子位置进行跟随
        self.chessman_sign.show()
        self.chessman_sign.move(c.pos())
        self.chessman_sign.raise_()
        # 记录这次落子
        self.history_record.append([*next_pos, self.whoseround])
        # 是否胜利了
        self.winner = checkWin(self.chessboard)
        if self.winner:
            self.showGameEndInfo()
            return
        # 切换回合方(其实就是改颜色)
        self.nextRound()
    '''改变落子方'''
    def nextRound(self):
        self.whoseround = self.player_color if self.whoseround == self.ai_color else self.ai_color
    '''显示游戏结束结果'''
    def showGameEndInfo(self):
        self.is_gaming = False
        info_img = QPixmap(self.cfg.WIN_IMAGEPATHS.get(self.winner))
        self.winner_info_label = QLabel(self)
        self.winner_info_label.setPixmap(info_img)
        self.winner_info_label.resize(info_img.size())
        self.winner_info_label.move(50, 50)
        self.winner_info_label.show()
    '''认输'''
    def givein(self):
        if self.is_gaming and (self.winner is None) and (self.whoseround == self.player_color):
            self.winner = self.ai_color
            self.showGameEndInfo()
    '''悔棋-只有我方回合的时候可以悔棋'''
    def regret(self):
        if (self.winner is not None) or (len(self.history_record) == 0) or (not self.is_gaming) and (self.whoseround != self.player_color):
            return
        for _ in range(2):
            pre_round = self.history_record.pop(-1)
            self.chessboard[pre_round[0]][pre_round[1]].close()
            self.chessboard[pre_round[0]][pre_round[1]] = None
        self.chessman_sign.hide()
    '''开始游戏-之前的对弈必须已经结束才行'''
    def startgame(self):
        if self.is_gaming:
            return
        self.is_gaming = True
        self.whoseround = self.player_color
        for i, j in product(range(19), range(19)):
            if self.chessboard[i][j]:
                self.chessboard[i][j].close()
                self.chessboard[i][j] = None
        self.winner = None
        self.winner_info_label.close()
        self.winner_info_label = None
        self.history_record.clear()
        self.chessman_sign.hide()
    '''关闭窗口事件'''
    def closeEvent(self, event):
        if not self.send_back_signal:
            self.exit_signal.emit()
    '''返回游戏主页面'''
    def goHome(self):
        self.send_back_signal = True
        self.close()
        self.back_signal.emit()

整个逻辑是这样的:

设计并实现游戏的基本界面之后,先默认永远是玩家先手(白子),电脑后手(黑子)。然后,当监听到玩家鼠标左键点击到棋盘网格所在的范围内的时候,捕获该位置,若该位置之前没有人落子过,则玩家成功落子,否则重新等待玩家鼠标左键点击事件。玩家成功落子后,判断是否因为玩家落子而导致游戏结束(即棋盘上有5颗同色子相连了),若游戏结束,则显示游戏结束界面,否则轮到AI落子。AI落子和玩家落子的逻辑类似,然后又轮到玩家落子,以此类推。

需要注意的是:为保证响应的实时性,AI落子算法应当写到鼠标左键点击后释放事件的响应中(感兴趣的小伙伴可以试试写到鼠标点击事件的响应中,这样会导致必须在AI计算结束并落子后,才能显示玩家上一次的落子和AI此次的落子结果)。

开始按钮就是重置游戏,没啥可说的,这里为了避免有些人喜欢耍赖,我实现的时候代码写的是必须完成当前对弈才能重置游戏(毕竟小伙子小姑娘们要学会有耐心地下完一盘棋呀)。

因为是和AI下,所以悔棋按钮直接悔两步,从历史记录列表里pop最后两次落子然后从棋盘对应位置取下这两次落子就OK了,并且保证只有我方回合可以悔棋以避免出现意料之外的逻辑出错。

认输按钮也没啥可说的,就是认输然后提前结束游戏。

接下来我们来实现一下联机对战,这里我们选择使用TCP/IP协议进行联机通信从而实现联机对战。先启动游戏的一方作为服务器端:


通过新开一个线程来实现监听:


threading.Thread(target=self.startListen).start()
'''开始监听客户端的连接'''
def startListen(self):
    while True:
       self.setWindowTitle('五子棋-微信公众号: Charles的皮卡丘 ——> 服务器端启动成功, 等待客户端连接中')
       self.tcp_socket, self.client_ipport = self.tcp_server.accept()
       self.setWindowTitle('五子棋-微信公众号: Charles的皮卡丘 ——> 客户端已连接, 点击开始按钮进行游戏')

后启动方作为客户端连接服务器端并发送客户端玩家的基本信息:


self.tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.tcp_socket.connect(self.server_ipport)
data = 'type': 'nickname', 'data': self.nickname
self.tcp_socket.sendall(packSocketData(data))

当客户端连接到服务器端时,服务器端也发送服务器端的玩家基本信息给客户端:


data = 'type': 'nickname', 'data': self.nickname
self.tcp_socket.sendall(packSocketData(data))

然后客户端和服务器端都利用新开的线程来实现网络数据监听接收:

'''接收客户端数据'''
def receiveClientData(self):
    while True:
        data = receiveAndReadSocketData(self.tcp_socket)
        self.receive_signal.emit(data)
'''接收服务器端数据'''
def receiveServerData(self):
    while True基于javaswing五子棋小游戏设计和实现(代码片段)

 订阅专栏获取源码前言:       五子棋相传起源于四千多年前的尧帝时期,比围棋的历史还要悠久,可能早在“尧造围棋”之前,民间就已有五子棋游戏。有关早期五子棋的文史资料与围棋有相似之处,... 查看详情

python实现简易五子棋小游戏(三种方式)(代码片段)

...39;helloworld!').pack()root.mainloop()弹窗结果:  五子棋小游戏实现(一): fromtkinterimport*importtkinter.messagebox#弹窗库importnumpyasnproot=Tk()#创建窗口root.title("五子棋游戏")#窗口名字w1=Canvas(root,width=600,heigh... 查看详情

使用pygame实现一个简单的五子棋游戏(代码片段)

...有点枯燥,正好看到pygame,感觉还挺简单,所以想先写个小游戏练练手。准备python基础相关准备:pygame的基础知识,参考目光博客的&ldq 查看详情

基于javaswing五子棋小游戏设计和实现

本项目演示链接地址》前言:       五子棋相传起源于四千多年前的尧帝时期,比围棋的历史还要悠久,可能早在“尧造围棋”之前,民间就已有五子棋游戏。有关早期五子棋的文史资料与围棋有相似之... 查看详情

《游戏学习》java实现连珠五子棋完整代码(代码片段)

游戏介绍五子棋是全国智力运动会竞技项目之一,是一种两人对弈的纯策略型棋类游戏。五子棋有两种玩法。玩法一:双方分别使用黑白两色的棋子,下在棋盘直线与横线的交叉点上,先形成五子连线者获胜。玩... 查看详情

《游戏学习》java实现连珠五子棋完整代码(代码片段)

游戏介绍五子棋是全国智力运动会竞技项目之一,是一种两人对弈的纯策略型棋类游戏。五子棋有两种玩法。玩法一:双方分别使用黑白两色的棋子,下在棋盘直线与横线的交叉点上,先形成五子连线者获胜。玩... 查看详情

关于三子棋游戏的简易实现与n子棋胜利判断方法(代码片段)

关于三子棋游戏的简易实现与N子棋胜利判断方法要实现三子棋游戏,主要需要实现以下几个要求:>需要一个棋盘,既然需要一个棋盘,棋盘是在一个平面上的,所以我们需要创建一个二维数组棋盘的打印玩家下... 查看详情

1000行python代码实现俄罗斯方块/扫雷/五子棋/贪吃蛇(代码片段)

文章目录Python开发小游戏,它有又双叒叕来了...一、效果展示1、俄罗斯方块2、扫雷3、五子棋4、贪吃蛇二、代码展示1、俄罗斯方块2、扫雷3、五子棋4、贪吃蛇Python开发小游戏,它有又双叒叕来了…一、效果展示1、俄罗... 查看详情

俄罗斯方块游戏设计与实现(python)(代码片段)

...31.2.3游戏操作31.3设计目的4第二章相关技术及开发工具52.1python介绍52.2python发展历史62.3python特点62.4python开发环境构建7第三章概要设计83.1程序流程93.1.1程序主流程93.1.2游戏视图103.1.3游戏控制流程103.2模块说明113.2.1游戏模块113.2.2... 查看详情

flutter从头到尾设计一款简单的五子棋游戏|具体代码设计(代码片段)

前言在前面两篇文章中,我们已经介绍了设计一款五子棋游戏的所使用的一些思想以及部分的代码,以便我们更好地对设计模式进行理解。这次我们全面把代码铺开来讲,注意,我们这次的设计是完全使用Flutter自... 查看详情

ai人机对战五子棋游戏python(pygame)+ai并实现软件输出(代码片段)

...是很清楚的可以参考文章点击这里目录1.系统架构分析1.1五子棋的基本棋型1.2功能模块2.具体实现2.1设置基础参数2.2绘制棋盘2.3编写函数intoNextTurn()2.4编写函数getLocate()2.5编写函数getIdex()2.6编写函数isInside()2.7编写函数isEmpty()2.8编写... 查看详情

pygame每日一练——五子棋小游戏(代码片段)

...备注:五子棋)后私信获取完整源码!五子棋小游戏1、简介五子棋是我们小时候经常玩的两人对弈策略小游戏,规则简单:1、对局双方各执一色棋子,常为黑白两色;2、空棋盘开局;3、黑先、白... 查看详情

五子棋程序设计实现技术文档(代码片段)

五子棋程序设计实现文档文章目录五子棋程序设计实现文档前言一、运行截图二、基本思路1.实现过程2.落子3.悔棋4.人机对战的实现1.机器人落子逻辑**2.改进胜负判断方法3.计算目标点的权值(白棋ai使用)4.计算目标点的权值(黑棋a... 查看详情

五子棋程序设计实现技术文档(代码片段)

五子棋程序设计实现文档文章目录五子棋程序设计实现文档前言一、运行截图二、基本思路1.实现过程2.落子3.悔棋4.人机对战的实现1.机器人落子逻辑**2.改进胜负判断方法3.计算目标点的权值(白棋ai使用)4.计算目标点的权值(黑棋a... 查看详情

java实现《五子棋》游戏|csdn创作打卡(代码片段)

前言五子棋是世界智力运动会竞技项目之一,是一种两人对弈的纯策略型棋类游戏,是世界智力运动会竞技项目之一,通常双方分别使用黑白两色的棋子,下在棋盘直线与横线的交叉点上,先形成5子连线者获... 查看详情

一日一技:用python做游戏有多简单(代码片段)

...#xff0c;有很多同学问我除了这种表白的,还有其他什么小游戏吗,游戏是怎么做的,难不难。我就用两篇文章来介绍一下,如果使用Python做游戏。兔子与灌俄罗斯方块休闲五子棋走迷宫推箱子消消乐超多小游戏玩转... 查看详情

前端开发趣味之五子棋小游戏(js+node+websocket)可分房间对战(代码片段)

主要通过js、canvas、node、websocket来实现五子棋游戏。tip:如果你想清除的了解怎么实现,请一步步看思路流程。首先搭建一个express服务:constexpress=require('express')constpath=require('path')constapp=express()//静 查看详情

课程设计小组报告——基于arm实验箱的捕鱼游戏的设计与实现(代码片段)

课程设计小组报告——基于ARM实验箱的捕鱼游戏的设计与实现一、任务简介1.1任务内容捕鱼游戏这个项目是一个娱乐性的游戏开发,该游戏可以给人们带来娱乐的同时还可以给人感官上的享受,所以很受人们的欢迎。本次游戏的... 查看详情