我试图在游戏中实现一个简单的Gomoku游戏(连接5),并希望得到一些帮助。到目前为止,基本的功能是很好的工作与2名球员之间的对立。
import numpy as np
import pygame
import sys
import math
# initialize the pygame program
pygame.init()
# static variables
ROW_COUNT = 15
COL_COUNT = 15
# define screen size
BLOCKSIZE = 50 # individual grid
S_WIDTH = COL_COUNT * BLOCKSIZE # screen width
S_HEIGHT = ROW_COUNT * BLOCKSIZE # screen height
PADDING_RIGHT = 200 # for game menu
SCREENSIZE = (S_WIDTH + PADDING_RIGHT,S_HEIGHT)
RADIUS = 20 # game piece radius
# colors
BLACK = (0,0,0)
WHITE = (255,255,255)
BROWN = (205,128,0)
# create a board array
def create_board(row, col):
board = np.zeros((row,col))
return board
# draw a board in pygame window
def draw_board(screen):
for x in range(0,S_WIDTH,BLOCKSIZE):
for y in range(0,S_HEIGHT,BLOCKSIZE):
rect = pygame.Rect(x, y, BLOCKSIZE, BLOCKSIZE)
pygame.draw.rect(screen,BROWN,rect)
# draw inner grid lines
# draw vertical lines
for x in range(BLOCKSIZE // 2, S_WIDTH - BLOCKSIZE // 2 + BLOCKSIZE, BLOCKSIZE):
line_start = (x, BLOCKSIZE // 2)
line_end = (x,S_HEIGHT-BLOCKSIZE // 2)
pygame.draw.line(screen, BLACK, line_start,line_end,2)
# draw horizontal lines
for y in range(BLOCKSIZE // 2, S_HEIGHT - BLOCKSIZE // 2 + BLOCKSIZE, BLOCKSIZE):
line_start = (BLOCKSIZE // 2,y)
line_end = (S_WIDTH-BLOCKSIZE // 2,y)
pygame.draw.line(screen, BLACK, line_start,line_end,2)
pygame.display.update()
# drop a piece
def drop_piece(board, row, col, piece):
board[row][col] = piece
# draw a piece on board
def draw_piece(screen,board):
# draw game pieces at mouse location
for x in range(COL_COUNT):
for y in range(ROW_COUNT):
circle_pos = (x * BLOCKSIZE + BLOCKSIZE//2, y * BLOCKSIZE + BLOCKSIZE//2)
if board[y][x] == 1:
pygame.draw.circle(screen, BLACK, circle_pos, RADIUS)
elif board[y][x] == 2:
pygame.draw.circle(screen, WHITE, circle_pos, RADIUS)
pygame.display.update()
# check if it is a valid location
def is_valid_loc(board, row, col):
return board[row][col] == 0
# victory decision
def who_wins(board, piece):
# check for horizontal win
for c in range(COL_COUNT - 4):
for r in range(ROW_COUNT):
if board[r][c] == piece and board[r][c+1] == piece and board[r][c+2] == piece and board[r][c+3] == piece\
and board[r][c+4] == piece:
return True
# check for vertical win
for c in range(COL_COUNT):
for r in range(ROW_COUNT-4):
if board[r][c] == piece and board[r+1][c] == piece and board[r+2][c] == piece and board[r+3][c] == piece\
and board[r+4][c] == piece:
return True
# check for positively sloped diagonal wih
for c in range(COL_COUNT-4):
for r in range(4,ROW_COUNT):
if board[r][c] == piece and board[r-1][c+1] == piece and board[r-2][c+2] == piece and board[r-3][c+3] == piece\
and board[r-4][c+4] == piece:
return True
# check for negatively sloped diagonal win
for c in range(COL_COUNT-4):
for r in range(ROW_COUNT-4):
if board[r][c] == piece and board[r+1][c+1] == piece and board[r+2][c+2] == piece and board[r+3][c+3] == piece\
and board[r+4][c+4] == piece:
return True
def main():
# game variables
game_over = False
turn = 0 # turn == 0 for player 1, turn == 1 for player 2
piece_1 = 1 # black
piece_2 = 2 # white
# FPS
FPS = 60
frames_per_sec = pygame.time.Clock()
# board 2D array
board = create_board(ROW_COUNT,COL_COUNT)
print(board)
# game screen
SCREEN = pygame.display.set_mode(SCREENSIZE)
SCREEN.fill(WHITE)
pygame.display.set_caption('Gomoku (Connet 5)')
# icon = pygame.image.load('icon.png')
# pygame.display.set_icon(icon)
# font
my_font = pygame.font.Font('freesansbold.ttf', 32)
# text message
label_1 = my_font.render('Black wins!', True, WHITE, BLACK)
label_2 = my_font.render('White wins!', True, WHITE, BLACK)
# display the screen
draw_board(SCREEN)
# game loop
while not game_over:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.MOUSEBUTTONDOWN:
x_pos = event.pos[0]
y_pos = event.pos[1]
col = int(math.floor(x_pos / BLOCKSIZE))
row = int(math.floor(y_pos / BLOCKSIZE))
# turn decision, if black(1)/white(2) piece already placed, go back to the previous turn
if board[row][col] == 1:
turn = 0
if board[row][col] == 2:
turn = 1
# Ask for Player 1 move
if turn == 0:
# check if its a valid location then drop a piece
if is_valid_loc(board, row, col):
drop_piece(board, row, col, piece_1)
draw_piece(SCREEN,board)
if who_wins(board,piece_1):
print('Black wins!')
SCREEN.blit(label_1, (280,50))
pygame.display.update()
game_over = True
# Ask for Player 2 move
else:
# check if its a valid location then drop a piece
if is_valid_loc(board, row, col):
drop_piece(board, row, col, piece_2)
draw_piece(SCREEN,board)
if who_wins(board,piece_2):
print('White wins!')
SCREEN.blit(label_2, (280,50))
pygame.display.update()
game_over = True
print(board)
# increment turn
turn += 1
turn = turn % 2
if game_over:
pygame.time.wait(4000)
frames_per_sec.tick(FPS)
if __name__ == '__main__':
main()游戏截图:


比赛似乎进行得很好。我将一些代码移到main()中,以便为下一步创建一个重新启动功能。
另外,我还想创建一些附加特性:
undo()函数删除的部分
任何批评/帮助都是非常欢迎的!
发布于 2021-07-11 13:07:21
当您使用代码检查胜利时,我可以提出一个小小的改进:
if board[r][c] == piece and board[r][c+1] == piece and board[r][c+2] == piece and board[r][c+3] == piece\
and board[r][c+4] == piece:您正在检查所有指定的位置是否等于piece,因此您可以编写一个助手:
def all_equal(xs, y):
return all(x == y for x in xs)并重复使用此函数进行各种检查,减少这种逻辑概念的重复,并使代码更加简洁和可读性更强。
另一种减少重复的方法是在这个代码块中:
if turn == 0:
# check if its a valid location then drop a piece
if is_valid_loc(board, row, col):
drop_piece(board, row, col, piece_1)
draw_piece(SCREEN,board)
if who_wins(board,piece_1):
print('Black wins!')
SCREEN.blit(label_1, (280,50))
pygame.display.update()
game_over = True
# Ask for Player 2 move
else:
# check if its a valid location then drop a piece
if is_valid_loc(board, row, col):
drop_piece(board, row, col, piece_2)
draw_piece(SCREEN,board)
if who_wins(board,piece_2):
print('White wins!')
SCREEN.blit(label_2, (280,50))
pygame.display.update()
game_over = True你可以
if turn == 0:
piece = piece_1
name = "Black"
label = label_1
else:
piece = piece_2
name = "White"
label = label_2然后:
if is_valid_loc(board, row, col):
drop_piece(board, row, col, piece)
draw_piece(SCREEN,board)
if who_wins(board,piece):
print(name + ' wins!')
SCREEN.blit(label, (280,50))
pygame.display.update()
game_over = True这就清楚地表明,玩家被用相同的程序逻辑处理,并且只有一些变量在处理两个播放器的轮转之间发生变化。
从总体上看,代码看起来非常干净,一开始就很好地划分了关注点和清晰的常量。
发布于 2021-07-11 23:45:08
为了检查玩家是否赢了,你不需要每次都扫描整个棋盘。只对刚刚放置在所有方向(水平,垂直,正斜面对角线和负斜面对角线)的部分进行扫描就足够了。
下面是这个想法的一个示例实现:
from enum import Enum, auto
class Direction(Enum):
N = auto()
NE = auto()
E = auto()
SE = auto()
S = auto()
SW = auto()
W = auto()
NW = auto()
@property
def vector(self):
return {
Direction.N: (-1, 0),
Direction.NE: (-1, 1),
Direction.E: (0, 1),
Direction.SE: (1, 1),
Direction.S: (1, 0),
Direction.SW: (1, -1),
Direction.W: (0, -1),
Direction.NW: (-1, -1),
}[self]
def count(board, row, col, direction):
"""
Return the number of consecutive pieces matching the starting piece's
color, starting from (but not including) the starting piece, and going
in the given direction.
row: starting piece's row
col: starting piece's column
"""
def on_board(row, col):
return 0 <= row < ROW_COUNT and 0 <= col < COL_COUNT
piece_color = board[row][col]
row_delta, col_delta = direction.vector
count = 0
row, col = row + row_delta, col + col_delta
while on_board(row, col) and board[row][col] == piece_color:
count += 1
row, col = row + row_delta, col + col_delta
return count
def is_win(board, row, col):
"""
Returns True if the piece played on (row, col) wins the game.
"""
def is_win_helper(board, row, col, d1, d2):
return count(board, row, col, d1) + 1 + count(board, row, col, d2) >= 5
return (
# horizontal win
is_win_helper(board, row, col, Direction.W, Direction.E)
# vertical win
or is_win_helper(board, row, col, Direction.N, Direction.S)
# positively sloped diagonal win
or is_win_helper(board, row, col, Direction.SW, Direction.NE)
# negatively sloped diagonal win
or is_win_helper(board, row, col, Direction.NW, Direction.SE)
)然后,您可以通过以下操作检查刚才在(row, col)打球的球员是否赢了:
if is_win(board, row, col):
# ...https://codereview.stackexchange.com/questions/263936
复制相似问题