python+pygame实现五子棋网络对战之二

上篇我们对python的Socket编程有了一个基本的认识,接下来就可以完成五子棋的网络对战的实现。步骤如下:

1、服务端开始侦听

2、客户端通过tcp连接上服务端,开局

3、判断输赢后,一方提出是否开新局

4、对方同意后,开新局。

接下来就简单了,只要把Socket编程的通信部分弄到以前的代码就可以了。

五子棋人机对战版:(

https://blog.csdn.net/cxhold/article/details/140126002

https://blog.csdn.net/cxhold/article/details/140133224

https://blog.csdn.net/cxhold/article/details/140136176

https://blog.csdn.net/cxhold/article/details/140142940

https://blog.csdn.net/cxhold/article/details/140159258)

五子棋人机代码

三、

代码结构:

服务端和客户端的代码区别就在main.py中

3.1 服务端main.py

# encoding:utf-8
import pygame
from pygame.locals import *
import sys
import os
from socket import *
import select

import  piece
from tkinter import *
from params import Params
from utils import *

pygame.init()
pygame.mixer.init()

WHITE = (255, 255, 255)
BLACK = (0, 0, 0)

rows = int(Params.get('ROWS'))
blocksize = int(Params.get('blockSize'))
width = int(Params.get('WIDTH'))
height = int(Params.get('HEIGHT'))

game_bgsize = width, height
# 棋盘
x = []    #x轴
y = []    #y轴

for i in range(0, rows):   #棋盘的所有交叉点坐标(x,y)
    x.append(28 + i * blocksize)
    y.append(28 + i * blocksize)

# 记录棋盘每个坐标的属性,没有棋子为0,白棋为1,黑棋为2
chess_map = {}    #结构是chess_map[28,28] = 0   ...

# 字体
fontpath = os.path.join(Params.get('resourcePath'), Params.get('fontFolder'), 'simkai.ttf')
myfont = pygame.font.Font(fontpath, 38)

# 起始选项
txtplayerandplayer = myfont.render("玩家与玩家", True, WHITE)
txtplayerandplayer_rect = txtplayerandplayer.get_rect()
txtplayerandplayer_rect.left, txtplayerandplayer_rect.top = (game_bgsize[0] - txtplayerandplayer_rect.width) // 2, \
                                    (game_bgsize[1] - txtplayerandplayer_rect.height) // 2 - 100

txtplayerandcomputer = myfont.render('玩家与电脑', True, WHITE)
txtplayerandcomputer_rect = txtplayerandcomputer.get_rect()
txtplayerandcomputer_rect.left, txtplayerandcomputer_rect.top = (game_bgsize[0] - txtplayerandplayer_rect.width) // 2, \
                                    (game_bgsize[1] - txtplayerandplayer_rect.height) // 2

txtplaysound = myfont.render('音效:  开', True, WHITE)
txtplaysound_rect = txtplaysound.get_rect()
txtplaysound_rect.left, txtplaysound_rect.top = (game_bgsize[0] - txtplaysound_rect.width) // 2, \
                                    (game_bgsize[1] - txtplaysound_rect.height) // 2 + 100

txtclosesound = myfont.render('音效:  关', True, WHITE)
txtclosesound_rect = txtclosesound.get_rect()
txtclosesound_rect.left, txtclosesound_rect.top = (game_bgsize[0] - txtclosesound_rect.width) // 2, \
                                    (game_bgsize[1] - txtclosesound_rect.height) // 2 + 100
 # 输赢
successtext = myfont.render("你有点屌哦!!!", True, WHITE)
successtext_rect = successtext.get_rect()
successtext_rect.left, successtext_rect.top = (game_bgsize[0] - successtext_rect.width) // 2, \
                                        (game_bgsize[1] - successtext_rect.height) // 2
failuretext = myfont.render("小趴菜...", True, WHITE)
failuretext_rect = failuretext.get_rect()
failuretext_rect.left, failuretext_rect.top = (game_bgsize[0] - failuretext_rect.width) // 2, \
                                            (game_bgsize[1] - failuretext_rect.height) // 2
playagaintext = myfont.render("再玩一局", True, WHITE)
menutext = myfont.render('主菜单', True, WHITE)

#连接
txtwatting = myfont.render('等待连接', True, WHITE)
txtwatting_rect = txtclosesound.get_rect()
txtwatting_rect.left, txtwatting_rect.top = (game_bgsize[0] - txtwatting_rect.width) // 2, \
                                (game_bgsize[1] - txtwatting_rect.height) // 2
txtclosed = myfont.render('对方不愿和你玩并断开了连接', True, WHITE)
txtclosed_rect = txtclosed.get_rect()
txtclosed_rect.left, txtclosed_rect.top = (game_bgsize[0] - txtclosed_rect.width) // 2, \
                                (game_bgsize[1] - txtclosed_rect.height) // 2
txtchallenge = myfont.render('对方再次向你发起挑战', True, WHITE)
txtchallenge_rect = txtchallenge.get_rect()
txtchallenge_rect.left, txtchallenge_rect.top = (game_bgsize[0] - txtchallenge_rect.width) // 2, \
                                (game_bgsize[1] - txtchallenge_rect.height) // 2
txtrecive = myfont.render('接受挑战         不接受挑战', True, WHITE)
txtrecive_rect = txtrecive.get_rect()
txtrecive_rect.left, txtrecive_rect.top = (game_bgsize[0] - txtrecive_rect.width) // 2, \
                                (game_bgsize[1] - txtrecive_rect.height) // 2 + 100

# TCP服务
HOST = ''  # 地址
POST = 23338  # 端口
BUFSIZE = 2048    #缓冲区
HOSTADDR = (HOST, POST)
tcpserversocket = socket(AF_INET, SOCK_STREAM)   #创建套接字
tcpserversocket.bind(HOSTADDR)
tcpserversocket.listen(1)   #listen(n)的n值表示socket的“排队个数”,表示的是服务器拒绝(超过限制数量的)连接之前,操作系统可以挂起的最大连接数量。
#一般情况下,一个进程只有一个主线程(也就是单线程),那么socket允许的最大连接数为: n + 1 \
# 如果服务器是多线程,比如开了2个线程,那么socket允许的最大连接数就是: n + 2 \
# 换句话说:排队的人数(就是那个n) + 正在就餐的人数(服务器正在处理的socket连接数) = 允许接待的总人数(socket允许的最大连接数)\
# 因此listen(1),最大连接数是2,就是1个处理,1个“排队”

inputs = [tcpserversocket]

# 判断棋盘某位置上是否有棋子
def isempty(theposition):
    global chess_map
    existpiece = False
    if chess_map[str(theposition[0]) + ',' + str(theposition[1])]:
        existpiece = True
    return existpiece

# 电脑选取落子的位置
def computerdecision():
    value = max1 = max2 = 0
    pos1 = pos2 = ()
    # 进攻
    for i in range(0, rows):
        row = 28 + i * blocksize
        for j in range(0, rows):
            col = 28 + j * blocksize
            pos = (row, col)
            if isempty(pos):
                continue
            value = pointvalue(chess_map,pos, 1, 2)   
            if value > max1:
                max1 = value
                pos1 = (row, col)

    # 防守
    for i in range(0, rows):
        for j in range(0, rows):
            row = 28 + i * blocksize
            col = 28 + j * blocksize
            if isempty((row, col)):
                continue
            value = pointvalue(chess_map,(row, col), 2, 1)  
            if value > max2:
                max2 = value
                pos2 = (row, col)
    if max1 > max2:
        return pos1
    else:
        return pos2

# 初始化棋盘
def init():
    global chess_map
    for i in x:
        for j in y:
            chess_map[str(i) + ',' + str(j)] = 0    #清空


def main():
    os.environ['SDL_VIDEO_CENTERED'] = '1'    #居中
    screen = pygame.display.set_mode(game_bgsize)
    pygame.display.set_caption('五子棋服务端')
    bgimagepath = os.path.join(Params.get('resourcePath'), Params.get('imgFolder'), 'bg.png')
    bg_image = pygame.image.load(bgimagepath).convert_alpha()  # 背景图片加载

    zzimagepath = os.path.join(Params.get('resourcePath'), Params.get('imgFolder'), 'zz.png') #遮罩图片
    zz_image = pygame.image.load(zzimagepath).convert_alpha()

    # 背景音乐
    bgsoundpath = os.path.join(Params.get('resourcePath'), Params.get('soundFolder'), '齐豫 - 莲花处处开.mp3')
    bg_sound = pygame.mixer.music.load(bgsoundpath)   # 背景音乐加载
    pygame.mixer.music.set_volume(0.08)
    pygame.mixer.music.play(-1)

    clicksoundpath = os.path.join(Params.get('resourcePath'), Params.get('soundFolder'), 'drop.wav')
    piece_sound = pygame.mixer.Sound(clicksoundpath) 

    clock = pygame.time.Clock()

    # 棋子
    white_chesses = []   #白棋子对象
    black_chesses = []   #黑棋子对象
    white_positions = [] #白棋子位置集合
    black_positions = [] #黑棋子位置集合
    chesses = []         #所有棋子集合,主要是显示用
 
    is_player = False   # 轮到哪方下棋, 
    is_finish = False     # 是否结束游戏

    # 赢方
    black_win = False
    white_win = False
 
    people2people = False   # 人与人,网络版  
    people2computer = False  # 人与电脑
    is_choise = False  # 是否做出选择对战方式,是people2people 还是 people2computer , 通过菜单选择对战方式
    is_play_sound = True   # 是否播放声音
    is_playagain = False    # 是否再来一局

    # 是否连接
    is_link = False

    # 对方是否发来重新开始的消息
    is_againmsg = False

    # 对面拒绝了重新开始
    is_reject = False

    # 初始化
    is_playagain = False
    running = True
    init()

    while running:
       
        screen.blit(bg_image, (0, 0))

        # 绘制游戏菜单
        if not is_choise:
            screen.blit(zz_image, (0, 0))  #遮罩层
            screen.blit(txtplayerandplayer, txtplayerandplayer_rect)
            screen.blit(txtplayerandcomputer, txtplayerandcomputer_rect)
            if not is_play_sound:
                screen.blit(txtclosesound, txtclosesound_rect)
            else:
                screen.blit(txtplaysound, txtplaysound_rect)
        else:  #
            if people2people:
                if not is_link and not is_reject:
                    screen.blit(txtwatting, txtwatting_rect)

        # 绘制棋盘
        if is_choise:
            if chesses:
                for i in chesses:
                    screen.blit(i.image, i.image_rect())

        for event in pygame.event.get():
            if event.type == QUIT:
                if is_link:
                    tcpclientsocket.close()
                if people2people:
                    tcpserversocket.close()
                pygame.quit()
                sys.exit()

            if event.type == MOUSEBUTTONDOWN:   #server下棋
                if event.button == 1 :
                    if is_finish :
                        if not is_againmsg and not is_reject:
                            pos = event.pos
                            if successtext_rect.left < pos[0] < successtext_rect.right  and \
                                    successtext_rect.top < pos[1] < successtext_rect.top + 30:
                                if people2people:
                                    tcpclientsocket.send('again'.encode('utf8'))
                                if people2computer:
                                    is_playagain = True
                                    is_player = True
                                    is_finish = False
                                    init()

                            if successtext_rect.left < pos[0] < successtext_rect.right - 50 and \
                                    successtext_rect.top + 50 < pos[1] < successtext_rect.top + 120:
                                people2people = False
                                is_choise = False
                                if is_link:
                                    is_link = False
                                    tcpclientsocket.send('no'.encode('utf8'))
                                main()

                    if is_reject:
                        pos = event.pos
                        if txtclosed_rect.left + 150 < pos[0] < txtclosed_rect.left + 250 and \
                                txtclosed_rect.top + 70 < pos[1] < txtclosed_rect.top + 190:
                            main()
                            is_choise = False

                    if is_againmsg:
                        pos = event.pos
                        if txtrecive_rect.left < pos[0] < txtrecive_rect.left + 150 and \
                                txtrecive_rect.top < pos[1] < txtrecive_rect.top + 120:
                            tcpclientsocket.send('yes'.encode('utf8'))
                            is_againmsg = False
                            is_playagain = True
                            is_player = False
                            is_finish = False
                            
                        if txtrecive_rect.left + 330 < pos[0] < txtrecive_rect.left + 480 and \
                                txtrecive_rect.top < pos[1] < txtrecive_rect.top + 120:
                            tcpclientsocket.send('no'.encode('utf8'))
                            main()

                    if is_choise:
                        # 判断是否轮到server下棋
                        if is_player  and not is_finish  and not is_againmsg:
                            pos = event.pos
                            pblack = piece.Piece(pos,'pieces_black.png') 
                            if not isempty(pblack.pointtrans()):
                                black_chesses.append(pblack)
                                black_positions.append(pblack.pointtrans())
                                chesses.append(pblack)
                                chess_map[str(pblack.pointtrans()[0]) + ',' + str(pblack.pointtrans()[1])] = 2
                                if people2people:   #
                                    tcpclientsocket.send(str(pos).encode('utf8'))
                                is_player = False
                                piece_sound.play()
                                # 判断输赢
                                if len(black_chesses)>=5 and not is_finish and checkwin(black_positions,pblack.pointtrans()[0],pblack.pointtrans()[1]) :
                                    is_finish = True
                                    black_win = True
                            else:
                                del (pblack)
                    else:
                        pos = event.pos
                        if txtplayerandplayer_rect.left <= pos[0] <= txtplayerandplayer_rect.left + 170 and \
                                txtplayerandplayer_rect.top  <= pos[1] <= txtplayerandplayer_rect.top + 30:
                            is_choise = True
                            people2people = True
                        if txtplayerandplayer_rect.left <= pos[0] <= txtplayerandplayer_rect.left + 170 and \
                                txtplayerandplayer_rect.top + 100 <= pos[1] <= txtplayerandplayer_rect.top + 130:
                            is_choise = True
                            people2computer = True
                            is_player = True
                        if txtplayerandplayer_rect.left <= pos[0] <= txtplayerandplayer_rect.left + 160 and \
                                txtplayerandplayer_rect.top + 200 <= pos[1] <= txtplayerandplayer_rect.top + 230:
                            is_play_sound = not is_play_sound
                            if not is_play_sound:
                                pygame.mixer.stop()
                                pygame.mixer.music.stop()
                            else:
                                pygame.mixer.music.play()          

        '''
        select 模块在 Python 中不是标准库的一部分,而是一个提供底层 socket 接口的系统级模块。它通常用于编写跨平台的非阻塞 socket 服务器。
        select 模块中最常用的函数是 select(),它接受三个参数:
            读取标准输入的文件描述符集合  inputs
            写入标准输出的文件描述符集合  outputs
            异常处理的文件描述符集合      
        '''

        if people2people:
            readable, writable, exceptional = select.select(inputs, [], [], 0)   # 使用 select 模块的 select 函数进行非阻塞地等待连接,标准写法
            for readline in readable:
                if readline is tcpserversocket:    # 处理新的连接
                    tcpclientsocket, HOSTADDR = tcpserversocket.accept()
                    inputs.append(tcpclientsocket)
                    is_link = True
                    # print('connenct')
                else:
                    try:         # 处理已连接的套接字数据
                        data = readline.recv(BUFSIZE)    #获取数据
                        # print(data.decode('utf8'))
                        if data.decode('utf8') == 'again':
                            is_againmsg = True
                        if data.decode('utf8') == 'yes':
                            is_playagain = True
                            is_player = False
                        if data.decode('utf8') == 'no':
                            is_reject = True
                            is_link = False
                        disconnected = not data    #如果没有数据,则关闭连接,disconnected为True
                    except error:      #异常或错误时,则关闭连接,disconnected为True,is_link为False
                        disconnected = True   
                        is_link = False
                    if disconnected:     #断开后,移除接收的消息
                        inputs.remove(readline)
                    else:
                        if not is_player and not is_finish:
                            pwhite = piece.Piece(eval(data),'pieces_white.png')  #接收客户端的下棋位置,画白棋
                            white_chesses.append(pwhite)
                            white_positions.append(pwhite.pointtrans())
                            chesses.append(pwhite)
                            is_player = True
           
            # 判断输赢
            if len(white_chesses)>=5 and not is_finish and checkwin(white_positions,pwhite.pointtrans()[0],pwhite.pointtrans()[1]) :
                is_finish = True
                white_win = True

        # 电脑落子
        if people2computer and not is_player:
            pwhite = piece.Piece(computerdecision(),'pieces_white.png')
            white_chesses.append(pwhite)
            white_positions.append(pwhite.pointtrans())
            chesses.append(pwhite)
            chess_map[str(pwhite.pointtrans()[0]) + ',' + str(pwhite.pointtrans()[1])] = 1
            is_player = True
            piece_sound.play()

            if len(white_chesses)>=5 and not is_finish and checkwin(white_positions,pwhite.pointtrans()[0],pwhite.pointtrans()[1]) :
                is_finish = True
                white_win = True

        if black_win and is_finish and not is_againmsg and not is_reject:
            screen.blit(zz_image, (0, 0))  #遮罩层
            screen.blit(successtext, (successtext_rect.left, successtext_rect.top - 80))
            screen.blit(playagaintext, successtext_rect)
            screen.blit(menutext, (successtext_rect.left, successtext_rect.top + 80))

        if white_win and is_finish and not is_againmsg and not is_reject:
            screen.blit(zz_image, (0, 0))  #遮罩层
            screen.blit(failuretext, (successtext_rect.left, successtext_rect.top - 80))
            screen.blit(playagaintext, successtext_rect)
            screen.blit(menutext, (successtext_rect.left, successtext_rect.top + 80))

        if is_againmsg:
            screen.blit(txtchallenge, txtchallenge_rect)
            screen.blit(txtrecive, txtrecive_rect)

        if is_reject:
            screen.blit(txtclosed, txtclosed_rect)
            screen.blit(menutext, (txtclosed_rect.left + 150, txtwatting_rect.top + 70))
            

        if is_playagain:
            init()
            white_chesses.clear()
            black_chesses.clear()
            white_positions.clear()
            black_positions.clear()
            chesses.clear()
            is_finish = False
            black_win = False
            white_win = False
            is_playagain = False

        pygame.display.flip()

        clock.tick(60)


if __name__ == '__main__':
    main()

3.2 客户端main.py

# encoding:utf-8
import pygame
from pygame.locals import *
import sys
import os
from socket import *
import select

import  piece
from tkinter import *
from params import Params
from utils import *

pygame.init()
pygame.mixer.init()

WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
rows = int(Params.get('ROWS'))
blocksize = int(Params.get('blockSize'))
width = int(Params.get('WIDTH'))
height = int(Params.get('HEIGHT'))


# 棋盘
x = []    #x轴
y = []    #y轴

for i in range(0, rows):   #棋盘的所有交叉点坐标(x,y)
    x.append(28 + i * blocksize)
    y.append(28 + i * blocksize)

# 记录棋盘每个坐标的属性,没有棋子为0,白棋为1,黑棋为2
chess_map = {}    #结构是chess_map[28,28] = 0   ...


# 判断棋盘某位置上是否有棋子
def isempty(theposition):
    global chess_map
    existpiece = False
    if chess_map[str(theposition[0]) + ',' + str(theposition[1])]:
        existpiece = True
    return existpiece

# 电脑选取落子的位置
def computerdecision():
    value = max1 = max2 = 0
    pos1 = pos2 = ()
    # 进攻
    for i in range(0, rows):
        row = 28 + i * blocksize
        for j in range(0, rows):
            col = 28 + j * blocksize
            pos = (row, col)
            if isempty(pos):
                continue
            value = pointvalue(chess_map,pos, 1, 2)   
            if value > max1:
                max1 = value
                pos1 = (row, col)

    # 防守
    for i in range(0, rows):
        for j in range(0, rows):
            row = 28 + i * blocksize
            col = 28 + j * blocksize
            if isempty((row, col)):
                continue
            value = pointvalue(chess_map,(row, col), 2, 1)  
            if value > max2:
                max2 = value
                pos2 = (row, col)
    if max1 > max2:
        return pos1
    else:
        return pos2

# 初始化棋盘
def init():
    global chess_map
    for i in x:
        for j in y:
            chess_map[str(i) + ',' + str(j)] = 0   #清空


def main():
    # TCP服务
    BUFSIZE = 2048
    tcpclientsocket = socket(AF_INET, SOCK_STREAM)

    # 输入IP地址
    def screenConnect():
        top = Tk()
        top.title('服务器IP')
        top.geometry('%dx%d+%d+%d' % (300, 200, 418, 338))
        HOST = ''
        POST = 23338
        nonlocal tcpclientsocket

        def fun():
            nonlocal HOST
            nonlocal POST
            nonlocal tcpclientsocket
            HOST = txtIP.get()
            HOSTADDR = (HOST, POST)
            try:
                tcpclientsocket.connect(HOSTADDR)
                lbl_msg = Label(top, text='')
                lbl_msg = Label(top, text='已连接')
                lbl_msg.grid(row=2, column=1)
            except error:
                lbl_msg = Label(top, text='连接失败')
                lbl_msg.grid(row=2, column=1)

        lblIP = Label(top, text='    IP 地址:',  padx=5, pady=30)
        lblIP.grid(row=1, column=0)
        txtIP = Entry(top)
        txtIP.grid(row=1, column=1)
        btnConn = Button(top, text='连接',  padx=1, command=fun)
        btnConn.grid(row=2, column=0)

        mainloop()

    game_bgsize = width, height
    os.environ['SDL_VIDEO_CENTERED'] = '1' 
    screen = pygame.display.set_mode(game_bgsize)

    pygame.display.set_caption('五子棋客户端')
    bgimagepath = os.path.join(Params.get('resourcePath'), Params.get('imgFolder'), 'bg.png')
    bg_image = pygame.image.load(bgimagepath).convert_alpha()  # 背景图片加载

    zzimagepath = os.path.join(Params.get('resourcePath'), Params.get('imgFolder'), 'zz.png') #遮罩图片
    zz_image = pygame.image.load(zzimagepath).convert_alpha()

    # 背景音乐
    bgsoundpath = os.path.join(Params.get('resourcePath'), Params.get('soundFolder'), '齐豫 - 莲花处处开.mp3')
    bg_sound = pygame.mixer.music.load(bgsoundpath)   # 背景音乐加载
    pygame.mixer.music.set_volume(0.08)
    pygame.mixer.music.play(-1)

    clicksoundpath = os.path.join(Params.get('resourcePath'), Params.get('soundFolder'), 'drop.wav')
    piece_sound = pygame.mixer.Sound(clicksoundpath) 

    running = True

    clock = pygame.time.Clock()

    inputs = [tcpclientsocket]

    # 棋子
    white_chesses = []   #白棋子对象
    black_chesses = []   #黑棋子对象
    white_positions = [] #白棋子位置集合
    black_positions = [] #黑棋子位置集合
    chesses = []         #所有棋子集合,主要是显示用

    is_player = True    # 轮到哪方下棋
    is_finish = False   # 是否结束游戏

    # 赢方
    black_win = False
    white_win = False
  
    people2people = False    # 人人对战,网络版 
    people2computer = False   # 人与电脑对战 
    is_choise = False   # 是否做出选择对战方式,是people2people 还是 people2computer , 通过菜单选择对战方式
    is_play_sound = True   # 是否播放声音 
    is_playagain = False   # 是否再来一局
 
    # 是否连接
    is_link = False

    # 对方是否发来重新开始的消息
    is_againmsg = False

    # 对面拒绝了重新开始
    is_reject = False

    # 字体
    fontpath = os.path.join(Params.get('resourcePath'), Params.get('fontFolder'), 'simkai.ttf')
    myfont = pygame.font.Font(fontpath, 38)

    # 起始选项
    txtplayerandplayer = myfont.render("玩家与玩家", True, WHITE)
    txtplayerandplayer_rect = txtplayerandplayer.get_rect()
    txtplayerandplayer_rect.left, txtplayerandplayer_rect.top = (game_bgsize[0] - txtplayerandplayer_rect.width) // 2, \
                                        (game_bgsize[1] - txtplayerandplayer_rect.height) // 2 - 100

    txtplayerandcomputer = myfont.render('玩家与电脑', True, WHITE)
    txtplayerandcomputer_rect = txtplayerandcomputer.get_rect()
    txtplayerandcomputer_rect.left, txtplayerandcomputer_rect.top = (game_bgsize[0] - txtplayerandplayer_rect.width) // 2, \
                                        (game_bgsize[1] - txtplayerandplayer_rect.height) // 2

    txtplaysound = myfont.render('音效:  开', True, WHITE)
    txtplaysound_rect = txtplaysound.get_rect()
    txtplaysound_rect.left, txtplaysound_rect.top = (game_bgsize[0] - txtplaysound_rect.width) // 2, \
                                        (game_bgsize[1] - txtplaysound_rect.height) // 2 + 100

    txtclosesound = myfont.render('音效:  关', True, WHITE)
    txtclosesound_rect = txtclosesound.get_rect()
    txtclosesound_rect.left, txtclosesound_rect.top = (game_bgsize[0] - txtclosesound_rect.width) // 2, \
                                        (game_bgsize[1] - txtclosesound_rect.height) // 2 + 100
    # 输赢
    successtext = myfont.render("你有点屌哦!!!", True, WHITE)
    successtext_rect = successtext.get_rect()
    successtext_rect.left, successtext_rect.top = (game_bgsize[0] - successtext_rect.width) // 2, \
                                            (game_bgsize[1] - successtext_rect.height) // 2
    failuretext = myfont.render("小趴菜...", True, WHITE)
    failuretext_rect = failuretext.get_rect()
    failuretext_rect.left, failuretext_rect.top = (game_bgsize[0] - failuretext_rect.width) // 2, \
                                                (game_bgsize[1] - failuretext_rect.height) // 2
    playagaintext = myfont.render("再玩一局", True, WHITE)
    menutext = myfont.render('主菜单', True, WHITE)

    #连接
    txtclosed = myfont.render("对方不愿和你玩并断开了连接", True, WHITE)
    txtclosed_rect = txtclosed.get_rect()
    txtclosed_rect.left, txtclosed_rect.top = (game_bgsize[0] - txtclosed_rect.width) // 2, \
                                    (game_bgsize[1] - txtclosed_rect.height) // 2
    txtchallenge = myfont.render('对方再次向你发起挑战', True, WHITE)
    txtchallenge_rect = txtchallenge.get_rect()
    txtchallenge_rect.left, txtchallenge_rect.top = (game_bgsize[0] - txtchallenge_rect.width) // 2, \
                                    (game_bgsize[1] - txtchallenge_rect.height) // 2
    txtrecive = myfont.render('接受挑战         返回主菜单', True, WHITE)
    txtrecive_rect = txtrecive.get_rect()
    txtrecive_rect.left, txtrecive_rect.top = (game_bgsize[0] - txtrecive_rect.width) // 2, \
                                    (game_bgsize[1] - txtrecive_rect.height) // 2 + 100

    # 初始化
    init()

    while running:
       
        screen.blit(bg_image, (0, 0))

        # 绘制游戏菜单
        if not is_choise:
            screen.blit(zz_image, (0, 0))  #遮罩层
            screen.blit(txtplayerandplayer, txtplayerandplayer_rect)
            screen.blit(txtplayerandcomputer, txtplayerandcomputer_rect)
            if not is_play_sound:
                screen.blit(txtclosesound, txtclosesound_rect)
            else:
                screen.blit(txtplaysound, txtplaysound_rect)

        # 绘制棋盘
        if is_choise:
            if chesses:
                for i in chesses:
                    screen.blit(i.image, i.image_rect())

        for event in pygame.event.get():
            if event.type == QUIT:
                if people2people:
                    tcpclientsocket.close()
                pygame.quit()
                sys.exit()

            if event.type == MOUSEBUTTONDOWN:   #client下棋
                if event.button == 1: 
                    if is_finish : 
                        if not is_againmsg and not is_reject:
                            pos = event.pos
                            if successtext_rect.left < pos[0] < successtext_rect.right - 50 and \
                                    successtext_rect.top < pos[1] < successtext_rect.top + 30:
                                if people2people:
                                    tcpclientsocket.send('again'.encode('utf8'))
                                if people2computer:
                                    is_playagain = True
                                    is_player = True
                                    is_finish = False
                                    init()

                            if successtext_rect.left < pos[0] < successtext_rect.right - 50 and \
                                    successtext_rect.top + 50 < pos[1] < successtext_rect.top + 120:
                                people2people = False
                                if is_link:
                                    is_link = False
                                    tcpclientsocket.send('no'.encode('utf8'))
                                tcpclientsocket.close()
                                main()

                    if is_reject :
                        pos = event.pos
                        if txtclosed_rect.left + 150 < pos[0] < txtclosed_rect.left + 250 and \
                                txtclosed_rect.top + 70 < pos[1] < txtclosed_rect.top + 190:
                            main()

                    if is_againmsg :
                        pos = event.pos
                        if txtrecive_rect.left < pos[0] < txtrecive_rect.left + 150 and \
                                txtrecive_rect.top < pos[1] < txtrecive_rect.top + 120:
                            tcpclientsocket.send('yes'.encode('utf8'))
                            is_againmsg = False
                            is_playagain = True
                            is_player = True
                            is_finish = False
                            white_win = False
                            black_win = False
                        if txtrecive_rect.left + 330 < pos[0] < txtrecive_rect.left + 480 and \
                                txtrecive_rect.top < pos[1] < txtrecive_rect.top + 120:
                            tcpclientsocket.send('no'.encode('utf8'))
                            main()

                    if is_choise:
                        pos = event.pos
                        # 判断是否是client下棋时间
                        if is_player  and not is_finish and  not is_againmsg:
                            pwhite = piece.Piece(pos,'pieces_white.png') 
                            if not isempty(pwhite.pointtrans()):
                                white_chesses.append(pwhite)
                                white_positions.append(pwhite.pointtrans())
                                chesses.append(pwhite)
                                chess_map[str(pwhite.pointtrans()[0]) + ',' + str(pwhite.pointtrans()[1])] = 1
                                if people2people:
                                    tcpclientsocket.send(str(pos).encode('utf8'))
                                is_player = False
                                piece_sound.play()

                                if len(white_chesses)>=5 and not is_finish and checkwin(white_positions,pwhite.pointtrans()[0],pwhite.pointtrans()[1]) :
                                    is_finish = True
                                    white_win = True
                            else:
                                del (pwhite)
                    else:
                        pos = event.pos
                        if txtplayerandplayer_rect.left <= pos[0] <= txtplayerandplayer_rect.left + 170 and \
                                txtplayerandplayer_rect.top  <= pos[1] <= txtplayerandplayer_rect.top + 30:
                            is_choise = True
                            people2people = True
                            screenConnect()
                        if txtplayerandplayer_rect.left <= pos[0] <= txtplayerandplayer_rect.left + 170 and \
                                txtplayerandplayer_rect.top + 100 <= pos[1] <= txtplayerandplayer_rect.top + 130:
                            is_choise = True
                            people2computer = True
                        if txtplayerandplayer_rect.left <= pos[0] <= txtplayerandplayer_rect.left + 160 and \
                                txtplayerandplayer_rect.top + 200 <= pos[1] <= txtplayerandplayer_rect.top + 230:
                            is_play_sound = not is_play_sound
                            if not is_play_sound:
                                pygame.mixer.stop()
                                pygame.mixer.music.stop()
                            else:
                                pygame.mixer.music.play()

                    

        # 电脑落子
        if people2computer and not is_player:
            pblack = piece.Piece(computerdecision(),'pieces_black.png')
            black_chesses.append(pblack)
            black_positions.append(pblack.pointtrans())
            chesses.append(pblack)
            chess_map[str(pblack.pointtrans()[0]) + ',' + str(pblack.pointtrans()[1])] = 2
            is_player = True
            piece_sound.play()
            
            # 判断输赢
            if len(black_chesses)>=5 and not is_finish and checkwin(black_positions,pblack.pointtrans()[0],pblack.pointtrans()[1]) :
                is_finish = True
                black_win = True
        
        #网络消息,注释略,见gobang_server
        if people2people:
            readable, writable, exceptional = select.select(inputs, [], [], 0)
            for readline in readable:
                if readline is tcpclientsocket:
                    try:
                        data = readline.recv(BUFSIZE)
                        # print(data.decode('utf8'))
                        is_link = True
                        disconnected = not data
                        if data.decode('utf8') == 'again':
                            is_againmsg = True
                        if data.decode('utf8') == 'yes':
                            is_playagain = True
                            is_player = True
                        if data.decode('utf8') == 'no':
                            is_reject = True
                            is_link = False
                        if not is_player and not is_finish:
                            pblack = piece.Piece(eval(data),'pieces_black.png')
                            black_chesses.append(pblack)
                            black_positions.append(pblack.pointtrans())
                            chesses.append(pblack)
                            is_player = True
                    except error:
                        disconnected = True
                        is_link = False

            # 判断输赢
            if len(black_chesses)>=5 and not is_finish and checkwin(black_positions,pblack.pointtrans()[0],pblack.pointtrans()[1]) :
                is_finish = True
                black_win = True

        if black_win and is_finish and not is_againmsg and not is_reject:
            screen.blit(zz_image, (0, 0))  #遮罩层
            screen.blit(failuretext, (successtext_rect.left, successtext_rect.top - 80))
            screen.blit(playagaintext, successtext_rect)
            screen.blit(menutext, (successtext_rect.left, successtext_rect.top + 80))

        if white_win and is_finish and not is_againmsg and not is_reject:
            screen.blit(zz_image, (0, 0))  #遮罩层
            screen.blit(successtext, (successtext_rect.left, successtext_rect.top - 80))
            screen.blit(playagaintext, successtext_rect)
            screen.blit(menutext, (successtext_rect.left, successtext_rect.top + 80))

        if is_againmsg:
            screen.blit(txtchallenge, txtchallenge_rect)
            screen.blit(txtrecive, txtrecive_rect)

        if is_reject:
            screen.blit(txtclosed, txtclosed_rect)
            screen.blit(menutext, (txtclosed_rect.left + 150, txtclosed_rect.top + 70))

        if is_playagain:
            init()
            white_chesses.clear()
            black_chesses.clear()
            white_positions.clear()
            black_positions.clear()
            chesses.clear()
            is_finish = False
            black_win = False
            white_win = False
            is_playagain = False

        pygame.display.flip()

        clock.tick(60)


if __name__ == '__main__':
    main()

3.3 先执行server的main.py,再执行client端的main.py

执行效果如下:

20240708_142557

五子棋Socket人人对战源码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值