繁体   English   中英

如何修复我的 Python 3.6 战舰代码?

[英]How to fix my Python 3.6 battleship code?

基本上,当我单击鼠标左键并且单元格的坐标匹配时,我想将参数 self.shot 永远更改为 True(它检查一个单元格之前是否被拍摄过,如果一个单元格被拍摄过,它会绘制一个点或一个尖角)。 问题是该参数仅在按下鼠标按钮时更改,并在按钮向上时更改回其标准值。 在这一点上,我真的不知道如何重建这段代码才能正常工作。

这是代码:

import pygame, random, time, math

pygame.init()

clock = pygame.time.Clock()

yours = 0
enemys = 1
exitPossible = False
gameStart = False
tour = random.randint(yours,enemys)

white = (255, 255, 255)
black = (0, 0, 0)
red = (255, 0, 0)

one = 32
two = 63
three = 94
four = 125
five = 156
six = 187
seven = 218
eight = 249
nine = 280
ten = 301

a = 32
b = 63
c = 94
d = 125
e = 156
f = 187
g = 218
h = 249
i = 280
j = 311

#lista

m = 0
n = 0
o = 0
p = 0
playerWins = 10
botWins = 0


window = pygame.display.set_mode((760, 410))
pygame.display.set_caption("Battleship")
font = pygame.font.SysFont("Arial", 30)

class crate:

    def __init__(self, sizex, sizey, shot, shiphere):

        self.sizex, self.sizey = sizex, sizey
        self.shot = shot
        self.shiphere = shiphere




    def crateShot(self):

        if not exitPossible:
            if not self.shot:
                if event.type == pygame.MOUSEBUTTONDOWN and self.sizex + 30 > mx > self.sizex and self.sizey + 30 > my > self.sizey:
                    self.shot = True


            if self.shot:
                if self.shiphere:
                    pygame.draw.line(window, white, (self.sizex, self.sizey), (self.sizex + 30, self.sizey + 30), 3)
                    pygame.draw.line(window, white, (self.sizex + 29, self.sizey), (self.sizex, self.sizey + 29), 3)
                else:
                    pygame.draw.circle(window, white, (self.sizex + 15, self.sizey + 15), 6, 5)




allCrates = ()

def crates(allCrates):
    a1 = crate(a, a, True, False)
    a1.crateShot()


    a2 = crate(b, a, True, True)
    a2.crateShot()


    a3 = crate(c, a, False, False)
    a3.crateShot()


    a4 = crate(d, a, False, True)
    a4.crateShot()



#slownik how to
ololollololol = {
    "" : 123
}

class ship:
    def __init__(self, size, amount):
        self.size = size
        self.amount = amount

    #def drawShip(self):


def ships():
    carrier = ship(4, 1)
    battleship = ship(3, 2)
    cruiser = ship(2, 3)
    destroyer = ship(1, 4)


def playerWindow(m, n):
    if not exitPossible:
        window.fill(black)
        for i in range(11):
            pygame.draw.line(window, white, (31 + m, 0), (31 + m, 341))
            m += 31
        for i in range(11):
            pygame.draw.line(window, white, (0, 31 + n), (341, 31 + n))
            n += 31


        a = font.render("A", True, white)
        window.blit(a, (4, 30))

        b = font.render("B", True, white)
        window.blit(b, (5, 61))

        c = font.render("C", True, white)
        window.blit(c, (4, 92))

        d = font.render("D", True, white)
        window.blit(d, (4, 123))

        e = font.render("E", True, white)
        window.blit(e, (5, 154))

        f = font.render("F", True, white)
        window.blit(f, (6, 185))

        g = font.render("G", False, white)
        window.blit(g, (3, 216))

        h = font.render("H", True, white)
        window.blit(h, (4, 247))

        i = font.render("I", True, white)
        window.blit(i, (12, 278))

        j = font.render("J", True, white)
        window.blit(j, (7, 309))

        a = font.render("1", True, white)
        window.blit(a, (39, -2))

        b = font.render("2", True, white)
        window.blit(b, (70, -2))

        c = font.render("3", True, white)
        window.blit(c, (101, -2))

        d = font.render("4", True, white)
        window.blit(d, (132, -2))

        e = font.render("5", True, white)
        window.blit(e, (163, -2))

        f = font.render("6", True, white)
        window.blit(f, (194, -2))

        g = font.render("7", True, white)
        window.blit(g, (225, -2))

        h = font.render("8", True, white)
        window.blit(h, (256, -2))

        i = font.render("9", True, white)
        window.blit(i, (287, -2))

        j = font.render("10", True, white)
        window.blit(j, (308, -2))


