用python写一个字符界面人机对战的五子棋游戏,游戏难度中等
时间: 2024-05-03 18:18:05 浏览: 18
好的,我来为你编写一个 Python 版本的字符界面人机对战的五子棋游戏。
首先我们需要导入必要的模块:
```python
import os
import time
import random
import numpy as np
```
然后我们定义一些常量:
```python
# 棋盘大小
BOARD_SIZE = 15
# 棋子类型
EMPTY, BLACK, WHITE = range(3)
# 棋子符号
SYMBOLS = ['.', 'X', 'O']
# 评估函数常量
WIN_VALUE, FOUR_VALUE, BLOCKED_THREE_VALUE, THREE_VALUE, TWO_VALUE = 100000, 1000, 100, 10, 1
# AI 难度
AI_LEVEL_EASY, AI_LEVEL_MEDIUM, AI_LEVEL_HARD = range(3)
# 搜索深度
SEARCH_DEPTH = [3, 5, 7]
```
接下来我们定义一些函数:
```python
def clear_screen():
"""清空屏幕"""
os.system('cls' if os.name == 'nt' else 'clear')
def display_board(board):
"""打印棋盘"""
clear_screen()
print(' |', end='')
for i in range(BOARD_SIZE):
print(' %d |' % i, end='')
print('')
print('---+' + '--+' * (BOARD_SIZE - 1))
for i in range(BOARD_SIZE):
print(' %d |' % i, end='')
for j in range(BOARD_SIZE):
print(' %s |' % SYMBOLS[board[i][j]], end='')
print('')
print('---+' + '--+' * (BOARD_SIZE - 1))
def get_move(player, board):
"""获取玩家输入的落子位置"""
while True:
try:
x, y = input('Player %d\'s turn (row column): ' % player).split()
x, y = int(x), int(y)
if x < 0 or x >= BOARD_SIZE or y < 0 or y >= BOARD_SIZE or board[x][y] != EMPTY:
raise ValueError('Invalid move')
return x, y
except Exception as e:
print(e)
def get_ai_move(player, board, level):
"""获取 AI 落子位置"""
moves = generate_moves(board, player)
if level == AI_LEVEL_EASY:
return random.choice(moves)
elif level == AI_LEVEL_MEDIUM:
best_move, _ = minimax(board, player, SEARCH_DEPTH[level])
return best_move
elif level == AI_LEVEL_HARD:
best_move, _ = alphabeta(board, player, SEARCH_DEPTH[level])
return best_move
def generate_moves(board, player):
"""生成所有可能的落子位置"""
moves = []
for i in range(BOARD_SIZE):
for j in range(BOARD_SIZE):
if board[i][j] == EMPTY:
moves.append((i, j))
return moves
def evaluate(board, player):
"""评估棋盘"""
value = 0
for i in range(BOARD_SIZE):
for j in range(BOARD_SIZE):
if board[i][j] == player:
value += evaluate_point(board, i, j, player)
elif board[i][j] == 3 - player:
value -= evaluate_point(board, i, j, 3 - player)
return value
def evaluate_point(board, x, y, player):
"""评估单个位置"""
value = 0
for direction in [(0, 1), (1, 0), (1, 1), (1, -1)]:
count = 0
blocked = False
for i in range(1, 5):
tx, ty = x + i * direction[0], y + i * direction[1]
if tx < 0 or tx >= BOARD_SIZE or ty < 0 or ty >= BOARD_SIZE or board[tx][ty] == 3 - player:
blocked = True
break
elif board[tx][ty] == player:
count += 1
else:
continue
if not blocked:
if count == 4:
value += WIN_VALUE
elif count == 3:
if (x - direction[0] >= 0 and y - direction[1] >= 0 and board[x - direction[0]][y - direction[1]] == EMPTY) or (x + 4 * direction[0] < BOARD_SIZE and y + 4 * direction[1] < BOARD_SIZE and board[x + 4 * direction[0]][y + 4 * direction[1]] == EMPTY):
value += FOUR_VALUE
else:
value += BLOCKED_THREE_VALUE
elif count == 2:
if (x - direction[0] >= 0 and y - direction[1] >= 0 and board[x - direction[0]][y - direction[1]] == EMPTY) and (x + 3 * direction[0] < BOARD_SIZE and y + 3 * direction[1] < BOARD_SIZE and board[x + 3 * direction[0]][y + 3 * direction[1]] == EMPTY):
value += TWO_VALUE
elif count == 1:
if (x - direction[0] >= 0 and y - direction[1] >= 0 and board[x - direction[0]][y - direction[1]] == EMPTY) and (x + 4 * direction[0] < BOARD_SIZE and y + 4 * direction[1] < BOARD_SIZE and board[x + 4 * direction[0]][y + 4 * direction[1]] == EMPTY):
value += TWO_VALUE
return value
def minimax(board, player, depth):
"""Minimax 搜索"""
if depth == 0:
return None, evaluate(board, player)
moves = generate_moves(board, player)
if not moves:
return None, evaluate(board, player)
best_move = None
if player == BLACK:
best_value = float('-inf')
for move in moves:
new_board = np.copy(board)
new_board[move[0]][move[1]] = player
_, value = minimax(new_board, WHITE, depth - 1)
if value > best_value:
best_move, best_value = move, value
else:
best_value = float('inf')
for move in moves:
new_board = np.copy(board)
new_board[move[0]][move[1]] = player
_, value = minimax(new_board, BLACK, depth - 1)
if value < best_value:
best_move, best_value = move, value
return best_move, best_value
def alphabeta(board, player, depth, alpha=float('-inf'), beta=float('inf')):
"""Alpha-Beta 剪枝"""
if depth == 0:
return None, evaluate(board, player)
moves = generate_moves(board, player)
if not moves:
return None, evaluate(board, player)
best_move = None
if player == BLACK:
best_value = float('-inf')
for move in moves:
new_board = np.copy(board)
new_board[move[0]][move[1]] = player
_, value = alphabeta(new_board, WHITE, depth - 1, alpha, beta)
if value > best_value:
best_move, best_value = move, value
alpha = max(alpha, best_value)
if alpha >= beta:
break
else:
best_value = float('inf')
for move in moves:
new_board = np.copy(board)
new_board[move[0]][move[1]] = player
_, value = alphabeta(new_board, BLACK, depth - 1, alpha, beta)
if value < best_value:
best_move, best_value = move, value
beta = min(beta, best_value)
if beta <= alpha:
break
return best_move, best_value
```
最后我们编写主函数:
```python
def main():
# 初始化棋盘
board = np.zeros((BOARD_SIZE, BOARD_SIZE), dtype=np.int32)
# 初始化玩家和 AI 难度
player = BLACK
level = AI_LEVEL_MEDIUM
# 游戏循环
while True:
# 打印棋盘
display_board(board)
# 玩家落子
if player == BLACK:
x, y = get_move(player, board)
else:
print('AI is thinking...')
time.sleep(1)
x, y = get_ai_move(player, board, level)
board[x][y] = player
# 判断游戏是否结束
if evaluate(board, player) >= WIN_VALUE:
display_board(board)
print('Player %d wins!' % player)
break
if len(generate_moves(board, EMPTY)) == 0:
display_board(board)
print('Tie game!')
break
# 切换玩家
player = 3 - player
```
运行主函数即可开始游戏:
```python
if __name__ == '__main__':
main()
```
游戏中,玩家使用数字键输入落子位置的行列坐标,例如“3 4”表示在第 3 行第 4 列落子。AI 的思考时间取决于难度等级,难度越高,思考时间越长。游戏结束后会显示胜利者或平局。
相关推荐
![pdf](https://img-home.csdnimg.cn/images/20210720083512.png)
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![pdf](https://img-home.csdnimg.cn/images/20210720083512.png)
![py](https://img-home.csdnimg.cn/images/20210720083646.png)
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)
![pdf](https://img-home.csdnimg.cn/images/20210720083512.png)