脚本之家,脚本语言编程技术及教程分享平台!
分类导航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服务器之家 - 脚本之家 - Python - python实现简单五子棋游戏

python实现简单五子棋游戏

2021-07-14 11:02wTen Python

这篇文章主要为大家详细介绍了python实现简单五子棋游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

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

python实现简单五子棋游戏

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
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()

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://blog.csdn.net/wsh596823919/article/details/80753087

延伸 · 阅读

精彩推荐