相對第一版本增強了電腦的演算法,程式碼分為三個檔案 gobanggame.py,button.py,computer.py。三個檔案。大家可以去百度雲下載我的打包檔案,程式碼為原創程式碼。
連結:https://pan.baidu.com/s/1wYl6O4Dvjtl8B8-l2...
提取碼:lbq7
gobanggame.py 主遊戲檔案
import pygame
import time
import computer
from button import Button
SCREEN_WIDTH=900
SCREEN_HEIGHT=800
BG_COLOR=pygame.Color(200, 200, 200)
Line_COLOR=pygame.Color(255, 255, 200)
TEXT_COLOR=pygame.Color(255, 0, 0)
# 定義顏色
BLACK = ( 0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = ( 0, 255, 0)
BLUE = ( 0, 0, 255)
class MainGame():
window = None
Start_X = 50
Start_Y = 50
Line_Span = 40
Max_X = Start_X + 18 * Line_Span
Max_Y = Start_Y + 18 * Line_Span
player1Color = 'B'
player2Color = 'W'
overColor = 'S'
# 1代表玩家1 , 2代表到玩家2 0代表結束
Putdownflag = player1Color
ChessmanList = []
button_go =None
def __init__(self):
'''初始化'''
def startGame(self):
MainGame.window = pygame.display.set_mode([SCREEN_WIDTH, SCREEN_HEIGHT])
pygame.display.set_caption("五子棋")
MainGame.button_go = Button(MainGame.window, "重新開始", SCREEN_WIDTH - 100, 300) # 建立開始按鈕
#初始化
while True:
time.sleep(0.1)
#獲取事件
MainGame.window.fill(BG_COLOR)
self.drawchChessboard()
self.bitechessman()
MainGame.button_go.draw_button()
self.VictoryOrDefeat()
self.Computerplay()
self.getEvent()
pygame.display.update()
pygame.display.flip()
def drawchChessboard(self):
for i in range(0,19):
x = MainGame.Start_X + i * MainGame.Line_Span
y = MainGame.Start_Y + i * MainGame.Line_Span
pygame.draw.line(MainGame.window, BLACK, [x, MainGame.Start_Y], [x, MainGame.Max_Y], 1)
pygame.draw.line(MainGame.window, BLACK, [MainGame.Start_X, y], [MainGame.Max_X, y], 1)
def getEvent(self):
# 獲取所有的事件
eventList = pygame.event.get()
for event in eventList:
if event.type == pygame.QUIT:
self.endGame()
elif event.type == pygame.MOUSEBUTTONDOWN:
pos = pygame.mouse.get_pos()
mouse_x = pos[0]
mouse_y = pos[1]
if (mouse_x > MainGame.Start_X- MainGame.Line_Span/2 and mouse_x < MainGame.Max_X + MainGame.Line_Span / 2) and (mouse_y > MainGame.Start_Y- MainGame.Line_Span/2 and mouse_y < MainGame.Max_Y + MainGame.Line_Span / 2):
#print( str(mouse_x) + "" + str(mouse_y))
#print(str(MainGame.Putdownflag))
if MainGame.Putdownflag != MainGame.player1Color:
return
click_x = round((mouse_x - MainGame.Start_X) / MainGame.Line_Span)
click_y = round((mouse_y - MainGame.Start_Y) / MainGame.Line_Span)
click_mod_x = (mouse_x - MainGame.Start_X) % MainGame.Line_Span
click_mod_y = (mouse_y - MainGame.Start_Y) % MainGame.Line_Span
if abs(click_mod_x-MainGame.Line_Span/2) >=5 and abs(click_mod_y-MainGame.Line_Span/2) >=5:
#print("有效點:x="+str(click_x)+" y="+str(click_y))
#有效點選點
self.putdownchess(MainGame.player1Color, click_x, click_y)
else:
print("out")
if MainGame.button_go.is_click():
self.restart()
print("button_go click")
else:
print("button_go click out")
def putdownchess(self, t, x, y):
flag = False
for item in MainGame.ChessmanList:
if item.x == x and item.y == y:
flag = True
if not flag:
cm = Chessman(t, x, y)
MainGame.ChessmanList.append(cm)
MainGame.Putdownflag = MainGame.player2Color
#print("ChessmanListlen:" + str(len(MainGame.ChessmanList)))
def bitechessman(self):
for item in MainGame.ChessmanList:
item.displaychessman()
def bureautime(self):
pass
def Computerplay(self):
if MainGame.Putdownflag == MainGame.player2Color:
print("輪到電腦了")
computer = self.getComputerplaychess()
if computer==None:
return
#print("computer x="+str(computer.x) + " y="+str(computer.y))
MainGame.ChessmanList.append(computer)
MainGame.Putdownflag = MainGame.player1Color
#判斷遊戲勝利
def VictoryOrDefeat(self):
for item in MainGame.ChessmanList:
if self.calHorizontalCount(item) == 5 or self.calVerticalityCount(item) == 5 or self.calBevelsUpCount(item) == 5 or self.calBevelsDownCount(item)==5:
txt =""
if item.troops == MainGame.player1Color :
txt = "玩家"
else:
txt = "電腦"
MainGame.window.blit(self.getTextSuface("%s獲勝" % txt), (SCREEN_WIDTH-100, 200))
MainGame.Putdownflag = MainGame.overColor
return
def restart(self):
MainGame.ChessmanList = []
def calHorizontalCount(self,chessman):
count = 1
for i in range(1, 5):
fi = filter(lambda x: x.troops == chessman.troops and x.x == chessman.x and x.y == chessman.y + i,
MainGame.ChessmanList)
if len(list(fi)) == 1:
count += 1
else:
break
return count
def calVerticalityCount(self, chessman):
count = 1
for i in range(1, 5):
fi = filter(lambda x:x.troops==chessman.troops and x.x == chessman.x+ i and x.y == chessman.y , MainGame.ChessmanList)
if len(list(fi)) == 1:
count += 1
else:
break
return count
def calBevelsUpCount(self, chessman):
count = 1
for i in range(1, 5):
fi = filter(lambda x: x.troops == chessman.troops and x.x == chessman.x + i and x.y == chessman.y - i,
MainGame.ChessmanList)
if len(list(fi)) == 1:
count += 1
else:
break
return count
def calBevelsDownCount(self, chessman):
count = 1
for i in range(1, 5):
fi = filter(lambda x: x.troops == chessman.troops and x.x == chessman.x + i and x.y == chessman.y + i,
MainGame.ChessmanList)
if len(list(fi)) == 1:
count += 1
else:
break
return count
def getTextSuface(self, text):
pygame.font.init()
# print(pygame.font.get_fonts())
font = pygame.font.SysFont('kaiti', 18)
txt = font.render(text, True, TEXT_COLOR)
return txt
def endGame(self):
print("exit")
exit()
def getComputerplaychess(self):
if len(MainGame.ChessmanList) == 0:
return Chessman(MainGame.player2Color, 9, 9)
arr = [[0 for i in range(19)] for j in range(19)]
for i in range(0, 19):
for j in range(0, 19):
if len(list(filter(lambda cm: cm.x == i and cm.y == j and cm.troops==MainGame.player1Color , MainGame.ChessmanList))):
arr[i][j] = 1
elif len(list(filter(lambda x: x.x == i and x.y == j and x.troops==MainGame.player2Color, MainGame.ChessmanList))):
arr[i][j] = 2
'''
newarr = computer.getPoint(arr)
if newarr.x != -1 and newarr.y != -1:
print("結果:"+ str(newarr.x) +" "+ str(newarr.y))
return Chessman(MainGame.player2Color, newarr.x, newarr.y)
'''
newarr = computer.getPoint(arr)
if newarr[0] != -1 and newarr[1] != -1:
print("結果:" + str(newarr[0]) + " " + str(newarr[1]))
return Chessman(MainGame.player2Color, newarr[0], newarr[1])
# 進攻
# 防守
for item in MainGame.ChessmanList:
if item.troops == MainGame.player1Color:
prev_x = item.x - 1
prev_y = item.y - 1
next_x = item.x + 1
next_y = item.y + 1
if next_x < 19 and len(list(filter(lambda x: x.x == next_x and x.y == item.y, MainGame.ChessmanList)))==0:
return Chessman(MainGame.player2Color, next_x, item.y)
if next_y < 19 and len(list(filter(lambda x: x.x == item.x and x.y == next_y, MainGame.ChessmanList)))==0:
return Chessman(MainGame.player2Color, item.x, next_y)
for i in range(0,18):
for j in range(0, 18):
fi= filter(lambda x: x.x == i and x.y == j, MainGame.ChessmanList)
if len(list(fi)) == 0 :
return Chessman(MainGame.player2Color, i, j)
return None
class Chessman():
def __init__(self,t,x,y):
self.images = {
'B' : pygame.image.load("imgs/black.gif"),
'W' : pygame.image.load('imgs/white.gif'),
}
self.troops = t
self.image = self.images[self.troops]
self.x = x
self.y = y
self.rect = self.image.get_rect()
self.rect.left = MainGame.Start_X + x * MainGame.Line_Span - MainGame.Line_Span/2
self.rect.top = MainGame.Start_Y + y * MainGame.Line_Span - MainGame.Line_Span/2
def displaychessman(self):
if self.troops != 'N':
self.image = self.images[self.troops]
MainGame.window.blit(self.image,self.rect)
if __name__ == '__main__':
MainGame().startGame()
computer.py檔案主要是電腦的演算法
play2 = 2
play1 = 1
play0 = 0
chess_important = 3
blank_importand = 1
def getPoint(arr):
list_score = []
score = 0
#c = che(-1,-1)
for i in range(0,19):
for j in range(0,19):
if arr[i][j] == play0:
arr[i][j] = play2
scorenext = getscore(arr,i,j,play2)
arr[i][j] = play1
scoreplay1=getscore(arr, i, j, play1)
list_score.append([scorenext,scoreplay1,scorenext-scoreplay1,i,j])
arr[i][j] = play0
print(score)
list_scorepalyer1= sorted(list_score, key=lambda tm: (tm[0], tm[1]), reverse=True)
list_scorepalyer2 = sorted(list_score, key=lambda tm: (tm[1], tm[0]), reverse=True)
#print(list_scorepalyer1)
#print(list_scorepalyer2)
result_x = -1
result_y = -1
if(list_scorepalyer1[0][0] >= list_scorepalyer2[0][1]):
result_x=list_scorepalyer1[0][3]
result_y=list_scorepalyer1[0][4]
else:
result_x = list_scorepalyer2[0][3]
result_y = list_scorepalyer2[0][4]
return [result_x,result_y]
def getscore(arr,x,y,player):
start_i = max(x-5,0)
end_i = min(x+5,18)
start_j= max(y-5,0)
end_j = min(y + 5, 18)
maxcount = 0
sumcombo = 0
#橫向
count1, combo1 = getCountCombo(player,[arr[i][y] for i in range(x,start_i, -1)])
count2, combo2 = getCountCombo(player,[arr[i][y] for i in range(x, end_i)])
maxcount = max(maxcount, count1 + count2 - chess_important * 2)
sumcombo += combo1 + combo2 - 2
#垂直
count1, combo1 = getCountCombo(player,[arr[x][i] for i in range(y, start_j, -1)])
count2, combo2 = getCountCombo(player,[arr[x][i] for i in range(y, end_j)])
maxcount = max(maxcount, count1 + count2 - chess_important * 2)
sumcombo += combo1 + combo2 - 2
#斜 左上右下
start_p1 = min(y - start_j, x - start_i)
end_p1 = min(end_i - x, end_j - y)
count1, combo1 = getCountCombo(player,[arr[x-i][y-i] for i in range(start_p1)])
count2, combo2 = getCountCombo(player,[arr[x+i][y+i] for i in range(end_p1)])
maxcount = max(maxcount, count1 + count2 - chess_important * 2)
sumcombo += combo1 + combo2 - 2
#斜 左下右上
start_p2 = min(end_j - y, x - start_i)
end_p2 = min(end_i - x, y - start_j)
count1, combo1 = getCountCombo(player,[arr[x - i][y + i] for i in range(start_p2)])
count2, combo2 = getCountCombo(player,[arr[x + i][y - i] for i in range(end_p2)])
maxcount = max(maxcount, count1 + count2 - chess_important * 2)
sumcombo += combo1 + combo2 - 2
'''
if maxcount >=3:
print(combo1)
print(combo2)'''
score = maxcount * 20 + sumcombo * 10
'''
if(score >0):
print("maxcount"+str(maxcount))
print("sumcombo"+str(sumcombo))
'''
return score
def getCountCombo(player,list):
count = 0
combo = 0
combo_count = True
for item in list :
if item == player:
count += chess_important
if combo_count:
combo += 1
elif item == play0:
combo_count = False
else:
break
return count,combo
class che():
x = -1
y = -1
def __init__(self,x,y):
self.x = x
self.y = y
button.py重新按鈕
import pygame
class Button():
def __init__(self, screen, msg, left,top): # msg為要在按鈕中顯示的文字
"""初始化按鈕的屬性"""
self.screen = screen
self.screen_rect = screen.get_rect()
self.width, self.height = 150, 50 # 這種賦值方式很不錯
self.button_color = (72, 61, 139) # 設定按鈕的rect物件顏色為深藍
self.text_color = (255, 255, 255) # 設定文字的顏色為白色
pygame.font.init()
self.font = pygame.font.SysFont('kaiti', 20) # 設定文字為預設字型,字號為40
self.rect = pygame.Rect(0, 0, self.width, self.height)
#self.rect.center = self.screen_rect.center # 建立按鈕的rect物件,並使其居中
self.left = left
self.top = top
self.deal_msg(msg) # 渲染影像
def deal_msg(self, msg):
"""將msg渲染為影像,並將其在按鈕上居中"""
self.msg_img = self.font.render(msg, True, self.text_color, self.button_color) # render將儲存在msg的文字轉換為影像
self.msg_img_rect = self.msg_img.get_rect() # 根據文字影像建立一個rect
self.msg_img_rect.center = self.rect.center # 將該rect的center屬性設定為按鈕的center屬性
def draw_button(self):
#self.screen.fill(self.button_color, self.rect) # 填充顏色
self.screen.blit(self.msg_img, (self.left,self.top)) # 將該影像繪製到螢幕
def is_click(self):
point_x, point_y = pygame.mouse.get_pos()
x = self.left
y = self.top
w, h = self.msg_img.get_size()
in_x = x < point_x < x + w
in_y = y < point_y < y + h
return in_x and in_y
本作品採用《CC 協議》,轉載必須註明作者和本文連結