55. Jump Game

本文介绍了解决跳跃问题的两种算法实现:一种采用深度优先搜索加剪枝策略;另一种使用贪心算法,通过记录可达最远距离来高效解决问题。这两种方法均可判断是否能够成功越过所有障碍。

深搜+剪枝

class Solution {
public:
    void Jump(vector<int>& nums,int sta,bool vist[],bool& tag)
    {
        if(sta>=nums.size()-1||sta+nums[sta]>=nums.size()-1)
        {
            tag=true;
            return;
        }
        if(tag==true||vist[sta+nums[sta]])
            return;
        
        for(int i=nums[sta];i>=1;i--)
        {
            if(vist[sta+i])
                break;
            Jump(nums,sta+i,vist,tag);
            vist[sta+i]=true;
        }
    }
    bool canJump(vector<int>& nums) {
        int n=nums.size();
        bool tag=false;
        bool vist[n+1];
        memset(vist,0,sizeof(vist));
        Jump(nums,0,vist,tag);
        return tag;
    }
};


 贪心,纪录最远能到达的距离,O(n)

class Solution {
public:
    bool canJump(vector<int>& nums) {
        int n=nums.size();
        int rightmost=1;
        for(int i=0;i<nums.size();i++)
        {
            rightmost--;
            if(i+rightmost>=nums.size()-1)
                return true;
            if(nums[i]>rightmost)
                rightmost=nums[i];
            if(rightmost==0)
                return false;
        }
        return true;
    }
};


import random import math from kivy.app import App from kivy.uix.widget import Widget from kivy.graphics import Rectangle, Color, Line from kivy.clock import Clock from kivy.core.window import Window from kivy.uix.label import Label from kivy.uix.button import Button from kivy.uix.boxlayout import BoxLayout # 游戏常量 GROUND_HEIGHT = 50 DINO_WIDTH = 40 DINO_HEIGHT = 60 OBSTACLE_WIDTH = 30 OBSTACLE_HEIGHT = [40, 60, 45] # 不同障碍物的高度 GRAVITY = 0.5 JUMP_FORCE = -12 GAME_SPEED = 5 CLOUD_SPEED = 1.5 class DinoGame(Widget): def __init__(self, **kwargs): super(DinoGame, self).__init__(**kwargs) self._keyboard = Window.request_keyboard(self._keyboard_closed, self) self._keyboard.bind(on_key_down=self._on_keyboard_down) # 游戏状态 self.score = 0 self.high_score = 0 self.game_over = False self.game_started = False # 恐龙参数 self.dino_x = 50 self.dino_y = GROUND_HEIGHT self.dino_jump_velocity = 0 self.is_jumping = False self.dino_frame = 0 # 用于动画切换 # 障碍物 self.obstacles = [] self.obstacle_speed = GAME_SPEED self.obstacle_timer = 0 self.obstacle_interval = 100 # 障碍物生成间隔 # 云朵 self.clouds = [] self.init_clouds() # 地面 self.ground_offset = 0 # 分数标签 self.score_label = Label(text='Score: 0', font_size='20sp', pos=(20, Window.height - 40)) self.add_widget(self.score_label) # 游戏结束标签 self.game_over_label = Label(text='GAME OVER', font_size='40sp', pos=(Window.width / 2 - 100, Window.height / 2), opacity=0) self.add_widget(self.game_over_label) # 开始提示 self.start_label = Label(text='Press SPACE to start', font_size='20sp', pos=(Window.width / 2 - 100, Window.height / 2)) self.add_widget(self.start_label) # 重新开始按钮 self.restart_btn = Button(text='Restart', size_hint=(None, None), size=(100, 50), pos=(Window.width / 2 - 50, Window.height / 2 - 100), opacity=0) self.restart_btn.bind(on_press=self.restart_game) self.add_widget(self.restart_btn) # 绑定更新函数 Clock.schedule_interval(self.update, 1.0 / 60.0) def init_clouds(self): for i in range(3): self.clouds.append({ 'x': random.randint(0, Window.width), 'y': random.randint(Window.height / 2, Window.height - 50), 'speed': random.uniform(0.5, 1.5) * CLOUD_SPEED, 'size': random.randint(50, 100) }) def _keyboard_closed(self): self._keyboard.unbind(on_key_down=self._on_keyboard_down) self._keyboard = None def _on_keyboard_down(self, keyboard, keycode, text, modifiers, **kwargs): """修正后的键盘事件处理""" if keycode[1] == 'spacebar': if not self.game_started and not self.game_over: self.game_started = True self.start_label.opacity = 0 elif not self.is_jumping and not self.game_over: self.dino_jump_velocity = JUMP_FORCE self.is_jumping = True elif self.game_over: self.restart_game() return True def jump(self): if not self.is_jumping and not self.game_over and self.game_started: self.dino_jump_velocity = JUMP_FORCE self.is_jumping = True def update_clouds(self): for cloud in self.clouds: cloud['x'] -= cloud['speed'] if cloud['x'] < -cloud['size']: cloud['x'] = Window.width cloud['y'] = random.randint(Window.height / 2, Window.height - 50) cloud['speed'] = random.uniform(0.5, 1.5) * CLOUD_SPEED def update_obstacles(self): # 生成新障碍物 self.obstacle_timer += 1 if self.obstacle_timer >= self.obstacle_interval and self.game_started and not self.game_over: self.obstacle_timer = 0 obstacle_type = random.randint(0, 2) self.obstacles.append({ 'x': Window.width, 'type': obstacle_type, 'passed': False }) # 随机间隔 self.obstacle_interval = random.randint(70, 150) # 移动障碍物 for obstacle in self.obstacles[:]: obstacle['x'] -= self.obstacle_speed if obstacle['x'] < -OBSTACLE_WIDTH: self.obstacles.remove(obstacle) def update_score(self): for obstacle in self.obstacles: if not obstacle['passed'] and obstacle['x'] + OBSTACLE_WIDTH < self.dino_x: obstacle['passed'] = True self.score += 1 self.score_label.text = f'Score: {self.score}' # 随着分数增加难度 if self.score % 10 == 0: self.obstacle_speed += 0.2 def check_collision(self): dino_rect = { 'x': self.dino_x, 'y': self.dino_y, 'width': DINO_WIDTH, 'height': DINO_HEIGHT } for obstacle in self.obstacles: obstacle_rect = { 'x': obstacle['x'], 'y': GROUND_HEIGHT, 'width': OBSTACLE_WIDTH, 'height': OBSTACLE_HEIGHT[obstacle['type']] } if (dino_rect['x'] < obstacle_rect['x'] + obstacle_rect['width'] and dino_rect['x'] + dino_rect['width'] > obstacle_rect['x'] and dino_rect['y'] < obstacle_rect['y'] + obstacle_rect['height'] and dino_rect['y'] + dino_rect['height'] > obstacle_rect['y']): self.game_over = True self.game_over_label.opacity = 1 self.restart_btn.opacity = 1 if self.score > self.high_score: self.high_score = self.score def update_dino(self): # 跳跃物理 if self.is_jumping: self.dino_y -= self.dino_jump_velocity self.dino_jump_velocity += GRAVITY if self.dino_y <= GROUND_HEIGHT: self.dino_y = GROUND_HEIGHT self.is_jumping = False # 奔跑动画 if not self.is_jumping and self.game_started and not self.game_over: self.dino_frame = (self.dino_frame + 1) % 10 def restart_game(self, *args): self.score = 0 self.score_label.text = 'Score: 0' self.obstacles = [] self.obstacle_speed = GAME_SPEED self.dino_y = GROUND_HEIGHT self.is_jumping = False self.game_over = False self.game_started = True self.game_over_label.opacity = 0 self.restart_btn.opacity = 0 def update(self, dt): if not self.game_started or self.game_over: return # 更新地面滚动 self.ground_offset = (self.ground_offset + self.obstacle_speed) % Window.width self.update_dino() self.update_clouds() self.update_obstacles() self.update_score() self.check_collision() self.draw() def draw(self): self.canvas.clear() # 绘制背景 with self.canvas: Color(0.9, 0.9, 0.9) # 浅灰色背景 Rectangle(pos=(0, 0), size=(Window.width, Window.height)) # 绘制云朵 Color(0.8, 0.8, 0.8) for cloud in self.clouds: Rectangle(pos=(cloud['x'], cloud['y']), size=(cloud['size'], cloud['size'] / 2)) # 绘制地面 Color(0.4, 0.4, 0.4) Rectangle(pos=(0, 0), size=(Window.width, GROUND_HEIGHT)) # 地面装饰线 Color(0.3, 0.3, 0.3) Line(points=[0, GROUND_HEIGHT, Window.width, GROUND_HEIGHT], width=1) # 绘制障碍物 Color(0.2, 0.6, 0.2) # 绿色障碍物 for obstacle in self.obstacles: height = OBSTACLE_HEIGHT[obstacle['type']] Rectangle(pos=(obstacle['x'], GROUND_HEIGHT), size=(OBSTACLE_WIDTH, height)) # 绘制恐龙 Color(0.2, 0.2, 0.2) # 黑色恐龙 # 简单的恐龙形状 - 可以根据需要替换为更复杂的图形 # 身体 Rectangle(pos=(self.dino_x, self.dino_y), size=(DINO_WIDTH, DINO_HEIGHT)) # 头 head_height = DINO_HEIGHT * 0.6 Rectangle(pos=(self.dino_x + DINO_WIDTH, self.dino_y + DINO_HEIGHT - head_height), size=(DINO_WIDTH * 0.5, head_height)) # 腿 - 根据动画帧切换 leg_width = DINO_WIDTH * 0.2 leg_height = DINO_HEIGHT * 0.3 if self.dino_frame < 5 or self.is_jumping: # 前腿向后 Rectangle(pos=(self.dino_x + DINO_WIDTH * 0.2, self.dino_y - leg_height), size=(leg_width, leg_height)) # 后腿向前 Rectangle(pos=(self.dino_x + DINO_WIDTH * 0.6, self.dino_y - leg_height), size=(leg_width, leg_height)) else: # 前腿向前 Rectangle(pos=(self.dino_x + DINO_WIDTH * 0.2, self.dino_y - leg_height), size=(leg_width, leg_height)) # 后腿向后 Rectangle(pos=(self.dino_x + DINO_WIDTH * 0.6, self.dino_y - leg_height), size=(leg_width, leg_height)) class DinoApp(App): def build(self): game = DinoGame() Window.bind(on_key_down=game._on_keyboard_down) return game if __name__ == '__main__': DinoApp().run() C:\Users\V82406169\PycharmProjects\ikun\.venv\Scripts\python.exe C:\Users\V82406169\PycharmProjects\ikun\.venv\dino.py [INFO ] [Logger ] Record log in C:\Users\V82406169\.kivy\logs\kivy_25-12-26_41.txt [INFO ] [deps ] Successfully imported "kivy_deps.angle" 0.4.0 [INFO ] [deps ] Successfully imported "kivy_deps.glew" 0.3.1 [INFO ] [deps ] Successfully imported "kivy_deps.sdl2" 0.7.0 [INFO ] [Kivy ] v2.3.0 [INFO ] [Kivy ] Installed at "C:\Users\V82406169\PycharmProjects\ikun\.venv\lib\site-packages\kivy\__init__.py" [INFO ] [Python ] v3.7.9 (tags/v3.7.9:13c94747c7, Aug 17 2020, 18:01:55) [MSC v.1900 32 bit (Intel)] [INFO ] [Python ] Interpreter at "C:\Users\V82406169\PycharmProjects\ikun\.venv\Scripts\python.exe" [INFO ] [Logger ] Purge log fired. Processing... [INFO ] [Logger ] Purge finished! [INFO ] [Factory ] 195 symbols loaded [INFO ] [Image ] Providers: img_tex, img_dds, img_sdl2 (img_pil, img_ffpyplayer ignored) [INFO ] [Window ] Provider: sdl2 [INFO ] [GL ] Using the "OpenGL" graphics system [INFO ] [GL ] GLEW initialization succeeded [INFO ] [GL ] Backend used <glew> [INFO ] [GL ] OpenGL version <b'3.3 (Compatibility Profile) Mesa 21.2.0-devel (git-ac6211dc0e)'> [INFO ] [GL ] OpenGL vendor <b'VMware, Inc.'> [INFO ] [GL ] OpenGL renderer <b'SVGA3D; build: RELEASE; LLVM;'> [INFO ] [GL ] OpenGL parsed version: 3, 3 [INFO ] [GL ] Shading version <b'3.30'> [INFO ] [GL ] Texture max size <8192> [INFO ] [GL ] Texture max units <16> [INFO ] [Window ] auto add sdl2 input provider [INFO ] [Window ] virtual keyboard not allowed, single mode, not docked [INFO ] [Text ] Provider: sdl2 [INFO ] [Base ] Start application main loop [INFO ] [GL ] NPOT texture support is available [INFO ] [Base ] Leaving application in progress... Traceback (most recent call last): File "C:\Users\V82406169\PycharmProjects\ikun\.venv\dino.py", line 282, in <module> DinoApp().run() File "C:\Users\V82406169\PycharmProjects\ikun\.venv\lib\site-packages\kivy\app.py", line 956, in run runTouchApp() File "C:\Users\V82406169\PycharmProjects\ikun\.venv\lib\site-packages\kivy\base.py", line 574, in runTouchApp EventLoop.mainloop() File "C:\Users\V82406169\PycharmProjects\ikun\.venv\lib\site-packages\kivy\base.py", line 341, in mainloop self.window.mainloop() File "C:\Users\V82406169\PycharmProjects\ikun\.venv\lib\site-packages\kivy\core\window\window_sdl2.py", line 778, in mainloop self.modifiers): File "kivy\\_event.pyx", line 727, in kivy._event.EventDispatcher.dispatch File "kivy\\_event.pyx", line 1307, in kivy._event.EventObservers.dispatch File "kivy\\_event.pyx", line 1231, in kivy._event.EventObservers._dispatch TypeError: _on_keyboard_down() takes 5 positional arguments but 6 were given
最新发布
12-27
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值