2013-10-30 4 views
0

지금 코드는 왼쪽 위부터 시작하여 행과 열을 왼쪽에서 오른쪽, 행별로 채 웁니다. 현재, 선택할 수있는 이미지가 많이 있습니다. 셰이프와 레어 스타일 사이에서 선택하는 IF 문을 사용하여 설정됩니다. 내가하는 방법을 알아 내려고 애 쓰고있는 것은 코드를 변경하여 무작위 래쉬 스타일을 선택하는 대신 래 레이스 모양이 무엇인지 결정할 수 있습니다. 아직 파이썬에 익숙하지 않고 다른 언어에서 나에게 의미가있는 많은 작은 것들을 발견하는 것은 파이썬에서 작동하지 않으므로 조금 벗어나게됩니다.목록에 특정 요소 표시

편집 :

여기에 전체 코드가 나와 있습니다. cactusbin이 작성하고 Gareth Rees가 개정 한 기본 코드에 대한 크레딧.

import pygame, random, time, sys 
from pygame.locals import * 
import itertools 
import os 

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

SHAPE_WIDTH = 64    # Width of each shape (pixels). 
SHAPE_HEIGHT = 64    # Height of each shape (pixels). 
PUZZLE_COLUMNS = 10    # Number of columns on the board. 
PUZZLE_ROWS = 11    # Number of rows on the board. 
MARGIN = 118      # Margin around the board (pixels). 
WINDOW_WIDTH = PUZZLE_COLUMNS * SHAPE_WIDTH + 2 * MARGIN + 485 
WINDOW_HEIGHT = PUZZLE_ROWS * SHAPE_HEIGHT + 2 * MARGIN - 150 
FONT_SIZE = 60 
TEXT_OFFSET = MARGIN + 950 

# Map from number of matches to points scored. 
MINIMUM_MATCH = 10 
EXTRA_LENGTH_POINTS = .1 
RANDOM_POINTS = .3 
DELAY_PENALTY_SECONDS = 1 
DELAY_PENALTY_POINTS = 0 

FPS = 30 
EXPLOSION_SPEED = 15   # In frames per second. 
SPIN_SPEED = 15 
REFILL_SPEED = 10    # In cells per second. 

VERTICAL = False 

class Cell(object): 
""" 
A cell on the board, with properties: 
`image` -- a `Surface` object containing the sprite to draw here. 
`offset` -- vertical offset in pixels for drawing this cell. 
""" 
def __init__(self, image): 
    self.offset = 0.0 
    self.image = image 

def tick(self, dt): 
    self.offset = max(0.0, self.offset - dt * REFILL_SPEED) 

class Board(object): 
""" 
A rectangular board of cells, with properties: 
`w` -- width in cells. 
`h` -- height in cells. 
`size` -- total number of cells. 
`board` -- list of cells. 
`matches` -- list of matches, each being a list of exploding cells. 
`refill` -- list of cells that are moving up to refill the board. 
`score` -- score due to chain reactions. 
""" 
def __init__(self, width, height): 
    self.explosion = [pygame.image.load('images/explosion{}.png'.format(i)) 
         for i in range(1, 7)] 
    self.spin = [pygame.image.load('images/powerframe{}.png'.format(i)) 
        for i in range (1, 12)] 
    self.image_color = {} 
    self.shapes = [] 
    self.rareshapes = [] 

    colors = 'red blue yellow' 
    letters = 'acgtu' 

    for c in colors.split(): 
     im = pygame.image.load('images/{}.png'.format(c)) 
     self.shapes.append(im) 
     self.image_color[im] = c 
     for l in letters: 
      im = pygame.image.load('rareimages/{}{}.png'.format(c, l)) 
      self.rareshapes.append(im) 
      self.image_color[im] = l 

    self.background = pygame.image.load("images/bg.png") 
    self.blank = pygame.image.load("images/blank.png") 
    self.x = pygame.image.load("images/x.png") 
    self.w = width 
    self.h = height 
    self.size = width * height 
    self.board = [Cell(self.blank) for _ in range(self.size)] 
    self.matches = [] 
    self.refill = [] 
    self.score = 0.0 
    self.spin_time = 15 


def randomize(self): 
    """ 
    Replace the entire board with fresh shapes. 
    """ 
    rare_shapes = [1, 9, 23, 27, 40, 42, 50, 56, 70, 81, 90] 

    for i in range(self.size): 
     if i in rare_shapes: 
      self.board[i] = Cell(random.choice(self.rareshapes)) 
     else: 
      self.board[i] = Cell(random.choice(self.shapes)) 

