欢迎访问我的个人网站,网站正在创建期间,主要供自己学习交流使用!

Tauri(2.5.1)+Leptos(0.8.2)开发自用桌面小程序--DeepSeek辅助编程(俄罗斯方块)



在之前工作基础上(Tauri(2.5.1)+Leptos(0.8.2)开发自用桌面小程序-CSDN博客),继续进行自用桌面小程序的开发,这次完全使用DeepSeek辅助编程做一个俄罗斯方块游戏,大部分代码由DeepSeek自主完成,Bug扔给DeepSeek自行处理,期间人为简单干预即可。具体游戏界面如下:

 

1. DeepSeek辅助编程界面
Win10的操作系统,使用VS Code及Rust analyzer插件搭建的Rust开发环境,使用Roo Code绑定DeepSeek API ,配置比较简单,网上教程很多。

 

 

2. 页面设置
还是使用leptos-router新建一个页面(类似浏览器的标签页),用于俄罗斯方块游戏界面。主要在src/app/app.rs文件中设置,具体代码如下:

#[warn(unused_imports)]
use leptos::prelude::*;
use leptos_router::components::{Route, Router, Routes};
use leptos_router::path;
mod acidinput;
mod schedule;
mod game2048;
mod game5;
mod match_game;

use acidinput::*;
use schedule::*;
use game2048::*;
use game5::*;
use match_game::*;

#[component]
pub fn App() -> impl IntoView {
   view! {
       <Router>
           <nav>
               <a class="nav" href="/">"工作进度表"</a>
               <a class="nav" href="/acidinput">"产品录入"</a>
               <a class="nav" href="/game2048">"2048数字游戏"</a>
               <a class="nav" href="/game5">"五子棋游戏"</a>
               <a class="nav" href="/matchgame">"俄罗斯方块"</a>
           </nav>
           <main>
               <Routes fallback=|| "Not found.">
                   // / just has an un-nested "Home"
                   <Route path=path!("/") view= || view! {<WorkSchedule />} />
                   <Route path=path!("/acidinput") view=|| view! {<AcidInput />} />
                   <Route path=path!("/game2048") view=|| view! {<GameBoard />} />
                   <Route path=path!("/game5") view=|| view! {<GomokuGame />} />
                   <Route path=path!("/matchgame") view=|| view! {<TetrisGameBoard />} />
               </Routes>                
           </main>
       </Router>
   }
}

AI写代码
rust
运行

3. 游戏主程序
俄罗斯方块游戏的代码被放在了文件src/app/match_game.rs中,绝大部分代码和注释都是DeepSeek完成的,具体代码如下:

use leptos::*;
use leptos::prelude::*;
use leptos::component;
use leptos::view;
use wasm_bindgen::prelude::*;
use web_sys;
use leptos::task::spawn_local;
use std::rc::Rc;
use std::cell::RefCell;
use wasm_bindgen::prelude::Closure;
use leptos::logging::log;

/// 方块形状枚举
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum Tetromino {
   I, // I形
   J, // J形
   L, // L形
   O, // O形
   S, // S形
   T, // T形
   Z, // Z形
}

/// 游戏方向枚举
#[derive(Clone, Copy, PartialEq)]
pub enum Direction {
   Left,
   Right,
   Down,
}

/// 游戏状态结构体
#[derive(Clone)]
pub struct Game {
   pub grid: [[Option<Tetromino>; 10]; 20], // 10x20游戏网格
   pub current_piece: (Tetromino, [[i32; 2]; 4]), // 当前方块及其位置
   pub next_piece: (Tetromino, u8), // 下一个方块及其旋转状态
   pub score: u32, // 当前得分
   pub level: u32, // 当前等级
   pub game_over: bool, // 游戏是否结束
   pub paused: bool, // 游戏是否暂停
   pub is_locked: bool, // 方块是否已锁定
   pub current_rotation: u8, // 当前旋转状态(0-3)
}

impl Game {
   /// 创建新游戏实例
   pub fn new() -> Self {
       let mut game = Game {
           grid: [[None; 10]; 20],
           current_piece: (Tetromino::I, [[0; 2]; 4]),
           next_piece: (Self::random_tetromino(), (rand::random::<f32>() * 4.0).floor() as u8),
           score: 0,
           level: 1,
           game_over: false,
           paused: false,
           is_locked: false,
           current_rotation: 0,
       };
       game.spawn_piece();
       game
   }

