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多线程下的变量问题
Apr 28 Python
举例讲解Python编程中对线程锁的使用
Jul 12 Python
微信 用脚本查看是否被微信好友删除
Oct 28 Python
Python列表list操作符实例分析【标准类型操作符、切片、连接字符、列表解析、重复操作等】
Jul 24 Python
学习python可以干什么
Feb 26 Python
Python判断对象是否为文件对象(file object)的三种方法示例
Apr 26 Python
Python函数中的可变长参数详解
Sep 12 Python
python-web根据元素属性进行定位的方法
Dec 13 Python
Python基于Serializer实现字段验证及序列化
Nov 04 Python
Pytorch实验常用代码段汇总
Nov 19 Python
Numpy ndarray 多维数组对象的使用
Feb 10 Python
Python一些基本的图像操作和处理总结
Jun 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
mysql+php分页类(已测)
2008/03/31 PHP
浅谈PHP中foreach/in_array的使用
2015/11/02 PHP
兼容IE、FireFox、Chrome等浏览器的xml处理函数js代码
2011/11/30 Javascript
JavaScript解析URL参数示例代码
2013/08/12 Javascript
关于js数组去重的问题小结
2014/01/24 Javascript
js 日期比较相关天数代码
2014/04/02 Javascript
js实现按钮加背景图片常用方法
2014/11/01 Javascript
javaScript的函数对象的声明详解
2015/02/06 Javascript
不同编码的页面表单数据乱码问题解决方法
2015/02/15 Javascript
jquery 动态增加删除行的简单实例(推荐)
2016/10/12 Javascript
JavaScript中关键字 in 的使用方法详解
2016/10/17 Javascript
详解Javascript数据类型的转换规则
2016/12/12 Javascript
node.js实现回调的方法示例
2017/03/01 Javascript
详解基于webpack和vue.js搭建开发环境
2017/04/05 Javascript
js下拉菜单生成器dropMenu使用方法详解
2017/08/01 Javascript
vuejs实现递归树型菜单组件
2018/01/13 Javascript
详解一次Vue低版本安卓白屏问题的解决过程
2019/05/30 Javascript
解决vue项目router切换太慢问题
2020/07/19 Javascript
vue中axios封装使用的完整教程
2021/03/03 Vue.js
[35:29]Secret vs VG 2018国际邀请赛淘汰赛BO3 第三场 8.23
2018/08/24 DOTA
[58:11]守擂赛第二周擂主赛 DeMonsTer vs Leopard
2020/04/28 DOTA
详解Python中的循环语句的用法
2015/04/09 Python
使用Python的Django框架结合jQuery实现AJAX购物车页面
2016/04/11 Python
python并发编程之多进程、多线程、异步和协程详解
2016/10/28 Python
PyQt4实现下拉菜单可供选择并打印出来
2018/04/20 Python
对pycharm 修改程序运行所需内存详解
2018/12/03 Python
python添加模块搜索路径和包的导入方法
2019/01/19 Python
利用Python对文件夹下图片数据进行批量改名的代码实例
2019/02/21 Python
Appium+python自动化之连接模拟器并启动淘宝APP(超详解)
2019/06/17 Python
python根据多个文件名批量查找文件
2019/08/13 Python
pytorch绘制并显示loss曲线和acc曲线,LeNet5识别图像准确率
2020/01/02 Python
5分钟弄清楚html5的drag and drop(小结)
2019/04/10 HTML / CSS
网站性能延迟加载图像的五种技巧(小结)
2020/08/13 HTML / CSS
do you have any Best Practice for testing
2016/06/04 面试题
产品调价通知函
2015/04/20 职场文书
SpringBoot深入分析讲解监听器模式下
2022/07/15 Java/Android