def pos(self, i, j): 
    """ 
    Return the index of the cell at position (i, j). 
    """ 
    assert(0 <= i < self.w) 
    assert(0 <= j < self.h) 
    return j * self.w + i 

def busy(self): 
    """ 
    Return `True` if the board is busy animating an explosion or a 
    refill and so no further swaps should be permitted. 
    """ 
    return self.refill or self.matches 

def tick(self, dt): 
    """ 
    Advance the board by `dt` seconds: move rising blocks (if 
    any); otherwise animate explosions for the matches (if any); 
    otherwise check for matches. 
    """ 
    if self.refill: 
     for c in self.refill: 
      c.tick(dt) 
     self.refill = [c for c in self.refill if c.offset > 0] 
     if self.refill: 
      return 
    elif self.matches: 
     self.explosion_time += dt 
     f = int(self.explosion_time * EXPLOSION_SPEED) 
     if f < len(self.explosion): 
      self.update_matches(self.explosion[f]) 
      return 
     self.update_matches(self.blank) 
     self.refill = list(self.refill_columns()) 
    self.explosion_time = 0 
    self.matches = self.find_matches() 

def draw(self, display): 
    """ 
    Draw the board on the pygame surface `display`. 
    """ 
    display.blit(self.background, (0, 0)) 
    for i, c in enumerate(self.board): 
     display.blit(c.image, 
        (MARGIN + SHAPE_WIDTH * (i % self.w), 
         MARGIN + SHAPE_HEIGHT * (i // self.w - c.offset) - 68)) 
    display.blit(self.x, (995, 735)) 
    display.blit(self.x, (1112, 735)) 
    display.blit(self.x, (1228, 735)) 

def swap(self, cursor): 
    """ 
    Swap the two board cells covered by `cursor` and update the 
    matches. 
    """ 
    i = self.pos(*cursor) 
    b = self.board 
    b[i], b[i+1] = b[i+1], b[i] 
    self.matches = self.find_matches() 


def find_matches(self): 
    """ 
    Search for matches (lines of cells with identical images) and 
    return a list of them, each match being represented as a list 
    of board positions. 
    """ 
    def lines(): 
     for j in range(self.h): 
      yield range(j * self.w, (j + 1) * self.w) 
     for i in range(self.w): 
      yield range(i, self.size, self.w) 
    def key(i): 
     return self.image_color.get(self.board[i].image) 
    def matches(): 
     for line in lines(): 
      for _, group in itertools.groupby(line, key): 
       match = list(group) 
       if len(match) >= MINIMUM_MATCH: 
        yield match 
        self.score = self.score + 1 
    return list(matches()) 

def update_matches(self, image): 
    """ 
    Replace all the cells in any of the matches with `image`. 
    """ 
    for match in self.matches: 
     for position in match: 
      self.board[position].image = image 

def refill_columns(self): 
    """ 
    Move cells downwards in columns to fill blank cells, and 
    create new cells as necessary so that each column is full. Set 
    appropriate offsets for the cells to animate into place. 
    """ 
    for i in range(self.w): 
     target = self.size - i - 1 
     for pos in range(target, -1, -self.w): 
      if self.board[pos].image != self.blank: 
       c = self.board[target] 
       c.image = self.board[pos].image 
       c.offset = (target - pos) // self.w 
       target -= self.w 
       yield c 
     offset = 1 + (target - pos) // self.w 
     for pos in range(target, -1, -self.w): 
      c = self.board[pos] 
      c.image = random.choice(self.shapes) 
      c.offset = offset 
      yield c 

class Game(object): 
""" 
The state of the game, with properties: 
`clock` -- the pygame clock. 
`display` -- the window to draw into. 
`font` -- a font for drawing the score. 
`board` -- the board of cells. 
`cursor` -- the current position of the (left half of) the cursor. 
`score` -- the player's score. 
`last_swap_ticks` -- 
`swap_time` -- time since last swap (in seconds). 
""" 
def __init__(self): 
    pygame.init() 
    pygame.display.set_caption("Nucleotide") 
    self.clock = pygame.time.Clock() 
    self.display = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT), 
              DOUBLEBUF) 
    self.board = Board(PUZZLE_COLUMNS, PUZZLE_ROWS) 
    self.font = pygame.font.Font(None, FONT_SIZE) 

def start(self): 
    """ 
    Start a new game with a random board. 
    """ 
    self.board.randomize() 
    self.cursor = [0, 0] 
    self.score = 0.0 
    self.swap_time = 125 

def quit(self): 
    """ 
    Quit the game and exit the program. 
    """ 
    pygame.quit() 
    sys.exit() 

def play(self): 
    """ 
    Play a game: repeatedly tick, draw and respond to input until 
    the QUIT event is received. 
    """ 
    self.start() 
    while True: 
     self.draw() 
     dt = min(self.clock.tick(FPS)/1000, 1/FPS) 
     self.swap_time -= dt 
     for event in pygame.event.get(): 
      if event.type == KEYUP: 
       self.input(event.key) 
      elif event.type == QUIT: 
       self.quit() 
      elif self.swap_time == 0: 
       self.quit() 
     self.board.tick(dt) 

def input(self, key): 
    """ 
    Respond to the player pressing `key`. 
    """ 
    if key == K_q: 
     self.quit() 
    elif key == K_RIGHT and self.cursor[0] < self.board.w - 2: 
     self.cursor[0] += 1 
    elif key == K_LEFT and self.cursor[0] > 0: 
     self.cursor[0] -= 1 
    elif key == K_DOWN and self.cursor[1] < self.board.h - 1: 
     self.cursor[1] += 1 
    elif key == K_UP and self.cursor[1] > 0: 
     self.cursor[1] -= 1 
    elif key == K_SPACE and not self.board.busy(): 
     self.swap() 

def swap(self): 
    """ 
    Swap the two cells under the cursor and update the player's score. 
    """ 
    self.board.swap(self.cursor) 

def draw(self): 
    self.board.draw(self.display) 
    self.draw_score() 
    self.draw_time() 
    if VERTICAL == False: 
     self.draw_cursor() 
    elif VERTICAL == True: 
     self.draw_cursor2() 
    pygame.display.update() 

def draw_time(self): 
    s = int(self.swap_time) 
    text = self.font.render(str(int(s/60)) + ":" + str(s%60).zfill(2), 
          True, BLACK) 
    self.display.blit(text, (TEXT_OFFSET, WINDOW_HEIGHT - 170)) 

def draw_score(self): 
    total_score = self.score 

def draw_cursor(self): 
    topLeft = (MARGIN + self.cursor[0] * SHAPE_WIDTH, 
      MARGIN + self.cursor[1] * SHAPE_HEIGHT - 68) 
    topRight = (topLeft[0] + SHAPE_WIDTH * 2, topLeft[1]) 
    bottomLeft = (topLeft[0], topLeft[1] + SHAPE_HEIGHT) 
    bottomRight = (topRight[0], topRight[1] + SHAPE_HEIGHT) 
    pygame.draw.lines(self.display, WHITE, True, 
      [topLeft, topRight, bottomRight, bottomLeft], 3) 

if __name__ == '__main__': 
    Game().play() 

답변

0

는 "나는 대신이 임의의 rareshape을 따기의 급부상 무엇 rareshape 결정할 수 있습니다"가 무엇을 의미 내게 불분명하다. 더 많은 설명을 하시겠습니까? 예고편에서 사용하려는 레어 스타일을 프로그램에 어떻게 설명할까요? 한편

는 여기에 코드의 좀 더 파이썬 버전입니다 : len(self.board) < min(self.size, 41)하지만 물론, 즉 현재의 코드가 무엇을 기본적으로 여전히 경우이 휴식 것

def randomize(self): 
    """ 
    Replace the entire board with fresh shapes. 
    """ 

    specials = dict((x, self.rareshapes) for x in (9, 23, 27)) 
    get_shape_source = lambda x: specials.get(x, self.shapes) 

    for i in xrange(min(self.size, 41)): 
     self.board[i] = Cell(random.choice(get_shape_source(i))) 

하는 것으로.

편집 : 덧글이 주어지면 명시 적으로 이미지를 스팟과 연관시키는 것이 어떤 레어 스케이프인지 명시 적으로 선택하는 명백한 방법입니다. 이제는 최선의 방법은 무엇입니까/최고의 장소에서 이것을 구성하는 가장 좋은 방법은 전체 코드 또는 적어도 게시 한 것 이상에 달려 있습니다.

from collections import ordereddict 

def load_images(self) 
    self.image_color = {} 
    self.shapes = [] 
    self.rareshapes = ordereddict() 

    colors = 'red', 'blue', 'yellow' 
    letters = 'acgtu' 

    for c in colors: 
     im = pygame.image.load('images/{}.png'.format(c)) 
     self.shapes.append(im) 
     self.image_color[im] = c 
     for l in letters: 
      im = pygame.image.load('rareimages/{}{}.png'.format(c, l)) 
      self.rareshapes.[(c, l)] = im 
      self.image_color[im] = l 

def randomize(self): 
    """ 
    Replace the entire board with fresh shapes. 
    """ 

    raremap = { 
     # spot index : rareshape 
     9: ('red', 'a')], 
     23: ('blue', 'u'), 
     27: ('yellow', 'g') 
     } 

    for i in xrange(self.size): 
     if i in raremap: 
      im = self.rareshapes[raremap[i]] 
     else: 
      im = random.choice(self.shapes) 
     self.board[i] = Cell(im) 

