猫史档案馆


AI五子棋

用户:121115121115查看:0 回复:0 评论:0 创建时间:2024-08-22T10:29:23


import pygame

pygame.init()
screen = pygame.display.set_mode((750,850))
pygame.display.set_caption("这是我自己做的五子棋——编程侯老师")

border_left = 25
border_right = 725
border_top = 25
border_bottom = 725
width = 50
height = 50

font = pygame.font.Font("font.ttf",24)

class Button:
    def __init__(self,x,y,width,height,text,color,click_color,text_color) -> None:
        self.text = text
        self.color = color
        self.click_color = click_color
        self.text_color = text_color
        self.rect = pygame.Rect(x,y,width,height)
        self.enabled = True
    
    def draw(self,screen):
        if self.enabled:
            pygame.draw.rect(screen,self.color,self.rect)
        else:
            pygame.draw.rect(screen,self.click_color,self.rect)
    
        text_surface = font.render(self.text,True,self.text_color)
        text_rect = text_surface.get_rect(center = self.rect.center)
        screen.blit(text_surface,text_rect)
    def handle_event(self,event,game):
        if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
            if self.rect.collidepoint(event.pos):
                if(not self.enabled):
                    print("游戏开始了,别点啦!")
                else:
                    if game.winner == 0:
                        game.mode = 0
                        self.enabled = False
                        button_ai.enabled = False
                        game.started = True
                        print("点击-已开始")
                    else:
                        game.mode = 0
                        self.enabled = False
                        button_ai.enabled = False
                        game.started = True
                        game.player = 1
                        game.winner = 0
                        game.map = [0]*15
                        for i in range(15):
                            game.map[i] = [0]*15
                        print("点击-重新开始了")

class Button_AI:
    def __init__(self,x,y,width,height,text,color,click_color,text_color) -> None:
        self.text = text
        self.color = color
        self.click_color = click_color
        self.text_color = text_color
        self.rect = pygame.Rect(x,y,width,height)
        self.enabled = True
    
    def draw(self,screen):
        if self.enabled:
            pygame.draw.rect(screen,self.color,self.rect)
        else:
            pygame.draw.rect(screen,self.click_color,self.rect)
    
        text_surface = font.render(self.text,True,self.text_color)
        text_rect = text_surface.get_rect(center = self.rect.center)
        screen.blit(text_surface,text_rect)
    def handle_event(self,event,game):
        if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
            if self.rect.collidepoint(event.pos):
                if(not self.enabled):
                    print("游戏开始了,别点啦!")
                else:
                    if game.winner == 0:
                        game.mode = 1
                        game.player = 2
                        button.enabled = False
                        self.enabled = False
                        game.started = True
                        print("点击-AI模式已开始")
                    else:
                        game.mode = 1
                        game.player = 2
                        button.enabled = False
                        self.enabled = False
                        game.started = True
                        game.winner = 0
                        game.map = [0]*15
                        for i in range(15):
                            game.map[i] = [0]*15
                        print("点击-重新开始了")

