关于python的class对象的建立

2018.03.18
author: wills

类是抽象的概念,对象是实例,建立类的时候我们把动态对象和静态属性都要分析到位

编程 7 原则

单一职责 原则

单一原则表示,一个函数只需要完成自己单一的功能就好了

def add(x, y)
    return x + y

比如上面这个加法函数,十分简洁精炼,功能单一,这就是单一性原则

里氏替换 原则

子类替换父类
当两个函数的关系是is - a类型时,比如 人–学生;人 – 老师。当需要建立这种对象时,我们可以先写一个人的父类,然后再去继承它

class Person(object):
    def __init__(self, name, age):
    self.name = name
    self.age = age

class Student(Person):
    def study(self, course):
        return '%s is studing %s' %(self.name, course)

class Teacher(Person):
    def teach(self, course):
        return '%s is teaching %s' %(self.name, course)

stu = Student('wills', 16)
print(stu.study('math'))
teacher = Teacher('williams', 27)
print(teacher.teach('math'))

#> wills is studing math
#> williams is teaching math

上述程序运行结果见注释,学生和老师都是继承了人这个类,所以虽然他们都没有写构造函数,但是他们的父类有构造函数,直接调用就好。在这里我们可以看到,子类 学生 和老师都远远比他们的父类 人强大,完全可以单向替换,即子类可以替换父类,但是父类却不能随便特换子类
在上面的类中 人 学生 老师都有相同的静态属性名字 and 年龄,学生 和 老师又有不同的 动态特征,那么这就是这个类的方法。

开闭 原则

依赖倒转 原则

接口隔离 原则

合成聚合复用 原则

类之间的关系主要分为继承,依赖,关联三种,上面的人与学生之间的关系就是继承,而比如像汽车与发动机,它们的关系很紧密但是又不能称发动机就是汽车,这种关系我们称为关联,这种关系的强化体,比如人 与 手,人是主体,主体决定了子体的的生命周期,这个种更强的关联关系称为合成。另外一种关系比如像人与驾照,本身它们之间没有任何关系,但是人依赖驾照才可以开车,这种关系称为依赖

能用强关联就不要用继承

迪米特法则(最少知识原则)

(不要和陌生人讲话)

总结

GoF 设计模式

面向对象这纯理论的说不好说,还是用例子来说明:例子采用五子棋,就是前天那个例子,不过这次我建立了两个类,分别是棋盘和棋子类。新增了游戏重开,悔棋等游戏内容。所有的内容都加了注释。

首先我们既然要建立棋盘类,那么先来想想他的

import pygame

EMPTY = 0
BLACK = 1
WHITE = 2
# 设置3个标签,表示棋盘是下的棋是黑还是白 还是没有下
BOARD_COLOR = (125, 95, 25)
BLACK_COLOR = (0, 0, 0)
WHITE_COLOR = (255, 255, 255)
WIN_COLOR = (250, 100, 20)
# 表示4用到的4种颜色的三原色值


class RenjuBoard(object):
    # 创建一个棋盘对象,属性有边长,每个小方格边长,颜色,以及棋盘列表表示下棋的位置
    def __init__(self, side=600, color=BLACK_COLOR):
        self.side = side if side % 15 == 0 else side // 15 * 15
        self.grid = self.side // 15
        self.color = color
        self.boards = [[EMPTY] * 15 for _ in range(15)]
        self.is_black = True

    def reset(self):
        """ 重置,将棋盘恢复初始化 """
        for row in range(len(self.boards)):
            self.boards[row] = [EMPTY] * 15

    def move(self, pos):
        # 下棋
        if self.grid <= pos[0] <= self.grid * 15 and self.grid <= pos[1] <= self.grid * 15:
            col = round((pos[0] - self.grid) / self.grid)
            row = round((pos[1] - self.grid) / self.grid)
            if self.boards[row][col] == EMPTY:
                self.boards[row][col] = BLACK if self.is_black else WHITE
                self.is_black = not self.is_black

    def take_back(self, piece):
        # 悔棋
        if len(piece.pieces) == 0:
            return
        # flag表示被悔棋的那个棋子
        flag = piece.pieces.popitem()
        for tup in flag:
            self.boards[tup[0]][tup[1]] = EMPTY
            self.is_black = not self.is_black
            break

    def draw(self, screen):
        # 将棋盘画出来
        for i in range(1, 16):
            pygame.draw.line(screen, self.color, (self.grid * i, self.grid), (self.grid * i, self.grid * 15))
            pygame.draw.line(screen, self.color, (self.grid, self.grid * i), (self.grid * 15, self.grid * i))
        pygame.draw.rect(screen, self.color, (self.grid, self.grid, self.grid * 14, self.grid * 14), 5)
        pygame.draw.circle(screen, self.color, (self.grid * 8, self.grid * 8), 5, 0)
        pygame.draw.circle(screen, self.color, (self.grid * 4, self.grid * 4), 3, 0)
        pygame.draw.circle(screen, self.color, (self.grid * 4, self.grid * 12), 3, 0)
        pygame.draw.circle(screen, self.color, (self.grid * 12, self.grid * 4), 3, 0)
        pygame.draw.circle(screen, self.color, (self.grid * 12, self.grid * 12), 3, 0)