을하지만 장기적으로 단지 이상 유지할 것 - 너무 많은 하드 코딩 물건, 그리고 하나의 방법에서 다른 새는 너무 많은 지식 : 아주 간단하고 최소한의 exemple, 당신은 그냥이있을 수 있습니다. 나는 '자기'가 어떤 것인가를 알지 못하지만 책임감을 나누어서 하나의 클래스에 불변의 부분이 있고 다른 부분에 "구성"(로드 할 이미지, 스팟/레어 맵 매핑 등)이 있어야합니다. 마음에 떠오르는 디자인 패턴 중에는 TemplateMethod (Invariant 파트와 "구성"파트를 구현하는 구체적인 하위 클래스가있는 추상 기본 클래스가있는 곳), 물론 Builder (물론 전략) 클래스가 있습니다. 구성의). 당신을 위해 무엇을 요구하는 것은 rareshapecount 간격이 정상적인 모양 대신 희귀 한 모양을 배치해야하는 더 쉽게 지정하는 방법 인 경우

+0

내가하려는 일에 대해 더 좋은 아이디어가 있는지 위의 내용을 확인하십시오. – Badge

+0

@Badge : cf 업데이트 된 답변 –

+0

나는 위에 게시 한 것을 행운으로 추가하려고 시도했다. 위의 게시물을 전체 코드로 편집하여 모든 것을 살펴볼 수 있습니다. 이 게임은 거대한 것이 될 가능성이 거의 없으며 결코 공개 될 가능성이 거의 없으므로 유지 관리가 필요하지 않습니다. 게시 한 메서드는 잘 보이고 이해하기 쉽지만 Python과 프로그래밍 지식이 부족하여 나를 막아주고 있습니다. 이러한 유형의 프로그램 작업은 실제로 작동하는 프로그램을보고 모든 코드를 검토하여 모든 작업을 수행 할 수있는 경우에 정말 도움이됩니다. – Badge