class Game:
    def __init__(self) -> None:
        self.first_move = True
        self.mode = 0 # 0:双人模式  1:AI模式
        self.started = False
        self.player = 1
        self.winner = 0
        self.map = [0]*15
        for i in range(15):
            self.map[i] = [0]*15
    def start(self):
        screen.fill("#EE9A49")

        #竖线
        for x in range(15):
            pygame.draw.line(screen,"#000000",[border_left+width*x,border_top],[border_left+width*x,border_bottom],2)
        #横线  
        for y in range(15):
            pygame.draw.line(screen,"#000000",[border_left,border_top+height*y],[border_right,border_top+height*y],2)

        pygame.draw.circle(screen,"#000000",[25+50*7,25+50*7],8)

        x,y = pygame.mouse.get_pos()
        if x >= border_left and x<=border_right and y >= border_top and y <= border_bottom:
            x = round((x - border_left)/width)*width + border_left
            y = round((y - border_top)/height)*height + border_top

            pygame.draw.rect(screen,"#FFFFFF",[x-25,y-25,50,50],2)

        button.draw(screen)
        button_ai.draw(screen)

        for row in range(15):
            for col in range(15):
                if self.map[row][col] == 1:
                    pygame.draw.circle(screen,"#ffffff",[col*width+border_left,row*height+border_top],25)
                elif self.map[row][col] == 2:
                    pygame.draw.circle(screen,"#000000",[col*width+border_left,row*height+border_top],25)

        if(self.winner!=0):
            if self.winner ==1:
                text = '白子赢了!'
                color = (255,255,255)
            else:
                text = '黑子赢了!'
                color = (0,0,0)
            font = pygame.font.Font("font.ttf",70)
            self.first_move = True
            text_surface = font.render(text,True,color)
            text_position = (180,100)
            screen.blit(text_surface,text_position)
            pygame.display.update()
            pygame.time.wait(3000)
            button.enabled = True
            button_ai.enabled = True
    def check(self,row,col):
        #判断左右方向是否五子连线
        score = 1
        for i in range(4):
            try:
                if self.map[row][col+i] == self.map[row][col+i+1]:
                    score = score + 1
                else:
                    break
            except:
                break
        for i in range(4):
            try:
                if self.map[row][col-i] == self.map[row][col-i-1]:
                    score = score + 1
                else:
                    break
            except:
                break
        if score >= 5:
            return True
        
        #判断上下方向是否五子连线
        score = 1
        for i in range(4):
            try:
                if self.map[row+i][col] == self.map[row+i+1][col]:
                    score = score + 1
                else:
                    break
            except:
                break
        for i in range(4):
            try:
                if self.map[row-i][col] == self.map[row-i-1][col]:
                    score = score + 1
                else:
                    break
            except:
                break
        if score >= 5:
            return True

        #判断左下到右上倾斜方向是否五子连线
        score = 1
        for i in range(4):
            try:
                if self.map[row+i][col+i] == self.map[row+i+1][col+i+1]:
                    score = score + 1
                else:
                    break
            except:
                break
        for i in range(4):
            try:
                if self.map[row-i][col-i] == self.map[row-i-1][col-i-1]:
                    score = score + 1
                else:
                    break
            except:
                break
        if score >= 5:
            return True

        #判断左上到右下倾斜方向是否五子连线
        score = 1
        for i in range(4):
            try:
                if self.map[row-i][col+i] == self.map[row-i-1][col+i+1]:
                    score = score + 1
                else:
                    break
            except:
                break
        for i in range(4):
            try:
                if self.map[row+i][col-i] == self.map[row+i+1][col-i-1]:
                    score = score + 1
                else:
                    break
            except:
                break
        if score >= 5:
            return True
    def mouse_click(self,x,y):
        if x >= border_left and x<=border_right and y >= border_top and y <= border_bottom:
            if self.started:
                col = round((x - 25)/50)
                row = round((y - 25)/50)
                if self.map[row][col] == 0:
                    print(row+1,col+1)
                    self.map[row][col] = self.player
                    if(self.check(row,col)):
                        self.winner = self.player
                    else:
                        if self.player == 1:
                            self.player = 2
                        else:
                            self.player = 1
                else:
                    print("没看到已经有棋子了嘛")
            else:
                print("游戏还没开始呢,先点击按钮吧")

    def evaluate_score(self,row,col):
        score = 0
        directions = [(0,1),(1,0),(1,1),(1,-1)]

        for direction in directions:
            x_offset, y_offset = direction
            count = 0            # AI连续子数量
            count_player = 0     # 玩家连续子数量
            block = 0            # AI连续子两端有无阻挡
            block_player = 0     # 玩家连续子两端有无阻挡

            for offset in [-1,1]:
                # 该方向上第一颗子的颜色
                if 0<=row + y_offset*offset<15 and 0<=col + x_offset*offset<15:
                    flag = self.map[row + y_offset*offset][col + x_offset*offset]
                else:
                    flag = 0
                    
                for step in range(1,5):
                    # 计算该点坐标
                    x = col + step*x_offset*offset
                    y = row + step*y_offset*offset
                    # 计算双方连续子与阻挡
                    if 0<=x<15 and 0<=y<15:
                        if flag == 2:
                            if self.map[y][x] == 2:
                                count += 1
                            elif self.map[y][x] == 1:
                                block += 1
                                break
                        elif flag == 1:
                            if self.map[y][x] == 1:
                                count_player += 1
                            elif self.map[y][x] == 2:
                                block_player += 1
                                break

            # 计算分数并返回
            if count == 4:
                score += 10000
            if count_player == 4:
                score += 9000
            elif count == 3:
                if block == 0:
                    score += 1000
                elif block == 1:
                    score += 100
            elif count_player == 3:
                if block_player == 0:
                    score += 900
                elif block_player == 1:
                    score += 90
            elif count == 2:
                if block == 0:
                    score += 100
                elif block == 1:
                    score += 10
            elif count_player == 2:
                if block_player == 0:
                    score += 90
                elif block_player == 1:
                    score += 9
            elif count == 1:
                score += 10
            elif count_player == 1:
                score += 10
        return score

    def ai_make_move(self):
        if self.first_move:
            row = 7
            col = 7
            self.map[row][col] = 2
            self.player = 1
            self.first_move = False
        else:
            empty_cells = []

            for row in range(15):
                for col in range(15):
                    if self.map[row][col] == 0:
                        empty_cells.append((row,col))

            if empty_cells:
                #row,col = random.choice(empty_cells)
                best_score = 0
                best_move = empty_cells[0]

                #贪心机制
                for move in empty_cells:
                    row,col = move
                    score = self.evaluate_score(row,col) # 计算这个位点的得分
                    if score > best_score:
                        best_score = score
                        best_move = move
                
                row,col = best_move
                self.map[row][col] = 2
                if self.check(row,col):
                    self.winner = 2
                else:
                    self.player = 1
            else:
                print("没有空余的格子可以落子了!")


button = Button(50,750,100,50,"双人模式",(153,51,250),(221,160,221),(255,255,255))
button_ai = Button_AI(200,750,100,50,"AI模式",(153,51,250),(221,160,221),(255,255,255))
game = Game()
while True:
    for event in pygame.event.get():
        button.handle_event(event,game)
        button_ai.handle_event(event,game)
        if event.type == pygame.QUIT:
            pygame.quit()
            exit()
        elif event.type == pygame.MOUSEBUTTONDOWN:
            x,y = pygame.mouse.get_pos()
            game.mouse_click(x,y)
    if game.winner == 0:
        if game.started and game.mode and game.player == 2:
            game.ai_make_move()
    game.start()
    pygame.display.update()

重点看make_ai_move函数和evaluate_score函数,尤其是evaluate_score函数。


回复

上一页1 页 / 共 0下一页