来,上代码(pygame要下载,不多说了!)
# 先导入tkinter, sys, re库
from tkinter import *
from tkinter import messagebox as msgbox
import sys
import re
"""五子棋之人机对战"""
import sys
import tkinter as tk
import random
import pygame
from pygame.locals import *
import pygame.gfxdraw
from collections import namedtuple
Chessman = namedtuple('Chessman', 'Name Value Color')
Point = namedtuple('Point', 'X Y')
BLACK_CHESSMAN = Chessman('黑子', 1, (45, 45, 45))
WHITE_CHESSMAN = Chessman('白子', 2, (219, 219, 219))
offset = [(1, 0), (0, 1), (1, 1), (1, -1)]
class Checkerboard:
def __init__(self, line_points):
self._line_points = line_points
self._checkerboard = [[0] * line_points for _ in range(line_points)]
def _get_checkerboard(self):
return self._checkerboard
checkerboard = property(_get_checkerboard)
# 判断是否可落子
def can_drop(self, point):
return self._checkerboard[point.Y][point.X] == 0
def drop(self, chessman, point):
"""
落子
:param chessman:
:param point:落子位置
:return:若该子落下之后即可获胜,则返回获胜方,否则返回 None
"""
print(f'{chessman.Name} ({point.X}, {point.Y})')
self._checkerboard[point.Y][point.X] = chessman.Value
if self._win(point):
print(f'{chessman.Name}获胜')
return chessman
# 判断是否赢了
def _win(self, point):
cur_value = self._checkerboard[point.Y][point.X]
for os in offset:
if self._get_count_on_direction(point, cur_value, os[0], os[1]):
return True
def _get_count_on_direction(self, point, value, x_offset, y_offset):
count = 1
for step in range(1, 5):
x = point.X + step * x_offset
y = point.Y + step * y_offset
if 0 <= x < self._line_points and 0 <= y < self._line_points and self._checkerboard[y][x] == value:
count += 1
else:
break
for step in range(1, 5):
x = point.X - step * x_offset
y = point.Y - step * y_offset
if 0 <= x < self._line_points and 0 <= y < self._line_points and self._checkerboard[y][x] == value:
count += 1
else:
break
return count >= 5
SIZE = 30 # 棋盘每个点时间的间隔
Line_Points = 19 # 棋盘每行/每列点数
Outer_Width = 20 # 棋盘外宽度
Border_Width = 4 # 边框宽度
Inside_Width = 4 # 边框跟实际的棋盘之间的间隔
Border_Length = SIZE * (Line_Points - 1) + Inside_Width * 2 + Border_Width # 边框线的长度
Start_X = Start_Y = Outer_Width + int(Border_Width / 2) + Inside_Width # 网格线起点(左上角)坐标
SCREEN_HEIGHT = SIZE * (Line_Points - 1) + Outer_Width * 2 + Border_Width + Inside_Width * 2 # 游戏屏幕的高
SCREEN_WIDTH = SCREEN_HEIGHT + 200 # 游戏屏幕的宽
Stone_Radius = SIZE // 2 - 3 # 棋子半径
Stone_Radius2 = SIZE // 2 + 3
Checkerboard_Color = (0xE3, 0x92, 0x65) # 棋盘颜色
BLACK_COLOR = (0, 0, 0)
WHITE_COLOR = (255, 255, 255)
RED_COLOR = (200, 30, 30)
BLUE_COLOR = (30, 30, 200)
RIGHT_INFO_POS_X = SCREEN_HEIGHT + Stone_Radius2 * 2 + 10
def print_text(screen, font, x, y, text, fcolor=(255, 255, 255)):
imgText = font.render(text, True, fcolor)
screen.blit(imgText, (x, y))
def main():
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption('单机练兵(困难模式)')
font1 = pygame.font.SysFont('SimHei', 32)
font2 = pygame.font.SysFont('SimHei', 72)
fwidth, fheight = font2.size('黑方获胜')
checkerboard = Checkerboard(Line_Points)
cur_runner = BLACK_CHESSMAN
winner = None
computer = AI(Line_Points, WHITE_CHESSMAN)
black_win_count = 0
white_win_count = 0
while True:
for event in pygame.event.get():
if event.type == QUIT:
sys.exit()
elif event.type == KEYDOWN:
if event.key == K_RETURN:
if winner is not None:
winner = None
cur_runner = BLACK_CHESSMAN
checkerboard = Checkerboard(Line_Points)
computer = AI(Line_Points, WHITE_CHESSMAN)
elif event.type == MOUSEBUTTONDOWN:
if winner is None:
pressed_array = pygame.mouse.get_pressed()
if pressed_array[0]:
mouse_pos = pygame.mouse.get_pos()
click_point = _get_clickpoint(mouse_pos)
if click_point is not None:
if checkerboard.can_drop(click_point):
winner = checkerboard.drop(cur_runner, click_point)
if winner is None:
cur_runner = _get_next(cur_runner)
computer.get_opponent_drop(click_point)
AI_point = computer.AI_drop()
winner = checkerboard.drop(cur_runner, AI_point)
if winner is not None:
white_win_count += 1
cur_runner = _get_next(cur_runner)
else:
black_win_count += 1
else:
print('超出棋盘区域')
# 画棋盘
_draw_checkerboard(screen)
# 画棋盘上已有的棋子
for i, row in enumerate(checkerboard.checkerboard):
for j, cell in enumerate(row):
if cell == BLACK_CHESSMAN.Value:
_draw_chessman(screen, Point(j, i), BLACK_CHESSMAN.Color)
elif cell == WHITE_CHESSMAN.Value:
_draw_chessman(screen, Point(j, i), WHITE_CHESSMAN.Color)
_draw_left_info(screen, font1, cur_runner, black_win_count, white_win_count)
if winner:
print_text(screen, font2, (SCREEN_WIDTH - fwidth)//2, (SCREEN_HEIGHT - fheight)//2, winner.Name + '获胜', RED_COLOR)
pygame.display.flip()
def _get_next(cur_runner):
if cur_runner == BLACK_CHESSMAN:
return WHITE_CHESSMAN
else:
return BLACK_CHESSMAN
# 画棋盘
def _draw_checkerboard(screen):
# 填充棋盘背景色
screen.fill(Checkerboard_Color)
# 画棋盘网格线外的边框
pygame.draw.rect(screen, BLACK_COLOR, (Outer_Width, Outer_Width, Border_Length, Border_Length), Border_Width)
# 画网格线
for i in range(Line_Points):
pygame.draw.line(screen, BLACK_COLOR,
(Start_Y, Start_Y + SIZE * i),
(Start_Y + SIZE * (Line_Points - 1), Start_Y + SIZE * i),
1)
for j in range(Line_Points):
pygame.draw.line(screen, BLACK_COLOR,
(Start_X + SIZE * j, Start_X),
(Start_X + SIZE * j, Start_X + SIZE * (Line_Points - 1)),
1)
# 画星位和天元
for i in (3, 9, 15):
for j in (3, 9, 15):
if i == j == 9:
radius = 5
else:
radius = 3
# pygame.draw.circle(screen, BLACK, (Start_X + SIZE * i, Start_Y + SIZE * j), radius)
pygame.gfxdraw.aacircle(screen, Start_X + SIZE * i, Start_Y + SIZE * j, radius, BLACK_COLOR)
pygame.gfxdraw.filled_circle(screen, Start_X + SIZE * i, Start_Y + SIZE * j, radius, BLACK_COLOR)
# 画棋子
def _draw_chessman(screen, point, stone_color):
# pygame.draw.circle(screen, stone_color, (Start_X + SIZE * point.X, Start_Y + SIZE * point.Y), Stone_Radius)
pygame.gfxdraw.aacircle(screen, Start_X + SIZE * point.X, Start_Y + SIZE * point.Y, Stone_Radius, stone_color)
pygame.gfxdraw.filled_circle(screen, Start_X + SIZE * point.X, Start_Y + SIZE * point.Y, Stone_Radius, stone_color)
# 画左侧信息显示
def _draw_left_info(screen, font, cur_runner, black_win_count, white_win_count):
_draw_chessman_pos(screen, (SCREEN_HEIGHT + Stone_Radius2, Start_X + Stone_Radius2), BLACK_CHESSMAN.Color)
_draw_chessman_pos(screen, (SCREEN_HEIGHT + Stone_Radius2, Start_X + Stone_Radius2 * 4), WHITE_CHESSMAN.Color)
print_text(screen, font, RIGHT_INFO_POS_X, Start_X + 3, '玩家', BLUE_COLOR)
print_text(screen, font, RIGHT_INFO_POS_X, Start_X + Stone_Radius2 * 3 + 3, '电脑', BLUE_COLOR)
print_text(screen, font, SCREEN_HEIGHT, SCREEN_HEIGHT - Stone_Radius2 * 8, '战况:', BLUE_COLOR)
_draw_chessman_pos(screen, (SCREEN_HEIGHT + Stone_Radius2, SCREEN_HEIGHT - int(Stone_Radius2 * 4.5)), BLACK_CHESSMAN.Color)
_draw_chessman_pos(screen, (SCREEN_HEIGHT + Stone_Radius2, SCREEN_HEIGHT - Stone_Radius2 * 2), WHITE_CHESSMAN.Color)
print_text(screen, font, RIGHT_INFO_POS_X, SCREEN_HEIGHT - int(Stone_Radius2 * 5.5) + 3, f'{black_win_count} 胜', BLUE_COLOR)
print_text(screen, font, RIGHT_INFO_POS_X, SCREEN_HEIGHT - Stone_Radius2 * 3 + 3, f'{white_win_count} 胜', BLUE_COLOR)
def _draw_chessman_pos(screen, pos, stone_color):
pygame.gfxdraw.aacircle(screen, pos[0], pos[1], Stone_Radius2, stone_color)
pygame.gfxdraw.filled_circle(screen, pos[0], pos[1], Stone_Radius2, stone_color)
# 根据鼠标点击位置,返回游戏区坐标
def _get_clickpoint(click_pos):
pos_x = click_pos[0] - Start_X
pos_y = click_pos[1] - Start_Y
if pos_x < -Inside_Width or pos_y < -Inside_Width:
return None
x = pos_x // SIZE
y = pos_y // SIZE
if pos_x % SIZE > Stone_Radius:
x += 1
if pos_y % SIZE > Stone_Radius:
y += 1
if x >= Line_Points or y >= Line_Points:
return None
return Point(x, y)
class AI:
def __init__(self, line_points, chessman):
self._line_points = line_points
self._my = chessman
self._opponent = BLACK_CHESSMAN if chessman == WHITE_CHESSMAN else WHITE_CHESSMAN
self._checkerboard = [[0] * line_points for _ in range(line_points)]
def get_opponent_drop(self, point):
self._checkerboard[point.Y][point.X] = self._opponent.Value
def AI_drop(self):
point = None
score = 0
for i in range(self._line_points):
for j in range(self._line_points):
if self._checkerboard[j][i] == 0:
_score = self._get_point_score(Point(i, j))
if _score > score:
score = _score
point = Point(i, j)
elif _score == score and _score > 0:
r = random.randint(0, 100)
if r % 2 == 0:
point = Point(i, j)
self._checkerboard[point.Y][point.X] = self._my.Value
return point
def _get_point_score(self, point):
score = 0
for os in offset:
score += self._get_direction_score(point, os[0], os[1])
return score
def _get_direction_score(self, point, x_offset, y_offset):
count = 0 # 落子处我方连续子数
_count = 0 # 落子处对方连续子数
space = None # 我方连续子中有无空格
_space = None # 对方连续子中有无空格
both = 0 # 我方连续子两端有无阻挡
_both = 0 # 对方连续子两端有无阻挡
# 如果是 1 表示是边上是我方子,2 表示敌方子
flag = self._get_stone_color(point, x_offset, y_offset, True)
if flag != 0:
for step in range(1, 6):
x = point.X + step * x_offset
y = point.Y + step * y_offset
if 0 <= x < self._line_points and 0 <= y < self._line_points:
if flag == 1:
if self._checkerboard[y][x] == self._my.Value:
count += 1
if space is False:
space = True
elif self._checkerboard[y][x] == self._opponent.Value:
_both += 1
break
else:
if space is None:
space = False
else:
break # 遇到第二个空格退出
elif flag == 2:
if self._checkerboard[y][x] == self._my.Value:
_both += 1
break
elif self._checkerboard[y][x] == self._opponent.Value:
_count += 1
if _space is False:
_space = True
else:
if _space is None:
_space = False
else:
break
else:
# 遇到边也就是阻挡
if flag == 1:
both += 1
elif flag == 2:
_both += 1
if space is False:
space = None
if _space is False:
_space = None
_flag = self._get_stone_color(point, -x_offset, -y_offset, True)
if _flag != 0:
for step in range(1, 6):
x = point.X - step * x_offset
y = point.Y - step * y_offset
if 0 <= x < self._line_points and 0 <= y < self._line_points:
if _flag == 1:
if self._checkerboard[y][x] == self._my.Value:
count += 1
if space is False:
space = True
elif self._checkerboard[y][x] == self._opponent.Value:
_both += 1
break
else:
if space is None:
space = False
else:
break # 遇到第二个空格退出
elif _flag == 2:
if self._checkerboard[y][x] == self._my.Value:
_both += 1
break
elif self._checkerboard[y][x] == self._opponent.Value:
_count += 1
if _space is False:
_space = True
else:
if _space is None:
_space = False
else:
break
else:
# 遇到边也就是阻挡
if _flag == 1:
both += 1
elif _flag == 2:
_both += 1
score = 0
if count == 4:
score = 10000
elif _count == 4:
score = 9000
elif count == 3:
if both == 0:
score = 1000
elif both == 1:
score = 100
else:
score = 0
elif _count == 3:
if _both == 0:
score = 900
elif _both == 1:
score = 90
else:
score = 0
elif count == 2:
if both == 0:
score = 100
elif both == 1:
score = 10
else:
score = 0
elif _count == 2:
if _both == 0:
score = 90
elif _both == 1:
score = 9
else:
score = 0
elif count == 1:
score = 10
elif _count == 1:
score = 9
else:
score = 0
if space or _space:
score /= 2
return score
# 判断指定位置处在指定方向上是我方子、对方子、空
def _get_stone_color(self, point, x_offset, y_offset, next):
x = point.X + x_offset
y = point.Y + y_offset
if 0 <= x < self._line_points and 0 <= y < self._line_points:
if self._checkerboard[y][x] == self._my.Value:
return 1
elif self._checkerboard[y][x] == self._opponent.Value:
return 2
else:
if next:
return self._get_stone_color(Point(x, y), x_offset, y_offset, False)
else:
return 0
else:
return 0
import random
import sys
import pygame
import numpy as np
# 0表示空棋
# 1表示黑棋
# 2表示白棋
# 3表示下棋的位置
cdata = [
# 一颗棋子的情况
[1, 3, 0, 0, 0], [0, 1, 3, 0, 0], [0, 0, 1, 3, 0], [0, 0, 0, 1, 3], [0, 0, 0, 3, 1],
[2, 3, 0, 0, 0], [0, 2, 3, 0, 0], [0, 0, 2, 3, 0], [0, 0, 0, 2, 3], [0, 0, 0, 3, 2],
# 二颗棋子的情况
[0, 1, 3, 1, 0], [1, 1, 3, 0, 0], [0, 0, 3, 1, 1],
[2, 2, 3, 0, 0], [0, 0, 3, 2, 2], [0, 2, 3, 2, 0],
# 三颗棋子的情况
[1, 1, 1, 3, 0], [0, 3, 1, 1, 1], [1, 1, 3, 1, 0], [1, 3, 1, 1, 0],
[2, 2, 0, 3, 2], [2, 3, 0, 2, 2], [0, 3, 2, 2, 2], [2, 2, 3, 2, 0],
[2, 3, 2, 2, 0], [0, 2, 3, 2, 2], [0, 2, 2, 3, 2], [2, 2, 2, 3, 0], [3, 2, 2, 2, 0],
# 四颗棋子情况
[1, 1, 1, 1, 3], [3, 1, 1, 1, 1], [1, 1, 1, 3, 1], [1, 3, 1, 1, 1], [1, 1, 3, 1, 1],
[2, 2, 2, 2, 3], [3, 2, 2, 2, 2], [2, 2, 3, 2, 2], [2, 3, 2, 2, 2], [2, 2, 2, 3, 2]
]
def auto_mach(row, col, level, dx, dy):
global ai_col, ai_row, max_level
col_sel = -1 # 暂存棋子列号
row_sel = -1 # 暂存棋子行号
isfind = True # 匹配成功的标记
for j in range(5):
cs = alist[row + j * dx][col + j * dy]
if cs == 0:
if cdata[level][j] == 3:
row_sel = row + j * dx
col_sel = col + j * dy
elif cdata[level][j] == 1:
isfind = False
break
elif cdata[level][j] == 2:
isfind = False
break
elif cs != cdata[level][j]:
isfind = False
break
if isfind:
ai_row = row_sel
ai_col = col_sel
max_level = level
return True
return False
def ai_play():
global ai_col, ai_row, max_level
ai_col = -1
ai_row = -1
max_level = -1
# 搜素棋盘每个位置
for i in range(19):
for j in range(19):
# 从高到低搜索
for level in range(len(cdata) - 1, -1, -1):
if level > max_level:
if i + 4 < 19:
if auto_mach(i, j, level, 1, 0):
break
if j + 4 < 19:
if auto_mach(i, j, level, 0, 1):
break
if i + 4 < 19 and j + 4 < 19:
if auto_mach(i, j, level, 1, 1):
break
if j + 4 < 19 and i - 4 > 0:
if auto_mach(i, j, level, -1, 1):
break
if ai_row!=-1 and ai_row!=-1:
alist[ai_row][ai_col]=2
return True
while True:
col = random.randint(0,18)
row = random.randint(0, 18)
if alist[row][col]==0:
alist[row][col]=2
ai_row=row
ai_col=col
return True
return False
def init():
pygame.init()
# 创建窗口,背景为棕色
global screen
screen = pygame.display.set_mode((615, 615))
pygame.display.set_caption('单机练兵(简单模式)')
screen.fill("#DD954F")
# 创建外边框
a = pygame.Surface((603, 603), flags=pygame.HWSURFACE)
a.fill(color='#121010')
b = pygame.Surface((585, 585), flags=pygame.HWSURFACE)
b.fill(color="#DD954F")
c = pygame.Surface((579, 579), flags=pygame.HWSURFACE)
c.fill(color='#121010')
e = pygame.Surface((31, 31), flags=pygame.HWSURFACE)
e.fill(color="#DD954F")
screen.blit(a, (6.5, 6.5))
screen.blit(b, (15, 15))
screen.blit(c, (18, 18))
# 棋盘格子
for j in range(18):
for i in range(18):
# 起点是20,间隔是32,每个格子大小31,所以格子间距1
screen.blit(e, (20 + 32 * i, 20 + 32 * j))
# 存储棋盘状态
global alist
alist = np.zeros((19, 19))
# 星位
pygame.draw.circle(screen, '#121010', [307.5, 307.5], 5)
pygame.draw.circle(screen, '#121010', [115.5, 307.5], 5)
pygame.draw.circle(screen, '#121010', [499.5, 307.5], 5)
pygame.draw.circle(screen, '#121010', [115.5, 499.5], 5)
pygame.draw.circle(screen, '#121010', [499.5, 499.5], 5)
pygame.draw.circle(screen, '#121010', [115.5, 115.5], 5)
pygame.draw.circle(screen, '#121010', [499.5, 115.5], 5)
pygame.draw.circle(screen, '#121010', [307.5, 499.5], 5)
pygame.draw.circle(screen, '#121010', [307.5, 115.5], 5)
# 刷新窗口
pygame.display.flip()
# 绘制棋子
def black(x, y):
a = 20
b = 20
c = 20
d = 0.01
# 循环50次,每次绘制50个半径颜色不同的同心圆
for i in range(50):
pygame.draw.circle(screen, (a, b, c), [19.5 + 32 * x, 19.5 + 32 * y], (16 / (d - 5) + 16))
a += 1
b += 1
c += 1
d += 0.08
pygame.display.update()
def white(x, y):
a = 170
b = 170
c = 170
d = 0.02
for i in range(50):
pygame.draw.circle(screen, (a, b, c), [19.5 + 32 * x, 19.5 + 32 * y], (16 / (d - 5) + 16))
a += 1
b += 1
c += 1
d += 0.08
pygame.display.update()
pygame.font.init()
font1 = pygame.font.Font(None, 250)
# 主要操作
def do(wb):
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN:
x, y = pygame.mouse.get_pos()
# 棋盘边界线的中点是19.5, 通过计算得到当前坐标在棋盘的行号和列号(x,y)
x = round((x - 19.5) / 32)
y = round((y - 19.5) / 32)
if x < 0:
x = 0
if x > 18:
x = 18
if y < 0:
y = 0
if y > 18:
y = 18
if alist[x][y] == 0:
black(x, y)
alist[x][y] = 1
wb1 = "You"
wb = "white"
check(x, y, wb1)
pygame.time.wait(100)
if ai_play():
white(ai_row, ai_col)
wb1 = "AI"
wb = "black"
check(ai_row, ai_col, wb1)
def check(x, y, wb1):
xx = x
yy = y
while True:
# 从最上边的棋子开始检查,记录颜色相同得棋子数量
# 先找到最同一条线上最上边的同色棋子
if xx == 0:
if alist[xx][yy] != alist[x][y]:
xx += 1
break
elif alist[xx][yy] != alist[x][y]:
xx += 1
break
else:
xx -= 1
num = 0
while True:
if xx == 18:
if alist[xx][yy] == alist[x][y]:
num += 1
break
elif alist[xx][yy] != alist[x][y]:
break
else:
xx += 1
num += 1
if num >= 5:
win(wb1)
# 从最边的棋子开始检查,记录颜色相同得棋子数量
# 先找到最同一条线上最左边的同色棋子
xx = x
yy = y
while True:
if yy == 0:
if alist[xx][yy] != alist[x][y]:
yy += 1
break
elif alist[xx][yy] != alist[x][y]:
yy += 1
break
else:
yy -= 1
num = 0
while True:
if yy == 18:
if alist[xx][yy] == alist[x][y]:
num += 1
break
elif alist[xx][yy] != alist[x][y]:
break
else:
yy += 1
num += 1
if num >= 5:
win(wb1)
# 从左上方的棋子开始检查,记录颜色相同得棋子数量
# 先找到最同一条线上左上方的同色棋子
xx = x
yy = y
while True:
if xx == 0:
if alist[xx][yy] != alist[x][y]:
xx += 1
yy += 1
break
elif yy == 0:
if alist[xx][yy] != alist[x][y]:
xx += 1
yy += 1
break
elif alist[xx][yy] != alist[x][y]:
xx += 1
yy += 1
break
else:
xx -= 1
yy -= 1
num = 0
while True:
if xx == 18:
if alist[xx][yy] == alist[x][y]:
num += 1
break
elif yy == 18:
if alist[xx][yy] == alist[x][y]:
num += 1
break
elif alist[xx][yy] != alist[x][y]:
break
else:
xx += 1
yy += 1
num += 1
if num >= 5:
win(wb1)
# 从右上方的棋子开始检查,记录颜色相同得棋子数量
# 先找到最同一条线上右上方的同色棋子
xx = x
yy = y
while True:
if xx == 0:
if alist[xx][yy] != alist[x][y]:
xx += 1
yy -= 1
break
elif yy == 18:
if alist[xx][yy] != alist[x][y]:
xx += 1
yy -= 1
break
elif alist[xx][yy] != alist[x][y]:
xx += 1
yy -= 1
break
else:
xx -= 1
yy += 1
num = 0
while True:
if xx == 18:
if alist[xx][yy] == alist[x][y]:
num += 1
break
elif yy == 0:
if alist[xx][yy] == alist[x][y]:
num += 1
break
elif alist[xx][yy] != alist[x][y]:
break
else:
xx += 1
yy -= 1
num += 1
if num >= 5:
win(wb1)
def win(wb1):
pygame.font.init()
font = pygame.font.Font(None, 70)
text = font.render(f"{wb1} win", True, (255, 255, 255))
screen.blit(text, ((655 - text.get_width()) / 2, (665 - text.get_height()) / 2))
pygame.display.update()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN:
init()
text = font.render("Start the game", True, (255, 255, 255))
screen.blit(text, ((655 - text.get_width()) / 2, (665 - text.get_height()) / 2))
pygame.display.update()
pygame.time.wait(500)
init()
do("black")
'''
@Auther : gaoxin
@Date : 2024.01.20
@Version : 1.0
'''
from tkinter import *
from tkinter import messagebox
import math
# 0表示空棋
# 1表示黑棋
# 2表示白棋
# 3表示下棋的位置
cdata = [
# 一颗棋子的情况
[1, 3, 0, 0, 0], [0, 1, 3, 0, 0], [0, 0, 1, 3, 0], [0, 0, 0, 1, 3], [0, 0, 0, 3, 1],
[2, 3, 0, 0, 0], [0, 2, 3, 0, 0], [0, 0, 2, 3, 0], [0, 0, 0, 2, 3], [0, 0, 0, 3, 2],
# 二颗棋子的情况
[0, 1, 3, 1, 0], [1, 1, 3, 0, 0], [0, 0, 3, 1, 1],
[2, 2, 3, 0, 0], [0, 0, 3, 2, 2], [0, 2, 3, 2, 0],
# 三颗棋子的情况
[1, 1, 1, 3, 0], [0, 3, 1, 1, 1], [1, 1, 3, 1, 0], [1, 3, 1, 1, 0],
[2, 2, 0, 3, 2], [2, 3, 0, 2, 2], [0, 3, 2, 2, 2], [2, 2, 3, 2, 0],
[2, 3, 2, 2, 0], [0, 2, 3, 2, 2], [0, 2, 2, 3, 2], [2, 2, 2, 3, 0], [3, 2, 2, 2, 0],
# 四颗棋子情况
[1, 1, 1, 1, 3], [3, 1, 1, 1, 1], [1, 1, 1, 3, 1], [1, 3, 1, 1, 1], [1, 1, 3, 1, 1],
[2, 2, 2, 2, 3], [3, 2, 2, 2, 2], [2, 2, 3, 2, 2], [2, 3, 2, 2, 2], [2, 2, 2, 3, 2]
]
def auto_mach(row, col, level, dx, dy):
global ai_col, ai_row, max_level
col_sel = -1 # 暂存棋子列号
row_sel = -1 # 暂存棋子行号
isfind = True # 匹配成功的标记
for j in range(5):
cs = alist[row + j * dx][col + j * dy]
if cs == 0:
if cdata[level][j] == 3:
row_sel = row + j * dx
col_sel = col + j * dy
elif cdata[level][j] == 1:
isfind = False
break
elif cdata[level][j] == 2:
isfind = False
break
elif cs != cdata[level][j]:
isfind = False
break
if isfind:
ai_row = row_sel
ai_col = col_sel
max_level = level
return True
return False
#定义棋盘类
class chessBoard() :
def __init__(self) :
self.window = Tk()
self.window.title("双人对战")
self.window.geometry("660x470")
self.window.resizable(0,0)
self.canvas=Canvas(self.window , bg="#EEE8AC" , width=470, height=470)
self.paint_board()
self.canvas.grid(row = 0 , column = 0)
def paint_board(self) :
for row in range(0,15) :
if row == 0 or row == 14 :
self.canvas.create_line(25 , 25+row*30 , 25+14*30 , 25+row*30 , width = 2)
else :
self.canvas.create_line(25 , 25+row*30 , 25+14*30 , 25+row*30 , width = 1)
for column in range(0,15) :
if column == 0 or column == 14 :
self.canvas.create_line(25+column*30 ,25, 25+column*30 , 25+14*30 ,width = 2)
else :
self.canvas.create_line(25+column*30 ,25, 25+column*30 , 25+14*30 , width = 1)
self.canvas.create_oval(112, 112, 118, 118, fill="black")
self.canvas.create_oval(352, 112, 358, 118, fill="black")
self.canvas.create_oval(112, 352, 118, 358, fill="black")
self.canvas.create_oval(232, 232, 238, 238, fill="black")
self.canvas.create_oval(352, 352, 358, 358, fill="black")
#定义五子棋游戏类
#0为黑子 , 1为白子 , 2为空位
class Gobang() :
#初始化
def __init__(self) :
self.board = chessBoard()
self.game_print = StringVar()
self.game_print.set("")
#16*16的二维列表,保证不会out of index
self.db = [([2] * 16) for i in range(16)]
#悔棋用的顺序列表
self.order = []
#棋子颜色
self.color_count = 0
self.color = 'black'
#清空与赢的初始化,已赢为1,已清空为1
self.flag_win = 1
self.flag_empty = 1
self.options()
#黑白互换
def change_color(self) :
self.color_count = (self.color_count + 1 ) % 2
if self.color_count == 0 :
self.color = "black"
elif self.color_count ==1 :
self.color = "white"
#落子
def chess_moving(self ,event) :
#不点击“开始”与“清空”无法再次开始落子
if self.flag_win ==1 or self.flag_empty ==0 :
return
#坐标转化为下标
x,y = event.x-25 , event.y-25
x = round(x/30)
y = round(y/30)
#点击位置没用落子,且没有在棋盘线外,可以落子
while self.db[y][x] == 2 and self.limit_boarder(y,x):
self.db[y][x] = self.color_count
self.order.append(x+15*y)
self.board.canvas.create_oval(25+30*x-12 , 25+30*y-12 , 25+30*x+12 , 25+30*y+12 , fill = self.color,tags = "chessman")
if self.game_win(y,x,self.color_count) :
self.game_print.set(self.color+"获胜")
messagebox.showinfo("game over",self.color+"获胜")
else :
self.change_color()
self.game_print.set("请"+self.color+"落子")
#保证棋子落在棋盘上
def limit_boarder(self , y , x) :
if x<0 or x>14 or y<0 or y>14 :
return False
else :
return True
#计算连子的数目,并返回最大连子数目
def chessman_count(self , y , x , color_count ) :
count1,count2,count3,count4 = 1,1,1,1
#横计算
for i in range(-1 , -5 , -1) :
if self.db[y][x+i] == color_count :
count1 += 1
else:
break
for i in range(1 , 5 ,1 ) :
if self.db[y][x+i] == color_count :
count1 += 1
else:
break
#竖计算
for i in range(-1 , -5 , -1) :
if self.db[y+i][x] == color_count :
count2 += 1
else:
break
for i in range(1 , 5 ,1 ) :
if self.db[y+i][x] == color_count :
count2 += 1
else:
break
#/计算
for i in range(-1 , -5 , -1) :
if self.db[y+i][x+i] == color_count :
count3 += 1
else:
break
for i in range(1 , 5 ,1 ) :
if self.db[y+i][x+i] == color_count :
count3 += 1
else:
break
#\计算
for i in range(-1 , -5 , -1) :
if self.db[y+i][x-i] == color_count :
count4 += 1
else:
break
for i in range(1 , 5 ,1 ) :
if self.db[y+i][x-i] == color_count :
count4 += 1
else:
break
return max(count1 , count2 , count3 , count4)
#判断输赢
def game_win(self , y , x , color_count ) :
if self.chessman_count(y,x,color_count) >= 5 :
self.flag_win = 1
self.flag_empty = 0
return True
else :
return False
#悔棋,清空棋盘,再画剩下的n-1个棋子
def withdraw(self ) :
if len(self.order)==0 or self.flag_win == 1:
return
self.board.canvas.delete("chessman")
z = self.order.pop()
x = z%15
y = z//15
self.db[y][x] = 2
self.color_count = 1
for i in self.order :
ix = i%15
iy = i//15
self.change_color()
self.board.canvas.create_oval(25+30*ix-12 , 25+30*iy-12 , 25+30*ix+12 , 25+30*iy+12 , fill = self.color,tags = "chessman")
self.change_color()
self.game_print.set("请"+self.color+"落子")
#清空
def empty_all(self) :
self.board.canvas.delete("chessman")
#还原初始化
self.db = [([2] * 16) for i in range(16)]
self.order = []
self.color_count = 0
self.color = 'black'
self.flag_win = 1
self.flag_empty = 1
self.game_print.set("")
def rules_of_the_game(self):
messagebox.showinfo("游戏规则","游戏规则:1.五子棋是两个人之间进行的竞技活动,由于对黑方白方规则不同,黑棋必须先行。2.五子棋专用盘为 15×15 ,五连子的方向为横、竖、斜。")
def take_a_stop(self):
self.color_count = self.color_count - 1
self.color_count = (self.color_count + 1 ) % 2
if self.color_count == 0 :
self.color = "black"
self.change_color()
self.game_print.set("请"+self.color+"落子")
elif self.color_count ==1 :
self.color = "white"
self.change_color()
self.game_print.set("请"+self.color+"落子")
#将self.flag_win置0才能在棋盘上落子
def game_start(self) :
#没有清空棋子不能置0开始
if self.flag_empty == 0:
return
self.flag_win = 0
self.game_print.set("请"+self.color+"落子")
def ren_shu(self):
if self.color == "black":
self.game_print.set("white获胜")
messagebox.showinfo("game over","white获胜")
self.flag_win = 1
self.flag_empty = 0
else:
self.game_print.set("black获胜")
messagebox.showinfo("game over","black获胜")
self.flag_win = 1
self.flag_empty = 0
def options(self) :
self.board.canvas.bind("<Button-1>",self.chess_moving)
Label(self.board.window , textvariable = self.game_print , font = ("Arial", 20) ).place(relx = 0, rely = 0 ,x = 495 , y = 200)
Button(self.board.window , text= "开始游戏" ,command = self.game_start,width = 13, font = ("Verdana", 12)).place(relx=0, rely=0, x=495, y=15)
Button(self.board.window , text= " 悔棋 " ,command = self.withdraw,width = 13, font = ("Verdana", 12)).place(relx=0, rely=0, x=495, y=60)
Button(self.board.window , text= "停走一步" ,command = self.take_a_stop,width = 13, font = ("Verdana", 12)).place(relx=0, rely=0, x=495, y=105)
Button(self.board.window , text= "清空棋局" ,command = self.empty_all,width = 13, font = ("Verdana", 12)).place(relx=0, rely=0, x=495, y=150)
Button(self.board.window , text= "结束游戏" ,command = self.board.window.destroy,width = 13, font = ("Verdana", 12)).place(relx=0, rely=0, x=495, y=420)
Button(self.board.window , text= "游戏规则" ,command = self.rules_of_the_game,width = 13, font = ("Verdana", 12)).place(relx=0, rely=0, x=495, y=375)
Button(self.board.window , text= " 认输 " ,command = self.ren_shu,width = 13, font = ("Verdana", 12)).place(relx=0, rely=0, x=495, y=330)
self.board.window.mainloop()
# 这里定义一个Tking类
class Tking(object):
def a(self):
self.winb.destroy()
init()
do("black")
def b(self):
self.wina.destroy()
game = Gobang()
def c(self):
self.winb.destroy()
main()
def d(self):
self.wina.destroy()
self.winb = Tk()
self.winb.geometry("300x200")
self.winb.title("难度选择")
button3 = Button(self.winb, text="简单模式", font=('宋体', 10), width=15, command=self.a)
button3.place(x=100, y=50)
button4 = Button(self.winb, text="困难模式", font=('宋体', 10), width=15, command=self.c)
button4.place(x=100, y=125)
# 初始化
def __init__(self):
self.win = Tk()
self.count = 3
# 定义函数来获取数据内容
def read1(self):
with open('zhanghao.txt', 'r')as f:
file = f.read()
return file
# 定义函数来实现“登录”按钮的功能
def js(self):
# 调用函数获取账号信息
data = self.read1()
# 获取用户输入的信息
user = self.username.get()
passwd = self.passwd.get()
# 使用正则得到我们想要的数据
user1 = re.findall(r'账号:(.*\d?)', data)
passwd1 = re.findall(r'密码:(.*\w?)', data)
# 这里判断输入错误的次数,等于次就结束程序
if self.count == 0:
msgbox.showinfo('警告!', '非法入侵!\n启动自动销毁模式!!!')
self.win.quit()
sys.exit(0)
# 这里对用户的数据和账号数据进行对比
for i in range(len(user1)):
if user == user1[i] and passwd == passwd1[i]:
msgbox.showinfo('登录', '登录成功!')
self.wina = Tk()
self.wina.geometry("300x200")
self.wina.title("五子棋")
buttona = Button(self.wina, text="单机练兵", font=('宋体', 10), width=15, command=self.d)
buttona.place(x=100, y=50)
button2 = Button(self.wina, text="双人对战", font=('宋体', 10), width=15, command=self.b)
button2.place(x=100, y=125)
self.win.destroy()
break
else:
msgbox.showinfo('失败!', '你还可以登录%s次' % self.count)
self.count -= 1
# 定义返回函数,使用“返回”按钮的功能
def fanhui(self):
# 使登录窗口恢复颜色,并销毁掉注册窗口
self.win.attributes('-alpha', 1)
self.win1.destroy()
# 定义函数,实现注册功能
def register(self):
# 获取用户输入的数据
username = self.username1.get()
passwd1 = self.passwd1.get()
passwd2 = self.passwd2.get()
if passwd1 == '' or passwd2 == '':
return msgbox.showerror('失败!', '不能填空!!!')
# 判断用户输入的数据
if passwd1 != passwd2:
msgbox.showerror('失败!', '注册失败,两次密码不一致!')
else:
msgbox.showinfo('成功', '恭喜你注册成功!')
with open('zhanghao.txt', 'a')as file:
file.write('账号:')
file.write(username + '\n')
file.write('密码:')
file.write(passwd2 + '\n')
# 定义函数实现“注册”按钮的功能
def js1(self):
# 使用登录界面变成透明色,让用户看不到
self.win.attributes('-alpha', -1)
# 定义窗口2,来实现注册窗口
self.win1 = Tk()
self.win1.geometry("300x200")
self.win1.title("注册")
# 定义输入框
self.username1 = Entry(self.win1)
self.passwd1 = Entry(self.win1, show="*")
self.passwd2 = Entry(self.win1, show="*")
self.username1.place(x=110, y=25)
self.passwd1.place(x=110, y=75)
self.passwd2.place(x=110, y=125)
# 定义标签
name4 = Label(self.win1, text="用户名:", font=('宋体', 15), width=10)
name4.place(x=1, y=20)
name5 = Label(self.win1, text="密码:", font=('宋体', 15), width=10)
name5.place(x=1, y=70)
name6 = Label(self.win1, text="确认密码:", font=('宋体', 15), width=10)
name6.place(x=1, y=120)
# 定义按钮
button = Button(self.win1, text="返回", font=('宋体', 10), width=5, command=self.fanhui)
button.place(x=250, y=170)
button1 = Button(self.win1, text="注册", font=('宋体', 15), width=10, command=self.register)
button1.place(x=100, y=160)
# 窗口运行
self.win1.mainloop()
# 定义函数,创建窗口
def windows(self):
self.win.geometry("300x200")
self.win.title("登录")
# 设置按钮
self.username = Entry(self.win)
self.passwd = Entry(self.win, show="*")
self.username.place(x=110, y=25)
self.passwd.place(x=110, y=75)
# 设置标签,实现在窗口上打印“用户名:”等
name1 = Label(self.win, text="用户名:", font=('宋体', 15), width=10)
name1.place(x=1, y=20)
name2 = Label(self.win, text="密码:", font=('宋体', 15), width=10)
name2.place(x=1, y=70)
# 设置按钮
button = Button(self.win, text="登录", font=('宋体', 15), width=10, command=self.js)
button.place(x=20, y=110)
button1 = Button(self.win, text="注册", font=('宋体', 15), width=10, command=self.js1)
button1.place(x=140, y=110)
# 窗口运行
self.win.mainloop()
# 调用类
if __name__ == '__main__':
tk = Tking()
tk.windows()