def botWindow(o, p):
    if not exitPossible:
        for i in range(11):
            pygame.draw.line(window, white, (419 + o, 0), (419 + o, 341))
            o += 31
        for i in range(11):
            pygame.draw.line(window, white, (419, 31 + p), (760, 31 + p))
            p += 31


        a = font.render("A", True, white)
        window.blit(a, (425, 30))

        b = font.render("B", True, white)
        window.blit(b, (425, 61))

        c = font.render("C", True, white)
        window.blit(c, (424, 92))

        d = font.render("D", True, white)
        window.blit(d, (424, 123))

        e = font.render("E", True, white)
        window.blit(e, (425, 154))

        f = font.render("F", True, white)
        window.blit(f, (426, 185))

        g = font.render("G", True, white)
        window.blit(g, (423, 216))

        h = font.render("H", True, white)
        window.blit(h, (424, 247))

        i = font.render("I", True, white)
        window.blit(i, (432, 278))

        j = font.render("J", True, white)
        window.blit(j, (427, 309))

        a = font.render("1", True, white)
        window.blit(a, (458, -2))

        b = font.render("2", True, white)
        window.blit(b, (489, -2))

        c = font.render("3", True, white)
        window.blit(c, (520, -2))

        d = font.render("4", True, white)
        window.blit(d, (551, -2))

        e = font.render("5", True, white)
        window.blit(e, (582, -2))

        f = font.render("6", True, white)
        window.blit(f, (613, -2))

        g = font.render("7", True, white)
        window.blit(g, (644, -2))

        h = font.render("8", True, white)
        window.blit(h, (675, -2))

        i = font.render("9", True, white)
        window.blit(i, (706, -2))

        j = font.render("10", True, white)
        window.blit(j, (727, -2))


def gameWindow(playerWins, botWins):
    if not exitPossible:
        score = font.render("SCORE:", True, white)
        window.blit(score, (325, 345))
        wins = font.render(str(playerWins) + " - " + str(botWins), True, white)
        window.blit(wins, (325, 375))
        auto = font.render("AUTO", True, white)
        window.blit(auto, (13, 359))
        pygame.draw.rect(window, white, (10, 361, 89, 30), 1)


while True:
    mx, my = pygame.mouse.get_pos()
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            quit()



        if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
            exitPossible = True

    if exitPossible:
        window.fill(black)
        uSure = font.render("ARE YOU SURE YOU WANT TO EXIT?", True, white)
        window.blit(uSure, (115, 145))
        YES = font.render("YES", True, white)
        window.blit(YES, (335, 195))
        NO = font.render("NO", True, white)
        window.blit(NO, (342, 230))

        if event.type == pygame.MOUSEBUTTONDOWN:
            if 390 >= mx >= 335 and 223 >= my >= 200:
                quit()
            elif 387 >= mx >= 342 and 256 >= my >= 235:
                exitPossible = False
                window.fill(black)


    playerWindow(m, n)
    botWindow(o, p)
    gameWindow(playerWins, botWins)
    crates(allCrates)
    pygame.display.flip()
    clock.tick(60)

目前代码需要一个新特性:

检测鼠标点击,确定它发生在哪个单元格“板条箱”(如果有)

然而,所有现有代码都使用一种“蛮力”方法,使用大量单个变量作为位置。 这使得如果不做 100 次就很难检查所有位置,每个箱子一次。

我认为,如果稍微更改一下以使用玩家网格的矩形列表,代码的向前推进会更容易。 请考虑代码:

# Create the click-grid for the player
GRID_SIZE   = 31
player_grid = []
for y_cell in [ a,b,c,d,e,f,g,h,i,j ]:
    for x_cell in [ one, two, three, four, five, six, seven, eight, nine, ten ]:
        player_grid.append( [ x_cell, y_cell, GRID_SIZE, GRID_SIZE ] )

