pygame实现井字棋之第三步逻辑优化

一、前言

先说一下本期的目标。
首先我们在判断出输赢、平局的时候,只有一个控制台输出,很明显不符合我们游戏的排面(doge
另外,之前的逻辑有一个漏洞,就是玩家一定是先手(就是第一个下棋的人,这个也需要修改)。
还有,有一个短暂的弹窗显示到谁了,游戏的可玩性就会有提高。
最后一个就是,如果点击位置有问题,我们需要显示。

二、渲染问题

翻车了,之前的逻辑是将九宫格背景颜色写死,而且之前都是直接在之前的基础上渲染,但是我们的弹窗需要在结束后及时撤下来,所以需要我们不断的重新渲染界面。

得,改吧。

首先,我们就不需要使用draw.rect方法创建矩形了,而是使用另外一个pygame.Rect函数。
同时,为了省去九行基本相同的代码,我创建了一个元组来存储。
格子创建最新版:

# 表示九个格子
rect = [0]*9
rect_wh = [
    (1,1), (single+3,1), (single*2+5,1),
    (1,single+3), (single+3,single+3), (single*2+5,single+3),
    (1,single*2+5), (single+3,single*2+5), (single*2+5,single*2+5)
    ]
for i in range(len(rect)):
    rect[i] = pygame.Rect(*rect_wh[i],single,single)
    rect[i] = Lattice(rect[i],screen)

Rect函数:
传入x、y坐标以及高度宽度,就能创建一个rect对象。
这里需要解释的是*rect_wh[i],后面的部分就是在元组列表中找到一个指定的元素,而星号的作用是将元组进行解封装。

三、封装和解封装

a, b = 1, 2
首先,我们将后面的两个变量封装成一个元组,从而赋值给等号前面的部分;
而前面为两个变量,所以我们还需要进行解封装,也就是将一个元组拆分成一个个的变量。

当时记录的笔记:

回到之前的格子问题,还有一个细节就是我们应该怎么显示格子周围的分割线,之前采用的是绘制矩形时自带的,现在因为刷新的问题,不能再使用了(不然每刷新一次创建9个矩形并绘制,这谁顶得住)。
我的办法是:减小了single的大小:

single = width/3 - 1

应该会注意到的,元组列表中我修改了(x,y)的值,这样我们就能绘制出这样的一个图形:

(原创不易,整这个眼睛都快要瞎了,还是没有很完美 -_-||)
bg_color = (0, 0, 0), 黑色。
我们还有个draw.rect方法,传入screen,(255, 255, 255),rect对象,我们就可以显示一个白色的矩形了。
因为宽高小了一点,所以我们就能看到很棒的边界(比我自己画的好多了)

(啊,为什么是黄色的啊,因为我把bg_color改了……,问题不大)

当前的update方法:

def update():
    screen.fill((255,228,181))
    for i in rect:
        pygame.draw.rect(screen,(255, 255, 255),i.rect)
        i.draw()

四、弹窗显示

添加的弹窗:
输赢、平局弹窗,3s后退出程序;
哪方下棋、下棋的位置有问题,0.3s后自己退出。

看过我大战外星人系列应该知道,有一个很大的遗憾就是给定的button类有一点专用,导致我后来只能自己添加按钮类。
这次,我自己写的弹窗类的适用性会更高一些。

popup.py

"""在游戏过程中,添加各种弹窗"""
import pygame
class Popup():
    def __init__(self, screen,msg):
        self.msg = msg
        self.screen = screen
        self.bg_color = (0, 0, 0)
        self.text_color = (230, 230, 230)
        self.font = pygame.font.SysFont(None,48)
        self.msg_image = self.font.render(msg,True,self.text_color,self.bg_color)
        self.msg_rect = self.msg_image.get_rect()
        self.screen_rect = self.screen.get_rect()
        self.msg_rect.center = self.screen_rect.center
        self.screen.blit(self.msg_image,self.msg_rect)

传入一个要显示的信息,然后就可以渲染到屏幕上了。
方法都是之前的,看这篇博客。
(所以适用性高是不是因为基本上没什么内容……)

第一种情况(以平局为例):

Popup(screen,"draw")
pygame.display.flip()
time.sleep(3)
exit()

调用类(调用一次就完了,不需要再使用实例)
显示屏幕
挂起三秒
退出程序

第二种情况下,我选择"computer choice”作为案例,也就是轮到电脑操作:

Popup(srceeen,"computer choice”)
pygame.display.filp()
time.sleep(0.3)

但这样,弹窗是不会自己消失的,所以我们还需要在后面跟一个update方法。

哦对了,还有一个没有讲怎么实现

五、实现判断点击是否有效

elif event.type == pygame.MOUSEBUTTONDOWN:
            mouse_x, mouse_y = pygame.mouse.get_pos()
            # 判断玩家是否点击成功
            success = 0
            for i in rect:
                if  not i.stats and i.rect.collidepoint(mouse_x,mouse_y):
                	# 如果点击有效,将变量置为1

            if not success:
                update(0.3,"you can't choose here!")

六、update优化

看了一下,基本上只有两种情况,一个是正常的update,另一个是需要跟弹窗和延时。

def update(time_sleep=0,msg=""):
    screen.fill((255,228,181))
    for i in rect:
        pygame.draw.rect(screen,(255, 255, 255),i.rect)
        i.draw()
    if msg:
        Popup(screen,msg)
    pygame.display.flip()
    if time_sleep:
        time.sleep(time_sleep)

对于正常的刷新,只需要调用update(),如果是需要弹窗和延时的,就自己加变量来处理。

主循环部分:

while not judge:
    update()
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == pygame.MOUSEBUTTONDOWN:
            mouse_x, mouse_y = pygame.mouse.get_pos()
            # 判断玩家是否点击成功
            success = 0
            for i in rect:
                # 确定玩家下了一步
                if  not i.stats and i.rect.collidepoint(mouse_x,mouse_y):
                    success = 1
                    # 玩家下棋
                    i.stats = -1
                    update()
                    win_or_lose()
                    # 电脑下棋
                    update(0.3,"Computer choice!")
                    computer()
                    update()
                    win_or_lose()
                    update(0.3,"your choice!")

            if not success:
                update(0.3,"you can't choose here!")

computer函数部分:

def computer():
    """电脑的回合,随机生成一个位置"""
    global judge
    random_num = [i for i in range(len(rect)) if not rect[i].stats]
    # 没位子下了,平局
    if not random_num:
        update(3,"draw")
        exit()
    rect[random.choice(random_num)].stats = 1

判断输赢部分:

def win_or_lose():
    global judge
    stats1 = [i for i in range(len(rect)) if rect[i].stats == 1]
    stats2 = [i for i in range(len(rect)) if rect[i].stats == -1]
    win_list = [
        [0, 1, 2], [3, 4, 5], [6, 7, 8],
        [0, 3, 6], [1, 4, 7], [2, 5, 8],
        [0, 4, 8], [2, 4, 6]
    ]
    for i in win_list:
        if i == [j for j in i if j in stats1]:
            update(3,"Computer win!")
            exit()
        elif i == [j for j in i if j in stats2]:
            update(3,"You win!")
            exit()

七、先手问题

这个,还是交给随机数。
使用random.randint(0,1)产生一个0/1,来判断先手,
如果先手是电脑,使用(0,8)选择一个将其stats置为1
代码:

def first_hand():
    """判断先手,如果随机数为1,则电脑先手"""
    x = random.randint(0,1)
    if x:
        x = random.randint(0,8)
        rect[x].stats = 1

循环开始前调用一下就行了。

八、结语

整体的游戏就实现了,很简单的一个,却能加深对pygame模块的使用。

往期博客:
pygame实现井字棋——1.绘制九宫格
pygame实现井字棋——2.逻辑实现

到此这篇关于pygame实现井字棋之第三步逻辑优化的文章就介绍到这了,更多相关pygame井字棋游戏内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Pygame做一期吃豆子游戏的示例代码

    Pygame的历史 Pygame是一个利用SDL库的写就的游戏库,SDL呢,全名Simple DirectMedia Layer,是一位叫做Sam Lantinga的大牛写的,据说他为了让Loki(致力于向Linux上移植Windows的游戏的一家大好人公司,可惜已经倒闭,唉好人不长命啊--)更有效的工作,创造了这个东东. SDL是用C写的,不过它也可以使用C++进行开发,当然还有很多其它的语言,Pygame就是Python中使用它的一个库.Pygame已经存在很多时间了,许多优秀的程序员加入其

  • python+pygame实现代码雨(黑客帝国既视感)

    本文主要介绍了python+pygame实现代码雨,分享给大家,具体如下: 效果: #!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2020/12/29 12:34 # @Author : huni # @File : 代码雨.py # @Software: PyCharm import random import pygame PANEL_width = 1600 PANEL_highly = 1000 FONT_PX = 15

  • pygame实现井字棋之第一步绘制九宫格

    一.前言 这次,自己尝试使用pygame模块实现一个九宫格游戏. 目标:形成一个界面,将界面分割成9个,然后对于没有被占领的方框,我们可以用鼠标点击进行占领. 游戏规则就不用说了,至于套路,自己百度一下吧. 这里的人机采用随机数模式,因为实在是没什么套路. 二.显示界面 import pygame import sys # 初始化模块,加一下稳一些 pygame.init() # 创建屏幕对象 screen = pygame.display.set_mode((width,height)) #

  • Python3+Pygame实现射击游戏完整代码

    之前看到过很多人写的飞机大战,当然了之前我也写过多个版本,总体来说功能是实现了,但总感觉不够"炫" 今天浏览Python资料的时候,意外发现了这个很好的"射击"类游戏,看上去类似飞机大战,但更好玩 一.游戏特点 1. 运行非常流畅 2. 默认有3条命,每条命的HP可以增加(吃补品)也可以减少(被击中) 3. 有碰撞时的音效 4. 有碰撞时的爆炸效果 二.运行效果展示 三.完整代码 from __future__ import division import pyga

  • pygame实现井字棋之第二步逻辑实现

    一.前言 我们在上一篇博客中实现了九宫格的绘制,为我们打下了基础. 这次我们来实现基本的逻辑,比如判断输赢.玩家和电脑分别下棋的逻辑. 二.下棋 2.1 玩家 我们之前在Lattice类中,有一个stats变量来表示格子的状态, # 0表示初始,1表示个人-1表示电脑 self.stats = 0 所以下棋本质上就是修改这个变量. 首先,我们是用鼠标点击的方式来实现下棋的,所以应当修改事件响应部分: for event in pygame.event.get(): # 退出 if event.t

  • pygame可视化幸运大转盘实现

    继续分享pygame有趣的技术知识,欢迎往下看. 一.先搭个架子 (一)黏贴背景图: 实现代码如下: import pygame pygame.init() # 初始化pygame类 screen = pygame.display.set_mode((600, 600)) # 设置窗口大小 pygame.display.set_caption('幸运大转盘') # 设置窗口标题 tick = pygame.time.Clock() fps = 10 # 设置刷新率,数字越大刷新率越高 # 方法一

  • pygame多种方式实现屏保操作(自动切换、鼠标切换、键盘切换)

    pygame多种方式实现屏保操作(自动切换.鼠标切换.键盘切换),欢迎往下观看. 一.图片处理 (一)图片采集 我认为有三种方法: 其一:使用爬虫技术从网上下载图片,可以开一个子线程负责采集网上图片,然后加载到list列表中: 其二:可以直接对电脑中所有的盘进行自动检索,然后加载到list列表中: 其三:指定目录,然后加载到list列表中: 我这里偷个懒,选择第三种方法实现.具体代码如下: path = './image/' files = [] dirs = os.listdir(path)

  • 详解pygame捕获键盘事件的两种方式

    方式1:在pygame中使用pygame.event.get()方法捕获键盘事件,使用这个方式捕获的键盘事件必须要是按下再弹起才算一次. 示例示例: for event in pygame.event.get(): # 捕获键盘事件 if event.type == pygame.QUIT: # 判断按键类型 print("按下了退出按键") 方式2:在pygame中可以使用pygame.key.get_pressed()来返回所有按键元组,通过判断键盘常量,可以在元组中判断出那个键被

  • pygame实现井字棋之第三步逻辑优化

    一.前言 先说一下本期的目标. 首先我们在判断出输赢.平局的时候,只有一个控制台输出,很明显不符合我们游戏的排面(doge 另外,之前的逻辑有一个漏洞,就是玩家一定是先手(就是第一个下棋的人,这个也需要修改). 还有,有一个短暂的弹窗显示到谁了,游戏的可玩性就会有提高. 最后一个就是,如果点击位置有问题,我们需要显示. 二.渲染问题 翻车了,之前的逻辑是将九宫格和背景颜色写死,而且之前都是直接在之前的基础上渲染,但是我们的弹窗需要在结束后及时撤下来,所以需要我们不断的重新渲染界面. 得,改吧.

  • python实现简单井字棋游戏

    井字棋,英文名叫Tic-Tac-Toe,是一种在3*3格子上进行的连珠游戏,和五子棋类似,由于棋盘一般不画边框,格线排成井字故得名.游戏需要的工具仅为纸和笔,然后由分别代表O和X的两个游戏者轮流在格子里留下标记(一般来说先手者为X),任意三个标记形成一条直线,则为获胜. 游戏的难点在于,如何判断连接成了一条线:横.竖.斜三个方向: 游戏的代码: #!/usr/bin/env python3 # -*- coding:utf-8 -*- u''' Created on 2019年4月13日 @au

  • Java实现简单井字棋小游戏代码实例

    Java第一次实验,老师让做一个井字棋,电脑随机下棋. 然后就想能不能聪明一点,可以判断出走哪一步棋:然后只能做到不会输,还是不够聪明,只能呆板地堵住用户,smartRobot的第三个判断逻辑找不到最佳位置,赢得概率比较小:而且我没事干时,想玩玩这个小游戏找找成就感,但每次都会赢了机器人,所以删删改改了四五次,最后才成. 可以选择谁先开始,但startGame里的代码更加冗余了.看着就很乱,但没想到好的办法. smartRobot里的代码全部重写了,比原来更聪明一点了:下在四个角的位置时,能优先

  • python实现简单的井字棋游戏(gui界面)

    项目输出 项目先决条件 要使用python构建井字游戏,我们需要tkinter模块和python的基本概念 Tkinter模块是用于渲染图形的标准图形用户界面. Tkinter.messagebox用于显示消息框 要安装tkinter模块,我们在命令提示符下使用了pip install命令: pip install tkinter 项目文件结构 这些是使用python构建井字游戏的步骤: 导入模块 初始化窗口 检查结果的功能 检查获胜者的功能 定义标签和按钮 1.导入模块 from tkinte

  • C语言实现简易井字棋游戏

    井子棋承载了每个人孩童时的美好时光,小到书本.纸张,大到课桌.墙壁,总能找到井字棋盘的痕迹.今天我们就来实际操作一番,用C语言完成一个简单的井字棋游戏,让我们一起重温美好. 棋盘如下: **功能描述:**棋盘共分为九个格子,一方执"O"为棋,一方执"X"为棋,双方依次选择格子.己方棋子率先连成三子的获胜,若棋盘占满仍未分胜负,则打成平局. 具体功能实现: 1.在页面选择玩家vs玩家,或玩家vs电脑 2.玩家下棋时,输入对应格子的坐标 3.电脑下棋时,使用随机值选择坐

  • C语言实现简单的井字棋游戏

    本文实例为大家分享了C语言实现简单井字棋游戏的具体代码,供大家参考,具体内容如下 1.什么是井字棋 井字棋相信大部分人都玩过 规则:双方轮流放子,当某一方的三个子连成一线(行,列,对角)时,该方获胜. 2.游戏前的准备 1. 菜单 游戏正式开始前我们可以为用户提供一个选择菜单,笔者做了一个最简单的游戏开始菜单: 代码: /*菜单*/ int menu() { printf("###########################\n"); printf("## 1.Play

  • C语言实现简单井字棋游戏

    本文实例为大家分享了C语言实现简单井字棋游戏的具体代码,供大家参考,具体内容如下 游戏截图 源代码 person.h //玩家对战 void person() { int i,j; initMap(map); //打印棋局 displayMap(map); //未分出胜负且棋局未落满子前无限循环 while(1) { //获取玩家下子位置 getXY(&i,&j); //玩家落子 setPiece(map,i,j); //清屏 system("cls"); //打印棋局

  • C语言实现井字棋(三子棋)

    本文实例为大家分享了C语言实现井字棋的具体代码,供大家参考,具体内容如下 一.实现思路 1.初始化数组 三子棋是九宫格的格式,所以用二维数组接收数据.用'O'代表电脑下的子,'X'代表玩家下的子.未下子的时候初始化 ' '(space).则二维数组为"char"类型,大小为char board[3][3]. 2.打印棋盘 打印出井字的棋盘,同时为了将数据显示在每格的中间,用空格隔开(" %c |")的格式设置棋盘"|"用来形成竖,接着打印&quo

随机推荐