服务器之家

服务器之家 > 正文

python实现简单五子棋游戏

时间:2021-07-14 11:02     来源/作者:wTen

本文实例为大家分享了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

标签:

相关文章

热门资讯

2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全
2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全 2019-12-26
yue是什么意思 网络流行语yue了是什么梗
yue是什么意思 网络流行语yue了是什么梗 2020-10-11
背刺什么意思 网络词语背刺是什么梗
背刺什么意思 网络词语背刺是什么梗 2020-05-22
苹果12mini价格表官网报价 iPhone12mini全版本价格汇总
苹果12mini价格表官网报价 iPhone12mini全版本价格汇总 2020-11-13
2021德云社封箱演出完整版 2021年德云社封箱演出在线看
2021德云社封箱演出完整版 2021年德云社封箱演出在线看 2021-03-15
返回顶部