python实现简单五子棋游戏


Posted in Python onJune 18, 2019

本文实例为大家分享了python实现简单五子棋游戏的具体代码,供大家参考,具体内容如下

python实现简单五子棋游戏

from graphics import *
from math import *
import numpy as np
 
 
def ai():
 """
 AI计算落子位置
 """
 maxmin(True, DEPTH, -99999999, 99999999)
 return next_point[0], next_point[1]
 
 
def maxmin(is_ai, depth, alpha, beta):
 """
 负值极大算法搜索 alpha + beta剪枝
 """
 # 游戏是否结束 | | 探索的递归深度是否到边界
 if game_win(list1) or game_win(list2) or depth == 0:
  return evaluation(is_ai)
 
 blank_list = list(set(list_all).difference(set(list3)))
 order(blank_list) # 搜索顺序排序 提高剪枝效率
 # 遍历每一个候选步
 for next_step in blank_list[0:60]:
 
  # 如果要评估的位置没有相邻的子, 则不去评估 减少计算
  if not has_neightnor(next_step):
   continue
 
  if is_ai:
   list1.append(next_step)
  else:
   list2.append(next_step)
  list3.append(next_step)
 
  value = -maxmin(not is_ai, depth - 1, -beta, -alpha)
  if is_ai:
   list1.remove(next_step)
  else:
   list2.remove(next_step)
  list3.remove(next_step)
 
  if value > alpha:
   if depth == DEPTH:
    next_point[0] = next_step[0]
    next_point[1] = next_step[1]
   # alpha + beta剪枝点
   if value >= beta:
    return beta
   alpha = value
 return alpha
 
 
def order(blank_list):
 """
 离最后落子的邻居位置最有可能是最优点
 计算最后落子点的8个方向邻居节点
 若未落子,则插入到blank列表的最前端
 :param blank_list: 未落子节点集合
 :return: blank_list
 """
 last_pt = list3[-1]
 # for item in blank_list:
 for i in range(-1, 2):
  for j in range(-1, 2):
   if i == 0 and j == 0:
    continue
   if (last_pt[0] + i, last_pt[1] + j) in blank_list:
    blank_list.remove((last_pt[0] + i, last_pt[1] + j))
    blank_list.insert(0, (last_pt[0] + i, last_pt[1] + j))
 
 
def has_neightnor(pt):
 """
 判断是否有邻居节点
 :param pt: 待评测节点
 :return:
 """
 for i in range(-1, 2):
  for j in range(-1, 2):
   if i == 0 and j == 0:
    continue
   if (pt[0] + i, pt[1] + j) in list3:
    return True
 return False
 
 
def evaluation(is_ai):
 """
 评估函数
 """
 if is_ai:
  my_list = list1
  enemy_list = list2
 else:
  my_list = list2
  enemy_list = list1
 # 算自己的得分
 score_all_arr = [] # 得分形状的位置 用于计算如果有相交 得分翻倍
 my_score = 0
 for pt in my_list:
  m = pt[0]
  n = pt[1]
  my_score += cal_score(m, n, 0, 1, enemy_list, my_list, score_all_arr)
  my_score += cal_score(m, n, 1, 0, enemy_list, my_list, score_all_arr)
  my_score += cal_score(m, n, 1, 1, enemy_list, my_list, score_all_arr)
  my_score += cal_score(m, n, -1, 1, enemy_list, my_list, score_all_arr)
 # 算敌人的得分, 并减去
 score_all_arr_enemy = []
 enemy_score = 0
 for pt in enemy_list:
  m = pt[0]
  n = pt[1]
  enemy_score += cal_score(m, n, 0, 1, my_list, enemy_list, score_all_arr_enemy)
  enemy_score += cal_score(m, n, 1, 0, my_list, enemy_list, score_all_arr_enemy)
  enemy_score += cal_score(m, n, 1, 1, my_list, enemy_list, score_all_arr_enemy)
  enemy_score += cal_score(m, n, -1, 1, my_list, enemy_list, score_all_arr_enemy)
 
 total_score = my_score - enemy_score * 0.1
 return total_score
 
 
