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使用Pycrypto库进行RSA加密的方法详解
Jun 06 Python
python运行时间的几种方法
Jun 17 Python
python绘制双柱形图代码实例
Dec 14 Python
Python3.5 处理文本txt,删除不需要的行方法
Dec 10 Python
使用Python横向合并excel文件的实例
Dec 11 Python
python利用Opencv实现人脸识别功能
Apr 25 Python
Django网络框架之创建虚拟开发环境操作示例
Jun 06 Python
python设计tcp数据包协议类的例子
Jul 23 Python
django如何自己创建一个中间件
Jul 24 Python
Django继承自带user表并重写的例子
Nov 18 Python
解决pip install psycopg2出错问题
Jul 09 Python
python中使用.py配置文件的方法详解
Nov 23 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
xml+php动态载入与分页
2006/10/09 PHP
php中经典方法实现判断多维数组是否为空
2011/10/23 PHP
PHP常用编译参数中文说明
2014/09/27 PHP
利用PHP访问MySql数据库的逻辑操作以及增删改查的实例讲解
2017/08/30 PHP
BOOM vs RR BO3 第二场2.13
2021/03/10 DOTA
你需要知道的10个最佳javascript开发实践小结
2012/04/15 Javascript
jquery easyui combox一些实用的小方法
2013/12/25 Javascript
jQuery拖动元素并对元素进行重新排序
2015/12/30 Javascript
jquery实现垂直和水平菜单导航栏
2020/08/27 Javascript
通过扫描二维码打开app的实现代码
2016/11/10 Javascript
JS获得一个对象的所有属性和方法实例
2017/02/21 Javascript
详解在Angular项目中添加插件ng-bootstrap
2017/07/04 Javascript
JavaScript中防止微信浏览器被整体拖动的方法
2017/08/25 Javascript
vue获取dom元素注意事项
2017/12/28 Javascript
vue里面父组件修改子组件样式的方法
2018/02/03 Javascript
vue.js内置组件之keep-alive组件使用
2018/07/10 Javascript
js实现按钮开关单机下拉菜单效果
2018/11/22 Javascript
vue实现select下拉显示隐藏功能
2019/09/30 Javascript
vue2.0 获取从http接口中获取数据,组件开发,路由配置方式
2019/11/04 Javascript
vue-router为激活的路由设置样式操作
2020/07/18 Javascript
[41:56]Spirit vs Liquid Supermajor小组赛A组 BO3 第一场 6.2
2018/06/03 DOTA
使用python 爬虫抓站的一些技巧总结
2018/01/10 Python
Python编程在flask中模拟进行Restful的CRUD操作
2018/12/28 Python
Python向excel中写入数据的方法
2019/05/05 Python
python使用 request 发送表单数据操作示例
2019/09/25 Python
Python进程Multiprocessing模块原理解析
2020/02/28 Python
在Ubuntu 20.04中安装Pycharm 2020.1的图文教程
2020/04/30 Python
Keras搭建自编码器操作
2020/07/03 Python
Python+Opencv实现把图片、视频互转的示例
2020/12/17 Python
pytorch __init__、forward与__call__的用法小结
2021/02/27 Python
Wedgwood英国官方网站:英式精致骨瓷餐具、礼品与生活精品,源于1759年
2019/09/02 全球购物
Conforama瑞士:家具、厨房、电器、装饰
2020/09/06 全球购物
出国考察邀请函
2014/01/21 职场文书
客服部班长工作责任制
2014/02/25 职场文书
六查六看六改心得体会
2014/10/14 职场文书
2015年仓库管理员工作总结
2015/04/21 职场文书