import sys
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)]
# pyinstaller -Fw 五子棋
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('单机五子棋v1.8')
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, 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,
python实现单机版五子棋(免费下载)
需积分: 0 196 浏览量
更新于2022-06-25
收藏 8KB ZIP 举报
在本文中,我们将深入探讨如何使用Python编程语言实现一个单机版五子棋游戏。五子棋,又称连珠,是一种两人对弈的策略棋类游戏,目标是先在棋盘上形成连续的五个同色棋子。Python因其简洁易懂的语法和丰富的库资源,成为实现此类项目的理想选择。
我们需要了解Python的基础知识,包括变量、数据类型、条件语句、循环以及函数等。这些是编写任何程序的基础。在五子棋项目中,我们可以定义棋盘为一个二维数组,用不同的数字或字符串表示黑白双方的棋子。
接下来,我们将创建棋盘类(`Board`),它将包含棋盘的状态、大小以及各种操作棋盘的方法,如放置棋子、检查是否有五子连珠等。在Python中,类的定义使用`class`关键字,并通过`__init__`方法初始化对象。例如:
```python
class Board:
def __init__(self, size=15):
self.board = [[' ' for _ in range(size)] for _ in range(size)]
self.size = size
def place_piece(self, row, col, piece):
if self.is_valid_move(row, col):
self.board[row][col] = piece
else:
print("Invalid move.")
# ...其他方法...
```
为了实现人机对弈,我们需要编写一个简单的AI算法。最基础的是基于深度优先搜索(DFS)的算法,用于探索所有可能的棋局,寻找最佳落子位置。这通常涉及到递归函数,用于遍历所有可能的棋步,直到达到五子连珠或者棋盘满。为了提高效率,可以使用剪枝技巧,提前结束无望的分支。
```python
def dfs(board, player, depth=0):
# ...实现DFS的代码...
# 在主循环中调用dfs来决定AI的下一步
ai_move = dfs(board, '黑', depth=1)
board.place_piece(ai_move[0], ai_move[1], '黑')
```
为了让用户能够与计算机对弈,我们需要实现用户输入功能,处理用户的棋步并验证其合法性。Python的`input()`函数可以获取用户输入,但需要注意处理非法输入。
```python
while not game_over:
print(board.display()) # 显示当前棋盘
user_move = input("请输入您的位置(如:3 4):")
row, col = map(int, user_move.split())
board.place_piece(row, col, '白')
if is_win('白'):
print("恭喜,您赢了!")
break
ai_move = dfs(board, '黑', depth=1)
board.place_piece(ai_move[0], ai_move[1], '黑')
if is_win('黑'):
print("很遗憾,AI赢了!")
break
```
在这个项目中,我们还可以添加图形界面,使用Python的Tkinter库,使得用户可以通过点击棋盘来落子。Tkinter提供了丰富的控件和事件处理机制,可以轻松创建交互式界面。
```python
import tkinter as tk
# 创建棋盘GUI
root = tk.Tk()
canvas = tk.Canvas(root, width=board.size*50, height=board.size*50)
# ...创建棋盘画布并绑定点击事件...
```
别忘了提供源码的下载链接,让感兴趣的人可以获取并运行这个程序。通过这个项目,初学者可以学习到Python的基础编程、面向对象设计、算法应用以及图形用户界面的开发,而有经验的开发者则可以进一步研究更复杂的AI策略,如Minimax算法或蒙特卡洛树搜索。
Python实现的五子棋项目是一个综合性的学习实践,涵盖了编程基础、算法设计、图形用户界面等多个方面,对于提升Python编程技能和理解游戏逻辑非常有帮助。无论是对初学者还是经验丰富的开发者来说,都是一个值得尝试的项目。