56星座屋
当前位置: 首页 星座百科

如何用python做一个五子棋游戏(用pygame实现一个简单的五子棋游戏)

时间:2023-05-29 作者: 小编 阅读量: 1 栏目名: 星座百科

准备python基础相关准备:pygame的基础知识,参考目光博客的“用Python和Pygame写游戏-从入门到精通”安装python3.8.0在python官网下载,不多说。判定黑子或白子五子连珠。一方胜利后弹出提示,结束游戏。输赢的判断,由于未出输赢的时候肯定没有五子连成线的,所以只需要判断最后落子位置的横、竖、斜、反斜四个方向上有没有五子连成线即可。

准备 python基础相关准备:

  1. pygame的基础知识,参考目光博客的“用Python和Pygame写游戏-从入门到精通”
  2. 安装python 3.8.0 在python官网下载,不多说。
  3. 安装pygame,命令:pip install pygame
  4. 如安装较慢,可以参考如下命令,更改pip源为国内镜像站点:
  5. pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
  6. 本章相关资源素材关注公众号python社区营

计划

准备完成五子棋单机人机游戏,目前已完成界面以及判定输赢等功能,还未加入电脑AI,以后有时间再加(不知是否会坑),目前实现主要功能如下:

  1. 五子棋界面的绘制,鼠标左键点击落子(黑子先下,黑白子交替顺序)。
  2. 判定黑子或白子五子连珠。
  3. 一方胜利后弹出提示,结束游戏。

游戏界面是下面这个样子:

开始

设计思路

整个游戏的核心是将棋盘分成两个层面,第一个层面是物理层面上的,代表在物理像素的位置,主要用于绘图等操作,另外一个层面是将棋盘抽象成15*15的一个矩阵,黑子和白子是落在这个矩阵上的某个位置,具体位置用坐标(i,j)(0<=i,j<15)来表示,主要用于判断输赢和落子等。

  1. 棋盘的绘制,网上有棋盘和黑白子的图片资源可以下载使用,我下载后由于棋盘图片格子线像素位置不太精确,所以自己用ps做了一张544544的木质背景图,然后用程序来绘制棋盘线(如果PS更熟悉点的话,建议棋盘格线之类就画在棋盘背景图上),棋盘格线上下左右空20像素,棋盘格子大小36像素,网上下载的棋子大小是3232像素的。
  2. 输赢的判断,由于未出输赢的时候肯定没有五子连成线的,所以只需要判断最后落子位置的横、竖、斜、反斜四个方向上有没有五子连成线即可。

主要代码

  1. main函数,pygame的主要控制流程,缩写代码如下:

def main():pygame.init()#pygame初始化size = width,height = 544,544screen = pygame.display.set_mode(size, 0, 32)pygame.display.set_caption('五子棋')font = pygame.font.Font('simhei.ttf', 48)clock = pygame.time.Clock()#设置时钟game_over = Falserenju = Renju()# Renju是核心类,实现落子及输赢判断等renju.init()# 初始化while True:clock.tick(20)# 设置帧率for event in pygame.event.get():if event.type == pygame.QUIT:sys.exit()if event.type == pygame.MOUSEBUTTONDOWN and (not game_over):if event.button == 1:# 按下的是鼠标左键i,j = renju.get_coord(event.pos)# 将物理坐标转换成矩阵的逻辑坐标if renju.check_at(i, j):# 检查(i,j)位置能否被占用,如未被占用返回Truerenju.drop_at(i, j)# 在(i,j)位置落子,该函数将黑子或者白子画在棋盘上if renju.check_over():# 检查是否存在五子连线,如存在则返回Truetext = ''if renju.black_turn:#check_at会切换落子的顺序,所以轮到黑方落子,意味着最后落子方是白方,所以白方顺利text = '白方获胜,游戏结束!'else:text = '黑方获胜,游戏结束!'gameover_text = font.render(text, True, (255,0,0))renju.chessboard().blit(gameover_text, (round(width/2-gameover_text.get_width()/2), round(height/2-gameover_text.get_height()/2)))game_over = Trueelse:print('此位置已占用,不能在此落子')screen.blit(renju.chessboard(),(0,0))pygame.display.update()pygame.quit()复制代码

2. renju类,核心类,落子及判断输赢等操作,代码如下:

Position = namedtuple('Position', ['x', 'y'])class Renju(object):background_filename = 'chessboard.png'white_chessball_filename = 'white_chessball.png'black_chessball_filename = 'black_chessball.png'top, left, space, lines = (20, 20, 36, 15)# 棋盘格子位置相关???color= (0, 0, 0)# 棋盘格子线颜色black_turn = True# 黑子先手ball_coord= []# 记录黑子和白子逻辑位置def init(self):try:self._chessboard = pygame.image.load(self.background_filename)self._white_chessball = pygame.image.load(self.white_chessball_filename).convert_alpha()self._black_chessball = pygame.image.load(self.black_chessball_filename).convert_alpha()self.font = pygame.font.SysFont('arial', 16)self.ball_rect = self._white_chessball.get_rect()self.points = [[] for i in range(self.lines)]for i in range(self.lines):for j in range(self.lines):self.points[i].append(Position(self.lefti*self.space, self.topj*self.space))self._draw_board()except pygame.error as e:print(e)sys.exit()def chessboard(self):return self._chessboard# 在(i,j)位置落子def drop_at(self, i, j):pos_x = self.points[i][j].x - int(self.ball_rect.width/2)pos_y = self.points[i][j].y - int(self.ball_rect.height/2)ball_pos = {'type':0 if self.black_turn else 1, 'coord':Position(i,j)}if self.black_turn:# 轮到黑子下self._chessboard.blit(self._black_chessball, (pos_x, pos_y))else:self._chessboard.blit(self._white_chessball, (pos_x, pos_y))self.ball_coord.append(ball_pos)# 记录已落子信息self.black_turn = not self.black_turn# 切换黑白子顺序# 画棋盘上的格子线,如果棋盘背景图做的足够精确,可省略此步骤def _draw_board(self):# 画坐标数字for i in range(1, self.lines):coord_text = self.font.render(str(i), True, self.color)self._chessboard.blit(coord_text, (self.points[i][0].x-round(coord_text.get_width()/2), self.points[i][0].y-coord_text.get_height()))self._chessboard.blit(coord_text, (self.points[0][i].x-coord_text.get_width(), self.points[0][i].y-round(coord_text.get_height()/2)))for x in range(self.lines):# 画横线pygame.draw.line(self._chessboard, self.color, self.points[0][x], self.points[self.lines-1][x])# 画竖线pygame.draw.line(self._chessboard, self.color, self.points[x][0], self.points[x][self.lines-1])# 判断是否已产生胜方def check_over(self):if len(self.ball_coord)>8:# 只有黑白子已下4枚以上才判断direct = [(1,0),(0,1),(1,1),(1,-1)]#横、竖、斜、反斜 四个方向检查for d in direct:if self._check_direct(d):return Truereturn False# 判断最后一个棋子某个方向是否连成5子,direct:(1,0),(0,1),(1,1),(1,-1)def _check_direct(self, direct):dt_x, dt_y = directlast = self.ball_coord[-1]line_ball = []# 存放在一条线上的棋子for ball in self.ball_coord:if ball['type'] == last['type']:x = ball['coord'].x - last['coord'].x y = ball['coord'].y - last['coord'].yif dt_x == 0:if x == 0:line_ball.append(ball['coord'])continueif dt_y == 0:if y == 0:line_ball.append(ball['coord'])continueif x*dt_y == y*dt_x:line_ball.append(ball['coord'])if len(line_ball) >= 5:# 只有5子及以上才继续判断sorted_line = sorted(line_ball)for i,item in enumerate(sorted_line): index = i 4if index < len(sorted_line):if dt_x == 0:y1 = item.yy2 = sorted_line[index].yif abs(y1-y2) == 4:# 此点和第5个点比较y值,如相差为4则连成5子return Trueelse:x1 = item.xx2 = sorted_line[index].xif abs(x1-x2) == 4: # 此点和第5个点比较x值,如相差为4则连成5子return Trueelse:breakreturn False# 检查(i,j)位置是否已占用def check_at(self, i, j):for item in self.ball_coord:if (i,j) == item['coord']:return Falsereturn True# 通过物理坐标获取逻辑坐标def get_coord(self, pos):x, y = posi, j = (0, 0)oppo_x = x - self.leftif oppo_x > 0:i = round(oppo_x / self.space)# 四舍五入取整oppo_y = y - self.topif oppo_y > 0:j = round(oppo_y / self.space)return (i, j)复制代码

Renju类有几个函数说明:

  1. init()方法主要做了几件事:
  1. drop_at(i,j)方法,在逻辑位置(i,j)落子,至于是落白子和黑子通过Renju类的控制开关black_turn来决定。画图,并将已落子信息存入ball_coord列表中。
  2. check_at(i,j)方法,通过遍历ball_coord列表来查看(i,j)位置是否能落子。
  3. check_over()方法判断是否存在五子连线的情况,主要通过调用_check_direct方法分别判断四个方向上的情况。
  4. _check_direct(direct)方法是判断五子连线的主要逻辑,通过判断最后一颗落子的某个方向落子实现。

结束