def cal_score(m, n, x_decrict, y_derice, enemy_list, my_list, score_all_arr):
 """
 每个方向上的分值计算
 :param m:
 :param n:
 :param x_decrict:
 :param y_derice:
 :param enemy_list:
 :param my_list:
 :param score_all_arr:
 :return:
 """
 add_score = 0 # 加分项
 # 在一个方向上, 只取最大的得分项
 max_score_shape = (0, None)
 
 # 如果此方向上,该点已经有得分形状,不重复计算
 for item in score_all_arr:
  for pt in item[1]:
   if m == pt[0] and n == pt[1] and x_decrict == item[2][0] and y_derice == item[2][1]:
    return 0
 
 # 在落子点 左右方向上循环查找得分形状
 for offset in range(-5, 1):
  # offset = -2
  pos = []
  for i in range(0, 6):
   if (m + (i + offset) * x_decrict, n + (i + offset) * y_derice) in enemy_list:
    pos.append(2)
   elif (m + (i + offset) * x_decrict, n + (i + offset) * y_derice) in my_list:
    pos.append(1)
   else:
    pos.append(0)
  tmp_shap5 = (pos[0], pos[1], pos[2], pos[3], pos[4])
  tmp_shap6 = (pos[0], pos[1], pos[2], pos[3], pos[4], pos[5])
 
  for (score, shape) in shape_score:
   if tmp_shap5 == shape or tmp_shap6 == shape:
    if score > max_score_shape[0]:
     max_score_shape = (score, ((m + (0 + offset) * x_decrict, n + (0 + offset) * y_derice),
            (m + (1 + offset) * x_decrict, n + (1 + offset) * y_derice),
            (m + (2 + offset) * x_decrict, n + (2 + offset) * y_derice),
            (m + (3 + offset) * x_decrict, n + (3 + offset) * y_derice),
            (m + (4 + offset) * x_decrict, n + (4 + offset) * y_derice)),
          (x_decrict, y_derice))
 
 # 计算两个形状相交, 如两个3活 相交, 得分增加 一个子的除外
 if max_score_shape[1] is not None:
  for item in score_all_arr:
   for pt1 in item[1]:
    for pt2 in max_score_shape[1]:
     if pt1 == pt2 and max_score_shape[0] > 10 and item[0] > 10:
      add_score += item[0] + max_score_shape[0]
 
  score_all_arr.append(max_score_shape)
 
 return add_score + max_score_shape[0]
 
 
def game_win(list):
 """
 胜利条件判断
 """
 # for m in range(COLUMN):
 #  for n in range(ROW):
 #   if n < ROW - 4 and (m, n) in list and (m, n + 1) in list and (m, n + 2) in list and (
 #     m, n + 3) in list and (m, n + 4) in list:
 #    return True
 #   elif m < ROW - 4 and (m, n) in list and (m + 1, n) in list and (m + 2, n) in list and (
 #     m + 3, n) in list and (m + 4, n) in list:
 #    return True
 #   elif m < ROW - 4 and n < ROW - 4 and (m, n) in list and (m + 1, n + 1) in list and (
 #     m + 2, n + 2) in list and (m + 3, n + 3) in list and (m + 4, n + 4) in list:
 #    return True
 #   elif m < ROW - 4 and n > 3 and (m, n) in list and (m + 1, n - 1) in list and (
 #     m + 2, n - 2) in list and (m + 3, n - 3) in list and (m + 4, n - 4) in list:
 #    return True
 return False
 
 
def draw_window():
 """
 绘制棋盘
 """
 # 绘制画板
 win = GraphWin("五子棋", GRAPH_HEIGHT, GRAPH_WIDTH)
 win.setBackground("gray")
 # 绘制列
 i1 = 0
 while i1 <= GRID_WIDTH * COLUMN:
  i1 = i1 + GRID_WIDTH
  l = Line(Point(i1, GRID_WIDTH), Point(i1, GRID_WIDTH * COLUMN))
  l.draw(win)
 # 绘制行
 i2 = 0
 while i2 <= GRID_WIDTH * ROW:
  i2 = i2 + GRID_WIDTH
  l = Line(Point(GRID_WIDTH, i2), Point(GRID_WIDTH * ROW, i2))
  l.draw(win)
 return win
 
 