1

는 다음과 같은 접근 방식은 더 읽을 수 :

def randomize(self): 
    """ 
    Replace the entire board with fresh shapes. 
    """ 
    # locations we want to place a rare shape 
    rare_shapes = [9, 23, 27] 

    for i in range(self.size): 
     if i in rare_shapes: 
     self.board[i] = Cell(random.choice(self.rareshapes)) 
     else: 
     self.board[i] = Cell (random.choice(self.shapes)) 

선택적으로, 매번 간격을 하드 코딩하지 않아도 다양한 경험을 할 수 있다면 (예 : 게임이나 비슷한 것을 디자인하는 경우) rare_shapes를 무작위로 채울 수 있습니다.

+0

이것은 대단한 변화였습니다! 내가 이것에 대해 생각하지 않았다는 것을 믿을 수 없다. 그러나, 그것은 아직도 내가 필요로하지 않습니다.(random.choice (self.rareshapes))보다는 각 방면에 rareshape가 들어갈 수있게하고 싶습니다. 따라서 9를 치면 reda.png 이미지가 나타납니다. 23에 도달하면 어쩌면 그 자리에 blueu.png을 표시하고 싶을 것입니다. 우리가 작업하려고하는 퍼즐 게임에 대해, 우리는 각 장소에 어떤 레이스 스타일이 나타날지 선택할 수 있어야합니다. (random.choice (self.shapes))는 단지 "필러"모양이기 때문에 항상 임의적 일 수 있습니다. 희망이 더 분명하다. – Badge