class Piece(object):

    def __init__(self):
        self.pos = (0, 0)
        self.color = BLACK_COLOR
        self.pieces = {}

    def reset(self):
         # 重置 表示一个棋都没有下
        self.pieces = {}

    def move(self, board, pos):
        # 下棋,棋子组成一个字典
        if board.grid <= pos[0] <= board.grid * 15 and board.grid <= pos[1] <= board.grid * 15:
            col = round((pos[0] - board.grid) / board.grid)
            row = round((pos[1] - board.grid) / board.grid)
            self.pieces.update({(row, col): board.boards[row][col]})

    def draw_self(self, screen, board):
        # 将字典中所有棋子画出来
        for key in self.pieces:
            self.pos = ((key[1] + 1) * board.grid, (key[0] + 1) * board.grid)
            self.color = BLACK_COLOR if self.pieces[key] == BLACK else WHITE_COLOR
            pygame.draw.circle(screen, self.color, self.pos, board.grid // 2)


def who_win(board):
    # 判断水平方向胜利
    for n in range(15):
        for num in range(1, 3):
            flag = 0
            for piece in board.boards[n]:
                if piece == num:
                    flag += 1
                    if flag == 5:
                        if num == 1:
                            return 1
                        else:
                            return 2
                else:
                    flag = 0
            # 判断垂直方向胜利
            flag = 0
            for piece in board.boards:
                if piece[n] == num:
                    flag += 1
                    if flag == 5:
                        if num == 1:
                            return 1
                        else:
                            return 2
                else:
                    flag = 0

    # 判断正斜方向胜利
    for num in range(1, 3):
        for n in range(4, 25):
            flag = 0
            for i, piece in enumerate(board.boards):
                if 0 <= n - i <= 14 and piece[n - i] == num:
                    flag += 1
                    if flag == 5:
                        if num == 1:
                            return 1
                        else:
                            return 2
                else:
                    flag = 0
        # 判断反斜方向胜利
        for n in range(10, -10, -1):
            flag = 0
            for i, piece in enumerate(board.boards):
                if 0 <= n + i <= 14 and piece[n + i] == num:
                    flag += 1
                    if flag == 5:
                        if num == 1:
                            return 1
                        else:
                            return 2
                else:
                    flag = 0
    return 0


def main():
    def refresh():
        """ 刷新界面 """
        nonlocal board, piece, screen
        screen.fill(BOARD_COLOR)
        board.draw(screen)
        piece.draw_self(screen, board)
        pygame.display.flip()

    def reset():
        """ 游戏重置 """
        nonlocal board, piece, game_over, screen
        board.reset()
        piece.reset()
        screen.fill(BOARD_COLOR)
        board.draw(screen)
        piece.draw_self(screen, board)
        pygame.display.flip()
        game_over = False

    def show_text(x):
        # 显示胜利或失败的文本
        if x == 1:
            x = ' BLACK WIN'
        elif x == 2:
            x = ' WHITE WIN'
        mfont = pygame.font.SysFont('Airal', 64)
        mtext = mfont.render('GAME OVER' + x, True, WIN_COLOR)
        screen.blit(mtext, (board.grid * 1, board.grid * 7))
        pygame.display.flip()

    def take_back():
        # 悔棋操作
        nonlocal board, piece, game_over
        board.take_back(piece)
        game_over = False

    board = RenjuBoard()
    piece = Piece()
    clock = pygame.time.Clock()

    pygame.init()
    screen = pygame.display.set_mode((650, 650))
    pygame.display.set_caption('五子棋')

    game_over = False
    # 标签表示游戏有没有结束
    running = True
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False

            elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
                # 下棋
                board.move(event.pos)
                piece.move(board, event.pos)
                #piece.draw_self(screen, board)

            elif event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
                # 悔棋
                take_back()

            elif event.type == pygame.KEYDOWN and event.key == pygame.K_F1:
                # 游戏重开
                reset()

            if not game_over:
                refresh()
                for n in range(1, 3):
                    if who_win(board) == n:
                        show_text(n)
                        game_over = True

        clock.tick(24)

    pygame.quit()


if __name__ == '__main__':
    main()

这个五子棋是我写的比较完善的五子棋了,一般五子棋游戏有的操作都有,只是不能提前判断胜负,必须至少下足够五颗棋子才可以

最后忠告一句,要想面向对象的好,我觉得前期就是要多写,疯狂的写,只要不断地练习,才能真正的掌握面向对象的精髓。但是不要每次都写一样的,需要不断地提高难度,让自己不断地突破。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章