def main():
 """
 程序循环
 :return:
 """
 mode = int(input("先手 AI先手 ? 1 0 \n"))
 # 绘制棋盘
 win = draw_window()
 # 添加棋盘所有点
 for i in range(COLUMN + 1):
  for j in range(ROW + 1):
   list_all.append((i, j))
 # 循环条件
 g = 0
 change = 0
 # 开始循环
 while g == 0:
  # AI
  if change % 2 == mode:
   # AI先手 走天元
   if change == 0:
    pos = (6, 6)
   else:
    pos = ai()
   # 添加落子
   list1.append(pos)
   list3.append(pos)
   # 绘制白棋
   piece = Circle(Point(GRID_WIDTH * (pos[0]), GRID_WIDTH * (pos[1])), 12)
   piece.setFill('white')
   piece.draw(win)
   # AI胜利
   if game_win(list1):
    message = Text(Point(GRAPH_WIDTH / 2, GRID_WIDTH / 2), "AI获胜")
    message.draw(win)
    g = 1
   change = change + 1
 
  # User
  else:
   p2 = win.getMouse()
   x = round((p2.getX()) / GRID_WIDTH)
   y = round((p2.getY()) / GRID_WIDTH)
 
   # 若点未被选取过
   if not (x, y) in list3:
    # 添加落子
    list2.append((x, y))
    list3.append((x, y))
    # 绘制黑棋
    piece = Circle(Point(GRID_WIDTH * x, GRID_WIDTH * y), 12)
    piece.setFill('black')
    piece.draw(win)
    # 胜利
    if game_win(list2):
     message = Text(Point(GRAPH_WIDTH / 2, GRID_WIDTH / 2), "人类胜利")
     message.draw(win)
     g = 1
    change = change + 1
 
 message = Text(Point(GRAPH_WIDTH / 2 + 100, GRID_WIDTH / 2), "游戏结束")
 message.draw(win)
 win.getMouse()
 win.close()
 
 