更多精彩文章关注公众号python社区营

    推荐阅读
  • 创业名言短句霸气十足(有关创业的说说)

    对所有创业者来说,永远告诉自己一句话:从创业得第一天起,你每天要面对的是困难和失败,而不是成功我最困难的时候还没有到,但有一天一定会到——马云,今天小编就来聊一聊关于创业名言短句霸气十足?——马云财富是猫的尾巴,只要勇往直前,财富就会悄悄跟在后面。——宗庆后不要控制失败的风险,而应控制失败的成本。——RobertA.Cooper我现在觉得,像李彦宏那样坚持独立发展是正确的。

  • aj1芝加哥13年复刻版(市价2000)

    aj1芝加哥13年复刻版AirJordan1毫无疑问是球鞋历史当中的经典鞋型,其中以芝加哥公牛队为主题打造的白红「芝加哥」配色,更是无数球鞋玩家心中的殿堂级配色。但是JordanBrand上一次复刻这双经典鞋款已经是7年前,近些年只有一些相似配色推出。近日,一双「芝加哥」配色AirJordan1释出官图,并即将迎来发售。另外AirJordan1LowGolf这款鞋型本身也较为稀有,几乎不存在撞鞋的可能性。发售价格为¥999元,这也是Jordan高尔夫鞋款少见的国内发售。

  • 森雅m80真实油耗(森雅m80真实油耗高吗)

    森雅m80一共使用了两款发动机,一款是1.3升自然吸气发动机,另一款是1.5升自然吸气发动机。森雅m80的前悬架使用了麦弗逊独立悬架,后悬架使用了五连杆后悬架。麦弗逊独立悬架是一种很常见的独立悬架,也是一种结构很简单的独立悬架。森雅m80是一款后轮驱动车型。

  • 年折旧率如何计算(年折旧率怎么计算公式)

    年折旧率的计算在会计上来说是很重要的。采用的折旧方法不同,年折旧率是存在着比较大的不同的。什么是折旧率“固定资产折旧率”的简称。固定资产年度应计提折旧额与原始价值的比率,它反映在年度内转移到产品成本或有关费用中的固定资产价值的程度。年折旧率除以12即为月折旧率。作为一名企业的会计,最好是明白,年折旧率是一项非常重要的数值,知道了年折旧率就可以轻松计算出年折旧额。

  • 1978年李云龙原型逝世(1978年李云龙原型逝世)

    同时,王近山担任中国人民解放军北京军区副司令员。虽然有人员伤亡,但是韩岫岩并没有大碍。虽然这次的战斗并没有得到上级的认可,本质上还是出于王近山的私人原因,但是因为战功巨大,上级也没有过多的为难王近山。至此,王近山和韩岫岩的感情越发深厚,很快他们也有了自己的孩子,然而,一场危机却出现了。

  • 如何路由器当交换机用(怎么设置路由器当交换机用)

    如何路由器当交换机用先用网线连接好电脑跟路由器,然后给路由器通上电、同时打开电脑。然后打开电脑里面的浏览器,在浏览器地址输入框输入“192.168.1.1”,此时路由器会提示设置密码,输入两次密码即可。此时进入设置向导界面,此时点击跳过向导即可。之后找到将路由器的“DHCP服务器”点“关闭”,然后保存。然后找到“LAN口这设置”,设置为手动模式,修改管理ip为主路由同一网段的不同ip,然后保存,则路由器作为无线交换机设置完成。

  • 粽叶泡多久可以包粽子(新鲜的粽子叶要煮吗)

    接下来我们就一起去了解一下吧!粽叶泡多久可以包粽子包粽子的叶子要泡两个小时左右。包粽子的叶子,也有南北差异之处,大多是根据当地的植物就地取材。一般来说,南方包粽子用的最多的叶子就是箬竹叶,也叫棕叶,是植物箬竹的叶子,北方则是用芦苇的叶子多一些。在包粽子之前,棕叶是要煮一下的,把水煮开。一来叶子软一点不会硬脆的,二来可以把叶子的那种青涩的味道去掉。煮了之后洗一下,再把叶子晾一晾,去掉水。

  • 年夜饭蒜蓉大虾的做法是什么(蒜蓉大虾怎么做)

    年夜饭蒜蓉大虾的做法是什么食材清单:大虾12只、龙口粉丝100克、大蒜多瓣、小葱几根、生抽1勺、小米椒1把、食用油适量、西蓝花1朵、清水、盐适量烹饪步骤小米椒切小碎,小葱切末,大蒜处理成末。龙口粉丝用热水浸泡2分钟后捞出沥水,泡软的粉丝在盘子中摆好,顶部摆上大虾,虾背朝上。

  • 水浒传幕后的冷知识(水浒传原著里的十大冷知识)

    但这两人的个人篇幅都占据了相当大的份量,尤其武松,一人独占十个章回。而晁盖、吴用这次却被官府完美破获了。这也从侧面证实了吴用的计策有时看似高明,却实际“无用”。高俅,和童贯争权失宠后,56岁得病而死。童贯,下场最惨,先被贬,后在被贬途中又被斩首,头颅则带回京师示众。

  • 植物奶油抹面有气泡怎么回事(奶油抹面怎么老有气泡)

    2、通常我们最好是将奶油打发至七八分就可以用来抹面了,也就是等到奶油会出现比较清晰的纹路,并且提起打蛋器之后不会有奶油滴落的状态就可以了。