Python小游戏(附带详细注释)

import pygame
from pygame.locals import *
import graphics
import sys
import time
SIZE = 16   #多少条线
UNIT = 35
BORDER_WIDTH = 50 #边框宽度
C_WRITE = (255,255,255)#纯白
C_BLACK = (0,0,0)
screen = None
chess_map = []

his_stack = []#颜色,X,Y坐标,坐标从(0,0)开始


# 获取当前状态
# 0 ~ 未开局
# 1 ~ 等待黑棋落子
# 2 ~ 等待白棋落子
# 3 ~ 结束(一方获胜)
status = 2
winner = 0.
#游戏初始化
def game_init():
    pygame.init()
    global screen,chess_map,his_stack,sound_black,sound_white,sound_win,\
    sound_error

    #初始化二维map
    #0~无棋子,1~黑旗,-1~白旗
    chess_map = [[0 for y in range(0,SIZE)] for x in range(0,SIZE)]
    #设置背景显示格式,横是X,竖是Y
    screen = pygame.display.set_mode((2*BORDER_WIDTH+UNIT*(SIZE-1),
                                      2*BORDER_WIDTH+UNIT*(SIZE-1)))
    #设置标题
    pygame.display.set_caption("五子棋")
    sy_img = pygame.image.load('img.png')

         #(0,0)是对其的坐标
    screen.blit(sy_img,(0,0))

     # 设置标题
    pygame.display.set_caption("五子棋")
    sound_black = pygame.mixer.Sound('1.wav')
    sound_white = pygame.mixer.Sound('2.wav')
    sound_win = pygame.mixer.Sound('3.wav')
    sound_error = pygame.mixer.Sound('4.wav')
#绘制棋盘
def draw_map():
    #设置字体
    s_font= pygame.font.SysFont('arial',16)

    #行
    for row in range(SIZE):
         pygame.draw.line(screen,C_BLACK,
                          (BORDER_WIDTH,BORDER_WIDTH+UNIT*row),
                          (BORDER_WIDTH+UNIT*(SIZE-1),BORDER_WIDTH+UNIT*row))
         #设置字母下标,ord函数返回ASCII数值
         s_surface = s_font.render(chr(ord('A')+row),True,C_BLACK)
         screen.blit(s_surface,(BORDER_WIDTH+UNIT*row-4,BORDER_WIDTH-25))
    #列
    for col in range(SIZE):
         pygame.draw.line(screen,C_BLACK,
                          (BORDER_WIDTH+UNIT*col,BORDER_WIDTH),
                          (BORDER_WIDTH+UNIT*col,BORDER_WIDTH+UNIT*(SIZE-1)))
         s_surface = s_font.render(f'{col}', True, C_BLACK)
         screen.blit(s_surface, (BORDER_WIDTH-20, BORDER_WIDTH+UNIT*col-8))

# 判断输赢的算法: 只需要判断当前落子相关的四条直线(横、竖、左斜、右斜),是否形成5个连子。
# 将直线上的落子(~ 1,白~ -1),依次相加,连续的子绝对值之和达到5,即可判定为胜利
def __check_winner_():
        tmp = 0
        last_step = his_stack[-1]
        # 竖向直线, x 固定
        a=last_step[1]
        b=last_step[2]
        for y in range(0, SIZE):
            # 必须是连续的,last_step[1]为上一步的X坐标
            tmp = 0
            if abs(chess_map[a][y-1]) > 0:

              tmp += abs(chess_map[a][y-1])
            if  tmp >= 5:

                tmp = 0
                for x in range(0, SIZE):
                 # 必须是连续的,last_step[2]为上一步的Y坐标
                    if abs(chess_map[x-1][b]) > 0:

                        tmp += abs(chess_map[x-1][b])
                    if abs(tmp) >= 5:
                        return last_step[0]



        # # 横向直线, y 固定
        # tmp = 0
        # for x in range(0, SIZE):
        #     # 必须是连续的,last_step[2]为上一步的Y坐标
        #     if x > 0 \
        #             and chess_map[x][b] != chess_map[x - 1][b]:
        #         tmp = 0
        #     tmp += chess_map[x][b]
        #     if abs(tmp) >= 5:
        #         return last_step[0]

        # 右斜直线,计算出左上角顶点的坐标。然后x,y都递增,到达最右下角顶点。
        tmp = 0
        min_dist = min(last_step[1], last_step[2])
        top_point = [last_step[1] - min_dist, last_step[2] - min_dist]
        for incr in range(0, SIZE):
            # 不能超出棋盘边界
            if top_point[0] + incr > SIZE - 1 \
                    or top_point[1] + incr > SIZE - 1:
                break
            # 必须是连续的
            if incr > 0 \
                    and chess_map[top_point[0] + incr][top_point[1] + incr] \
                    != chess_map[top_point[0] + incr - 1][top_point[1] + incr - 1]:
                tmp = 0
            tmp += chess_map[top_point[0] + incr][top_point[1] + incr]
            if abs(tmp) >= 5:
                return last_step[0]

        # 左斜直线,计算出右上角顶点的坐标。然后x递减、y递增,到达最左下角顶点。
        tmp = 0
        min_dist = min(SIZE - 1 - last_step[1], last_step[2])
        top_point = [last_step[1] + min_dist, last_step[2] - min_dist]
        for incr in range(0, SIZE):
            # 不能超出棋盘边界
            if top_point[0] - incr < 0 \
                    or top_point[1] + incr > SIZE - 1:
                break
            # 必须是连续的
            if incr > 0 \
                    and chess_map[top_point[0] - incr][top_point[1] + incr] \
                    != chess_map[top_point[0] - incr + 1][top_point[1] + incr - 1]:
                tmp = 0
            tmp += chess_map[top_point[0] - incr][top_point[1] + incr]
            if abs(tmp) >= 5:
                return last_step[0]

        return 0

#判断·是否结束
def __check_end():
        # global  winner
        # # 赢了,winner记录谁赢了
        winner = __check_winner_()

        if winner != 0:
            return 1
        # 未结束
        return 0
def move(pos):
    #X,Y不能越界
    global status
    if pos[0]<BORDER_WIDTH or pos[0]>BORDER_WIDTH+UNIT*(SIZE-1)\
            or pos[1]<BORDER_WIDTH or pos[1]>BORDER_WIDTH+UNIT*(SIZE-1):
        sound_error.play()
        return
    x = round((pos[0] - BORDER_WIDTH)/UNIT)
    y = round((pos[1] - BORDER_WIDTH) / UNIT)
    #已经有棋子
    if chess_map[x][y]!= 0:
        return
    #加音效
    if status == 1:
       sound_black.play()
    else:
        sound_white.play()

    t = 1 if status == 1 else -1
    his_stack.append([t,x,y])
    #表示这个位置新加了棋子
    chess_map[x][y] = t

    status = 2 if status == 1 else 1
    pygame.draw.circle(screen, t,
                       (BORDER_WIDTH + UNIT * x, BORDER_WIDTH + UNIT * y),
                       int(UNIT / 2.5))
    pygame.display.flip()
    if __check_end() == 1:
        sound_win.play()
        time.sleep(3)
        sys.exit()
#游戏运行
def game_run():
    while True:
        for event in pygame.event.get():   #监听用户事件
            if event.type == pygame.QUIT:   # 判断用户是否点击了关闭按钮
                exit()
            if event.type == MOUSEBUTTONUP:
                move(event.pos)
        # 刷新画面
        pygame.display.flip()
if __name__== '__main__':
    game_init()
    draw_map()
    game_run()

  • 3
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小王子y

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值