Add idiom solitaire project
This commit is contained in:
parent
c745693acb
commit
fc848dc333
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
.env
|
||||||
|
.venv/
|
||||||
|
__pycache__/
|
||||||
|
.DS_Store
|
||||||
392
gomoku_game.py
392
gomoku_game.py
@ -1,392 +0,0 @@
|
|||||||
import pygame
|
|
||||||
import sys
|
|
||||||
|
|
||||||
# 初始化pygame
|
|
||||||
pygame.init()
|
|
||||||
|
|
||||||
# 游戏常量设置
|
|
||||||
SCREEN_SIZE = 600 # 窗口大小
|
|
||||||
GRID_SIZE = 30 # 每个格子的大小
|
|
||||||
LINE_WIDTH = 2 # 棋盘线宽度
|
|
||||||
BOARD_SIZE = 19 # 棋盘大小(19x19)
|
|
||||||
PIECE_RADIUS = 14 # 棋子半径
|
|
||||||
PIECE_WIDTH = 2 # 棋子边框宽度
|
|
||||||
|
|
||||||
# 颜色定义
|
|
||||||
BLACK = (0, 0, 0)
|
|
||||||
WHITE = (255, 255, 255)
|
|
||||||
BG_COLOR = (240, 220, 180) # 棋盘背景色(木纹色)
|
|
||||||
LINE_COLOR = (100, 100, 100)# 棋盘线颜色
|
|
||||||
|
|
||||||
# 计算棋盘起始位置(居中显示)
|
|
||||||
START_X = (SCREEN_SIZE - (BOARD_SIZE - 1) * GRID_SIZE) // 2
|
|
||||||
START_Y = (SCREEN_SIZE - (BOARD_SIZE - 1) * GRID_SIZE) // 2
|
|
||||||
|
|
||||||
# 创建游戏窗口
|
|
||||||
screen = pygame.display.set_mode((SCREEN_SIZE, SCREEN_SIZE))
|
|
||||||
pygame.display.set_caption("五子棋")
|
|
||||||
|
|
||||||
# 游戏模式:0表示双人对战,1表示AI对战
|
|
||||||
game_mode = 1 # 默认AI对战
|
|
||||||
mode_selected = False # 是否已选择游戏模式
|
|
||||||
|
|
||||||
# 初始化棋盘数据,0表示空,1表示黑子,2表示白子
|
|
||||||
board = [[0 for _ in range(BOARD_SIZE)] for _ in range(BOARD_SIZE)]
|
|
||||||
current_player = 1 # 1表示黑方,2表示白方
|
|
||||||
game_over = False
|
|
||||||
winner = None
|
|
||||||
|
|
||||||
# AI评估权重
|
|
||||||
WEIGHTS = {
|
|
||||||
'win': 100000, # 获胜
|
|
||||||
'block_win': 50000, # 阻挡对方获胜
|
|
||||||
'four': 10000, # 四子连珠
|
|
||||||
'block_four': 5000, # 阻挡对方四子
|
|
||||||
'three': 1000, # 三子连珠
|
|
||||||
'block_three': 500, # 阻挡对方三子
|
|
||||||
'two': 100, # 二子连珠
|
|
||||||
'block_two': 50, # 阻挡对方二子
|
|
||||||
'one': 10, # 一子
|
|
||||||
'block_one': 5 # 阻挡对方一子
|
|
||||||
}
|
|
||||||
|
|
||||||
def draw_board():
|
|
||||||
"""绘制棋盘"""
|
|
||||||
# 填充背景色
|
|
||||||
screen.fill(BG_COLOR)
|
|
||||||
|
|
||||||
# 绘制棋盘网格线
|
|
||||||
for i in range(BOARD_SIZE):
|
|
||||||
# 竖线
|
|
||||||
pygame.draw.line(
|
|
||||||
screen, LINE_COLOR,
|
|
||||||
(START_X + i * GRID_SIZE, START_Y),
|
|
||||||
(START_X + i * GRID_SIZE, START_Y + (BOARD_SIZE - 1) * GRID_SIZE),
|
|
||||||
LINE_WIDTH
|
|
||||||
)
|
|
||||||
# 横线
|
|
||||||
pygame.draw.line(
|
|
||||||
screen, LINE_COLOR,
|
|
||||||
(START_X, START_Y + i * GRID_SIZE),
|
|
||||||
(START_X + (BOARD_SIZE - 1) * GRID_SIZE, START_Y + i * GRID_SIZE),
|
|
||||||
LINE_WIDTH
|
|
||||||
)
|
|
||||||
|
|
||||||
# 绘制棋子
|
|
||||||
for row in range(BOARD_SIZE):
|
|
||||||
for col in range(BOARD_SIZE):
|
|
||||||
if board[row][col] != 0:
|
|
||||||
center_x = START_X + col * GRID_SIZE
|
|
||||||
center_y = START_Y + row * GRID_SIZE
|
|
||||||
color = BLACK if board[row][col] == 1 else WHITE
|
|
||||||
# 绘制棋子
|
|
||||||
pygame.draw.circle(screen, color, (center_x, center_y), PIECE_RADIUS)
|
|
||||||
# 绘制棋子边框(增加视觉效果)
|
|
||||||
pygame.draw.circle(screen, BLACK, (center_x, center_y), PIECE_RADIUS, PIECE_WIDTH)
|
|
||||||
|
|
||||||
def get_click_pos(pos):
|
|
||||||
"""将鼠标点击位置转换为棋盘坐标"""
|
|
||||||
x, y = pos
|
|
||||||
# 计算所在格子
|
|
||||||
col = (x - START_X + GRID_SIZE // 2) // GRID_SIZE
|
|
||||||
row = (y - START_Y + GRID_SIZE // 2) // GRID_SIZE
|
|
||||||
|
|
||||||
# 检查是否在棋盘范围内
|
|
||||||
if 0 <= row < BOARD_SIZE and 0 <= col < BOARD_SIZE:
|
|
||||||
return (row, col)
|
|
||||||
return None
|
|
||||||
|
|
||||||
def check_win(row, col):
|
|
||||||
"""检查落子后是否获胜"""
|
|
||||||
player = board[row][col]
|
|
||||||
directions = [
|
|
||||||
(0, 1), # 横向
|
|
||||||
(1, 0), # 纵向
|
|
||||||
(1, 1), # 正对角线
|
|
||||||
(1, -1) # 反对角线
|
|
||||||
]
|
|
||||||
|
|
||||||
for dr, dc in directions:
|
|
||||||
count = 1
|
|
||||||
# 正方向检查
|
|
||||||
r, c = row + dr, col + dc
|
|
||||||
while 0 <= r < BOARD_SIZE and 0 <= c < BOARD_SIZE and board[r][c] == player:
|
|
||||||
count += 1
|
|
||||||
r += dr
|
|
||||||
c += dc
|
|
||||||
|
|
||||||
# 反方向检查
|
|
||||||
r, c = row - dr, col - dc
|
|
||||||
while 0 <= r < BOARD_SIZE and 0 <= c < BOARD_SIZE and board[r][c] == player:
|
|
||||||
count += 1
|
|
||||||
r -= dr
|
|
||||||
c -= dc
|
|
||||||
|
|
||||||
# 五子连珠则获胜
|
|
||||||
if count >= 5:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def evaluate_position(row, col, player):
|
|
||||||
"""评估指定位置对玩家的价值"""
|
|
||||||
if board[row][col] != 0:
|
|
||||||
return -1000000 # 已经有棋子的位置
|
|
||||||
|
|
||||||
score = 0
|
|
||||||
opponent = 1 if player == 2 else 2
|
|
||||||
|
|
||||||
# 模拟落子
|
|
||||||
board[row][col] = player
|
|
||||||
|
|
||||||
# 检查是否获胜
|
|
||||||
if check_win(row, col):
|
|
||||||
score += WEIGHTS['win']
|
|
||||||
|
|
||||||
# 评估各个方向的连珠情况
|
|
||||||
directions = [(0, 1), (1, 0), (1, 1), (1, -1)]
|
|
||||||
for dr, dc in directions:
|
|
||||||
# 检查当前玩家的连珠
|
|
||||||
count = 1
|
|
||||||
# 正方向
|
|
||||||
r, c = row + dr, col + dc
|
|
||||||
while 0 <= r < BOARD_SIZE and 0 <= c < BOARD_SIZE and board[r][c] == player:
|
|
||||||
count += 1
|
|
||||||
r += dr
|
|
||||||
c += dc
|
|
||||||
# 反方向
|
|
||||||
r, c = row - dr, col - dc
|
|
||||||
while 0 <= r < BOARD_SIZE and 0 <= c < BOARD_SIZE and board[r][c] == player:
|
|
||||||
count += 1
|
|
||||||
r -= dr
|
|
||||||
c -= dc
|
|
||||||
|
|
||||||
# 根据连珠数量加分
|
|
||||||
if count == 4:
|
|
||||||
score += WEIGHTS['four']
|
|
||||||
elif count == 3:
|
|
||||||
score += WEIGHTS['three']
|
|
||||||
elif count == 2:
|
|
||||||
score += WEIGHTS['two']
|
|
||||||
elif count == 1:
|
|
||||||
score += WEIGHTS['one']
|
|
||||||
|
|
||||||
# 撤销模拟落子
|
|
||||||
board[row][col] = 0
|
|
||||||
|
|
||||||
# 模拟对方落子,检查需要阻挡的情况
|
|
||||||
board[row][col] = opponent
|
|
||||||
if check_win(row, col):
|
|
||||||
score += WEIGHTS['block_win']
|
|
||||||
|
|
||||||
for dr, dc in directions:
|
|
||||||
# 检查对方的连珠
|
|
||||||
count = 1
|
|
||||||
# 正方向
|
|
||||||
r, c = row + dr, col + dc
|
|
||||||
while 0 <= r < BOARD_SIZE and 0 <= c < BOARD_SIZE and board[r][c] == opponent:
|
|
||||||
count += 1
|
|
||||||
r += dr
|
|
||||||
c += dc
|
|
||||||
# 反方向
|
|
||||||
r, c = row - dr, col - dc
|
|
||||||
while 0 <= r < BOARD_SIZE and 0 <= c < BOARD_SIZE and board[r][c] == opponent:
|
|
||||||
count += 1
|
|
||||||
r -= dr
|
|
||||||
c -= dc
|
|
||||||
|
|
||||||
# 根据连珠数量加分(阻挡)
|
|
||||||
if count == 4:
|
|
||||||
score += WEIGHTS['block_four']
|
|
||||||
elif count == 3:
|
|
||||||
score += WEIGHTS['block_three']
|
|
||||||
elif count == 2:
|
|
||||||
score += WEIGHTS['block_two']
|
|
||||||
elif count == 1:
|
|
||||||
score += WEIGHTS['block_one']
|
|
||||||
|
|
||||||
# 撤销模拟落子
|
|
||||||
board[row][col] = 0
|
|
||||||
|
|
||||||
# 中心位置加成
|
|
||||||
center_row, center_col = BOARD_SIZE // 2, BOARD_SIZE // 2
|
|
||||||
distance = abs(row - center_row) + abs(col - center_col)
|
|
||||||
score += (10 - distance) * 2
|
|
||||||
|
|
||||||
return score
|
|
||||||
|
|
||||||
def ai_move():
|
|
||||||
"""AI落子"""
|
|
||||||
best_score = -float('inf')
|
|
||||||
best_move = None
|
|
||||||
|
|
||||||
# 遍历棋盘上的所有空位
|
|
||||||
for row in range(BOARD_SIZE):
|
|
||||||
for col in range(BOARD_SIZE):
|
|
||||||
if board[row][col] == 0:
|
|
||||||
# 评估该位置的价值
|
|
||||||
score = evaluate_position(row, col, current_player)
|
|
||||||
if score > best_score:
|
|
||||||
best_score = score
|
|
||||||
best_move = (row, col)
|
|
||||||
|
|
||||||
# 执行最佳落子
|
|
||||||
if best_move:
|
|
||||||
row, col = best_move
|
|
||||||
board[row][col] = current_player
|
|
||||||
return (row, col)
|
|
||||||
return None
|
|
||||||
|
|
||||||
def show_winner():
|
|
||||||
"""显示获胜信息"""
|
|
||||||
# 尝试使用系统中文字体
|
|
||||||
try:
|
|
||||||
font = pygame.font.SysFont(["SimHei", "Microsoft YaHei", "Arial"], 60)
|
|
||||||
except:
|
|
||||||
font = pygame.font.Font(None, 60)
|
|
||||||
text = f"{'黑方' if winner == 1 else '白方'}获胜!"
|
|
||||||
text_surface = font.render(text, True, (255, 0, 0))
|
|
||||||
text_rect = text_surface.get_rect(center=(SCREEN_SIZE//2, SCREEN_SIZE//2))
|
|
||||||
screen.blit(text_surface, text_rect)
|
|
||||||
|
|
||||||
# 显示重新开始提示
|
|
||||||
try:
|
|
||||||
font_small = pygame.font.SysFont(["SimHei", "Microsoft YaHei", "Arial"], 30)
|
|
||||||
except:
|
|
||||||
font_small = pygame.font.Font(None, 30)
|
|
||||||
restart_text = "按R键重新开始 | 按Q键退出"
|
|
||||||
restart_surface = font_small.render(restart_text, True, BLACK)
|
|
||||||
restart_rect = restart_surface.get_rect(center=(SCREEN_SIZE//2, SCREEN_SIZE//2 + 50))
|
|
||||||
screen.blit(restart_surface, restart_rect)
|
|
||||||
|
|
||||||
def show_mode_selection():
|
|
||||||
"""显示游戏模式选择界面"""
|
|
||||||
# 填充背景色
|
|
||||||
screen.fill(BG_COLOR)
|
|
||||||
|
|
||||||
# 显示标题
|
|
||||||
try:
|
|
||||||
title_font = pygame.font.SysFont(["SimHei", "Microsoft YaHei", "Arial"], 48)
|
|
||||||
except:
|
|
||||||
title_font = pygame.font.Font(None, 48)
|
|
||||||
title_text = "五子棋"
|
|
||||||
title_surface = title_font.render(title_text, True, BLACK)
|
|
||||||
title_rect = title_surface.get_rect(center=(SCREEN_SIZE//2, SCREEN_SIZE//2 - 100))
|
|
||||||
screen.blit(title_surface, title_rect)
|
|
||||||
|
|
||||||
# 显示模式选择
|
|
||||||
try:
|
|
||||||
font = pygame.font.SysFont(["SimHei", "Microsoft YaHei", "Arial"], 36)
|
|
||||||
except:
|
|
||||||
font = pygame.font.Font(None, 36)
|
|
||||||
|
|
||||||
# 双人对战选项
|
|
||||||
pvp_text = "1. 双人对战"
|
|
||||||
pvp_surface = font.render(pvp_text, True, BLACK)
|
|
||||||
pvp_rect = pvp_surface.get_rect(center=(SCREEN_SIZE//2, SCREEN_SIZE//2))
|
|
||||||
screen.blit(pvp_surface, pvp_rect)
|
|
||||||
|
|
||||||
# AI对战选项
|
|
||||||
ai_text = "2. AI对战"
|
|
||||||
ai_surface = font.render(ai_text, True, BLACK)
|
|
||||||
ai_rect = ai_surface.get_rect(center=(SCREEN_SIZE//2, SCREEN_SIZE//2 + 60))
|
|
||||||
screen.blit(ai_surface, ai_rect)
|
|
||||||
|
|
||||||
# 显示操作提示
|
|
||||||
try:
|
|
||||||
hint_font = pygame.font.SysFont(["SimHei", "Microsoft YaHei", "Arial"], 24)
|
|
||||||
except:
|
|
||||||
hint_font = pygame.font.Font(None, 24)
|
|
||||||
hint_text = "请按数字键选择游戏模式"
|
|
||||||
hint_surface = hint_font.render(hint_text, True, BLACK)
|
|
||||||
hint_rect = hint_surface.get_rect(center=(SCREEN_SIZE//2, SCREEN_SIZE//2 + 120))
|
|
||||||
screen.blit(hint_surface, hint_rect)
|
|
||||||
|
|
||||||
pygame.display.update()
|
|
||||||
|
|
||||||
def restart_game():
|
|
||||||
"""重新开始游戏"""
|
|
||||||
global board, current_player, game_over, winner, mode_selected
|
|
||||||
board = [[0 for _ in range(BOARD_SIZE)] for _ in range(BOARD_SIZE)]
|
|
||||||
current_player = 1
|
|
||||||
game_over = False
|
|
||||||
winner = None
|
|
||||||
mode_selected = False # 重新开始时需要重新选择模式
|
|
||||||
|
|
||||||
def main():
|
|
||||||
"""游戏主循环"""
|
|
||||||
global current_player, game_over, winner, game_mode, mode_selected
|
|
||||||
|
|
||||||
clock = pygame.time.Clock()
|
|
||||||
|
|
||||||
while True:
|
|
||||||
for event in pygame.event.get():
|
|
||||||
if event.type == pygame.QUIT:
|
|
||||||
pygame.quit()
|
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
# 键盘事件处理
|
|
||||||
if event.type == pygame.KEYDOWN:
|
|
||||||
if event.key == pygame.K_r: # 按R重新开始
|
|
||||||
restart_game()
|
|
||||||
if event.key == pygame.K_q: # 按Q退出
|
|
||||||
pygame.quit()
|
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
# 游戏模式选择
|
|
||||||
if not mode_selected:
|
|
||||||
if event.key == pygame.K_1:
|
|
||||||
game_mode = 0 # 双人对战
|
|
||||||
mode_selected = True
|
|
||||||
elif event.key == pygame.K_2:
|
|
||||||
game_mode = 1 # AI对战
|
|
||||||
mode_selected = True
|
|
||||||
|
|
||||||
# 鼠标点击落子(游戏未结束且已选择模式时)
|
|
||||||
if event.type == pygame.MOUSEBUTTONDOWN and not game_over and mode_selected:
|
|
||||||
pos = pygame.mouse.get_pos()
|
|
||||||
board_pos = get_click_pos(pos)
|
|
||||||
|
|
||||||
if board_pos:
|
|
||||||
row, col = board_pos
|
|
||||||
# 检查位置是否为空
|
|
||||||
if board[row][col] == 0:
|
|
||||||
board[row][col] = current_player
|
|
||||||
|
|
||||||
# 检查是否获胜
|
|
||||||
if check_win(row, col):
|
|
||||||
game_over = True
|
|
||||||
winner = current_player
|
|
||||||
else:
|
|
||||||
# 切换玩家
|
|
||||||
current_player = 2 if current_player == 1 else 1
|
|
||||||
|
|
||||||
# 如果是AI对战模式且当前玩家是AI(白方),则AI落子
|
|
||||||
if game_mode == 1 and current_player == 2:
|
|
||||||
ai_pos = ai_move()
|
|
||||||
if ai_pos:
|
|
||||||
ai_row, ai_col = ai_pos
|
|
||||||
# 检查AI落子后是否获胜
|
|
||||||
if check_win(ai_row, ai_col):
|
|
||||||
game_over = True
|
|
||||||
winner = current_player
|
|
||||||
else:
|
|
||||||
# 切换回玩家
|
|
||||||
current_player = 1
|
|
||||||
|
|
||||||
# 如果未选择模式,显示模式选择界面
|
|
||||||
if not mode_selected:
|
|
||||||
show_mode_selection()
|
|
||||||
else:
|
|
||||||
# 绘制游戏界面
|
|
||||||
draw_board()
|
|
||||||
|
|
||||||
# 如果游戏结束,显示获胜信息
|
|
||||||
if game_over:
|
|
||||||
show_winner()
|
|
||||||
|
|
||||||
# 更新屏幕显示
|
|
||||||
pygame.display.update()
|
|
||||||
clock.tick(60)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
1553
idiom_solitaire.py
Normal file
1553
idiom_solitaire.py
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,3 +0,0 @@
|
|||||||
# DeepSeek API Key
|
|
||||||
# Get your API key from https://platform.deepseek.com/
|
|
||||||
DEEPSEEK_API_KEY=sk-b04b9134730c4375a5789e2e00978ee0
|
|
||||||
@ -1 +0,0 @@
|
|||||||
3.13
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,14 +0,0 @@
|
|||||||
# Welcome to Chainlit! 🚀🤖
|
|
||||||
|
|
||||||
Hi there, Developer! 👋 We're excited to have you on board. Chainlit is a powerful tool designed to help you prototype, debug and share applications built on top of LLMs.
|
|
||||||
|
|
||||||
## Useful Links 🔗
|
|
||||||
|
|
||||||
- **Documentation:** Get started with our comprehensive [Chainlit Documentation](https://docs.chainlit.io) 📚
|
|
||||||
- **Discord Community:** Join our friendly [Chainlit Discord](https://discord.gg/k73SQ3FyUh) to ask questions, share your projects, and connect with other developers! 💬
|
|
||||||
|
|
||||||
We can't wait to see what you create with Chainlit! Happy coding! 💻😊
|
|
||||||
|
|
||||||
## Welcome screen
|
|
||||||
|
|
||||||
To modify the welcome screen, edit the `chainlit.md` file at the root of your project. If you do not want a welcome screen, just leave this file empty.
|
|
||||||
@ -1,14 +0,0 @@
|
|||||||
[project]
|
|
||||||
name = "my-ai-app"
|
|
||||||
version = "0.1.0"
|
|
||||||
description = "Add your description here"
|
|
||||||
readme = "README.md"
|
|
||||||
requires-python = ">=3.13"
|
|
||||||
dependencies = [
|
|
||||||
"openai>=2.14.0",
|
|
||||||
"python-dotenv>=1.2.1",
|
|
||||||
"streamlit>=1.30.0",
|
|
||||||
"chainlit>=0.1.160",
|
|
||||||
"fastapi>=0.128.0",
|
|
||||||
"uvicorn>=0.40.0",
|
|
||||||
]
|
|
||||||
3037
my-ai-app/uv.lock
generated
3037
my-ai-app/uv.lock
generated
File diff suppressed because it is too large
Load Diff
@ -1,12 +1,32 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "my-ai-app"
|
name = "my-ai-app"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
description = "Add your description here"
|
description = "AI-powered Gomoku game with web interface"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.13"
|
requires-python = ">=3.12" # 2026 Recommended
|
||||||
dependencies = [
|
|
||||||
"openai>=2.14.0",
|
[build-system]
|
||||||
"python-dotenv>=1.2.1",
|
requires = ["setuptools>=61.0"]
|
||||||
"streamlit>=1.30.0",
|
build-backend = "setuptools.build_meta"
|
||||||
"chainlit>=0.1.160",
|
|
||||||
]
|
[tool.uv]
|
||||||
|
environments = ["default"]
|
||||||
|
|
||||||
|
[tool.uv.environment.default]
|
||||||
|
python = ">=3.12"
|
||||||
|
|
||||||
|
[tool.uv.dependencies]
|
||||||
|
flask = "^3.0.0"
|
||||||
|
python-dotenv = "^1.2.1"
|
||||||
|
requests = "^2.32.0"
|
||||||
|
streamlit = "^1.30.0"
|
||||||
|
chainlit = "^0.1.160"
|
||||||
|
pygame = "^2.6.0"
|
||||||
|
pydantic = "^2.0.0"
|
||||||
|
pydantic-settings = "^2.0.0"
|
||||||
|
|
||||||
|
[tool.uv.dependencies.dev]
|
||||||
|
pytest = "^7.0.0"
|
||||||
|
black = "^23.0.0"
|
||||||
|
isort = "^5.0.0"
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user