if __name__ == '__main__':
 GRID_WIDTH = 40
 COLUMN = 11
 ROW = 11
 GRAPH_WIDTH = GRID_WIDTH * (ROW + 1)
 GRAPH_HEIGHT = GRID_WIDTH * (COLUMN + 1)
 
 list1 = [] # AI
 list2 = [] # human
 list3 = [] # all
 list_all = [] # 整个棋盘的点
 next_point = [0, 0] # AI下一步最应该下的位置
 
 mode=int(input("请选择: 快不准 或 慢却准 ? 1 : 0 \n"))
 if mode==1:
  DEPTH=1
 elif mode==0:
  DEPTH=3
 else:
  DEPTH=3
 
 shape_score = [(50, (0, 1, 1, 0, 0)),
     (50, (0, 0, 1, 1, 0)),
     (200, (1, 1, 0, 1, 0)),
     (500, (0, 0, 1, 1, 1)),
     (500, (1, 1, 1, 0, 0)),
     (5000, (0, 1, 1, 1, 0)),
     (5000, (0, 1, 0, 1, 1, 0)),
     (5000, (0, 1, 1, 0, 1, 0)),
     (5000, (1, 1, 1, 0, 1)),
     (5000, (1, 1, 0, 1, 1)),
     (5000, (1, 0, 1, 1, 1)),
     (5000, (1, 1, 1, 1, 0)),
     (5000, (0, 1, 1, 1, 1)),
     (50000, (0, 1, 1, 1, 1, 0)),
     (99999999, (1, 1, 1, 1, 1))]
 main()

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python虚拟环境virtualenv的安装与使用
Sep 21 Python
1 行 Python 代码快速实现 FTP 服务器
Jan 25 Python
numpy判断数值类型、过滤出数值型数据的方法
Jun 09 Python
python批量修改ssh密码的实现
Aug 08 Python
python 解决flask uwsgi 获取不到全局变量的问题
Dec 22 Python
python正则过滤字母、中文、数字及特殊字符方法详解
Feb 11 Python
pandas中的ExcelWriter和ExcelFile的实现方法
Apr 24 Python
Python中zipfile压缩文件模块的基本使用教程
Jun 14 Python
Python如何读取、写入CSV数据
Jul 28 Python
Django如何在不停机的情况下创建索引
Aug 02 Python
python Cartopy的基础使用详解
Nov 01 Python
Django2.1.7 查询数据返回json格式的实现
Dec 29 Python
Python基础学习之函数方法实例详解
Jun 18 #Python
pyqt5 实现在别的窗口弹出进度条
Jun 18 #Python
Python弹出输入框并获取输入值的实例
Jun 18 #Python
python使用tkinter库实现五子棋游戏
Jun 18 #Python
Python基础学习之基本数据结构详解【数字、字符串、列表、元组、集合、字典】
Jun 18 #Python
python 弹窗提示警告框MessageBox的实例
Jun 18 #Python
python实现五子棋小程序
Jun 18 #Python
You might like
PHP Token(令牌)设计
2008/03/15 PHP
PHP中基本符号及使用方法
2010/03/23 PHP
php 表单提交大量数据发生丢失的解决方法
2014/03/03 PHP
PHP通过反射动态加载第三方类和获得类源码的实例
2015/11/27 PHP
js实现的类似于asp数据字典的数据类型代码实例
2014/09/03 Javascript
JQuery中模拟image的ajaxPrefilter与ajaxTransport处理
2015/06/19 Javascript
jQueryUI中的datepicker使用方法详解
2016/05/25 Javascript
Easyui笔记2:实现datagrid多行删除的示例代码
2017/01/14 Javascript
JavaScript中object和Object的区别(详解)
2017/02/27 Javascript
JS+CSS实现滚动数字时钟效果
2017/12/25 Javascript
vuejs前后端数据交互之从后端请求数据的实例
2018/08/11 Javascript
BootStrap表单验证中的非Submit类型按钮点击时触发验证的坑
2019/09/05 Javascript
微信小程序页面渲染实现方法
2019/11/06 Javascript
Python中条件选择和循环语句使用方法介绍
2013/03/13 Python
python中使用urllib2伪造HTTP报头的2个方法
2014/07/07 Python
Python使用email模块对邮件进行编码和解码的实例教程
2016/07/01 Python
Python装饰器(decorator)定义与用法详解
2018/02/09 Python
Python tkinter的grid布局及Text动态显示方法
2018/10/11 Python
Linux上使用Python统计每天的键盘输入次数
2019/04/17 Python
python实现知乎高颜值图片爬取
2019/08/12 Python
Python3实现将一维数组按标准长度分隔为二维数组
2019/11/29 Python
python可迭代对象去重实例
2020/05/15 Python
使用gunicorn部署django项目的问题
2020/12/30 Python
浅析pandas随机排列与随机抽样
2021/01/22 Python
CSS3实现文字波浪线效果示例代码
2016/11/20 HTML / CSS
css3新单位vw、vh的使用教程
2018/03/23 HTML / CSS
欧洲领先的技术商店:eibmarkt.com
2019/05/10 全球购物
会计主管岗位职责范文
2013/11/08 职场文书
致标枪运动员广播稿
2014/02/06 职场文书
音乐学专业求职信
2014/07/22 职场文书
代理人委托书
2014/08/01 职场文书
党员“一帮一”活动总结
2015/05/07 职场文书
婚宴领导致辞
2015/07/28 职场文书
小学音乐课教学反思
2016/02/18 职场文书
经典格言警句:没有热忱,世间便无进步
2019/11/13 职场文书
JavaScript数组 几个常用方法总结
2021/11/11 Javascript