├── AI.py ├── Checkerboard.py ├── In_package.py ├── PVE02.png ├── README.md ├── __init__.py ├── main.py ├── prepare.py ├── start02.png ├── tiaoshi.py ├── timg.png └── tubiao.ico /AI.py: -------------------------------------------------------------------------------- 1 | # 机器下棋 2 | import random 3 | from In_package import * 4 | 5 | 6 | class AI: 7 | def __init__(self, line_points, chessman): 8 | self._line_points = line_points 9 | self._my = chessman 10 | self._opponent = BLACK_CHESSMAN if chessman == WHITE_CHESSMAN else WHITE_CHESSMAN # 对手的棋子 11 | self._checkerboard = [[0] * line_points for _ in range(line_points)] 12 | 13 | def randDrop(self): # 随机落子 14 | x = random.randint(8, 10) 15 | y = random.randint(8, 10) 16 | point = Point(x, y) 17 | self._checkerboard[point.Y][point.X] = self._my.Value 18 | return point 19 | 20 | def get_opponent_drop(self, point): 21 | self._checkerboard[point.Y][point.X] = self._opponent.Value 22 | 23 | def AI_drop(self): 24 | point = None 25 | score = 0 26 | for i in range(self._line_points): 27 | for j in range(self._line_points): 28 | if self._checkerboard[j][i] == 0: 29 | _score = self._get_point_score(Point(i, j)) 30 | if _score > score: 31 | score = _score 32 | point = Point(i, j) 33 | elif _score == score and _score > 0: 34 | r = random.randint(0, 100) 35 | if r % 2 == 0: 36 | point = Point(i, j) 37 | self._checkerboard[point.Y][point.X] = self._my.Value # 标记位置 38 | return point 39 | 40 | def _get_point_score(self, point): 41 | score = 0 42 | for os in offset: 43 | score += self._get_direction_score(point, os[0], os[1]) 44 | return score 45 | 46 | def _get_direction_score(self, point, x_offset, y_offset): 47 | count = 0 # 落子处我方连续子数 48 | _count = 0 # 落子处对方连续子数 49 | space = None # 我方连续子中有无空格 50 | _space = None # 对方连续子中有无空格 51 | both = 0 # 我方连续子两端有无阻挡 52 | _both = 0 # 对方连续子两端有无阻挡 53 | # 如果是 1 表示是边上是我方子 2 表示敌方子 54 | flag = self._get_stone_color(point, x_offset, y_offset, True) 55 | if flag != 0: 56 | for step in range(1, 6): 57 | x = point.X + step * x_offset 58 | y = point.Y + step * y_offset 59 | if 0 <= x < self._line_points and 0 <= y < self._line_points: 60 | if flag == 1: 61 | if self._checkerboard[y][x] == self._my.Value: 62 | count += 1 63 | if space is False: 64 | space = True 65 | elif self._checkerboard[y][x] == self._opponent.Value: 66 | _both += 1 67 | break 68 | else: 69 | if space is None: 70 | space = False 71 | else: 72 | break # 遇到第二个空格退出 73 | elif flag == 2: 74 | if self._checkerboard[y][x] == self._my.Value: 75 | _both += 1 76 | break 77 | elif self._checkerboard[y][x] == self._opponent.Value: 78 | _count += 1 79 | if _space is False: 80 | _space = True 81 | else: 82 | if _space is None: 83 | _space = False 84 | else: 85 | break 86 | else: 87 | # 遇到边也就是阻挡 88 | if flag == 1: 89 | both += 1 90 | elif flag == 2: 91 | _both += 1 92 | if space is False: 93 | space = None 94 | if _space is False: 95 | _space = None 96 | _flag = self._get_stone_color(point, -x_offset, -y_offset, True) 97 | if _flag != 0: 98 | for step in range(1, 6): 99 | x = point.X - step * x_offset 100 | y = point.Y - step * y_offset 101 | if 0 <= x < self._line_points and 0 <= y < self._line_points: 102 | if _flag == 1: 103 | if self._checkerboard[y][x] == self._my.Value: 104 | count += 1 105 | if space is False: 106 | space = True 107 | elif self._checkerboard[y][x] == self._opponent.Value: 108 | _both += 1 109 | break 110 | else: 111 | if space is None: 112 | space = False 113 | else: 114 | break # 遇到第二个空格退出 115 | elif _flag == 2: 116 | if self._checkerboard[y][x] == self._my.Value: 117 | _both += 1 118 | break 119 | elif self._checkerboard[y][x] == self._opponent.Value: 120 | _count += 1 121 | if _space is False: 122 | _space = True 123 | else: 124 | if _space is None: 125 | _space = False 126 | else: 127 | break 128 | else: 129 | # 遇到边也就是阻挡 130 | if _flag == 1: 131 | both += 1 132 | elif _flag == 2: 133 | _both += 1 134 | # 评估棋格获胜分数。 135 | # 使计算机计算获胜分值越高的棋格,就能确定能让自己的棋子最有可能达成联机的位置,也就是最佳进攻位置, 136 | # 而一旦计算机能确定自己的最高分值的位置,计算机就具备了进攻能力。 137 | # 同理,计算机能计算出玩家的最大分值位置,并抢先玩家获得该位置,这样计算机就具有了防御的能力。 138 | # 在计算机下棋之前,会计算空白棋格上的获胜分数,根据分数高低获取最佳位置。 139 | # 计算机会将棋子下在获胜分数最高的地方。 140 | # 当已放置4颗棋子时,必须在第五个空棋格上设置绝对高的分值。也就是10000 141 | # 当获胜组合上有部分位置已被对手的棋格占据而无法连成五子时,获胜组合上空棋格的获胜分数会直接设置为0。(四颗棋子,你把中间断了) 142 | # 当有两组及其以上的获胜组合位置交叉时,对该位置的分数进行叠加,形成分数比周围位置明显高。(五子棋中三三相连) 143 | score = 0 144 | if count == 4: 145 | score = 10000 146 | elif _count == 4: 147 | score = 9000 148 | elif count == 3: 149 | if both == 0: 150 | score = 1000 151 | elif both == 1: 152 | score = 100 153 | else: 154 | score = 0 155 | elif _count == 3: 156 | if _both == 0: 157 | score = 900 158 | elif _both == 1: 159 | score = 90 160 | else: 161 | score = 0 162 | elif count == 2: 163 | if both == 0: 164 | score = 100 165 | elif both == 1: 166 | score = 10 167 | else: 168 | score = 0 169 | elif _count == 2: 170 | if _both == 0: 171 | score = 90 172 | elif _both == 1: 173 | score = 9 174 | else: 175 | score = 0 176 | elif count == 1: 177 | score = 10 178 | elif _count == 1: 179 | score = 9 180 | else: 181 | score = 0 182 | if space or _space: 183 | score /= 2 184 | return score 185 | 186 | # 判断指定位置处在指定方向上是我方子、对方子、空 187 | def _get_stone_color(self, point, x_offset, y_offset, next): 188 | x = point.X + x_offset 189 | y = point.Y + y_offset 190 | if 0 <= x < self._line_points and 0 <= y < self._line_points: 191 | if self._checkerboard[y][x] == self._my.Value: 192 | return 1 193 | elif self._checkerboard[y][x] == self._opponent.Value: 194 | return 2 195 | else: 196 | if next: 197 | return self._get_stone_color(Point(x, y), x_offset, y_offset, False) 198 | else: 199 | return 0 200 | else: 201 | return 0 202 | -------------------------------------------------------------------------------- /Checkerboard.py: -------------------------------------------------------------------------------- 1 | # 检查输赢 2 | offset = [(1, 0), (0, 1), (1, 1), (1, -1)] # - | / \ 3 | 4 | 5 | class Checkerboard: 6 | def __init__(self, line_points): 7 | self._line_points = line_points 8 | self._checkerboard = [[0] * line_points for _ in range(line_points)] 9 | self.ls = [] # 划线标记 10 | 11 | def _get_checkerboard(self): # 私有 12 | return self._checkerboard 13 | 14 | # property() 函数的作用是在新式类中返回属性值。 15 | checkerboard = property(_get_checkerboard) 16 | 17 | def can_drop(self, point): # 判断是否可落子,看这个地方有没有被标记过 18 | return self._checkerboard[point.Y][point.X] == 0 19 | 20 | def drop(self, chessman, point): # 落子 21 | # print(f'{chessman.Name} ({point.X}, {point.Y})') 22 | self._checkerboard[point.Y][point.X] = chessman.Value # point:落子位置 相当于标记 23 | # 打印获胜方出来 24 | ls = self._win(point) 25 | if ls: 26 | self.ls = self._tans(ls) 27 | return chessman # return:若该子落下之后即可获胜,则返回获胜方,否则返回 None 28 | 29 | def _tans(self, a): # 逻辑->物理 # a [(11, 8), (11, 9), (11, 10), (11, 11), (11, 12)] 30 | return [(26 + 30 * a[0][0], 26 + 30 * a[0][1]), (26 + 30 * a[-1][0], 26 + 30 * a[-1][1])] 31 | 32 | # 判断是否赢了 33 | def _win(self, point): # 私有方法 34 | cur_value = self._checkerboard[point.Y][point.X] 35 | for os in offset: 36 | ls = self._get_count_on_direction(point, cur_value, os[0], os[1]) # 获取到五颗棋子的位置,如果赢 37 | if ls: 38 | return ls 39 | 40 | # 数步数 41 | def _get_count_on_direction(self, point, value, x_offset, y_offset): # 数步数 42 | count = 1 43 | ls = [] 44 | for step in range(1, 5): # 前进数 45 | x = point.X + step * x_offset 46 | y = point.Y + step * y_offset 47 | if 0 <= x < self._line_points and 0 <= y < self._line_points and self._checkerboard[y][x] == value: 48 | ls.append((x, y)) 49 | count += 1 50 | else: 51 | break 52 | for step in range(1, 5): # 后退数 53 | x = point.X - step * x_offset 54 | y = point.Y - step * y_offset 55 | if 0 <= x < self._line_points and 0 <= y < self._line_points and self._checkerboard[y][x] == value: 56 | ls.append((x, y)) 57 | count += 1 58 | else: 59 | break 60 | if count == 5: 61 | ls.append((point.X, point.Y)) 62 | # print(ls) 63 | a = sorted(ls) 64 | return a # 好像放这里有点多余,但是只是想得到划线的xy 65 | return count >= 5 # 0,1 66 | -------------------------------------------------------------------------------- /In_package.py: -------------------------------------------------------------------------------- 1 | from collections import namedtuple 2 | import pygame 3 | # 画棋盘 4 | SIZE = 30 # 棋盘每个点时间的间隔 5 | Line_Points = 19 # 棋盘每行/每列点数 6 | Outer_Width = 20 # 棋盘外宽度 7 | Border_Width = 4 # 边框宽度 8 | Inside_Width = 4 # 边框跟实际的棋盘之间的间隔 9 | Border_Length = SIZE * (Line_Points - 1) + Inside_Width * 2 + Border_Width # 边框线的长度 10 | Start_X = Start_Y = Outer_Width + int(Border_Width / 2) + Inside_Width # 网格线起点(左上角)坐标 11 | SCREEN_HEIGHT = SIZE * (Line_Points - 1) + Outer_Width * 2 + Border_Width + Inside_Width * 2 # 游戏屏幕的高 12 | SCREEN_WIDTH = SCREEN_HEIGHT + 200 # 游戏屏幕的宽 13 | Stone_Radius = SIZE // 2 - 3 # 棋子半径 12 14 | Stone_Radius2 = SIZE // 2 + 3 # 18 放提示栏 15 | Checkerboard_Color = (247, 230, 208) # 棋盘颜色,RGB值 16 | BLACK_COLOR = (0, 0, 0) #黑棋颜色 17 | WHITE_COLOR = (255, 255, 255) #白棋颜色 18 | RED_COLOR = (200, 30, 30) 19 | BLUE_COLOR = (30, 30, 200) 20 | RED = (255, 0, 0) 21 | RIGHT_INFO_POS_X = SCREEN_HEIGHT + Stone_Radius2 * 2 + 10 22 | Chessman = namedtuple('Chessman', 'Name Value Color') 23 | Point = namedtuple('Point', 'X Y') 24 | BLACK_CHESSMAN = Chessman('黑子', 1, (45, 45, 45)) 25 | WHITE_CHESSMAN = Chessman('白子', 2, (219, 219, 219)) 26 | offset = [(1, 0), (0, 1), (1, 1), (1, -1)] # - | / \ 27 | pygame.init() 28 | # 加载标记位图片 29 | image = pygame.image.load("timg.png") 30 | font1 = pygame.font.SysFont('SimHei', 32) # 字体:黑体,32号 31 | font2 = pygame.font.SysFont('SimHei', 72) # 字体:黑体,72号 32 | screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) # 游戏屏幕的高,宽 33 | 34 | # print(SCREEN_WIDTH, SCREEN_HEIGHT) -------------------------------------------------------------------------------- /PVE02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PengyuTmz/Five-in-a-row/7ef5eb0f5bf2b3746774776bbbd77c0f98c343a1/PVE02.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Run and start 2 | 3 | ``` 4 | python main.py 5 | ``` 6 | 7 | ![start](https://github.com/PengyuTmz/GoBang/blob/main/start02.png) 8 | 9 | ![then](https://github.com/PengyuTmz/GoBang/blob/main/PVE02.png) 10 | -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PengyuTmz/Five-in-a-row/7ef5eb0f5bf2b3746774776bbbd77c0f98c343a1/__init__.py -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import pygame as pyg 2 | import sys 3 | from Checkerboard import Checkerboard # 检查 4 | from AI import AI # 电脑下棋 5 | from In_package import * # 全局变量 6 | from prepare import Prepare # 需要准备的函数,比如画棋盘,画棋子,棋盘的提示信息 7 | 8 | 9 | # 初始化游戏界面 10 | def start(): 11 | pyg.init() 12 | # screen = pyg.display.set_mode((792, 592)) 13 | screen = pyg.display.set_mode((512, 512)) 14 | surf = pyg.image.load("start02.png").convert() 15 | while True: 16 | screen.blit(surf, (0, 0)) 17 | pygame.display.flip() 18 | for event in pyg.event.get(): 19 | if event.type == pyg.QUIT: 20 | pyg.quit() 21 | sys.exit() 22 | elif event.type == pyg.constants.MOUSEBUTTONDOWN: 23 | if event.button == 1: 24 | x, y = event.pos[0], event.pos[1] 25 | pygame.display.flip() # 刷新屏幕 26 | # 如果点击‘人机对战’ 27 | if 135 < x < 385 and 265 < y < 330: 28 | pve() 29 | print("人机对战") 30 | 31 | # 点击‘人人对战’ 32 | elif 135 < x < 385 and 350 < y < 415: 33 | pvp() 34 | print("人人对战") 35 | 36 | 37 | # 人机对战界面 38 | def pve(): 39 | pre = Prepare() 40 | Pve = pyg.image.load("PVE02.png").convert() 41 | while True: 42 | screen.blit(Pve, (0, 0)) 43 | pygame.display.flip() 44 | for event in pyg.event.get(): 45 | if event.type == pyg.QUIT: 46 | pyg.quit() 47 | exit() 48 | elif event.type == pyg.constants.MOUSEBUTTONDOWN: 49 | if event.button == 1: 50 | x, y = event.pos[0], event.pos[1] 51 | pre.draw_checkerboard(screen) # 画棋盘 52 | pygame.display.flip() # 刷新屏幕显示出来 53 | # 如果点击‘人机对战’ 54 | if 135 < x < 385 and 265 < y < 330: 55 | PVE('me') 56 | print("我方先") 57 | # 点击‘人人对战’ 58 | elif 135 < x < 385 and 350 < y < 415: 59 | PVE('com') 60 | print("电脑先") 61 | 62 | 63 | # 人人对战界面 64 | def pvp(): 65 | screen = pyg.display.set_mode((792, 592)) 66 | fwidth, fheight = font2.size('黑子获胜') 67 | checkerboard = Checkerboard(Line_Points) 68 | pre = Prepare() 69 | cur_runner = BLACK_CHESSMAN # 玩家一 70 | winner = None 71 | # 设置黑白双方初始连子为0 72 | black_win_count = 0 73 | white_win_count = 0 74 | AI_x = 0 75 | AI_y = 0 76 | while True: 77 | for event in pygame.event.get(): 78 | if event.type == pyg.QUIT: 79 | sys.exit() 80 | elif event.type == pyg.MOUSEBUTTONDOWN: # 检测鼠标落下 81 | if winner is None: # 检测是否有一方胜出 82 | pressed_array = pygame.mouse.get_pressed() 83 | if pressed_array[0]: 84 | mouse_pos = pygame.mouse.get_pos() 85 | click_point = pre.get_clickpoint(mouse_pos) 86 | if click_point: 87 | AI_x, AI_y = click_point[0], click_point[ 88 | 1] # prevent 'NoneType' object is not subscriptable 89 | if click_point is not None: # 检测鼠标是否在棋盘内点击 #玩家1 90 | if checkerboard.can_drop(click_point): 91 | winner = checkerboard.drop(cur_runner, click_point) 92 | if winner is None: # 再次判断是否有胜出 93 | # 每下一次检测一次 94 | cur_runner = pre.get_next(cur_runner) # 换成玩家2下棋 95 | if click_point is not None: # 检测鼠标是否在棋盘内点击 96 | if checkerboard.can_drop(click_point): # 落子 97 | winner = checkerboard.drop(cur_runner, click_point) 98 | if winner is not None: # 再次检测是否有胜出 99 | white_win_count += 1 100 | cur_runner = pre.get_next(cur_runner) 101 | else: 102 | black_win_count += 1 103 | x, y = event.pos[0], event.pos[1] 104 | if 610 < x < 800 and 333 < y < 360: # 点击重新开始 105 | pvp() 106 | elif 600 < x < 800 and 400 < y < 500: # 点击‘回到主界面’ 107 | start() 108 | pre.draw_checkerboard(screen) # 画棋盘 109 | pre.draw_all(checkerboard, AI_x, AI_y) # 画棋盘上的棋子 110 | pre.remind_chess(cur_runner) 111 | 112 | pre.draw_left_info_every(screen, font1) 113 | if winner: 114 | pre.print_text(screen, font2, (SCREEN_WIDTH - fwidth) // 2, (SCREEN_HEIGHT - fheight) // 2, 115 | winner.Name + '获胜', 116 | RED_COLOR) 117 | pygame.display.flip() 118 | 119 | 120 | 121 | def PVE(first): # 人机对战 122 | screen = pyg.display.set_mode((792, 592)) 123 | fwidth, fheight = font2.size('黑子获胜') 124 | checkerboard = Checkerboard(Line_Points) 125 | computer = AI(Line_Points, WHITE_CHESSMAN) # 实例化一个对象 126 | pre = Prepare() 127 | black_win_count = 0 128 | AI_x = 0 129 | AI_y = 0 130 | winner = None 131 | cur_runner = BLACK_CHESSMAN # 电脑下玩之后,到我方下棋 132 | # 设置黑白双方初始连子为0 133 | white_win_count = 0 134 | while True: 135 | """ 136 | 默认黑子优先 137 | """ 138 | if first == "com": 139 | # 电脑落子是让电脑在5-13之间随机选一个位置(这里在中间部分) 140 | AI_point = computer.randDrop() # 电脑落子 141 | print("hellouuu", AI_point) 142 | AI_x = AI_point[0] 143 | AI_y = AI_point[1] 144 | winner = checkerboard.drop(cur_runner, AI_point) 145 | if winner is not None: 146 | white_win_count += 1 147 | cur_runner = pre.get_next(cur_runner) 148 | first = "other" 149 | else: 150 | for event in pygame.event.get(): 151 | if event.type == pyg.QUIT: 152 | sys.exit() 153 | elif event.type == pyg.MOUSEBUTTONDOWN: # 检测鼠标落下 154 | if winner is None: # 检测是否有一方胜出 155 | """ 156 | pygame.mouse.get_pressed() 表示左键和右键被按下(左键、中键、右键) 157 | (True, False, False) 158 | """ 159 | pressed_array = pygame.mouse.get_pressed() 160 | if pressed_array[0]: # 按下左键 161 | mouse_pos = pygame.mouse.get_pos() # 获取点击位置 162 | 163 | click_point = pre.get_clickpoint(mouse_pos) # 物理->逻辑 根据鼠标点击位置,返回游戏区坐标 164 | if click_point is not None: # 检测鼠标是否在棋盘内点击 165 | if checkerboard.can_drop(click_point): # 玩家落子 166 | # flag = 0 167 | # 这个是点击标记的,电脑下棋并不是靠点击啊!!! 168 | # mouse_x,mouse_y = mouse_pos[0],mouse_pos[1] 169 | winner = checkerboard.drop(cur_runner, click_point) 170 | if winner is None: # 再次判断是否有胜出 171 | # 一个循环内检测两次,意思就是人出一次检测一下,电脑出一次检测一下。 172 | cur_runner = pre.get_next(cur_runner) 173 | computer.get_opponent_drop(click_point) # 电脑获得人落子位置 174 | AI_point = computer.AI_drop() # 电脑落子 175 | 176 | # 逻辑->物理, 并且是电脑落子才标记,人落子就不用标记 177 | AI_x, AI_y = AI_point[0], AI_point[1] 178 | 179 | winner = checkerboard.drop(cur_runner, AI_point) 180 | if winner is not None: 181 | white_win_count += 1 182 | cur_runner = pre.get_next(cur_runner) 183 | else: 184 | black_win_count += 1 185 | x, y = event.pos[0], event.pos[1] 186 | if 610 < x < 800 and 333 < y < 360: # 点击重新开始,需要回到刚开始选择是哪方先手 187 | PVE(first) 188 | elif 600 < x < 800 and 400 < y < 500: # 点击‘回到主界面’ 189 | start() 190 | pre.draw_checkerboard(screen) # 画棋盘 191 | pre.draw_all(checkerboard, AI_x, AI_y) # 画棋盘上的棋子 192 | pre.draw_left_info_computer(screen, font1, first) 193 | if winner: 194 | pygame.draw.line(screen, RED_COLOR, checkerboard.ls[0], checkerboard.ls[1], 5) # 画线段 195 | # pygame.gfxdraw.aacircle(screen, 26 + 30 * i, 26 + 30 * j, radius, BLACK_COLOR) 196 | pre.print_text(screen, font2, (SCREEN_WIDTH - fwidth) // 2, (SCREEN_HEIGHT - fheight) // 2, 197 | winner.Name + '获胜', 198 | RED_COLOR) 199 | 200 | pygame.display.flip() 201 | 202 | 203 | start() 204 | -------------------------------------------------------------------------------- /prepare.py: -------------------------------------------------------------------------------- 1 | #准备工作 2 | from In_package import * 3 | import pygame.gfxdraw 4 | 5 | class Prepare: 6 | def __init__(self): 7 | pass 8 | # 画棋盘 9 | def draw_checkerboard(self,screen): 10 | screen.fill(Checkerboard_Color) # 填充棋盘背景色 11 | # 画棋盘网格线外的边框 12 | pygame.draw.rect(screen, BLACK_COLOR, (Outer_Width, Outer_Width, Border_Length, Border_Length), Border_Width) 13 | for i in range(19): # 画网格线 14 | pygame.draw.line(screen, BLACK_COLOR, (26, 26 + 30 * i), (26 + 30 * 18, 26 + 30 * i), 1) 15 | for j in range(19): 16 | pygame.draw.line(screen, BLACK_COLOR, (26 + 30 * j, 26), (26 + 30 * j, 26 + 30 * 18), 1) 17 | for i in (3, 9, 15): # 画星位和天元 18 | for j in (3, 9, 15): 19 | if i == j == 9: 20 | radius = 5 21 | else: 22 | radius = 3 # i,j逻辑上的横纵坐标 23 | pygame.gfxdraw.aacircle(screen, 26 + 30 * i, 26 + 30 * j, radius, BLACK_COLOR) 24 | pygame.gfxdraw.filled_circle(screen, 26 + 30 * i, 26 + 30 * j, radius, BLACK_COLOR) 25 | 26 | # 画棋子 #这个只是放在提示栏旁边的棋子 27 | def draw_chessman_pos(self,screen, pos, stone_color): 28 | pygame.gfxdraw.aacircle(screen, pos[0], pos[1], Stone_Radius2, stone_color) 29 | pygame.gfxdraw.filled_circle(screen, pos[0], pos[1], Stone_Radius2, stone_color) 30 | 31 | # 画棋盘上已有的棋子 #游戏中画的棋子 32 | def _draw_chessman(self,screen, point, stone_color, flag): 33 | pygame.gfxdraw.aacircle(screen, 26 + 30 * point.X, 26 + 30 * point.Y, Stone_Radius, stone_color) 34 | pygame.gfxdraw.filled_circle(screen, 26 + 30 * point.X, 26 + 30 * point.Y, Stone_Radius, stone_color) 35 | if flag: # 标记当前最新新棋子就行,就不用管是黑棋还是白棋 36 | screen.blit(image, [16 + 30 * point.X, 10 + 30 * point.Y]) 37 | 38 | def draw_all(self,checkerboard, AI_x, AI_y): # 每次都要重新画一次 39 | for i, row in enumerate(checkerboard.checkerboard): # 画棋盘上已有的棋子 因为下一次刷新一次, 40 | for j, cell in enumerate(row): 41 | if cell == BLACK_CHESSMAN.Value: 42 | if j == AI_x and i == AI_y: # 增加标记位 43 | flag = 1 44 | else: 45 | flag = 0 46 | 47 | self._draw_chessman(screen, Point(j, i), BLACK_CHESSMAN.Color, flag) 48 | elif cell == WHITE_CHESSMAN.Value: 49 | if j == AI_x and i == AI_y: # 增加标记位 50 | flag = 1 51 | else: 52 | flag = 0 53 | self._draw_chessman(screen, Point(j, i), WHITE_CHESSMAN.Color, flag) 54 | 55 | # 文本信息提示 56 | 57 | def print_text(self,screen, font, x, y, text, fcolor=(255, 255, 255)): 58 | imgText = font.render(text, True, fcolor) 59 | screen.blit(imgText, (x, y)) 60 | 61 | def draw_left_info_begin(self,screen, font): # 右侧信息提示 62 | self.print_text(screen, font, 324, 170, '五子棋', BLUE_COLOR) 63 | self.print_text(screen, font, 310, 270, '人人对战', BLUE_COLOR) 64 | self.print_text(screen, font, 310, 370, '人机对战', BLUE_COLOR) 65 | 66 | def draw_left_info_every(self,screen, font): # 人人对战 67 | self.print_text(screen, font, 610, 50, '当前状态', BLUE_COLOR) 68 | # print_text(screen, font, 630, 270, '悔棋', BLUE_COLOR) 69 | self.print_text(screen, font, 610, 333, '重新开始', BLUE_COLOR) 70 | self.print_text(screen, font, 600, 400, '回到主界面', BLUE_COLOR) 71 | 72 | def draw_left_info_computer(self,screen, font, first): # 人机对战 #左边文字显示 73 | self.draw_chessman_pos(screen, (SCREEN_HEIGHT + Stone_Radius2, Start_X + Stone_Radius2), WHITE_CHESSMAN.Color) 74 | self.draw_chessman_pos(screen, (SCREEN_HEIGHT + Stone_Radius2, Start_X + Stone_Radius2 * 4), BLACK_CHESSMAN.Color) 75 | if first == "me": # 没有选棋,默认白棋先下 76 | self.print_text(screen, font, 638, 29, '电脑', BLUE_COLOR) 77 | self.print_text(screen, font, 638, 83, '玩家', BLUE_COLOR) 78 | else: 79 | self.print_text(screen, font, 638, 29, '玩家', BLUE_COLOR) 80 | self.print_text(screen, font, 638, 83, '电脑', BLUE_COLOR) 81 | self.print_text(screen, font, 610, 333, '重新开始', BLUE_COLOR) 82 | self.print_text(screen, font, 600, 400, '回到主界面', BLUE_COLOR) ##r 83 | 84 | 85 | # 根据鼠标点击位置,返回游戏区坐标 物理->逻辑 86 | def get_clickpoint(self,click_pos): 87 | pos_x = click_pos[0] - Start_X 88 | pos_y = click_pos[1] - Start_Y 89 | if pos_x < -Inside_Width or pos_y < -Inside_Width: 90 | return None 91 | x = pos_x // SIZE 92 | y = pos_y // SIZE 93 | if pos_x % SIZE > Stone_Radius: 94 | x += 1 95 | if pos_y % SIZE > Stone_Radius: 96 | y += 1 97 | if x >= Line_Points or y >= Line_Points: 98 | return None 99 | return Point(x, y) 100 | 101 | # 提示当前是谁下棋 ,人人对战时需要 102 | def remind_chess(self,cur_runner): 103 | 104 | if cur_runner == BLACK_CHESSMAN: 105 | pygame.draw.rect(screen, Checkerboard_Color, [630, 100, 150, 50]) # 先把上一次的类容用一个矩形覆盖 106 | # print_text(screen, font1, 630, 100, '黑子', BLUE_COLOR) 107 | self.draw_chessman_pos(screen, (660, 140), BLACK_CHESSMAN.Color) 108 | else: 109 | pygame.draw.rect(screen, Checkerboard_Color, [630, 100, 150, 50]) 110 | # print_text(screen, font1, 630, 100, '白子', BLUE_COLOR) 111 | self.draw_chessman_pos(screen, (660, 140), WHITE_CHESSMAN.Color) 112 | 113 | # 黑白棋轮流下 114 | def get_next(self,cur_runner): 115 | if cur_runner == BLACK_CHESSMAN: 116 | return WHITE_CHESSMAN 117 | else: 118 | return BLACK_CHESSMAN 119 | -------------------------------------------------------------------------------- /start02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PengyuTmz/Five-in-a-row/7ef5eb0f5bf2b3746774776bbbd77c0f98c343a1/start02.png -------------------------------------------------------------------------------- /tiaoshi.py: -------------------------------------------------------------------------------- 1 | # import cv2 2 | # import numpy as np 3 | # 4 | # img1 = cv2.imread("D:\\demo\\lesson\\wuziqi\\fiveChess-main\\fiveChess-main\\package\\PVE.png") 5 | # img2 = cv2.resize(img1, (512, 512)) 6 | # cv2.imshow('start', img2) 7 | # cv2.imwrite("D:\\demo\\lesson\\wuziqi\\fiveChess-main\\fiveChess-main\\package\\PVE02.png",img2) 8 | # cv2.waitKey() 9 | # cv2.destroyWindow('start') 10 | import cv2 11 | import numpy as np 12 | #144621、142832、142836、142744、142739、142733、145448、 13 | 14 | # 图片路径 15 | img = cv2.imread("start02.png") 16 | a = [] 17 | b = [] 18 | 19 | 20 | def on_EVENT_LBUTTONDOWN(event, x, y, flags, param): 21 | if event == cv2.EVENT_LBUTTONDOWN: 22 | xy = "%d,%d" % (x, y) 23 | a.append(x) 24 | b.append(y) 25 | cv2.circle(img, (x, y), 1, (0, 0, 255), thickness=-1) 26 | cv2.putText(img, xy, (x, y), cv2.FONT_HERSHEY_PLAIN, 27 | 1.0, (0, 0, 0), thickness=1) 28 | cv2.imshow("image", img) 29 | 30 | 31 | cv2.namedWindow("image") 32 | cv2.setMouseCallback("image", on_EVENT_LBUTTONDOWN) 33 | cv2.imshow("image", img) 34 | cv2.waitKey(0) 35 | print(a[0], b[0]) 36 | 37 | -------------------------------------------------------------------------------- /timg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PengyuTmz/Five-in-a-row/7ef5eb0f5bf2b3746774776bbbd77c0f98c343a1/timg.png -------------------------------------------------------------------------------- /tubiao.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PengyuTmz/Five-in-a-row/7ef5eb0f5bf2b3746774776bbbd77c0f98c343a1/tubiao.ico --------------------------------------------------------------------------------