diff --git a/代码/.DS_Store b/代码/.DS_Store deleted file mode 100644 index a3bba44..0000000 Binary files a/代码/.DS_Store and /dev/null differ diff --git a/代码/.vscode/launch.json b/代码/.vscode/launch.json deleted file mode 100644 index aa52e5b..0000000 --- a/代码/.vscode/launch.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - // 使用 IntelliSense 了解相关属性。 - // 悬停以查看现有属性的描述。 - "version": "0.2.0", - "configurations": [ - { - "name": "Python 调试程序: 当前文件", - "type": "debugpy", - "request": "launch", - "program": "${file}", - "console": "integratedTerminal" - } - ] -} \ No newline at end of file diff --git a/代码/__pycache__/config_4.cpython-311.pyc b/代码/__pycache__/config_4.cpython-311.pyc new file mode 100644 index 0000000..8b1e70e Binary files /dev/null and b/代码/__pycache__/config_4.cpython-311.pyc differ diff --git a/代码/config_4.py b/代码/config_4.py new file mode 100644 index 0000000..8ac3728 --- /dev/null +++ b/代码/config_4.py @@ -0,0 +1,193 @@ +WIDTH, HEIGHT = 800, 615 +RED = (255, 48, 48) +BLUE = (65, 105, 225) +GREEN = (0, 139, 0) +board = [[' '] * 15 for line in range(15)] + +# 棋型编号 +# 第一位是主棋子的数量 +# 第二位是一级棋型编号,规则是连在一起的主棋子有多到少 +# 第三位是二级棋型编号,规则是从左向右修改,先修改空格,再添加对方棋子(比如O) + +value_model_X_test = { + '5': { + '5': ('XXXXX', 1000) + }, + '4': { + '4p_0': (' XXXX ', 400), + '4_0_1_e': (' XXXX', 100), # 结尾 + '4_0_2': (' XXXXO', 100), + '4_0_3_s': ('XXXX ', 100), # 开头 + '4_0_4': ('OXXXX ', 100), + + '4_1_e': (' XXX X', 120), # 结尾 + '4_1_1': (' XXX XO', 120), + '4_1_2_e': (' XXX X', 101), # 结尾 + '4_1_3': (' XXX XO', 101), + '4_1_4_s': ('XXX X', 100), # 无需在结尾检测,因为结尾的情况已枚举完毕 + '4_1_6_e': ('OXXX X', 100), # 结尾 + '4_1_7': ('OXXX XO', 100), + + '4_2': (' XX XX ', 110), + '4_2_1': (' XX XX ', 108), + '4_2_2': (' XX XX ', 106), + '4_2_3_e': (' XX XX', 105), # 结尾 + '4_2_4': (' XX XXO', 105), + '4_2_5': (' XX XX ', 108), + '4_2_6': (' XX XX ', 106), + '4_2_7': (' XX XX ', 104), + '4_2_8_e': (' XX XX', 102), # 结尾 + '4_2_9': (' XX XXO', 102), + '4_2_10': (' XX XX ', 106), + '4_2_11': (' XX XX ', 103), + '4_2_12': (' XX XX ', 102), + '4_2_13_e': (' XX XX', 101), # 结尾 + '4_2_14': (' XX XXO', 101), + '4_2_15_s': ('XX XX ', 105), # 开头 + '4_2_16_s': ('XX XX ', 102), # 开头 + '4_2_17_s': ('XX XX ', 101), # 开头 + '4_2_19_s': ('XX XXO', 100), # 开头 + '4_2_20': ('OXX XX ', 105), + '4_2_21': ('OXX XX ', 102), + '4_2_22': ('OXX XX ', 101), + '4_2_23_e': ('OXX XX', 100), # 结尾 + '4_2_24': ('OXX XXO', 100), + + '4_3': (' X XXX ', 121), + '4_3_1': (' X XXX ', 102), + '4_3_2_e': (' X XXX', 101), + '4_3_3': (' X XXXO', 101), + '4_3_4_s': ('X XXX ', 120), # 开头 + '4_3_5_s': ('X XXX ', 101), # 开头 + '4_3_6_e': ('OX XXX', 100), + '4_3_7_s': ('X XXXO', 100), # 开头 + '4_3_8': ('OX XXX ', 120), + '4_3_9': ('OX XXX ', 101), + '4_3_10': ('OX XXXO', 100), + }, + '3': { + '3p_0': (' XXX ', 60), + '3p_0_1': (' XXX ', 30), + '3_0_2_e': (' XXX', 25), # 结尾 + '3_0_3': (' XXXO', 25), + '3p_0_4': (' XXX ', 30), + '3_0_5': (' XXX ', 25), + '3_0_6_s': ('XXX ', 25), # 开头 + '3_0_7': ('OXXX ', 25), + + '3p_1': (' XX X ', 37), + '3_1_1_e': (' XX X', 27), # 结尾 + '3_1_2': (' XX XO', 27), + '3p_1_3': (' XX X ', 31), + '3_1_4_e': (' XX X', 26), # 结尾 + '3_1_5': (' XX XO', 26), + '3p_1_6': (' XX X ', 30), + '3_1_7_e': (' XX X', 25), # 结尾 + '3_1_8': (' XX XO', 25), + '3_1_9_s': ('XX X ', 25), # 开头 + '3_1_10': ('OXX X ', 25), + + '3p_2': (' X XX ', 37), + '3p_2_1': (' X XX ', 31), + '3p_2_2': (' X XX ', 30), + '3p_2_3_e': (' X XX', 25), # 结尾 + '3_2_4': (' X XXO', 25), + '3_2_5_s': ('X XX ', 27), # 开头 + '3_2_6_s': ('X XX ', 26), # 开头 + '3_2_7_s': ('X XX ', 25), # 开头 + '3_2_8': ('OX XX ', 27), + '3_2_9': ('OX XX ', 26), + '3_2_10': ('OX XX ', 25), + + '3_3': (' X X X ', 27), + '3_3_1': (' X X X ', 26), + '3_3_2_e': (' X X X', 25), # 结尾 + '3_3_3': (' X X XO', 25), + '3_3_4': (' X X X ', 26), + '3_3_5': (' X X X ', 25), + '3_3_6_e': (' X X X', 24), # 结尾 + '3_3_7': (' X X XO', 24), + '3_3_8_s': ('X X X ', 25), # 开头 + '3_3_9_s': ('X X X ', 24), # 开头 + '3_3_10_s': ('X X XO', 24), # 开头 + '3_3_11': ('OX X X ', 25), + '3_3_12': ('OX X X ', 24), + '3_3_13_e': ('OX X X', 23), # 结尾 + '3_3_14': ('OX X XO', 23), + }, + '2': { + '2_0': (' XX ', 8), + '2_0_1': (' XX ', 4), + '2_0_2': (' XX ', 3), + '2_0_3_e': (' XX', 1), # 结尾 + '2_0_4': (' XXO', 1), + '2_0_5': (' XX ', 4), + '2_0_6': (' XX ', 3), + '2_0_7': (' XX ', 2), + '2_0_8': (' XX ', 3), + '2_0_9': (' XX ', 2), + '2_0_10_s': ('XX ', 1), # 开头 + '2_0_11': ('OXX ', 1), + + '2_1': (' X X ', 4), + '2_1_1': (' X X ', 3), + '2_1_2_e': (' X X', 1), # 结尾 + '2_1_3': (' X XO', 1), + '2_1_4': (' X X ', 3), + '2_1_5': (' X X ', 2), + '2_1_6_s': ('X X ', 1), # 开头 + '2_1_7': ('OX X ', 1), + + '2_2': (' X X ', 4), + '2_2_1': (' X X ', 3), + '2_2_2_e': (' X X', 2), + '2_2_3': (' X XO', 2), + '2_2_4': (' X X ', 3), + '2_2_5': (' X X ', 2), + '2_2_6_e': (' X X', 1), + '2_2_7': (' X XO', 1), + '2_2_8_s': ('X X ', 2), + '2_2_9_s': ('X X ', 1), + '2_2_10': ('OX X ', 1), + '2_2_11': ('OX X ', 1), + + '2_3': (' X X ', 3), + '2_3_1_e': (' X X', 2), + '2_3_2': (' X XO', 2), + '2_3_3_s': ('X X ', 2), + '2_3_4_s': ('X X', 1), + '2_3_5_s': ('X XO', 1), + '2_3_6': ('OX X ', 2), + '2_3_7_e': ('OX X', 1), + '2_3_8': ('OX XO', 1) + } +} + +value_model_O_test = \ + {_[0]: {s[0]: (s[1][0].replace('O', '*').replace('X', 'O').replace('*', 'X'), s[1][1]) for s in _[1].items()} + for _ in value_model_X_test.items()} + +value_model_X = [ + {_[0]: [s for s in _[1].items() if s[0][-1] in ['s'] + [str(_) for _ in list(range(10))]] + for _ in value_model_X_test.items()}, + {_[0]: [s for s in _[1].items() if s[0][-1] in [str(_) for _ in list(range(10))]] + for _ in value_model_X_test.items()}, + {_[0]: [s for s in _[1].items() if s[0][-1] in ['e'] + [str(_) for _ in list(range(10))]] + for _ in value_model_X_test.items()} +] + +value_model_O = [ + {_[0]: [s for s in _[1].items() if s[0][-1] in ['s'] + [str(_) for _ in list(range(10))]] + for _ in value_model_O_test.items()}, + {_[0]: [s for s in _[1].items() if s[0][-1] in [str(_) for _ in list(range(10))]] + for _ in value_model_O_test.items()}, + {_[0]: [s for s in _[1].items() if s[0][-1] in ['e'] + [str(_) for _ in list(range(10))]] + for _ in value_model_O_test.items()} +] + +if __name__ == '__main__': + # print(value_model_X) + # print(value_model_O) + test_l = [t for _ in value_model_X_test.items() for t in _[1].items()] + print(len(test_l)) + diff --git a/代码/data/.DS_Store b/代码/data/.DS_Store index 8f33625..ccbec84 100644 Binary files a/代码/data/.DS_Store and b/代码/data/.DS_Store differ diff --git a/代码/data/bg.png b/代码/data/bg.png index c47b082..e57b465 100644 Binary files a/代码/data/bg.png and b/代码/data/bg.png differ diff --git a/代码/data/bg_old.png b/代码/data/bg_old.png new file mode 100644 index 0000000..c47b082 Binary files /dev/null and b/代码/data/bg_old.png differ diff --git a/代码/data/storn_black.png b/代码/data/chess_black.png similarity index 100% rename from 代码/data/storn_black.png rename to 代码/data/chess_black.png diff --git a/代码/data/storn_white.png b/代码/data/chess_white.png similarity index 100% rename from 代码/data/storn_white.png rename to 代码/data/chess_white.png diff --git a/代码/frame_begin.py b/代码/frame_begin.py deleted file mode 100644 index 5891f62..0000000 --- a/代码/frame_begin.py +++ /dev/null @@ -1,68 +0,0 @@ -# 五子棋棋盘:一个15*15的棋盘 -board = [[' ']*15 for line in range(15)] -for line in board: - print(line) - -# 落子:黑棋白棋轮流落子,只能在把棋子落在两条线的交点上,已落子的地方不能再重复落子; -def set_chess(x,y,color): - # 有棋子 - if board[x][y] != ' ': - print('该位置已有棋子') - return False - # 位置为空落子 - else: - board[x][y] = color - for i in board: - print(i) - return True - -# 用X代表黑棋,O代表白棋 -flag = 0 -going = True -while going: - if flag == 0: - print('黑棋回合') - x = int(input('请输入棋子横坐标0-14:')) - y = int(input('请输入棋子纵坐标0-14:')) - set_chess(x,y,'X') - flag = 1 - else: - print('白棋回合') - x = int(input('请输入棋子横坐标0-14:')) - y = int(input('请输入棋子纵坐标0-14:')) - set_chess(x,y,'O') - flag = 0 - - -# 胜利条件:横、竖、正斜、反斜四个方向相同颜色五子连珠的一方,获胜; -def check_win(board): - for line in board: - if ''.join(line).find('O'*5) != -1: - print('白棋获胜') - return 0 - elif ''.join(line).find('X'*5) != -1: - print('黑棋获胜') - return 1 - else: - return -1 - -board_b = [list(l) for l in zip(*board)] -board_c = [[] for line in range(29)] -for x in range(15): - for y in range(15): - board_c[x-y].append(board[x][y]) -board_d = [[] for line in range(29)] -for x in range(15): - for y in range(15): - board_d[x+y].append(board[x][y]) - -def check_win_all(board): - board_c = [[] for line in range(29)] - for x in range(15): - for y in range(15): - board_c[x-y].append(board[x][y]) - board_d = [[] for line in range(29)] - for x in range(15): - for y in range(15): - board_d[x+y].append(board[x][y]) - return [check_win(board), check_win([list(l) for l in zip(*board)]), check_win(board_c), check_win(board_d)] \ No newline at end of file diff --git a/代码/frame_board.py b/代码/frame_board.py deleted file mode 100644 index d86e97f..0000000 --- a/代码/frame_board.py +++ /dev/null @@ -1,22 +0,0 @@ -board = [[] for i in range(15)] - -for i in range(15): - for j in range(15): - board[i].append((i,j)) - - -board_b = [list(l) for l in zip(*board)] - -board_c = [[] for line in range(29)] -for x in range(15): - for y in range(15): - board_c[x-y].append(board[x][y]) -for line in board_c: - print(line) - -board_d = [[] for line in range(29)] -for x in range(15): - for y in range(15): - board_d[x+y].append(board[x][y]) -for line in board_d: - print(line) \ No newline at end of file diff --git a/代码/frame_new.py b/代码/frame_new.py deleted file mode 100644 index 059d68f..0000000 --- a/代码/frame_new.py +++ /dev/null @@ -1,55 +0,0 @@ -def set_chess(x,y,color): - if board[x][y] != ' ': - print('该位置已有棋子') - return False - else: - board[x][y] = color - for i in board: - print(i) - return True - -def check_win(board): - for line in board: - if ''.join(line).find('O'*5) != -1: - print('白棋获胜') - return 0 - elif ''.join(line).find('X'*5) != -1: - print('黑棋获胜') - return 1 - else: - return -1 - -def check_win_all(board): - board_c = [[] for line in range(29)] - for x in range(15): - for y in range(15): - board_c[x-y].append(board[x][y]) - board_d = [[] for line in range(29)] - for x in range(15): - for y in range(15): - board_d[x+y].append(board[x][y]) - return [check_win(board), check_win([list(l) for l in zip(*board)]), check_win(board_c), check_win(board_d)] - -if __name__ == '__main__': - board = [[' ']*15 for line in range(15)] - for i in board: - print(i) - flag = 0 - going = True - while going: - if flag == 0: - print('黑棋回合') - x = int(input('请输入棋子横坐标0-14:')) - y = int(input('请输入棋子纵坐标0-14:')) - set_chess(x,y,'X') - flag = 1 - if 0 or 1 in check_win_all(board): - going = False - else: - print('白棋回合') - x = int(input('请输入棋子横坐标0-14:')) - y = int(input('请输入棋子纵坐标0-14:')) - set_chess(x,y,'O') - flag = 0 - if 0 or 1 in check_win_all(board): - going = False \ No newline at end of file diff --git a/代码/frame_prep.py b/代码/frame_prep.py deleted file mode 100644 index 42dc3ac..0000000 --- a/代码/frame_prep.py +++ /dev/null @@ -1,45 +0,0 @@ - -list = ['','','','','','','','','','','','','','',''] -list_2 = ['']*15 -list_3 = ['' for i in range(15)] -print(list) -print(list_2) -print(list_3) - - -str = 'XXXXX' -print(str) - - -for i in range(10): - print(i) - - -def foo(x,y): - print('两数之和为{}'.format(x+y)) - -foo(10,11) - - -board = [[' ']*15 for line in range(15)] - - -list_4 = ['X','X','O','O'] -list_str = ''.join(list_4) -print(list_str) - - -line = ['O','O','O','O','O'] -line_2 = ['O','O','O','O','X'] -print('line转化为字符串:',''.join(line)) -print('line_2转化为字符串:',''.join(line_2)) -print('查找line是否有5个O:',''.join(line).find('O'*5)) -print('查找line_2是否有5个O:',''.join(line_2).find('O'*5)) - -def set_chess(x,y,color): - if board[x][y] != ' ': - print('该位置已有棋子') - return False - else: - board[x][y] = color - return True \ No newline at end of file diff --git a/代码/gui_new.py b/代码/gui_new.py deleted file mode 100644 index 31c9753..0000000 --- a/代码/gui_new.py +++ /dev/null @@ -1,29 +0,0 @@ -import pygame as pg -if __name__ == '__main__': - pg.init() - WIDTH = 615 - HEIGHT = 615 - clock = pg.time.Clock() - screen = pg.display.set_mode((WIDTH, HEIGHT)) - black = pg.image.load("data/storn_black.png").convert_alpha() - white = pg.image.load("data/storn_white.png").convert_alpha() - background = pg.image.load("data/bg.png").convert_alpha() - objects = [] - pg.display.set_caption("五子棋") - going = True - while going: - screen.blit(background, (0, 0)) - for event in pg.event.get(): - if event.type == pg.QUIT: - going = False - elif event.type == pg.KEYDOWN and event.key == pg.K_ESCAPE: - going = False - elif event.type == pg.MOUSEBUTTONDOWN: - pos = pg.mouse.get_pos() - print(pos) - objects.append([black,(pos[0]-18,pos[1]-18)]) - for o in objects: - screen.blit(o[0], o[1]) - clock.tick(60) - pg.display.update() - pg.quit() \ No newline at end of file diff --git a/代码/gui_prep.py b/代码/gui_prep.py deleted file mode 100644 index 4e79e27..0000000 --- a/代码/gui_prep.py +++ /dev/null @@ -1,38 +0,0 @@ -import pygame as pg - - -pg.init() - -WIDTH = 615 -HEIGHT = 615 -screen = pg.display.set_mode((WIDTH, HEIGHT)) #游戏窗口 -clock = pg.time.Clock() -objects = [] # 新创建的元素,全都放到这个列表里 - -background = pg.image.load("data/bg.png").convert_alpha() -black = pg.image.load("data/storn_black.png").convert_alpha() -white = pg.image.load("data/storn_white.png").convert_alpha() - -pg.display.set_caption("五子棋")#标题 - -going = True -while going: - screen.blit(background, (0,0)) - for event in pg.event.get(): - - if event.type == pg.QUIT: - going = False - - elif event.type == pg.KEYDOWN and event.key == pg.K_ESCAPE: - going = False - - elif event.type == pg.MOUSEBUTTONDOWN: - pos = pg.mouse.get_pos() - print(pos) - objects.append([black,(pos[0]-18,pos[1]-18)]) - for o in objects: - screen.blit(o[0], o[1]) - clock.tick(60) - pg.display.update() - -pg.quit() \ No newline at end of file diff --git a/代码/main3.py b/代码/main3.py deleted file mode 100644 index 0e56b9a..0000000 --- a/代码/main3.py +++ /dev/null @@ -1,141 +0,0 @@ - -import pygame as pg -import os - -class GameObject: - def __init__(self, image, pos): - self.image = image - self.pos = image.get_rect(center= pos) - -def load_image(name): - path = os.path.join(main_dir, "data", name) - return pg.image.load(path).convert_alpha() - -def main(objects,board): - pg.init() - clock = pg.time.Clock() - screen = pg.display.set_mode((WIDTH, HEIGHT)) - black = load_image("storn_black.png") - white = load_image("storn_white.png") - background = load_image("bg.png") - - # 窗体的标题 - pg.display.set_caption("五子棋") - font = pg.font.Font('font/12345.TTF', 20) - flag = 1 - going = True - while going: - if flag % 2 == 0: - if pg.font: - text = font.render("白棋回合", True, (255, 255, 255)) - else: - if pg.font: - text = font.render("黑棋回合", True, (0, 0, 0)) - textpos = text.get_rect(centerx=background.get_width() / 2, y=2) - screen.blit(background, (0, 0)) - screen.blit(text, textpos) - for event in pg.event.get(): - if event.type == pg.QUIT: - going = False - elif event.type == pg.KEYDOWN and event.key == pg.K_ESCAPE: - going = False - elif event.type == pg.MOUSEBUTTONDOWN: - pos = pg.mouse.get_pos() - if pos[0] > 587: - x = 14 - elif pos[0] < 27: - x = 0 - else: - x = round((pos[0] - 27)/40) - if pos[1] > 587: - y = 14 - elif pos[1] < 27: - y = 0 - else: - y = round((pos[1] - 27)/40) - if flag % 2 == 0: - if set_chess(board,x,y,'O'): - objects.append(GameObject(white,(27+x*40, 27+y*40))) - flag = 1 - else: - hint_text = font.render("该位置已有棋子", True, (255, 255, 255)) - hint_textpos = hint_text.get_rect(centerx=background.get_width() / 2, y=200) - - screen.blit(hint_text, hint_textpos) - pg.display.update() - - else: - if set_chess(board,x,y,'X'): - objects.append(GameObject(black,(27+x*40, 27+y*40))) - flag = 0 - else: - hint_text = font.render("该位置已有棋子", True, (255, 255, 255)) - hint_textpos = hint_text.get_rect(centerx=background.get_width() / 2, y=200) - for o in objects: - screen.blit(o.image, o.pos) - screen.blit(hint_text, hint_textpos) - pg.display.update() - pg.time.delay(300) - for o in objects: - screen.blit(o.image, o.pos) - if 0 in check_win_all(board): - win_text = font.render("白棋获胜,游戏5秒后重新开始", True, (255, 255, 255)) - win_textpos = win_text.get_rect(centerx=background.get_width() / 2, y=200) - screen.blit(win_text, win_textpos) - pg.display.update() - pg.time.delay(5000) - board = [[' ']*15 for line in range(15)] - objects = [] - flag = 1 - elif 1 in check_win_all(board): - win_text = font.render("黑棋获胜,游戏5秒后重新开始", True, (0, 0, 0)) - win_textpos = win_text.get_rect(centerx=background.get_width() / 2, y=200) - screen.blit(win_text, win_textpos) - pg.display.update() - pg.time.delay(5000) - board = [[' ']*15 for line in range(15)] - objects = [] - flag = 1 - clock.tick(60) - pg.display.update() - -def set_chess(board,x,y,color): - if board[x][y] != ' ': - print('该位置已有棋子') - return False - else: - board[x][y] = color - return True - -def check_win(board): - for list_str in board: - if ''.join(list_str).find('O'*5) != -1: - print('白棋获胜') - return 0 - elif ''.join(list_str).find('X'*5) != -1: - print('黑棋获胜') - return 1 - else: - return -1 - -def check_win_all(board): - board_c = [[] for line in range(29)] - for x in range(15): - for y in range(15): - board_c[x+y].append(board[x][y]) - board_d = [[] for line in range(29)] - for x in range(15): - for y in range(15): - board_d[x-y].append(board[x][y]) - return [check_win(board) , check_win([list(l) for l in zip(*board)]) , check_win(board_c) , check_win(board_d)] - -if __name__ == "__main__": - main_dir = os.path.split(os.path.abspath(__file__))[0] - WIDTH = 615 - HEIGHT = 615 - SPRITE_WIDTH = 36 - SPRITE_HEIGHT = 36 - board = [[' ']*15 for line in range(15)] - objects = [] - main(objects,board) - pg.quit() \ No newline at end of file diff --git a/代码/main_1103_ai_config_4.py b/代码/main_1103_ai_config_4.py new file mode 100644 index 0000000..bbc0358 --- /dev/null +++ b/代码/main_1103_ai_config_4.py @@ -0,0 +1,497 @@ +import pygame as pg +import os +from config_4 import * +import time + + +class GameObject: + # 具有棋子的图像、类别和坐标三个属性 + def __init__(self, image, color, pos): + self.image = image + self.color = color + self.pos = image.get_rect(center=pos) + + +# 按钮类,生成了悔棋按钮和恢复按钮 +class Button(object): + # 具有图像surface,宽高和坐标属性 + def __init__(self, text, color, x=None, y=None): + self.surface = font_big.render(text, True, color) + self.WIDTH = self.surface.get_width() + self.HEIGHT = self.surface.get_height() + self.x = x + self.y = y + + # 这个方法用于确定鼠标是否点击了对应的按钮 + def check_click(self, position): + x_match = self.x < position[0] < self.x + self.WIDTH + y_match = self.y < position[1] < self.y + self.HEIGHT + if x_match and y_match: + return True + else: + return False + + +def set_chess(board_inner, x, y, chr): + if board_inner[x][y] != ' ': + print('该位置已有棋子') + print(x, y) + return False + else: + board_inner[x][y] = chr + print(x, y) + # for _ in board_inner: + # print(_) + # print() + return True + + +def check_win(board_inner): + for list_str in board_inner: + if ''.join(list_str).find('O' * 5) != -1: + print('白棋获胜') + return 0 + elif ''.join(list_str).find('X' * 5) != -1: + print('黑棋获胜') + return 1 + else: + return -1 + +#查看整个棋局上是否有获胜的条件 +def check_win_all(board_inner): + board_c = [[] for _ in range(29)] + for x in range(15): + for y in range(15): + board_c[x - y].append(board_inner[x][y]) + board_d = [[] for _ in range(29)] + for x in range(15): + for y in range(15): + board_d[x + y].append(board_inner[x][y]) + return [check_win(board_inner), check_win([list(i) for i in zip(*board_inner)]), check_win(board_c), + check_win(board_d)] + + +# 遍历棋盘获得每一行的分数 +def value(board_inner, temp_list, value_model, chr): + score = 0 + num = 0 + # 第一层循环,遍历棋盘,计算每一行的得分 + for list_str in board_inner: + # 如果一行里指定棋子数量少于2个,则跳过这一行 + if ''.join(list_str).count(chr) < 2: + continue + a = 0 # a是一个跳过参数,识别到指定棋型后,需要跳过若干位 + # 第二层循环,双指针第一个指针。每一行需要逐位识别,因为最短的棋型是5位,因此range(11)就够了 + for i in range(11): + if a == 0: # 若a为0,则正常处理 + temp = [] # temp用于存储识别到的棋型 + # 第三层循环,双指针第二个指针。最短的棋型是5位,最长的棋型是11位;因此需要不断截取指定长度的切片与不同的棋型进行对比 + for j in range(5, 12): + # 如果超出本行长度,则跳出这层循环 + if i + j > len(list_str): + break + num += 1 # num用于测试调试时计算循环次数 + s = ''.join(list_str[i:i + j]) # s是本次用于对比的切片 + s_num = min(s.count(chr), 5) # s_num是s中本方棋子的数量 + # 如果本方棋子少于2个,则跳过本次循环 + if s_num < 2: + continue + else: + # 如果是本行的开头,则与开头棋型和通用棋型进行对比 + if i == 0: + # 这个列表推导式从棋型文件中剔除了切片不可能匹配成功的棋型(比如切片只有3个X,则把包含4个X和5个X的棋型剔除) + for k in [t for _ in value_model[0].items() for t in _[1] if int(_[0]) <= s_num]: + # 如果切片与棋型完全相等,则把结果记录在temp中 + if s == k[1][0]: + temp.append((i, k)) + else: + # 如果既不是开头也不是结尾,与通用棋型进行对比 + if i + j < len(list_str): + for k in [t for _ in value_model[1].items() for t in _[1] if int(_[0]) <= s_num]: + if s == k[1][0]: + temp.append((i, k)) + # 如果是结尾,与结尾棋型和通用棋型进行对比 + elif i + j == len(list_str): + for k in [t for _ in value_model[2].items() for t in _[1] if int(_[0]) <= s_num]: + if s == k[1][0]: + temp.append((i, k)) + # 如果a不等于1,则相当于跳过本次比对,a-1,temp要记得重新赋值为[] + else: + a -= 1 + temp = [] + # 对temp进行判空操作,避免报错 + if temp: + # 用列表推导式从temp中抽离出有效信息,获得切片匹配到的最高分 + max_value = max([i[1][1][1] for i in temp]) + # 基于最高分找到匹配到的棋型 + max_shape = [i for i in temp if i[1][1][1] == max_value][0] + # 棋型特殊处理,若匹配到某些棋型,需要在匹配时跳过若干位 + if max_shape[1][0] in ['4_1_e', '4_1_1', + '4_2_5', '4_2_6', '4_2_7', '4_2_8_e', '4_2_9', + '4_3_4_s', + '3p_0', '3p_0_1', + '3p_1_3', '3_1_4_e', '3_1_5', + '3_2_5_s', + '3_3', '3_3_1', '3_3_2_e', '3_3_3', + '2_0_5', + '2_1', + '2_2_1', '2_2_2_e', '2_2_3']: + a = 1 + elif max_shape[1][0] in ['4_2_1', '4_2_2', '4_2_3_e', '4_2_4', + '4_3', '4_3_8', '4_3_9', + '3p_1', '3_1_1_e', '3_1_2', + '2_0', + '2_2']: + a = 2 + elif max_shape[1][0] in ['3p_2']: + a = 3 + elif max_shape[1][0] in ['4_2']: + a = 5 + # 用temp_list保存每一行、每一位匹配到的棋型 + temp_list.append(max_shape) + # 用score记录总分值 + score += max_value + # print(temp_list) + # print('value函数循环次数{}'.format(num)) + return score + + +# 计算某一方的附加分 +def additional(te_list): + score = 0 + # 对te_list做一些处理得到temp_list + temp_list = [i[1][0][:2] for i in te_list] + # 死四 + 活三 >= 2,则附加分加30分 + if sum([temp_list.count(i) for i in ['4_', '3p']]) >= 2: + score += 30 + # 活三 + 死三 >= 2 且 活三 > 0,则附加分加15分 + elif sum([temp_list.count(i) for i in ['3p', '3_']]) >= 2 \ + and sum([temp_list.count(i) for i in ['3p']]) > 0: + score += 15 + return score + + +# 计算棋盘横、竖、正斜、反斜四个方向分数,和附加分,加在一起成为最终总分 +def value_all(board_inner, temp_list, value_model, chr): + board_c = [[] for _ in range(29)] + for x in range(15): + for y in range(15): + board_c[x + y].append(board_inner[x][y]) + board_d = [[] for _ in range(29)] + for x in range(15): + for y in range(15): + board_d[x - y].append(board_inner[x][y]) + a = value(board_inner, temp_list, value_model, chr) + b = value([list(i) for i in zip(*board_inner)], temp_list, value_model, chr) + c = value(board_c, temp_list, value_model, chr) + d = value(board_d, temp_list, value_model, chr) + # 进行四个方向检测时,共用一个temp_list,因此附加分是考虑了全部四个方向 + add = additional(temp_list) + # print(temp_list) + # print('横{},竖{},正斜{},反斜{},附加{}'.format(a, b, c, d, add)) + return a + b + c + d + add + + +# 落子决策函数,通过遍历可落子区域,结合获胜、防守和进攻,从而输出最佳落子位置 +def value_chess(board_inner): + t1 = time.time() + # 如果棋盘为空,则黑棋直接落在天元位置,分数为0 + if board_inner == [[' '] * 15 for _ in range(15)]: + return 7, 7, 0 + # 一系列数据初始化 + temp_list_x = [] + temp_list_o = [] + tp_list_x_2 = [] + tp_list_o_2 = [] + tp_list_d = [] + score_x = value_all(board_inner, temp_list_x, value_model_X, 'X') # 落子前,黑棋分数 + pos_x = (0, 0) + score_o = value_all(board_inner, temp_list_o, value_model_O, 'O') # 落子前,白棋分数 + pos_o = (0, 0) + pos_d = (0, 0) + score_x_2 = 0 + score_o_2 = 0 + score_diff = 0 + # 获得横竖两个方向,棋子落子范围;比如最左棋子在第5列,最右棋子在第9列;最上棋子在第5行,最下棋子在第9行; + # 目的是为了缩小遍历范围;离当前棋子过远的区域,影响较小,就不再考虑遍历了; + chess_range_x = [x for x in range(15) if ''.join(board_inner[x]).replace(' ', '') != ''] + chess_range_y = [y for y in range(15) if ''.join([list(i) for i in zip(*board_inner)][y]).replace(' ', '') != ''] + # 在棋子最大范围的基础上,做一些小小的拓展,得到落子检测区域;在上下左右四个方向各拓展2行/列; + range_x = (max(0, min(chess_range_x) - 2), min(max(chess_range_x) + 2, 15)) + range_y = (max(0, min(chess_range_y) - 2), min(max(chess_range_y) + 2, 15)) + num = 0 + # 遍历落子检测区域所有的位置 + for x in range(*range_x): + for y in range(*range_y): + tp_list_x = [] + tp_list_o = [] + tp_list_c = [] + # 如果该位置已有棋子,则跳过 + if board_inner[x][y] != ' ': + continue + else: + num += 1 # num用于循环次数计数,从而检测value_chess函数的性能 + # 假定在该位置落黑子 + board_inner[x][y] = 'X' + score_a = value_all(board_inner, tp_list_x, value_model_X, 'X') # 该位置落黑子,黑棋分数 + score_c = value_all(board_inner, tp_list_c, value_model_O, 'O') # 该位置落黑子,白棋分数 + # score_x_2用于记录黑棋最高分对应的落子信息 + if score_a > score_x_2: + pos_x = x, y + tp_list_x_2 = tp_list_x + score_x_2 = score_a + # 假定在该位置落白子 + board_inner[x][y] = 'O' + score_b = value_all(board_inner, tp_list_o, value_model_O, 'O') # 该位置落白子,白棋分数 + # score_x_2用于记录白棋最高分对应的落子信息 + if score_b > score_o_2: + pos_o = x, y + tp_list_o_2 = tp_list_o + score_o_2 = score_b + # 将该位置棋子信息复原 + board_inner[x][y] = ' ' + # diff = = 1.1 * 黑棋分数增长 + (白棋原分数 - 落子后白棋分数) + (白棋预期最高分 - 落子后白棋分数) + # 之所以(白棋预期最高分 - 落子后白棋分数),是为了增加防守的逻辑; + # 之所以设置1.1的系数,是为了鼓励进攻,毕竟只有进攻才能获得胜利 + diff = 1.1 * (score_a - score_x) + score_o - score_c + score_b - score_c + # score_diff用于记录diff的最大值 + if diff > score_diff: + pos_d = x, y + tp_list_d = tp_list_x + score_diff = diff + print('value_chess本次循环次数:{}'.format(num)) + print("value_chess循环遍历执行完毕,用时{}秒".format(round(time.time() - t1, 2))) + # 三种不同的策略,打印出对应的信息 + if score_x_2 >= 1000: + print('——' * 30) + print('策略1棋面:') + print('黑棋棋面:', temp_list_x) + print('白棋棋面:', temp_list_o) + score = score_x_2 + pos = pos_x + x, y = pos + board_inner[x][y] = 'X' + # temp_list_x.clear() + # score = value_all(board_inner, temp_list_x, value_model_X) + score_o_e = value_all(board_inner, temp_list_o, value_model_O, 'O') + board_inner[x][y] = ' ' + print('执行策略1、直接获胜') + print('黑棋最佳落子:坐标{},黑棋得分{},白棋得分{}'.format(pos, score, score_o_e)) + # print('白棋最佳落子:坐标{}'.format(pos_o)) + print('白棋原分数{},预期最高分数{},分数差值{}'.format(score_o, score_o_2, score_o_2 - score_o)) + print('若白棋落子{},白棋棋型{}'.format(pos_o, tp_list_o_2)) + print('黑棋原分数{},预期最高分数{},分数差值{}'.format(score_x, score_x_2, score_x_2 - score_x)) + print('若黑棋落子{},黑棋棋型{}'.format(pos_x, tp_list_x_2)) + print('——' * 30) + print("value_chess执行完毕,用时{}秒".format(round(time.time() - t1, 2))) + elif score_o_2 >= 1000: + print('——' * 30) + print('策略2棋面:') + print('黑棋棋面:', temp_list_x) + print('白棋棋面:', temp_list_o) + x, y = pos_o + board_inner[x][y] = 'X' + temp_list_x.clear() + score = value_all(board_inner, temp_list_x, value_model_X, 'X') + score_o_e = value_all(board_inner, temp_list_o, value_model_O, 'O') + board_inner[x][y] = ' ' + pos = pos_o + print('执行策略2、防守:防止对方获胜') + print('黑棋最佳落子:坐标{},黑棋得分{},白棋得分{}'.format(pos, score, score_o_e)) + # print('白棋最佳落子:坐标{}'.format(pos_o)) + print('白棋原分数{},预期最高分数{},分数差值{}'.format(score_o, score_o_2, score_o_2 - score_o)) + print('若白棋落子{},白棋棋型{}'.format(pos_o, tp_list_o_2)) + print('黑棋原分数{},预期最高分数{},分数差值{}'.format(score_x, score_x_2, score_x_2 - score_x)) + print('若黑棋落子{},黑棋棋型{}'.format(pos_x, tp_list_x_2)) + print('——' * 30) + print("value_chess执行完毕,用时{}秒".format(round(time.time() - t1, 2))) + else: + print('——' * 30) + print('策略3棋面:') + print('黑棋棋面:', temp_list_x) + print('白棋棋面:', temp_list_o) + x, y = pos_d + board_inner[x][y] = 'X' + temp_list_x.clear() + temp_list_o.clear() + score = value_all(board_inner, temp_list_x, value_model_X, 'X') + score_o_e = value_all(board_inner, temp_list_o, value_model_O, 'O') + board_inner[x][y] = 'O' + score_test = value_all(board_inner, [], value_model_O, 'O') + board_inner[x][y] = ' ' + pos = pos_d + print('黑棋原得分', score_x) + print('黑棋得分', score) + print('白棋原得分', score_o) + print('白棋得分', score_o_e) + print('若该位置落白棋,白棋得分', score_test) + print('落子后黑棋棋面', temp_list_x) + print('执行策略3、防守:防守+进攻') + print('我方增长得分+对方减少得分:{}'.format(score_diff)) + print('黑棋最佳落子:坐标{},黑棋得分{},白棋得分{}'.format(pos, score, score_o_e)) + # print('白棋最佳落子:坐标{}'.format(pos_o)) + print('白棋原分数{},预期最高分数{},分数差值{}'.format(score_o, score_o_2, score_o_2 - score_o)) + print('若白棋落子{},白棋棋型{}'.format(pos_o, tp_list_o_2)) + print('黑棋原分数{},预期最高分数{},分数差值{}'.format(score_x, score_x_2, score_x_2 - score_x)) + print('若黑棋落子{},黑棋棋型{}'.format(pos_x, tp_list_x_2)) + print('——' * 30) + print("value_chess执行完毕,用时{}秒".format(round(time.time() - t1, 2))) + # 返回最终策略对应的黑棋落子坐标和黑棋得分 + return *pos, score + + +def main(board_inner): + pg.init() + # 一系列数据初始化 + clock = pg.time.Clock() # pygame时钟 + objects = [] # 下棋记录列表 + recover_objects = [] # 恢复棋子时用到的列表,即悔棋记录列表 + ob_list = [objects, recover_objects] # 将以上两个列表放到一个列表中,主要是增强抽象度,简少了代码行数 + screen = pg.display.set_mode((WIDTH, HEIGHT)) # 游戏窗口 + black = pg.image.load("data/chess_black.png").convert_alpha() # 黑棋棋子图像 + white = pg.image.load("data/chess_white.png").convert_alpha() # 白棋棋子图像 + background = pg.image.load("data/bg.png").convert_alpha() # 棋盘背景图像 + regret_button = Button('悔棋', RED, 665, 200) # 创建悔棋按钮 + recover_button = Button('恢复', BLUE, 665, 300) # 创建恢复按钮 + restart_button = Button('重新开始', GREEN, 625, 400) # 创建重新开始按钮 + screen.blit(regret_button.surface, (regret_button.x, regret_button.y)) # 把悔棋按钮打印游戏窗口 + screen.blit(recover_button.surface, (recover_button.x, recover_button.y)) # 把恢复按钮打印游戏窗口 + screen.blit(restart_button.surface, (restart_button.x, restart_button.y)) # 把重新开始按钮打印游戏窗口 + pg.display.set_caption("五子棋") # 窗体的标题 + flag = 0 # 回合变量,用于识别当前是哪一方回合 + going = True # 主循环变量,用于控制主循环继续或者结束 + chess_list = [black, white] # 棋子图像列表,主要是增强抽象度,简少了代码行数 + letter_list = ['X', 'O'] # 棋子类型列表,主要是增强抽象度,简少了代码行数 + word_list = ['黑棋', '白棋'] # 棋子文字名称列表,主要是增强抽象度,简少了代码行数 + word_color = [(0, 0, 0), (255, 255, 255)] # 棋子文字颜色列表,主要是增强抽象度,简少了代码行数 + while going: + screen.blit(background, (0, 0)) # 将棋盘背景打印到游戏窗口 + text = font.render("{}回合".format(word_list[flag]), True, word_color[flag]) # 创建一个文本对象,显示当前是哪方的回合 + text_pos = text.get_rect(centerx=background.get_width() / 2, y=2) # 确定文本对象的显示位置 + screen.blit(text, text_pos) # 将文本对象打印到游戏窗口 + # 通过循环不断识别玩家操作 + for event in pg.event.get(): + # 如果关闭窗口,主循环结束 + if event.type == pg.QUIT: + going = False + # 如果点击键盘ESC键,主循环结束 + elif event.type == pg.KEYDOWN and event.key == pg.K_ESCAPE: + going = False + # 如果玩家进行了鼠标点击操作 + elif event.type == pg.MOUSEBUTTONDOWN: + pos = pg.mouse.get_pos() # 获取鼠标点击坐标 + # 如果点击了悔棋按钮或者恢复按钮 + if regret_button.check_click(pos) or recover_button.check_click(pos): + index = 0 if regret_button.check_click(pos) else 1 # 点击悔棋按钮index = 0,点击恢复按钮index = 1 + # 对指定列表进行判空操作,然后对下棋记录列表或者悔棋记录列表进行操作 + if ob_list[index]: + # print(ob_list[index][-1].pos) + # 将游戏/悔棋记录列表里的图像坐标,转化为board坐标 + # 人机对战需要黑方、白方各悔一步棋;(如果只是玩家悔棋,AI会立即下出一步,导致悔棋失败) + x, y = [round((p + 18 - 27) / 40) for p in ob_list[index][-1].pos[:2]] + # print(y, x) + # 如果是悔棋操作,则board指定元素值恢复为' ';如果是恢复操作,则指定坐标board指定元素重新赋值 + board_inner[y][x] = ' ' if index == 0 else ob_list[index][-1].color + ob_list[index - 1].append(ob_list[index][-1]) # 将游戏/悔棋记录列表的最后一个值添加到悔棋/下棋记录列表 + ob_list[index].pop() # 将游戏/悔棋记录列表的最后一个值删除 + if ob_list[index]: # 因为是连续悔棋,因此还需要再加一次判空操作 + x, y = [round((p + 18 - 27) / 40) for p in ob_list[index][-1].pos[:2]] + # print(y, x) + # 如果是悔棋操作,则board指定元素值恢复为' ';如果是恢复操作,则指定坐标board指定元素重新赋值 + board_inner[y][x] = ' ' if index == 0 else ob_list[index][-1].color + ob_list[index - 1].append(ob_list[index][-1]) # 将游戏/悔棋记录列表的最后一个值添加到悔棋/下棋记录列表 + ob_list[index].pop() # 将游戏/悔棋记录列表的最后一个值删除 + + # flag = [1, 0][flag] # 变更回合方 + elif restart_button.check_click(pos): + hint_text = font.render("游戏重新开始", True, word_color[flag]) # 提示文案 + hint_text_pos = hint_text.get_rect(centerx=background.get_width() / 2, y=200) # 提示文案位置 + screen.blit(hint_text, hint_text_pos) # 把提示文案打印到游戏窗口 + pg.display.update() # 对游戏窗口进行刷新 + pg.time.delay(1000) # 暂停1秒,保证文案能够清晰展示 + board_inner = [[' '] * 15 for _ in range(15)] # 对board进行初始化 + objects.clear() # 下棋记录列表初始化 + recover_objects.clear() # 悔棋记录列表初始化 + flag = 0 # flag初始化 + continue # 通过continue跳过下一行代码,从而保证flag赋值不会异常 + else: + # 若用户点击的不是悔棋、恢复按钮,则进行落子操作 + a, b = round((pos[0] - 27) / 40), round((pos[1] - 27) / 40) # 将用户鼠标点击位置的坐标,换算为board坐标 + # 若坐标非法(即点击到了黑色区域),则不做处理 + if a >= 15 or b >= 15: + continue + else: + x, y = max(0, a) if a < 0 else min(a, 14), max(0, b) if b < 0 else min(b, 14) # 将a、b进行处理得到x和y + # 若落子操作合法,则进行落子 + if set_chess(board_inner, y, x, letter_list[flag]): + # 下棋记录列表添加指定棋子 + objects.append(GameObject(chess_list[flag], letter_list[flag], (27 + x * 40, 27 + y * 40))) + # 一旦成功落子,则将悔棋记录列表清空;不这么做,一旦在悔棋和恢复中间掺杂落子操作,就会有问题 + recover_objects.clear() + # recover_objects = [] + # 判断是否出现获胜方 + if 0 in check_win_all(board_inner) or 1 in check_win_all(board_inner): + # 将下棋记录的棋子打印到游戏窗口 + for o in objects: + screen.blit(o.image, o.pos) + # 根据flag获取到当前获胜方,生成获胜文案 + win_text = font.render("{}获胜,游戏5秒后重新开始".format(word_list[flag]), True, + word_color[flag]) + # 设定获胜文案的位置 + win_text_pos = win_text.get_rect(centerx=background.get_width() / 2, y=200) + screen.blit(win_text, win_text_pos) # 把获胜文案打印到游戏窗口 + pg.display.update() # 对游戏窗口进行刷新 + pg.time.delay(5000) # 暂停5秒,保证文案能够清晰展示 + board_inner = [[' '] * 15 for _ in range(15)] # 对board进行初始化 + objects.clear() # 下棋记录列表初始化 + recover_objects.clear() # 悔棋记录列表初始化 + flag = 0 # flag初始化 + continue # 通过continue跳过下一行代码,从而保证flag赋值不会异常 + flag = [1, 0][flag] + # 若落子位置已经有棋子,则进行提示 + else: + hint_text = font.render("该位置已有棋子", True, word_color[flag]) # 提示文案 + hint_text_pos = hint_text.get_rect(centerx=background.get_width() / 2, y=200) # 提示文案位置 + # 将下棋记录的棋子打印到游戏窗口 + for o in objects: + screen.blit(o.image, o.pos) + screen.blit(hint_text, hint_text_pos) # 把提示文案打印到游戏窗口 + pg.display.update() # 对游戏窗口进行刷新 + pg.time.delay(300) # 暂停0.3秒,保证文案能够清晰展示 + # AI执黑,AI进行落子 + if flag == 0: + y, x = value_chess(board_inner)[:2] + if set_chess(board_inner, y, x, letter_list[flag]): + objects.append(GameObject(chess_list[flag], letter_list[flag], (27 + x * 40, 27 + y * 40))) + if 0 in check_win_all(board_inner) or 1 in check_win_all(board_inner): + # 将下棋记录的棋子打印到游戏窗口 + for o in objects: + screen.blit(o.image, o.pos) + # 根据flag获取到当前获胜方,生成获胜文案 + win_text = font.render("{}获胜,游戏5秒后重新开始".format(word_list[flag]), True, + word_color[flag]) + # 设定获胜文案的位置 + win_text_pos = win_text.get_rect(centerx=background.get_width() / 2, y=200) + screen.blit(win_text, win_text_pos) # 把获胜文案打印到游戏窗口 + pg.display.update() # 对游戏窗口进行刷新 + pg.time.delay(5000) # 暂停5秒,保证文案能够清晰展示 + board_inner = [[' '] * 15 for _ in range(15)] # 对board进行初始化 + objects.clear() # 下棋记录列表初始化 + recover_objects.clear() # 悔棋记录列表初始化 + flag = 0 # flag初始化 + continue + flag = [1, 0][flag] + # 将下棋记录的棋子打印到游戏窗口 + for o in objects: + screen.blit(o.image, o.pos) + clock.tick(60) # 游戏帧率每秒60帧 + pg.display.update() # 对游戏窗口进行刷新 + + +if __name__ == '__main__': + pg.init() + main_dir = os.path.split(os.path.abspath(__file__))[0] + font = pg.font.Font('font/12345.TTF', 20) + font_big = pg.font.Font('font/12345.TTF', 40) + main(board) + pg.quit() diff --git a/代码/main_new.py b/代码/main_new.py deleted file mode 100644 index e2fa9e9..0000000 --- a/代码/main_new.py +++ /dev/null @@ -1,79 +0,0 @@ -import pygame as pg - -#设置棋盘上的棋子 -def set_chess(x, y, color): - if board[x][y] != ' ': - print('该位置已有棋子') #有了 - return False - else:#没有棋子 - board[x][y] = color - return True - -#检查是否获胜 -def check_win(board): - for list_str in board: #遍历棋盘的每一行 - if ''.join(list_str).find('O'*5) != -1: #如果找到连续的五个'O',表示白棋获胜,并返回一个0表示白棋获胜 - print('白棋获胜') - return 0 - elif ''.join(list_str).find('X'*5) != -1: - print('黑棋获胜') - return 1 - else: - return -1 #都没有获胜 - -#检查所有方向的获胜情况 -def check_win_all(board): - board_c = [[] for line in range(29)] #水平方向的棋盘副本 - for x in range(15): - for y in range(15): - board_c[x-y].append(board[x][y]) #根据斜线填充棋盘副本 - board_d = [[] for line in range(29)] #反对角线方向的棋盘副本 - for x in range(15): - for y in range(15): - board_d[x+y].append(board[x][y]) #根据反对角线填充棋盘副本 - #返回四个方向的检查结果 - return [check_win(board), check_win([list(l) for l in zip(*board)]), check_win(board_c), check_win(board_d)] - - -def main(): - pg.init() - clock = pg.time.Clock() - screen = pg.display.set_mode((WIDTH, HEIGHT)) #设置显示模式 - - black = pg.image.load("data/storn_black.png").convert_alpha() - white = pg.image.load("data/storn_white.png").convert_alpha() - background = pg.image.load("data/bg.png").convert_alpha() - - objects = [] #棋子列表 - pg.display.set_caption("五子棋") #标题 - flag = 0 #当前下棋的标记 - going = True #游戏是否继续的标志 - chess_list = [black, white] #黑棋和白棋的列表 - letter_list = ['X', 'O'] #黑棋和白棋的标记列表 - while going: - screen.blit(background, (0, 0)) - for event in pg.event.get(): - if event.type == pg.QUIT: #点击关闭窗口 - going = False - elif event.type == pg.KEYDOWN and event.key == pg.K_ESCAPE: #如果按下Esc键 - going = False - elif event.type == pg.MOUSEBUTTONDOWN: #鼠标点击 - pos = pg.mouse.get_pos() #获取位置 - a, b = round((pos[0] - 27)/40), round((pos[1] - 27)/40) #计算棋盘坐标 - x, y = max(0, a) if a < 0 else min(a, 14), max(0, b) if b < 0 else min(b, 14) #限制棋子棋盘内 - if set_chess(x, y, letter_list[flag]): #成功放置棋子 - objects.append([chess_list[flag], (9+x*40, 9+y*40)]) #将棋子添加到棋子列表 - flag = [1, 0][flag] #转换下棋方 - if 0 in check_win_all(board) or 1 in check_win_all(board): #检查是否有人获胜 - going = False #有人获胜,结束游戏 - for o in objects: - screen.blit(o[0], o[1]) - clock.tick(60) - pg.display.update() - -if __name__ == '__main__': - WIDTH = 615 - HEIGHT = 615 - board = [[' ']*15 for line in range(15)] - main() - pg.quit() \ No newline at end of file