这个操作之后我们得到的是一个python 列表列表,所以player_grid[0][ one, a, 31, 31 ] ,然后是[ two, a, 31, 31 ]等。 player_grid列表中的所有元素只是 position 和大小的记录,并不复杂。 go 的所有这些麻烦制作列表的原因是因为它允许代码简单地循环检查它们内部的所有矩形。

在示例中,我使用了代码现有abc , ...变量,因为它们已经在问题的代码中定义。 但这很容易是range( 0, 10 )和一些窗口大小的因素。

所以现在在player_grid我们有 100 个矩形。 如果我们可以用同样的方式制作一个crate object,让这个crate “知道”它的 position,那会更好。 这允许板条箱 object(给定 x,y)告诉我们它是否被点击。 因此,让我们对crate做一些小的修改 - 将__init__()更改为采用xy ,并将PyGame Rect作为成员变量存储:

class crate:
    def __init__(self, x, y, sizex, sizey, shot, shiphere):
        self.x        = x
        self.y        = y
        self.sizex    = sizex
        self.sizey    = sizey
        self.rect     = pygame.Rect( x, y, sizex, sizey )
        self.shot     = shot
        self.shiphere = shiphere

现在,在类似于之前的循环中创建一个crate列表:

# Create the click-grid for the player
GRID_SIZE   = 31
all_crates  = []
for y_cell in [ a,b,c,d,e,f,g,h,i,j ]:
    for x_cell in [ one, two, three, four, five, six, seven, eight, nine, ten ]:
        all_crates.append( crate( x_cell, y_cell, GRID_SIZE, GRID_SIZE, False, False ) )

在这个操作之后,我们得到的是一个pythoncrate对象列表,每个对象都包含一个PyGame Rect 这种意义上的 Rect 只是一个 position 和大小,它并不太复杂。 但它确实允许一些更容易的检查,因为在 PyGame Rect 中有一堆方便的碰撞函数

回到问题——用户点击了屏幕,我们需要看看它是否在 100 个crate之一中。 现在每个板条箱都知道它是矩形 position,很容易遍历它们,依次检查:

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            quit()
        elif event.type == pygame.MOUSEBUTTONUP:  # User released mouse button
            mx, my = pygame.mouse.get_pos()       # Position of the click

            # Loop through all crate objects, seeing if any where clicked
            for c in all_crates:
                if c.rect.collidepoint( mx, my ) == True:
                    # User clicked inside a crate
                    c.crateShot( mx, my )         # Test for hit
                    break                         # No further checks needed

就个人而言,我会在crate中创建一个成员 function ,并使用它而不是直接从 object 外部引用crate.rect

def wasClicked( self, mouse_x, mouse_y ):
    return self.rect.collidepoint( mouse_x, mouse_y )

虽然在这种情况下微不足道,但它允许将任何未来的额外处理和检查添加到crate object 中,而不是“污染”主循环的简单性。

注意:我尝试尽可能少地更改代码,同时保留样式和现有代码。 但是我认为重写屏幕网格逻辑以使用 window 大小的因子并动态构建网格而不是手动调整坐标列表是一个很好的学习练习。 尽管最初需要更多的努力,但像绘制网格字母标题列表这样的事情可能会变成一个简单的 5 行循环。

例如,类似:

WINDOW_WIDTH  = 1000
WINDOW_HEIGHT = 500
CELL_COUNT    = 10
GRID_SIZE     = WINDOW_HEIGHT // (CELL_COUNT * 0.7)  # cells cover 70% of the window-height
GRID_OFFSET   = GRID_SIZE * 2                        # Leave room for headings, etc.

# Define the player grid
player_grid = []
for y in range( 0, CELL_COUNT ):
    for x in range( 0, CELL_COUNT ):
        pos_x = x + GRID_OFFSET  # move the grid away from the edge
        pos_y = y + GRID_OFFSET 
        player_grid.append( pygame.Rect( pos_x, pos_y, GRID_SIZE, GRID_SIZE ) )

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM