[LintCode] 395. Coins in a Line 2_Medium tag: Dynamic Programming, 博弈

本文介绍了一个关于博弈论的问题:两名玩家轮流从一排不同价值的硬币中取走一枚或两枚,最终获得硬币总价值较高者获胜。文章通过动态规划方法,特别是MinMax算法,来决定先手玩家是否能赢得比赛。

Description

There are n coins with different value in a line. Two players take turns to take one or two coins from left side until there are no more coins left. The player who take the coins with the most value wins.

Could you please decide the first player will win or lose?

Example

Given values array A = [1,2,2], return true.

Given A = [1,2,4], return false.

 

这个题目思路实际上跟[LintCode] 394. Coins in a Line_ Medium tag:Dynamic Programming_博弈很像, 然后博弈类的如果要取最大值, 需要用minmax算法, 得到关系式

A[i] = max(min(ans[i-2], ans[i-3]) + values[n-i], min(ans[i-3], ans[i-4] + values[n-i] + values[n-i+1])) ,

第一个就是只选1个coin, 第二个就是选两个coins, 最后return ans[n] > sum(values) //2

 

1. Constraints

1) values 长度大于等于0

2) element 是大于0 的integer

 

2. Ideas

Dynamic Programming      T: O(n)           S; O(n)  optimal  O(1)

 

3. Code

1) S; O(n)

class Solution:
    def coinsInLine2(self, values):
        ans = [0]*5
        ans[1]= values[0]
        ans[2] = ans[3] = sum(values[:2])
        n = len(values)
        if n < 4: return ans[n] > sum(values) //2
        ans[4] = values[0] + max(values[1], values[3])
        ans = ans + [0]*(n-4)
        for i in range(5, n+1):
            ans[i] = max(min(ans[i-2], ans[i-3]) + values[n-i], min(ans[i-3], ans[i-4]) + values[n-i] + values[n-i+1])
        return ans[n] > sum(values)//2

 

2) 可以用滚动数组方式将Space降为O(1)

 

4. Test cases 

1) [1,5,2,10]

转载于:https://www.cnblogs.com/Johnsonxiong/p/9369191.html

import pygame import sys import random from pygame import mixer import math # 初始化pygame pygame.init() mixer.init() # 游戏常量 SCREEN_WIDTH = 1000 SCREEN_HEIGHT = 700 FPS = 60 GRAVITY = 0.75 SCROLL_THRESH = 200 TILE_SIZE = 40 # 颜色定义 WHITE = (255, 255, 255) BLACK = (0, 0, 0) RED = (255, 0, 0) GREEN = (0, 255, 0) BLUE = (0, 0, 255) YELLOW = (255, 255, 0) SKY_BLUE = (135, 206, 235) GROUND_COL = (144, 118, 82) PURPLE = (128, 0, 128) ORANGE = (255, 165, 0) # 创建游戏窗口 screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) pygame.display.set_caption("障碍狂跳(Obstacle Bounce)") clock = pygame.time.Clock() # 初始化字体 try: font_large = pygame.font.SysFont('Arial', 50) font_medium = pygame.font.SysFont('Arial', 30) font_small = pygame.font.SysFont('Arial', 20) except: font_large = pygame.font.Font(None, 50) font_medium = pygame.font.Font(None, 30) font_small = pygame.font.Font(None, 20) # 辅助函数:居中绘制文本 def draw_centered_text(text, font, color, y_offset=0): img = font.render(text, True, color) x = (SCREEN_WIDTH - img.get_width()) // 2 y = (SCREEN_HEIGHT - img.get_height()) // 2 + y_offset screen.blit(img, (x, y)) # 绘制文本函数 def draw_text(text, font, color, x, y): img = font.render(text, True, color) screen.blit(img, (x, y)) # 加载图像(使用简单形状) def load_image(name, scale=1, colorkey=None): img = pygame.Surface((50, 50), pygame.SRCALPHA) if "player" in name: pygame.draw.circle(img, BLUE, (25, 25), 20) elif "enemy" in name: pygame.draw.rect(img, RED, (10, 10, 30, 30)) elif "coin" in name: pygame.draw.circle(img, YELLOW, (25, 25), 15) elif "platform" in name: pygame.draw.rect(img, GROUND_COL, (0, 0, 50, 50)) elif "obstacle_static" in name: pygame.draw.rect(img, BLACK, (5, 5, 40, 40)) elif "obstacle_moving" in name: pygame.draw.rect(img, PURPLE, (5, 5, 40, 40)) elif "obstacle_tracking" in name: pygame.draw.polygon(img, RED, [(25, 5), (5, 45), (45, 45)]) elif "obstacle_jumping" in name: pygame.draw.rect(img, ORANGE, (5, 5, 40, 40)) elif "powerup" in name: pygame.draw.circle(img, GREEN, (25, 25), 15) size = img.get_size() return pygame.transform.scale(img, (int(size[0] * scale), int(size[1] * scale))) # 游戏资源 class Assets: def __init__(self): # 玩家动画帧 self.player_imgs = { "idle": [load_image("player_idle_1"), load_image("player_idle_2")], "run": [load_image("player_run_1"), load_image("player_run_2"), load_image("player_run_3")], "jump": [load_image("player_jump")], "fall": [load_image("player_fall")] } # 敌人图像 self.enemy_imgs = { "slime": [load_image("enemy_slime_1"), load_image("enemy_slime_2")], "flying": [load_image("enemy_flying")], "spike": [load_image("enemy_spike")] } # 物品图像 self.item_imgs = { "coin": [load_image("coin_1"), load_image("coin_2"), load_image("coin_3")], "health": load_image("health"), "powerup": load_image("powerup") } # 障碍物图像 self.obstacle_imgs = { "static": load_image("obstacle_static"), "moving": load_image("obstacle_moving"), "tracking": load_image("obstacle_tracking"), "jumping": load_image("obstacle_jumping") } # 平台和背景 self.platform_img = load_image("platform", scale=2) self.bg_img = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT)) self.bg_img.fill(SKY_BLUE) # 游戏参数 self.coin_respawn_time = 5000 # 金币刷新时间(毫秒) self.max_coins = 15 # 最大金币数 self.obstacle_respawn_time = 6000 # 障碍物刷新时间 self.max_obstacles = 8 # 最大障碍物数 self.initial_obstacle_distance = 300 # 初始障碍物间距 self.min_obstacle_distance = 100 # 最小障碍物间距 self.difficulty_increase_interval = 30000 # 每30秒增加难度(毫秒) self.last_difficulty_increase = 0 # 上次增加难度的时间 self.difficulty_level = 1 # 当前难度等级 # 音效 self.sounds = { "jump": None, "coin": None, "hurt": None, "powerup": None } # 尝试加载音效 try: self.sounds["jump"] = mixer.Sound("jump.wav") if mixer.get_init() else None self.sounds["coin"] = mixer.Sound("coin.wav") if mixer.get_init() else None self.sounds["hurt"] = mixer.Sound("hurt.wav") if mixer.get_init() else None self.sounds["powerup"] = mixer.Sound("powerup.wav") if mixer.get_init() else None except: pass assets = Assets() # 玩家类 class Player(pygame.sprite.Sprite): def __init__(self, x, y): super().__init__() self.reset(x, y) def reset(self, x, y): self.image = assets.player_imgs["idle"][0] self.rect = self.image.get_rect() self.rect.x = x self.rect.y = y self.width = self.image.get_width() self.height = self.image.get_height() # 玩家属性 self.vel_y = 0 self.jumped = False self.direction = 1 self.in_air = True self.flip = False self.frame_index = 0 self.action = "idle" self.update_time = pygame.time.get_ticks() # 游戏属性 self.score = 0 self.health = 100 self.max_health = 100 self.coins = 0 self.lives = 3 self.invincible = False # 无敌状态 self.invincible_time = 0 # 无敌时间 self.powered_up = False # 强化状态 self.power_time = 0 # 强化时间 self.jump_power = 15 # 默认跳跃力量 def update(self, game_over, world): dx = 0 dy = 0 scroll = 0 if not game_over: # 处理状态效果 current_time = pygame.time.get_ticks() if self.invincible and current_time - self.invincible_time > 1000: # 1秒无敌时间 self.invincible = False if self.powered_up and current_time - self.power_time > 10000: # 10秒强化时间 self.powered_up = False self.jump_power = 15 # 获取按键输入 key = pygame.key.get_pressed() if key[pygame.K_SPACE] and not self.jumped and not self.in_air: self.vel_y = -self.jump_power self.jumped = True if assets.sounds["jump"]: assets.sounds["jump"].play() if not key[pygame.K_SPACE]: self.jumped = False if key[pygame.K_LEFT]: dx -= 5 self.direction = -1 self.flip = True if key[pygame.K_RIGHT]: dx += 5 self.direction = 1 self.flip = False # 应用重力 self.vel_y += GRAVITY if self.vel_y > 10: self.vel_y = 10 dy += self.vel_y # 检查碰撞 self.in_air = True for tile in world.tile_list: if tile[1].colliderect(self.rect.x + dx, self.rect.y, self.width, self.height): dx = 0 if tile[1].colliderect(self.rect.x, self.rect.y + dy, self.width, self.height): if self.vel_y < 0: dy = tile[1].bottom - self.rect.top self.vel_y = 0 elif self.vel_y >= 0: dy = tile[1].top - self.rect.bottom self.vel_y = 0 self.in_air = False # 更新玩家坐标 self.rect.x += dx self.rect.y += dy # 屏幕滚动 if self.rect.right > SCREEN_WIDTH - SCROLL_THRESH and world.level_length > SCREEN_WIDTH: scroll = -(SCREEN_WIDTH - SCROLL_THRESH - self.rect.right) self.rect.right = SCREEN_WIDTH - SCROLL_THRESH elif self.rect.left < SCROLL_THRESH and scroll < 0: scroll = SCROLL_THRESH - self.rect.left self.rect.left = SCROLL_THRESH # 更新动画状态 if dx != 0: self.update_action("run") elif self.in_air: if self.vel_y < 0: self.update_action("jump") else: self.update_action("fall") else: self.update_action("idle") # 更新动画 self.update_animation() return scroll def update_animation(self): ANIMATION_COOLDOWN = 100 self.image = assets.player_imgs[self.action][self.frame_index] if pygame.time.get_ticks() - self.update_time > ANIMATION_COOLDOWN: self.update_time = pygame.time.get_ticks() self.frame_index += 1 if self.frame_index >= len(assets.player_imgs[self.action]): self.frame_index = 0 def update_action(self, new_action): if new_action != self.action: self.action = new_action self.frame_index = 0 self.update_time = pygame.time.get_ticks() def take_damage(self, amount): if not self.invincible and not self.powered_up: self.health -= amount self.invincible = True self.invincible_time = pygame.time.get_ticks() if assets.sounds["hurt"]: assets.sounds["hurt"].play() if self.health <= 0: self.lives -= 1 self.health = 100 return True # 表示生命减少 return False def activate_powerup(self): self.powered_up = True self.power_time = pygame.time.get_ticks() self.jump_power = 20 # 强化跳跃高度 if assets.sounds["powerup"]: assets.sounds["powerup"].play() # 敌人类 class Enemy(pygame.sprite.Sprite): def __init__(self, x, y, enemy_type): super().__init__() self.enemy_type = enemy_type self.image = assets.enemy_imgs[enemy_type][0] self.rect = self.image.get_rect() self.rect.x = x self.rect.y = y self.move_direction = 1 self.move_counter = 0 self.vel_y = 0 self.flip = False self.frame_index = 0 self.update_time = pygame.time.get_ticks() # 敌人特有属性 if enemy_type == "flying": self.vel_y = random.choice([-1, 1]) self.move_range = random.randint(50, 150) elif enemy_type == "spike": self.move_direction = random.choice([-1, 1]) self.speed = random.randint(2, 4) def update(self, scroll, world): if self.enemy_type == "slime": self.rect.x += self.move_direction self.move_counter += 1 if abs(self.move_counter) > 50: self.move_direction *= -1 self.move_counter *= -1 self.flip = not self.flip # 应用重力 self.vel_y += GRAVITY if self.vel_y > 10: self.vel_y = 10 self.rect.y += self.vel_y # 地面碰撞检测 for tile in world.tile_list: if tile[1].colliderect(self.rect.x, self.rect.y + self.vel_y, self.rect.width, self.rect.height): if self.vel_y >= 0: self.rect.bottom = tile[1].top self.vel_y = 0 elif self.enemy_type == "flying": # 上下飞行 self.rect.y += self.vel_y self.move_counter += 1 if abs(self.move_counter) > self.move_range: self.vel_y *= -1 self.move_counter *= -1 elif self.enemy_type == "spike": # 快速左右移动 self.rect.x += self.move_direction * self.speed self.move_counter += 1 if self.move_counter > 100: self.move_direction *= -1 self.move_counter = 0 # 动画更新 ANIMATION_COOLDOWN = 150 self.image = assets.enemy_imgs[self.enemy_type][self.frame_index] if pygame.time.get_ticks() - self.update_time > ANIMATION_COOLDOWN: self.update_time = pygame.time.get_ticks() self.frame_index = (self.frame_index + 1) % len(assets.enemy_imgs[self.enemy_type]) # 应用屏幕滚动 self.rect.x += scroll # 物品类 class Item(pygame.sprite.Sprite): def __init__(self, x, y, item_type): super().__init__() self.item_type = item_type if isinstance(assets.item_imgs[item_type], list): self.animation_frames = assets.item_imgs[item_type] self.image = self.animation_frames[0] else: self.animation_frames = [assets.item_imgs[item_type]] self.image = assets.item_imgs[item_type] self.rect = self.image.get_rect() self.rect.center = (x, y) self.frame_index = 0 self.update_time = pygame.time.get_ticks() self.spawn_time = pygame.time.get_ticks() # 特殊属性 if item_type == "powerup": self.float_offset = 0 self.float_direction = 1 def update(self, scroll): ANIMATION_COOLDOWN = 150 if isinstance(self.animation_frames, list): self.image = self.animation_frames[self.frame_index] if pygame.time.get_ticks() - self.update_time > ANIMATION_COOLDOWN: self.update_time = pygame.time.get_ticks() self.frame_index = (self.frame_index + 1) % len(self.animation_frames) # 特殊物品浮动效果 if self.item_type == "powerup": self.float_offset += 0.1 * self.float_direction if abs(self.float_offset) > 5: self.float_direction *= -1 self.rect.y += 0.1 * self.float_direction # 应用屏幕滚动 self.rect.x += scroll # 障碍物类 class Obstacle(pygame.sprite.Sprite): def __init__(self, x, y, obstacle_type, difficulty_level=1): super().__init__() self.obstacle_type = obstacle_type self.image = assets.obstacle_imgs[obstacle_type] self.rect = self.image.get_rect() self.rect.x = x self.rect.y = y self.move_direction = random.choice([-1, 1]) self.move_counter = 0 self.speed = random.randint(1, 3) * difficulty_level self.lifetime = random.randint(8000, 12000) // max(1, difficulty_level) self.spawn_time = pygame.time.get_ticks() self.move_range = random.randint(50, 200) # 移动障碍物的移动范围 # 跳跃障碍物特有属性 if obstacle_type == "jumping": self.jump_height = random.randint(5, 15) self.jump_speed = random.uniform(0.05, 0.1) * difficulty_level self.jump_offset = 0 self.jump_direction = 1 def update(self, scroll, player=None): # 移动逻辑 if self.obstacle_type == "moving": self.rect.x += self.move_direction * self.speed self.move_counter += 1 if self.move_counter > self.move_range: self.move_direction *= -1 self.move_counter = 0 elif self.obstacle_type == "tracking" and player: # 追踪逻辑 - 只在y轴追踪,x轴保持移动 self.rect.x += self.move_direction * self.speed # 在x轴边界反弹 if self.rect.left < 0 or self.rect.right > SCREEN_WIDTH: self.move_direction *= -1 # 在y轴追踪玩家,但有延迟 if self.rect.y < player.rect.y: self.rect.y += min(self.speed, player.rect.y - self.rect.y) elif self.rect.y > player.rect.y: self.rect.y -= min(self.speed, self.rect.y - player.rect.y) elif self.obstacle_type == "jumping": # 跳跃障碍物上下跳动 self.jump_offset += self.jump_speed * self.jump_direction if abs(self.jump_offset) > self.jump_height: self.jump_direction *= -1 self.rect.y += self.jump_speed * self.jump_direction # 同时可能左右移动 self.rect.x += self.move_direction * (self.speed / 2) self.move_counter += 1 if self.move_counter > self.move_range: self.move_direction *= -1 self.move_counter = 0 # 生命周期检查 if pygame.time.get_ticks() - self.spawn_time > self.lifetime: self.kill() # 应用屏幕滚动 self.rect.x += scroll # 世界类 class World(): def __init__(self, level_data): self.tile_list = [] self.coin_spawn_areas = [] self.obstacle_spawn_areas = [] # 创建世界 row_count = 0 for row in level_data: col_count = 0 for tile in row: if tile == 1: img = assets.platform_img img_rect = img.get_rect() img_rect.x = col_count * TILE_SIZE img_rect.y = row_count * TILE_SIZE tile = (img, img_rect) self.tile_list.append(tile) elif tile == 0: # 检查下方是否有平台 if row_count < len(level_data) - 1 and level_data[row_count + 1][col_count] == 1: self.coin_spawn_areas.append((col_count * TILE_SIZE, row_count * TILE_SIZE)) self.obstacle_spawn_areas.append((col_count * TILE_SIZE, row_count * TILE_SIZE)) col_count += 1 row_count += 1 self.level_length = len(level_data[0]) * TILE_SIZE def draw(self, screen, scroll): for tile in self.tile_list: tile[1].x += scroll screen.blit(tile[0], tile[1]) tile[1].x -= scroll def get_random_coin_position(self): if self.coin_spawn_areas: return random.choice(self.coin_spawn_areas) return (random.randint(100, SCREEN_WIDTH - 100), random.randint(100, SCREEN_HEIGHT - 200)) def get_smart_obstacle_position(self, player_x, last_obstacle_x, min_distance): # 尝试找到合适位置最多尝试10次 for _ in range(10): if self.obstacle_spawn_areas: x, y = random.choice(self.obstacle_spawn_areas) else: x, y = random.randint(100, SCREEN_WIDTH - 100), random.randint(100, SCREEN_HEIGHT - 200) # 检查与玩家的距离 if abs(x - player_x) < min_distance: continue # 检查与上一个障碍物的距离 if last_obstacle_x and abs(x - last_obstacle_x) < min_distance: continue return x, y # 如果找不到理想位置,返回随机位置 if self.obstacle_spawn_areas: return random.choice(self.obstacle_spawn_areas) return (random.randint(100, SCREEN_WIDTH - 100), random.randint(100, SCREEN_HEIGHT - 200)) # 开始界面 def show_start_screen(): screen.fill(SKY_BLUE) # 居中绘制所有文本 draw_centered_text("Obstacle Bounce", font_medium, BLACK, -150) draw_centered_text("Start: Space", font_medium, BLACK, -50) draw_centered_text("Move: Arrow Keys", font_small, BLACK, 20) draw_centered_text("Jump: Spacebar", font_small, BLACK, 50) draw_centered_text("Pause: Esc", font_small, BLACK, 80) draw_centered_text("Collect coins, avoid obstacles!", font_small, BLACK, 120) draw_centered_text("Green items: Power boost", font_small, GREEN, 150) pygame.display.update() waiting = True while waiting: clock.tick(FPS) for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() if event.type == pygame.KEYDOWN: if event.key == pygame.K_SPACE: waiting = False if event.key == pygame.K_ESCAPE: pygame.quit() sys.exit() # 暂停界面 def show_pause_screen(): screen.fill(SKY_BLUE) draw_centered_text("游戏暂停", font_large, BLACK, -50) draw_centered_text("按ESC键继续游戏", font_medium, BLACK, 20) draw_centered_text("按Q键退出游戏", font_medium, BLACK, 60) pygame.display.update() paused = True while paused: clock.tick(FPS) for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() if event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: paused = False if event.key == pygame.K_q: pygame.quit() sys.exit() # 结束界面 def show_game_over_screen(score): screen.fill(SKY_BLUE) draw_centered_text("Game Over", font_large, RED, -100) draw_centered_text(f"Final Score: {score}", font_medium, BLACK, -30) draw_centered_text("Restart: R", font_medium, BLACK, 30) draw_centered_text("Quit: Q", font_medium, BLACK, 80) pygame.display.update() waiting = True while waiting: clock.tick(FPS) for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() if event.type == pygame.KEYDOWN: if event.key == pygame.K_r: waiting = False if event.key == pygame.K_q: pygame.quit() sys.exit() return True # 游戏主循环 def main(): # 创建玩家 player = Player(100, SCREEN_HEIGHT - 130) # 创建世界 world_data = [ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] ] world = World(world_data) # 创建精灵组 enemies = pygame.sprite.Group() items = pygame.sprite.Group() obstacles = pygame.sprite.Group() # 添加初始敌人和金币 enemies.add(Enemy(300, SCREEN_HEIGHT - 180, "slime")) enemies.add(Enemy(600, SCREEN_HEIGHT - 180, "slime")) enemies.add(Enemy(450, SCREEN_HEIGHT - 400, "flying")) enemies.add(Enemy(800, SCREEN_HEIGHT - 180, "spike")) for i in range(5): items.add(Item(200 + i * 150, SCREEN_HEIGHT - 200, "coin")) # 添加初始障碍物 obstacles.add(Obstacle(400, SCREEN_HEIGHT - 250, "static", assets.difficulty_level)) obstacles.add(Obstacle(700, SCREEN_HEIGHT - 250, "moving", assets.difficulty_level)) obstacles.add(Obstacle(500, SCREEN_HEIGHT - 350, "jumping", assets.difficulty_level)) # 游戏变量 scroll = 0 game_over = False running = True paused = False # 计时器和距离跟踪 last_coin_spawn_time = pygame.time.get_ticks() last_obstacle_spawn_time = pygame.time.get_ticks() last_powerup_spawn_time = pygame.time.get_ticks() last_obstacle_x = None min_obstacle_distance = assets.initial_obstacle_distance # 显示开始界面 show_start_screen() while running: current_time = pygame.time.get_ticks() clock.tick(FPS) # 事件处理 for event in pygame.event.get(): if event.type == pygame.QUIT: running = False if event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE and not game_over: paused = not paused if paused: show_pause_screen() if game_over: if event.key == pygame.K_r: # 重置游戏状态 player.reset(100, SCREEN_HEIGHT - 130) scroll = 0 game_over = False # 重置所有元素 enemies.empty() enemies.add(Enemy(300, SCREEN_HEIGHT - 180, "slime")) enemies.add(Enemy(600, SCREEN_HEIGHT - 180, "slime")) enemies.add(Enemy(450, SCREEN_HEIGHT - 400, "flying")) enemies.add(Enemy(800, SCREEN_HEIGHT - 180, "spike")) items.empty() for i in range(5): items.add(Item(200 + i * 150, SCREEN_HEIGHT - 200, "coin")) obstacles.empty() obstacles.add(Obstacle(400, SCREEN_HEIGHT - 250, "static", 1)) obstacles.add(Obstacle(700, SCREEN_HEIGHT - 250, "moving", 1)) obstacles.add(Obstacle(500, SCREEN_HEIGHT - 350, "jumping", 1)) last_coin_spawn_time = current_time last_obstacle_spawn_time = current_time last_powerup_spawn_time = current_time last_obstacle_x = None min_obstacle_distance = assets.initial_obstacle_distance assets.difficulty_level = 1 assets.last_difficulty_increase = current_time elif event.key == pygame.K_q: running = False if paused: continue if game_over: if show_game_over_screen(player.score): # 重置游戏状态 player.reset(100, SCREEN_HEIGHT - 130) scroll = 0 game_over = False # 重置所有元素 enemies.empty() enemies.add(Enemy(300, SCREEN_HEIGHT - 180, "slime")) enemies.add(Enemy(600, SCREEN_HEIGHT - 180, "slime")) enemies.add(Enemy(450, SCREEN_HEIGHT - 400, "flying")) enemies.add(Enemy(800, SCREEN_HEIGHT - 180, "spike")) items.empty() for i in range(5): items.add(Item(200 + i * 150, SCREEN_HEIGHT - 200, "coin")) obstacles.empty() obstacles.add(Obstacle(400, SCREEN_HEIGHT - 250, "static", 1)) obstacles.add(Obstacle(700, SCREEN_HEIGHT - 250, "moving", 1)) obstacles.add(Obstacle(500, SCREEN_HEIGHT - 350, "jumping", 1)) last_coin_spawn_time = current_time last_obstacle_spawn_time = current_time last_powerup_spawn_time = current_time last_obstacle_x = None min_obstacle_distance = assets.initial_obstacle_distance assets.difficulty_level = 1 assets.last_difficulty_increase = current_time else: running = False continue # 难度递增系统 if current_time - assets.last_difficulty_increase > assets.difficulty_increase_interval: assets.difficulty_level += 0.5 assets.last_difficulty_increase = current_time # 逐渐减少最小间距,但不低于最小值 min_obstacle_distance = max( assets.min_obstacle_distance, assets.initial_obstacle_distance - (assets.difficulty_level * 20) ) # 金币刷新逻辑 if (current_time - last_coin_spawn_time > assets.coin_respawn_time and len(items) < assets.max_coins): x, y = world.get_random_coin_position() items.add(Item(x, y, "coin")) last_coin_spawn_time = current_time # 强化道具刷新逻辑 (每20-30秒) if (current_time - last_powerup_spawn_time > random.randint(20000, 30000) and len([i for i in items if i.item_type == "powerup"]) < 1): x, y = world.get_random_coin_position() items.add(Item(x, y, "powerup")) last_powerup_spawn_time = current_time # 障碍物刷新逻辑 if (current_time - last_obstacle_spawn_time > assets.obstacle_respawn_time and len(obstacles) < assets.max_obstacles): # 获取智能位置 x, y = world.get_smart_obstacle_position( player.rect.x, last_obstacle_x, min_obstacle_distance ) # 随机选择障碍物类型,难度越高追踪和跳跃障碍物出现几率越大 obstacle_types = ["static", "moving", "tracking", "jumping"] weights = [ 0.4, # static 0.3, # moving 0.1 + (assets.difficulty_level * 0.1), # tracking 0.2 + (assets.difficulty_level * 0.1) # jumping ] obstacle_type = random.choices(obstacle_types, weights=weights, k=1)[0] obstacles.add(Obstacle(x, y, obstacle_type, assets.difficulty_level)) last_obstacle_spawn_time = current_time last_obstacle_x = x # 更新游戏状态 scroll = player.update(game_over, world) enemies.update(scroll, world) items.update(scroll) obstacles.update(scroll, player) # 检查碰撞 - 敌人 for enemy in enemies: if player.rect.colliderect(enemy.rect): if player.take_damage(10): if player.lives <= 0: game_over = True # 检查碰撞 - 物品 for item in items: if player.rect.colliderect(item.rect): if item.item_type == "coin": player.score += 10 player.coins += 1 if assets.sounds["coin"]: assets.sounds["coin"].play() elif item.item_type == "powerup": player.activate_powerup() items.remove(item) # 30%几率立即生成新金币 if random.random() < 0.3 and item.item_type == "coin": x, y = world.get_random_coin_position() items.add(Item(x, y, "coin")) # 检查碰撞 - 障碍物 for obstacle in obstacles: if player.rect.colliderect(obstacle.rect): if player.take_damage(15): if player.lives <= 0: game_over = True # 绘制游戏 screen.blit(assets.bg_img, (0, 0)) world.draw(screen, scroll) enemies.draw(screen) items.draw(screen) obstacles.draw(screen) # 绘制玩家(无敌状态时闪烁) if not player.invincible or (pygame.time.get_ticks() // 200) % 2 == 0: screen.blit(pygame.transform.flip(player.image, player.flip, False), (player.rect.x - scroll, player.rect.y)) # 绘制UI draw_text(f"score: {player.score}", font_small, BLACK, 20, 20) draw_text(f"life: {player.lives}", font_small, BLACK, 20, 50) draw_text(f"coin: {player.coins}", font_small, BLACK, 20, 80) # 血条 pygame.draw.rect(screen, RED, (20, 110, player.health, 20)) pygame.draw.rect(screen, BLACK, (20, 110, player.max_health, 20), 2) # 难度指示器 draw_text(f"Level: {int(assets.difficulty_level)}", font_small, BLACK, 20, 140) # 强化状态指示器 if player.powered_up: remaining_time = max(0, 10 - (pygame.time.get_ticks() - player.power_time) / 1000) draw_text(f"Power-up: {remaining_time:.1f}s", font_small, GREEN, 20, 170) pygame.display.update() pygame.quit() sys.exit() if __name__ == "__main__": main() 给里面的角色和障碍添加图片
06-18
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值