   /// 随机生成方块
   fn random_tetromino() -> Tetromino {
       use rand::random;
       let piece = match (random::<f64>() * 7.0).floor() as u8 {
           0 => Tetromino::I,
           1 => Tetromino::J,
           2 => Tetromino::L,
           3 => Tetromino::O,
           4 => Tetromino::S,
           5 => Tetromino::T,
           _ => Tetromino::Z,
       };
       log!("Generated new piece: {:?}", piece);
       piece
   }

   /// 生成新方块
   fn spawn_piece(&mut self) {
       //log!("[SPAWN] Current state - next_piece: {:?}, current_piece: {:?}",
       //    self.next_piece, self.current_piece.0);
       
       // 保存当前预览方块及其旋转状态
       let (current_falling, preview_rotation) = self.next_piece;
       let actual_rotation = preview_rotation % 4;
       //log!("[SPAWN] Will spawn: {:?} with preview_rotation {:?} (actual: {:?})",
       //    current_falling, preview_rotation, actual_rotation);
       
       // 验证旋转状态一致性
       //log!("[ROTATION VERIFY] Preview rotation: {}, Actual rotation: {}",
       //    preview_rotation, actual_rotation);
       
       // 确保预览和实际方块类型一致
       //log!("[SPAWN] Verifying piece types - preview: {:?}, actual: {:?}",
       //    current_falling, self.next_piece.0);
       
       // 设置当前方块状态
       self.current_piece.0 = current_falling;
       self.is_locked = false;
       self.current_rotation = actual_rotation; // 确保旋转状态同步
       
       // 使用与预览完全相同的旋转状态计算方式
       let positions = match (current_falling, actual_rotation) {
           // 调整初始位置,确保最下端在第0行,其他部分可以在第0行以上
           (Tetromino::I, 0) => [[-2, 3], [-2, 4], [-2, 5], [-2, 6]],  // I型水平
           (Tetromino::I, 1) => [[-3, 4], [-2, 4], [-1, 4], [0, 4]],    // I型垂直
           (Tetromino::I, 2) => [[-2, 3], [-2, 4], [-2, 5], [-2, 6]],   // I型水平(反向)
           (Tetromino::I, 3) => [[-3, 4], [-2, 4], [-1, 4], [0, 4]],    // I型垂直(反向)
           (Tetromino::O, _) => [[-1, 4], [-1, 5], [0, 4], [0, 5]],     // O型
           (Tetromino::J, 0) => [[-1, 4], [0, 4], [0, 5], [0, 6]],      // J型初始
           (Tetromino::J, 1) => [[-2, 5], [-2, 6], [-1, 5], [0, 5]],    // J型90度
           (Tetromino::J, 2) => [[-1, 4], [-1, 5], [-1, 6], [0, 6]],    // J型180度
           (Tetromino::J, 3) => [[-2, 5], [-1, 5], [0, 5], [0, 4]],     // J型270度
           (Tetromino::L, 0) => [[-1, 6], [0, 4], [0, 5], [0, 6]],      // L型初始
           (Tetromino::L, 1) => [[-2, 4], [-1, 4], [0, 4], [0, 5]],     // L型90度
           (Tetromino::L, 2) => [[-1, 4], [-1, 5], [-1, 6], [0, 4]],    // L型180度
           (Tetromino::L, 3) => [[-2, 4], [-2, 5], [-1, 5], [0, 5]],     // L型270度
           (Tetromino::S, 0) => [[-1, 5], [-1, 6], [0, 4], [0, 5]],     // S型初始(右凸)
           (Tetromino::S, 1) => [[-2, 5], [-1, 5], [-1, 6], [0, 6]],    // S型90度(左凸)
           (Tetromino::S, 2) => [[-1, 5], [-1, 6], [0, 4], [0, 5]],    // S型180度(右凸)
           (Tetromino::S, 3) => [[-2, 4], [-1, 4], [-1, 5], [0, 5]],    // S型270度(左凸)
           (Tetromino::T, 0) => [[-1, 5], [0, 4], [0, 5], [0, 6]],      // T型初始
           (Tetromino::T, 1) => [[-2, 5], [-1, 5], [-1, 6], [0, 5]],    // T型90度
           (Tetromino::T, 2) => [[-1, 4], [-1, 5], [-1, 6], [0, 5]],    // T型180度
           (Tetromino::T, 3) => [[-2, 5], [-1, 4], [-1, 5], [0, 5]],    // T型270度
           (Tetromino::Z, 0) => [[-1, 4], [-1, 5], [0, 5], [0, 6]],     // Z型初始
           (Tetromino::Z, 1) => [[-2, 6], [-1, 5], [-1, 6], [0, 5]],    // Z型90度
           (Tetromino::Z, 2) => [[-1, 4], [-1, 5], [0, 5], [0, 6]],     // Z型180度
           (Tetromino::Z, 3) => [[-2, 5], [-1, 4], [-1, 5], [0, 4]],    // Z型270度
           _ => unreachable!("Invalid rotation state"),
       };
       //log!("[POSITION] Final positions for {:?} with rotation {}: {:?}",
       //    current_falling, actual_rotation, positions);
       //log!("[POSITION] Calculated positions for {:?} with rotation {}: {:?}",
       //    current_falling, actual_rotation, positions);
       self.current_piece.1 = positions;
       
       // 生成新预览方块及随机旋转状态(0-3)
       let new_piece = Self::random_tetromino();
       let new_rotation = (rand::random::<f32>() * 4.0).floor() as u8;
       let new_preview = (new_piece, new_rotation);
       
       //log!("[SPAWN] Generated new preview: {:?} with rotation {} (will be next piece)",
       //    new_preview.0, new_preview.1);
       
       // 双重验证预览方块类型
       if new_preview.0 != current_falling {
           log!("[SPAWN] Preview and current piece match verified");
       }
       
       // 更新预览方块
       self.next_piece = new_preview;
       //log!("[SPAWN] Updated next_piece to: {:?}", self.next_piece);
       
       //log!("[SPAWN] After update - next_piece: {:?}, current_piece: {:?}",
       //    self.next_piece, self.current_piece.0);
       
       // 检查新方块位置是否有效(允许部分超出顶部)
       let dropped_pos = self.get_dropped_position();
       if !self.is_valid_position(&dropped_pos) || dropped_pos == self.current_piece.1 {
           self.lock_piece();
       } else {
           // 检查新方块位置是否有效(允许部分超出顶部)
           let mut valid_spawn = true;
           for &[i, j] in &self.current_piece.1 {
               if j < 0 || j >= 10 || i >= 20 || (i >= 0 && self.grid[i as usize][j as usize].is_some()) {
                   valid_spawn = false;
                   break;
               }
           }
           self.game_over = !valid_spawn;
       }
   }

   /// 检查方块是否完全无法移动
   fn is_piece_stuck(&self) -> bool {
       // 检查方块是否无法继续下落
       for &[i, j] in &self.current_piece.1 {
           // 如果方块在网格内(i >= 0)
           if i >= 0 {
               // 检查是否到达底部或下方有方块
               if i >= 19 || self.grid[(i + 1) as usize][j as usize].is_some() {
                   return true;
               }
           }
       }
       false
   }

   /// 移动方块
   pub fn move_piece(&mut self, direction: Direction) {
       if self.game_over || self.paused || self.is_locked {
           return;
       }

       let mut new_positions = self.current_piece.1;
       
       // 计算新位置
       for pos in &mut new_positions {
           match direction {
               Direction::Left => pos[1] -= 1,
               Direction::Right => pos[1] += 1,
               Direction::Down => pos[0] += 1,
           }
       }

       // 检查新位置是否有效
       if self.is_valid_position(&new_positions) {
           self.current_piece.1 = new_positions;
           
           // 如果是向下移动
           if direction == Direction::Down {
               // 检查是否已经到底部
               if self.is_piece_stuck() {
                   self.lock_piece();
                   return; // 锁定后立即返回,防止后续移动
               }
           } else if self.is_piece_stuck() {
               // 其他方向移动时检查是否卡住
               self.lock_piece();
               return; // 锁定后立即返回,防止后续移动
           }
       } else if direction == Direction::Down && self.is_piece_stuck() {
           // 如果向下移动无效且方块卡住,也锁定
           self.lock_piece();
       }
   }

   /// 旋转方块
   pub fn rotate_piece(&mut self) {
       if self.game_over || self.paused || self.current_piece.0 == Tetromino::O {
           return; // O方块不需要旋转
       }

       // 获取当前旋转状态(0-3)
       let current_rot = self.current_rotation;
       //log!("[ROTATE] Rotating {:?} from state {}", self.current_piece.0, current_rot);
       
       // 根据方块类型定义精确旋转中心(取第二和第三个方块中间)
       let (center_x, center_y) = match self.current_piece.0 {
           Tetromino::I => (
               (self.current_piece.1[1][0] + self.current_piece.1[2][0]) / 2,
               (self.current_piece.1[1][1] + self.current_piece.1[2][1]) / 2
           ),
           Tetromino::O => (self.current_piece.1[0][0] + 1, self.current_piece.1[0][1] + 1), // O型中心在四个方块中间
           Tetromino::J => (
               (self.current_piece.1[1][0] + self.current_piece.1[2][0]) / 2,
               (self.current_piece.1[1][1] + self.current_piece.1[2][1]) / 2
           ),
           Tetromino::L => (
               (self.current_piece.1[1][0] + self.current_piece.1[2][0]) / 2,
               (self.current_piece.1[1][1] + self.current_piece.1[2][1]) / 2
           ),
           Tetromino::S => (
               (self.current_piece.1[1][0] + self.current_piece.1[2][0]) / 2,
               (self.current_piece.1[1][1] + self.current_piece.1[2][1]) / 2
           ),
           Tetromino::Z => (
               (self.current_piece.1[1][0] + self.current_piece.1[2][0]) / 2,
               (self.current_piece.1[1][1] + self.current_piece.1[2][1]) / 2
           ),
           Tetromino::T => (self.current_piece.1[1][0], self.current_piece.1[1][1]), // T型中心取第二个方块
       };
       //log!("[ROTATE] Fixed center for {:?}: ({}, {})", self.current_piece.0, center_x, center_y);

       let mut new_positions = self.current_piece.1.clone();
       
       // 应用旋转
       for pos in &mut new_positions {
           // 计算相对于中心的坐标
           let x = pos[1] - center_y;
           let y = pos[0] - center_x;
           
           // 应用标准90度顺时针旋转矩阵
           let new_x = -y;
           let new_y = x;
           
           // 计算新位置
           pos[1] = center_y + new_x;
           pos[0] = center_x + new_y;
       }

       // 尝试原始位置
       if self.is_valid_position(&new_positions) {
           self.apply_rotation(new_positions, current_rot);
           return;
       }

       // 墙踢: 尝试左右移动1-2格
       for offset in [1, -1, 2, -2].iter() {
           let mut kicked_positions = new_positions.clone();
           for pos in &mut kicked_positions {
               pos[1] += offset;
           }
           
           if self.is_valid_position(&kicked_positions) {
               self.apply_rotation(kicked_positions, current_rot);
               //log!("[ROTATE] Applied wall kick with offset {}", offset);
               return;
           }
       }

       //log!("[ROTATE] Rotation failed - all positions invalid");
   }


   /// 检查位置是否有效
   fn is_valid_position(&self, positions: &[[i32; 2]; 4]) -> bool {
       for &[i, j] in positions {
           // 允许i<0(顶部以上),只要j在有效范围内
           // 仅检查网格内(i>=0)的方块重叠
           if j < 0 || j >= 10 || i >= 20 || (i >= 0 && self.grid[i as usize][j as usize].is_some()) {
               return false;
           }
       }
       true
   }

   /// 获取下落到底部的位置
   fn get_dropped_position(&self) -> [[i32; 2]; 4] {
       let mut dropped = self.current_piece.1;
       loop {
           for pos in &mut dropped {
               pos[0] += 1;
           }
           if !self.is_valid_position(&dropped) {
               for pos in &mut dropped {
                   pos[0] -= 1;
               }
               break;
           }
       }
       dropped
   }

   /// 硬降(直接下落到底部)
   pub fn hard_drop(&mut self) {
       if self.game_over || self.paused {
           return;
       }

       self.current_piece.1 = self.get_dropped_position();
       self.lock_piece();
   }

   /// 固定当前方块到网格
   fn lock_piece(&mut self) {
       if self.is_locked || self.game_over {
           return;
       }
       
       let piece_type = self.current_piece.0;
       for &[i, j] in &self.current_piece.1 {
           if i >= 0 {
               self.grid[i as usize][j as usize] = Some(piece_type);
               // 如果方块被锁定在第0行,游戏结束
               if i == 0 {
                   self.game_over = true;
               }
           }
       }
       self.is_locked = true;
       self.clear_lines();
       
       if !self.game_over {
           self.spawn_piece();
       }
   }

   /// 应用旋转并更新状态(内部方法)
   pub(crate) fn apply_rotation(&mut self, positions: [[i32; 2]; 4], current_rot: u8) {
       self.current_piece.1 = positions;
       self.current_rotation = (current_rot + 1) % 4;
       //log!("[ROTATE] Success! New state: {}", self.current_rotation);
       //log!("[ROTATE] New positions: {:?}", self.current_piece.1);
       
       // 旋转后检查是否卡住
       if self.is_piece_stuck() {
           self.lock_piece();
       }
   }

   /// 清除完整的行
   fn clear_lines(&mut self) {
       let mut lines_cleared = 0;
       
       // 从下往上扫描
       let mut row = 19;
       while row > 0 {
           if self.grid[row].iter().all(|cell| cell.is_some()) {
               lines_cleared += 1;
               // 将上方行下移
               for move_row in (1..=row).rev() {
                   self.grid[move_row] = self.grid[move_row - 1];
               }
               // 清空最顶行
               self.grid[0] = [None; 10];
               // 继续检查当前行(因为上方行已经下移)
               continue;
           }
           row -= 1;
       }

       // 更新分数
       match lines_cleared {
           1 => self.score += 100 * self.level,
           2 => self.score += 300 * self.level,
           3 => self.score += 500 * self.level,
           4 => self.score += 800 * self.level,
           _ => (),
       }

       // 更新等级
       if lines_cleared > 0 {
           self.level = (self.score / 2000) + 1;
       }
   }

   /// 暂停/继续游戏
   pub fn toggle_pause(&mut self) {
       if !self.game_over {
           self.paused = !self.paused;
       }
   }
}

/// 游戏界面组件
#[component]
pub fn TetrisGameBoard() -> impl IntoView {
   // 创建游戏状态信号
   let (game, set_game) = signal(Game::new());
   
   // 设置游戏循环(自动下落)
   let tick = move || {
       set_game.update(|g| {
           if !g.game_over && !g.paused {
               g.move_piece(Direction::Down);
           }
       });
   };
   
   // 每500ms触发一次下落(速度随等级提高)
   let tick_interval = move || {
       500.0 / (game.get_untracked().level as f64).max(1.0)
   };
   
   // 使用Leptos的spawn_local和web_sys的set_timeout实现游戏循环
   spawn_local(async move {
       let window = web_sys::window().expect("no global window exists");
       let closure: Rc<RefCell<Option<Closure<dyn FnMut()>>>> = Rc::new(RefCell::new(None));
       let closure_clone = Rc::clone(&closure);
       
       *closure_clone.borrow_mut() = Some(Closure::<dyn FnMut()>::new({
           let closure_clone = Rc::clone(&closure_clone);
           let window = window.clone();
           move || {
               if !game.get_untracked().game_over && !game.get_untracked().paused {
                   tick();
               }
               
               let interval = tick_interval();
               window.set_timeout_with_callback_and_timeout_and_arguments_0(
                   closure_clone.borrow().as_ref().unwrap().as_ref().unchecked_ref(),
                   interval as i32
               ).expect("failed to set timeout");
           }
       }));
       
       // 初始调用
       window.set_timeout_with_callback_and_timeout_and_arguments_0(
           closure.borrow().as_ref().unwrap().as_ref().unchecked_ref(),
           tick_interval() as i32
       ).expect("failed to set timeout");
   });
   
   // 监听键盘事件
   let key_listener = window_event_listener(ev::keydown, move |ev| {
       if game.get().game_over {
           return;
       }
       ev.prevent_default();
       match &ev.key()[..] {
           "ArrowLeft" => set_game.update(|g| g.move_piece(Direction::Left)),
           "ArrowRight" => set_game.update(|g| g.move_piece(Direction::Right)),
           "ArrowDown" => set_game.update(|g| g.move_piece(Direction::Down)),
           "ArrowUp" => set_game.update(|g| g.rotate_piece()),
           " " => {
               if !game.get().paused {
                   set_game.update(|g| g.hard_drop());
               }
           },
           "p" | "P" => set_game.update(|g| g.toggle_pause()),
           _ => (),
       }
   });
   
   // 组件卸载时清理事件监听器和闭包
   on_cleanup(move || {
       key_listener.remove();
       // 闭包会在离开作用域时自动释放
   });
   
   // 根据方块类型返回对应的CSS颜色类
   fn tile_color(tile: Option<Tetromino>) -> &'static str {
       if let Some(t) = tile {
           match t {
               Tetromino::I => "tetromino-i",
               Tetromino::J => "tetromino-j",
               Tetromino::L => "tetromino-l",
               Tetromino::O => "tetromino-o",
               Tetromino::S => "tetromino-s",
               Tetromino::T => "tetromino-t",
               Tetromino::Z => "tetromino-z",
           }
       } else {
           "tetromino-empty"
       }
   }
   
   // 渲染预览方块
   fn render_preview((tetromino, rotation): (Tetromino, u8)) -> impl IntoView {
       // 使用与实际方块相同的旋转状态
       let rotation_mod = rotation % 4;
       //log!("[PREVIEW] Rendering {:?} with rotation {}", tetromino, rotation_mod);
       
       // 使用与实际方块相同的精确旋转中心(取第二和第三方块中间)
       let (center_x, center_y) = match tetromino {
           Tetromino::I => (1, 2),  // I型中心(第二和第三方块中间)
           Tetromino::O => (1, 1),  // O型中心(四个方块中间)
           Tetromino::J => (1, 1),  // J型中心(第二和第三方块中间)
           Tetromino::L => (1, 1),  // L型中心(第二和第三方块中间)
           Tetromino::S => (1, 1),  // S型中心(第二和第三方块中间)
           Tetromino::Z => (1, 1),  // Z型中心(第二和第三方块中间)
           Tetromino::T => (1, 1),  // T型中心(第二个方块)
       };

       // 根据旋转状态计算相对位置
       let positions = match (tetromino, rotation_mod) {
           (Tetromino::I, 0) => vec![(center_x, center_y-2), (center_x, center_y-1), (center_x, center_y), (center_x, center_y+1)],
           (Tetromino::I, 1) => vec![(center_x-1, center_y), (center_x, center_y), (center_x+1, center_y), (center_x+2, center_y)],
           (Tetromino::I, 2) => vec![(center_x, center_y-2), (center_x, center_y-1), (center_x, center_y), (center_x, center_y+1)],
           (Tetromino::I, 3) => vec![(center_x-1, center_y), (center_x, center_y), (center_x+1, center_y), (center_x+2, center_y)],
           (Tetromino::O, _) => vec![(center_x, center_y), (center_x, center_y+1), (center_x+1, center_y), (center_x+1, center_y+1)],
           // J型方块定义
           (Tetromino::J, 0) => vec![(center_x, center_y), (center_x+1, center_y), (center_x+1, center_y+1), (center_x+1, center_y+2)],
           (Tetromino::J, 1) => vec![(center_x, center_y+1), (center_x, center_y+2), (center_x+1, center_y+1), (center_x+2, center_y+1)],
           (Tetromino::J, 2) => vec![(center_x+1, center_y), (center_x+1, center_y+1), (center_x+1, center_y+2), (center_x+2, center_y+2)],
           (Tetromino::J, 3) => vec![(center_x, center_y+1), (center_x+1, center_y+1), (center_x+2, center_y), (center_x+2, center_y+1)],
           // L型方块定义
           (Tetromino::L, 0) => vec![(center_x, center_y+2), (center_x+1, center_y), (center_x+1, center_y+1), (center_x+1, center_y+2)],
           (Tetromino::L, 1) => vec![(center_x, center_y+1), (center_x+1, center_y+1), (center_x+2, center_y+1), (center_x+2, center_y+2)],
           (Tetromino::L, 2) => vec![(center_x+1, center_y), (center_x+1, center_y+1), (center_x+1, center_y+2), (center_x+2, center_y)],
           (Tetromino::L, 3) => vec![(center_x, center_y), (center_x, center_y+1), (center_x+1, center_y+1), (center_x+2, center_y+1)],
           (Tetromino::S, 0) => vec![(center_x, center_y), (center_x, center_y+1), (center_x+1, center_y-1), (center_x+1, center_y)],
           (Tetromino::S, 1) => vec![(center_x-1, center_y), (center_x, center_y), (center_x, center_y+1), (center_x+1, center_y+1)],
           (Tetromino::S, 2) => vec![(center_x-1, center_y), (center_x-1, center_y+1), (center_x, center_y-1), (center_x, center_y)],
           (Tetromino::S, 3) => vec![(center_x-1, center_y-1), (center_x, center_y-1), (center_x, center_y), (center_x+1, center_y)],
           (Tetromino::T, 0) => vec![(center_x, center_y), (center_x+1, center_y-1), (center_x+1, center_y), (center_x+1, center_y+1)],
           (Tetromino::T, 1) => vec![(center_x-1, center_y), (center_x, center_y), (center_x, center_y+1), (center_x+1, center_y)],
           (Tetromino::T, 2) => vec![(center_x, center_y-1), (center_x, center_y), (center_x, center_y+1), (center_x-1, center_y)],
           (Tetromino::T, 3) => vec![(center_x-1, center_y), (center_x, center_y-1), (center_x, center_y), (center_x+1, center_y)],
           // Z型方块定义
           (Tetromino::Z, 0) => vec![(center_x, center_y), (center_x, center_y+1), (center_x+1, center_y+1), (center_x+1, center_y+2)],
           (Tetromino::Z, 1) => vec![(center_x, center_y+1), (center_x+1, center_y), (center_x+1, center_y+1), (center_x+2, center_y)],
           (Tetromino::Z, 2) => vec![(center_x, center_y), (center_x, center_y+1), (center_x+1, center_y+1), (center_x+1, center_y+2)],
           (Tetromino::Z, 3) => vec![(center_x, center_y+1), (center_x+1, center_y), (center_x+1, center_y+1), (center_x+2, center_y)],
           _ => unreachable!("Invalid rotation state"),
       };
       //log!("[PREVIEW] Calculated relative positions: {:?}", positions);
       
       view! {
           <div style="display: grid; grid-template-columns: repeat(4, 20px); grid-template-rows: repeat(4, 20px); width: 80px; height: 80px; gap: 1px;">
               {positions.into_iter().map(|(i, j)| {
                   view! {
                       <div
                           style=format!("grid-row: {}; grid-column: {};", i + 1, j + 1)
                           class=format!("{} tetromino-border", tile_color(Some(tetromino)))
                       ></div>
                   }
               }).collect::<Vec<_>>()}
           </div>
       }
   }
   
   // 重置游戏函数
   let reset = move |_| {
       set_game.update(|g| *g = Game::new());
   };
   
   // 暂停/继续游戏函数
   let toggle_pause = move |_| {
       set_game.update(|g| g.toggle_pause());
   };
   
   // 游戏界面视图
   view! {
       <div class="game-container">
           <div class="game-header">
               //<h1 class="game-title" style="display: block; text-align: center; width: 100%; margin-bottom: 1rem;">"俄罗斯方块"</h1>
               <div class="game-controls-container">
                   <div class="game-scores-container">
                       <div class="game-score-box">
                           <div class="game-score-label">"得分:"{move || game.get().score}</div>
                       </div>
                       <div class="game-score-box">
                           <div class="game-score-label">"等级:"{move || game.get().level}</div>
                       </div>
                   </div>
                   <div class="game-buttons-container">
                       <button
                           on:click=toggle_pause
                           class="game-button"
                       >
                           {move || if game.get().paused { "继续" } else { "暂停" }}
                       </button>
                       <button
                           on:click=reset
                           class="game-button"
                       >
                           "新游戏"
                       </button>
                   </div>
               </div>
           </div>
           
           <div style="display: flex; justify-content: space-between; align-items: flex-start; width: 100%; margin-top: 1rem;">
               <div class="game-main-area">
                   <div class="game-board">
                       <div style="display: grid; grid-template-columns: repeat(10, 24px); grid-template-rows: repeat(20, 24px); gap: 1px;">
                           {move || {
                               // 创建网格副本用于渲染
                               let mut render_grid = game.get().grid.clone();
                               
                               // 添加当前方块到渲染网格
                               if !game.get().game_over {
                                   for &[i, j] in &game.get().current_piece.1 {
                                       if i >= 0 {
                                           render_grid[i as usize][j as usize] = Some(game.get().current_piece.0);
                                       }
                                   }
                               }
                               
                               // 渲染网格
                               render_grid.iter().flat_map(|row| {
                                   row.iter().map(|&tile| {
                                       view! {
                                           <div class=format!("{} tetromino-border", tile_color(tile))></div>
                                       }
                                   })
                               }).collect::<Vec<_>>()
                           }}
                       </div>
                   </div>
               </div>
               
               <div class="game-side-panel">
                   <div class="game-preview">
                       <h2 class="game-preview-title">"下一个"</h2>
                       {move || {
                           let (tetromino, rotation) = game.get().next_piece;
                           render_preview((tetromino, rotation))
                       }}
                   </div>
                   
                   <div class="game-instructions">
                       <h2 class="game-instructions-title">"操作说明"</h2>
                       <ul class="game-instructions-list">
                           <li>"← → : 左右移动"</li>
                           <li>"↓ : 加速下落"</li>
                           <li>"↑ : 旋转方块"</li>
                           <li>"空格 : 硬降到底部"</li>
                           <li>"P : 暂停/继续"</li>
                       </ul>
                   </div>
               </div>
           </div>
           
           {/* 游戏结束提示 */}
           <Show when=move || game.get().game_over>
               <div class="game-over-message">
                   "游戏结束! 最终得分: " {move || game.get().score}
               </div>
           </Show>
           
           {/* 暂停提示 */}
           <Show when=move || game.get().paused>
               <div class="game-paused-message">
                   "游戏暂停"
               </div>
           </Show>
       </div>
   }
}

AI写代码
rust
运行

DeepSeek刚写出来的程序bug比较多,要一步一步引导其修改完善。游戏界面的css设置文件内容如下:

/* 俄罗斯方块颜色 */
.tetromino-i {
 background-color: #06b6d4; /* I方块 - 青色 */
}

.tetromino-l {
 background-color: #f97316; /* L方块 - 橙色 */
}

.tetromino-z {
 background-color: #ef4444; /* Z方块 - 红色 */
}

.tetromino-j {
 background-color: #2563eb; /* J方块 - 深蓝色 */
}

.tetromino-s {
 background-color: #10b981; /* S方块 - 绿色 */
}

.tetromino-o {
 background-color: #facc15; /* O方块 - 黄色 */
}

.tetromino-t {
 background-color: #a855f7; /* T方块 - 紫色 */
}

.tetromino-empty {
 background-color: #1f2937; /* 空单元格 - 深灰色 */
}

/* 边框样式 */
.tetromino-border {
 border: 1px solid #374151;
}

/* 按钮样式 */
.game-button {
 background-color: #3b82f6;
 color: #000;
 padding: 0.5rem 1rem;
 border-radius: 0.25rem;
 margin: 10px 5px;
}

.game-button:hover {
 background-color: #2563eb;
}

/* 容器样式 */
.game-container {
 width: 550px;
 margin-left: auto;
 margin-right: auto;
 padding: 1rem;
}

.game-header {
 display: block;
 margin-bottom: 1rem;
}

.game-title {
 font-size: 1.875rem;
 font-weight: bold;
 text-align: center;
 margin-bottom: 1rem;
 display: block;
}

.game-score-container {
 display: flex;
 justify-content: center;
 gap: 1rem;
 margin-bottom: 1rem;
}

.game-title {
 font-size: 1.875rem;
 font-weight: bold;
}

.game-controls-container {
 display: flex;
 justify-content: center;
 align-items: center;
 gap: 2rem;
 width: 100%;
}

.game-scores-container {
 display: flex;
 gap: 1rem;
 align-items: center;
 justify-content: center;
}

.game-buttons-container {
 display: flex;
 gap: 1rem;
 align-items: center;
 justify-content: center;
}

.game-score-box {
 display: flex;
 flex-direction: column;
 align-items: center;
 justify-content: center;
 text-align: center;
}

.game-score-container {
 display: flex;
 gap: 1rem;
}

.game-score-box {
 background-color: #e5e7eb;
 padding: 0.5rem;
 border-radius: 0.25rem;
}

.game-score-label {
 font-size: 1rem;
 font-weight: bold;
}

.game-score-value {
 font-size: 1.25rem;
 font-weight: bold;
}

.game-content-wrapper {
 display: flex;
 gap: 1rem;
}

.game-main-area {
 width:250px;
 margin:0px 0px 0px 10px;
}

.game-board {
 width:100%;
 background-color: #1f2937;
 padding: 0.5rem;
 border-radius: 0.5rem;
}

.game-side-panel {
 width:250px;
}

.game-preview {
 width:100%;
 background-color: #e5e7eb;
 padding: 1rem;
 border-radius: 0.25rem;
}

.game-instructions {
 width:100%;
 background-color: #e5e7eb;
 padding: 1rem;
 border-radius: 0.25rem;
}

.game-over-message {
 margin-top: 1rem;
 padding: 1rem;
 background-color: #ef4444;
 color: #000;
 border-radius: 0.25rem;
 text-align: center;
}

.game-paused-message {
 margin-top: 1rem;
 padding: 1rem;
 background-color: #facc15;
 color: #000;
 border-radius: 0.25rem;
 text-align: center;
}
AI写代码
css

总体而言,DeekSeek辅助编程效率还是很高的,对于编程初学者尤其方便。
————————————————


湘公网安备43012102001039    湘ICP备14007447号-1    邮箱:35744243#qq.com