游戏理解入门:Rust+Bracket开发一个小游戏

news2024/11/20 20:31:51

1. Game loop

使用game loop可以使得游戏运行更加流畅和顺滑,它可以:

  • 初始化窗口、图形和其他资源;
  • 每当屏幕刷新他都会运行(通常是每秒30,60 );
  • 每次通过循环,他都会调用游戏的tick()函数。

大致的原理流程如下:

image-20240428105116174


2. 游戏引擎/库

这里选择使用一款名为bracket-Lib的游戏编程库,这是基于rust

  • 抽象了游戏开发中很多复杂的东西,但是保留了相关的概念,可以作为简单的教学工具。
  • 包括了随机数生成、几何、寻路、颜色处理、常用算法等。

2.1 Bracket-terminal

这个终端主要负责Bracket-Lib中的显示部分。

  • 提供了模拟控制台;
  • 可以与多种渲染平台配合
    • 从文本控制台到Web Assembly
    • 例如:OpenGL,Vulkan,Metal;
  • 支持sprites和原生的OpenGL开发。

2.2 Codepage437

  • 这是IBM扩展的ACSLL字符集。来自Dos PC上得到字符,用于终端输出,除了字母和数字,还提供一些符号。
  • Bracket-lib会把字符翻译为图形sprites并提供一个有限的字符集,字符所展示的是相应的图片;

3. 开始编码

3.1 游戏窗口初始化

使用cargo new创建游戏项目并导入Gracket-lib依赖。下面是第一部分代码实现,创建了游戏终窗口并打印一条简单的输出:

use bracket_lib::prelude::*;

// 保留帧状态

struct State {

}

// 状态怎么和哟游戏帧关联上呢?,这就用到了一个名为GaemState的trait
impl GameState for State {
    // 实现tick函数
    fn tick(&mut self, ctx: &mut BTerm) {
        // 清屏
        ctx.cls();
        // 在屏幕上打印输出,坐标系x,y从屏幕左上角开始计算(0,0)
        ctx.print(1, 1, "Hello,Bracket Terminall!");


    }
}
fn main() -> BError {
    // 创建一个80x50的简单窗口,标题为游戏名称,?表示这个build可能会出错,出错就捕获返回,否则成功
    let context = BTermBuilder::simple80x50()
    .with_title("Flappy Dragon")
    .build()?;
    
    main_loop (context,State{})
}

运行结果:

image-20240428112645545


3.2 游戏模式

一般情况下,游戏都是有一些明确的游戏模式,每种模式会明确游戏在当前的tick()中应该作的任务。

这个游戏也不例外,主要涉及三种模式:

  • 菜单
  • 游戏中
  • 结束

下面先将大致的框架构建好。

use bracket_lib::prelude::*;

// 保留帧状态
struct State {
    mode:GameMode,

}
// 为游戏状态实现一个叫new的关联函数
impl State {
    fn new() ->Self {
        State {
            mode:GameMode::Menu, // 设置游戏初始状态为菜单模式
        }
    }

    // 实现play方法
    fn play(&mut self,ctx:&mut BTerm) {
        //TODO
		self.mode = GameMode::End;
    }
    
  	// restart
    fn resatrt(&mut self) {
        self.mode = GameMode::Playing;
    }
    
    fn main_menu(&mut self, ctx: &mut BTerm) {
        // TODO

    }
    
    // 实现end方法
    fn dead(&mut self, ctx: &mut BTerm) {
        
    }
    
    // 实现menu方法
    
}
// 游戏模式枚举并存储到游戏状态中
enum GameMode{
    Menu,
    Playing,
    End,
}


// 状态怎么和哟游戏帧关联上呢?,这就用到了一个名为GaemState的trait
impl GameState for State {
    // 实现tick函数
    fn tick(&mut self, ctx: &mut BTerm) {
        // 根据游戏状态选择方向
        match self.mode {
            GameMode::Menu =>self.main_menu(ctx),
            GameMode::Playing => self.dead(ctx),
            GameMode::End => self.play(ctx),
        }
        
    }
}
fn main() -> BError {
    // 创建一个80x50的简单窗口,标题为游戏名称,?表示这个build可能会出错,出错就捕获返回,否则成功
    let context = BTermBuilder::simple80x50()
    .with_title("Flappy Dragon")
    .build()?;
    
    main_loop (context,State::new())
}

3.2.1 游戏菜单实现

游戏菜单的实现逻辑比较简单,主要是提供一个游戏操作的入口以供玩家进行选择操作:

  • 清理屏幕
  • 打印欢迎语
  • 开始游戏§
  • 离开游戏(Q)
fn main_menu(&self, ctx: &mut BTerm) {
    // TODO
    ctx.cls();
    // print_centered会在屏幕水平中间位置进行打印
    ctx.print_centered( 5,"欢迎来到Flappy Dragon!");
    ctx.print_centered( 8, "(P) 开始游戏");
    ctx.print_centered(9, " (Q) 离开游戏");

    if let Some(key) =ctx.key {
        match key {
            VirtualKeyCode::P => self.resatrt(),
            VirtualKeyCode::Q => ctx.quitting = true,
            _ => {}
        }
    }
}

3.2.2 游戏结束的实现

这块代码和游戏菜单差不多,把提示词换一下

// 实现end方法
fn dead(&mut self, ctx: &mut BTerm) {
    ctx.cls();
    // print_centered会在屏幕水平中间位置进行打印
    ctx.print_centered( 5,"小菜鸡,你已经嘎了!");
    ctx.print_centered( 8, "(P) 不服,再战");
    ctx.print_centered(9, " (Q) 离开游戏" );

    if let Some(key) =ctx.key {
        match key {
            VirtualKeyCode::P => self.resatrt(),
            VirtualKeyCode::Q => ctx.quitting = true,
            _ => {}
        }
    }
}

3.3.3 第一阶段效果

下面是该阶段全部代码,实现了游戏基本窗口以及三个基本模式的逻辑。

use bracket_lib::prelude::*;

// 保留帧状态
struct State {
    mode:GameMode,

}
// 为游戏状态实现一个叫new的关联函数
impl State {
    fn new() ->Self {
        State {
            mode:GameMode::Menu, // 设置游戏初始状态为菜单模式
        }
    }

    // 实现play方法
    fn play(&mut self,ctx:&mut BTerm) {
        //TODO
        self.mode = GameMode::End;
    }

    // menu方法
    fn main_menu(&mut self, ctx: &mut BTerm) {
        // TODO
        ctx.cls();
        // print_centered会在屏幕水平中间位置进行打印
        ctx.print_centered( 5,"Welcome to Flappy Dragon!");
        ctx.print_centered( 8, "(P) Start play");
        ctx.print_centered(9, " (Q) Quit game");
        
        if let Some(key) =ctx.key {
            match key {
                VirtualKeyCode::P => self.resatrt(),
                VirtualKeyCode::Q => ctx.quitting = true,
                _ => {}
            }
        }
    }

    // restart
    fn resatrt(&mut self) {
        self.mode = GameMode::Playing;
    }
    
    // 实现end方法
    fn dead(&mut self, ctx: &mut BTerm) {
        ctx.cls();
        // print_centered会在屏幕水平中间位置进行打印
        ctx.print_centered( 5,"You are dead!");
        ctx.print_centered( 8, "(P) replay");
        ctx.print_centered(9,  "(Q) quit game");
        
        if let Some(key) =ctx.key {
            match key {
                VirtualKeyCode::P => self.resatrt(),
                VirtualKeyCode::Q => ctx.quitting = true,
                _ => {}
            }
        }
    }
    
    
}
// 游戏模式枚举并存储到游戏状态中
enum GameMode{
    Menu,
    Playing,
    End,
}


// 状态怎么和哟游戏帧关联上呢?,这就用到了一个名为GaemState的trait
impl GameState for State {
    // 实现tick函数
    fn tick(&mut self, ctx: &mut BTerm) {
        // 根据游戏状态选择方向
        match self.mode {
            GameMode::Menu =>self.main_menu(ctx),
            GameMode::Playing => self.dead(ctx),
            GameMode::End => self.play(ctx),
        }
        
    }
}
fn main() -> BError {
    // 创建一个80x50的简单窗口,标题为游戏名称,?表示这个build可能会出错,出错就捕获返回,否则成功
    let context = BTermBuilder::simple80x50()
    .with_title("Flappy Dragon")
    .build()?;
    
    main_loop (context,State::new())
}

  • 运行效果:

image-20240428121025278


3.3 添加play

这部分主要在游戏窗口添加一个玩家角色,这里以字符@作为龙,实现玩家通过空格键控制该角色的上下移动:

  • 一定时间不按空格,角色会下落,当下落碰到屏幕时游戏失败并结束游戏;
  • 按下空格时,龙会网上移动。
use bracket_lib::prelude::*;

// 保留帧状态
struct State {
    player:Player,
    frame_time:f32,// 结果多少帧后累计的时间
    mode:GameMode,

}

const SCREEN_WIDTH:i32 = 80; // 屏幕宽度
const SCREEN_HEIGHT:i32 = 50; // 屏幕高度
const FRAME_DURATION:f32 = 75.0; //

struct Player {
    x:i32,
    y:i32,
    velocity:f32,// 纵向速度 > 0 玩家就会往下掉
}
// 游戏模式枚举并存储到游戏状态中
enum GameMode{
    Menu,
    Playing,
    End,
}
impl Player {
    fn new(x:i32,y:i32)-> Self {
        Player {
            x:0,
            y:0,
            velocity:0.0, // 下落更加丝滑
        }
    }

    // 使用'@’在屏幕上表示玩家
    fn render (&mut self,ctx:&mut BTerm) {
        ctx.set(0, self.y, YELLOW, BLACK, to_cp437('@'))
    }


    fn gravity_and_move (&mut self) {
        // 当下降速度小于2.0时让它的重力加速度每次增加0.2
        if self.velocity < 2.0 {
            self.velocity += 0.2;
        }

        self.y += self.velocity as i32;
        self.x += 1;

        if self.y < 0 {
            self.y = 0;
        }
    }
    // 按下空格实现玩家角色的向上移动
    fn flap (&mut self) {
        self.velocity = -2.0;
    }

}

// 为游戏状态实现一个叫new的关联函数
impl State {
    fn new() ->Self {
        State {
            player:Player::new(5,25),
            frame_time:0.0,
            mode:GameMode::Menu, // 设置游戏初始状态为菜单模式
        }
    }

    // 实现play方法
    fn play(&mut self,ctx:&mut BTerm) {
        ctx.cls_bg(NAVY);
        self.frame_time += ctx.frame_time_ms;

        if self.frame_time >FRAME_DURATION {
            self.frame_time = 0.0;
            self.player.gravity_and_move();
        }

        if let Some(VirtualKeyCode::Space) = ctx.key {
            self.player.flap();
        }

        self.player.render(ctx);
        ctx.print(0,0,  "Press Space to Flap");
        
        if self.player.y > SCREEN_HEIGHT {
            self.mode = GameMode::End;
        }
    }

    // menu方法
    fn main_menu(&mut self, ctx: &mut BTerm) {
        ctx.cls();
        // print_centered会在屏幕水平中间位置进行打印
        ctx.print_centered( 5,"Welcome to Flappy Dragon!");
        ctx.print_centered( 8, "(P) Play Game");
        ctx.print_centered(9,  "(Q) Quit Game");
        
        if let Some(key) =ctx.key {
            match key {
                VirtualKeyCode::P => self.mode = GameMode::Playing,
                VirtualKeyCode::Q => ctx.quitting = true,
                _ => {}
            }
        }
    }

    // restart
    fn resatrt(&mut self) {
        self.player = Player::new(5,25);
        self.frame_time = 0.0;
        self.mode = GameMode::Menu;
    }
    
    // 实现end方法
    fn dead(&mut self, ctx: &mut BTerm) {
        ctx.cls();
        // print_centered会在屏幕水平中间位置进行打印
        ctx.print_centered( 5,"You are dead!");
        ctx.print_centered( 8, "(P) replay");
        ctx.print_centered(9,  "(Q) quit game");
        
        if let Some(key) =ctx.key {
            match key {
                VirtualKeyCode::P => self.resatrt(),
                VirtualKeyCode::Q => ctx.quitting = true,
                _ => {}
            }
        }
    }
    
    
}



// 状态怎么和哟游戏帧关联上呢?,这就用到了一个名为GaemState的trait
impl GameState for State {
    // 实现tick函数
    fn tick(&mut self, ctx: &mut BTerm) {
        // 根据游戏状态选择方向
        match self.mode {
            GameMode::Menu =>self.main_menu(ctx),
            GameMode::Playing => self.play(ctx),
            GameMode::End => self.dead(ctx),
        }
    }
}
fn main() -> BError {
    // 创建一个80x50的简单窗口,标题为游戏名称,?表示这个build可能会出错,出错就捕获返回,否则成功
    let context = BTermBuilder::simple80x50()
    .with_title("Flappy Dragon")
    .build()?;
    
    main_loop (context,State::new())
}

3.4 添加障碍物

use std::fmt::format;

use bracket_lib::{prelude::*, random};

// 保留帧状态
struct State {
    player:Player,
    frame_time:f32,// 结果多少帧后累计的时间
    mode:GameMode,
    obstacle:Obstacle,
    score:i32,

}

const SCREEN_WIDTH:i32 = 80; // 屏幕宽度
const SCREEN_HEIGHT:i32 = 50; // 屏幕高度
const FRAME_DURATION:f32 = 75.0; //

struct Player {
    x:i32,
    y:i32,
    velocity:f32,// 纵向速度 > 0 玩家就会往下掉
}
// 游戏模式枚举并存储到游戏状态中
enum GameMode{
    Menu,
    Playing,
    End,
}
impl Player {
    fn new(x:i32,y:i32)-> Self {
        Player {
            x:0,
            y:0,
            velocity:0.0, // 下落更加丝滑
        }
    }

    // 使用'@’在屏幕上表示玩家
    fn render (&mut self,ctx:&mut BTerm) {
        ctx.set(0, self.y, YELLOW, BLACK, to_cp437('@'))
    }


    fn gravity_and_move (&mut self) {
        // 当下降速度小于2.0时让它的重力加速度每次增加0.2
        if self.velocity < 2.0 {
            self.velocity += 0.2;
        }

        self.y += self.velocity as i32;
        self.x += 1;

        if self.y < 0 {
            self.y = 0;
        }
    }
    // 按下空格实现玩家角色的向上移动
    fn flap (&mut self) {
        self.velocity = -2.0;
    }

}

// 为游戏状态实现一个叫new的关联函数
impl State {
    fn new() ->Self {
        State {
            player:Player::new(5,25),
            frame_time:0.0,
            mode:GameMode::Menu, // 设置游戏初始状态为菜单模式
            obstacle:Obstacle::new(SCREEN_WIDTH,0),
            score:0,
        }
    }

    // 实现play方法
    fn play(&mut self,ctx:&mut BTerm) {
        ctx.cls_bg(NAVY);
        self.frame_time += ctx.frame_time_ms;

        if self.frame_time >FRAME_DURATION {
            self.frame_time = 0.0;
            self.player.gravity_and_move();
        }

        if let Some(VirtualKeyCode::Space) = ctx.key {
            self.player.flap();
        }

        self.player.render(ctx);
        ctx.print(0,0,  "Press Space to Flap");
        ctx.print(0, 1, &format!("Score:{}",self.score));

        self.obstacle.render(ctx, self.player.x);
        
        if self.player.x > self.obstacle.x {
            self.score += 1;
            self.obstacle = Obstacle::new(self.player.x + SCREEN_WIDTH,self.score);
        }

        if self.player.y > SCREEN_HEIGHT || self.obstacle.hit_obstacle(&self.player) {
            self.mode = GameMode::End;
        }

        if self.player.y > SCREEN_HEIGHT {
            self.mode = GameMode::End;
        }
    }

    // menu方法
    fn main_menu(&mut self, ctx: &mut BTerm) {
        ctx.cls();
        // print_centered会在屏幕水平中间位置进行打印
        ctx.print_centered( 5,"Welcome to Flappy Dragon!");
        ctx.print_color_right(60, 7, WEB_GREEN, BLACK,"by:Gemini48");
        ctx.print_centered( 8, "(P) Play Game");
        ctx.print_centered(9,  "(Q) Quit Game");
        
        if let Some(key) =ctx.key {
            match key {
                VirtualKeyCode::P => self.mode = GameMode::Playing,
                VirtualKeyCode::Q => ctx.quitting = true,
                _ => {}
            }
        }
    }

    // restart
    fn resatrt(&mut self) {
        self.player = Player::new(5,25);
        self.frame_time = 0.0;
        //self.mode = GameMode::Menu;
        self.mode = GameMode::Playing;
        self.obstacle = Obstacle::new(SCREEN_WIDTH,0);
        self.score = 0;

    }
    
    // 实现end方法
    fn dead(&mut self, ctx: &mut BTerm) {
        ctx.cls();
        // print_centered会在屏幕水平中间位置进行打印
        ctx.print_centered( 5,"You are dead!");
        ctx.print_centered(6,&format!("You earned {} points",self.score));
        ctx.print_centered( 8, "(P) Play Again");
        ctx.print_centered(9,  "(Q) Quit Game");
        
        if let Some(key) =ctx.key {
            match key {
                VirtualKeyCode::P => self.resatrt(),
                VirtualKeyCode::Q => ctx.quitting = true,
                _ => {}
            }
        }
    }
    
    
}



// 状态怎么和哟游戏帧关联上呢?,这就用到了一个名为GaemState的trait
impl GameState for State {
    // 实现tick函数
    fn tick(&mut self, ctx: &mut BTerm) {
        // 根据游戏状态选择方向
        match self.mode {
            GameMode::Menu =>self.main_menu(ctx),
            GameMode::Playing => self.play(ctx),
            GameMode::End => self.dead(ctx),
        }
    }
}

struct Obstacle {
    x:i32,
    gap_y:i32, // 表示上下两个障碍物之间的空隙
    size:i32,
}

impl Obstacle {
    fn new(x:i32,score:i32) -> Self {
        let mut random = RandomNumberGenerator::new();
        Obstacle {
            x,
            gap_y:random.range(10, 40), // 障碍纵向高度缝隙随机
            size:i32::max(2,20-score),
        }
    }

    fn render(&mut self,ctx:&mut BTerm,player_x:i32) {
        let screen_x = self.x -  player_x; // 屏幕空间
        let half_size:i32  = self.size / 2;

        for y in 0..self.gap_y - half_size {
            ctx.set(screen_x,y, RED,BLACK, to_cp437('|'));
        }

        for y in self.gap_y + half_size..SCREEN_HEIGHT {
            ctx.set(screen_x,y,RED,BLACK,to_cp437('|'));
        }
    }

    // 玩家碰撞到障碍物的处理
    fn hit_obstacle(&self,player:&Player) -> bool {
        let half_size = self.size / 2;
        let does_x_match = player.x == self.x; // 玩家x和障碍物x坐标
        let player_above_gap  =player.y < self.gap_y - half_size;
        let player_below_gap = player.y > self.gap_y + half_size;
        does_x_match && (player_above_gap || player_below_gap)
    }
}


fn main() -> BError {
    // 创建一个80x50的简单窗口,标题为游戏名称,?表示这个build可能会出错,出错就捕获返回,否则成功
    let context = BTermBuilder::simple80x50()
    .with_title("Flappy Dragon")
    .build()?;
    
    main_loop (context,State::new())
}


4. 效果截图

image-20240508210136226

image-20240508210155766

源码地址

参考&引用

  • Rust依赖库:crates.io
  • bracket-lib

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1654917.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

那个在买珠宝的年轻人

金价搭上过山车&#xff0c;今年以来价格一路飙涨。 珍珠身价同步飙升&#xff0c;晋级珠宝圈“新宠”。 文玩圈“减龄”&#xff0c;盘珠串不再只是“老头乐”。 月薪3000的年轻人&#xff0c;悄悄实现“宝石”自由。 黄金珠宝走俏&#xff0c;这届年轻人到底有着怎样的珠宝…

揭秘文件加密利器:24年度最值得信赖的5大加密软件评测

数据安全与隐私保护已成为我们每个人都必须面对的重要问题。 文件加密软件作为保障数据安全的关键工具&#xff0c;其重要性不言而喻。 在众多的加密软件中&#xff0c;哪些软件能够在保障数据安全的同时&#xff0c;又具备良好的易用性和稳定性呢&#xff1f; 本文将为您揭秘…

快过VS Code,10天暴增20k star,高性能多人协作IDE横空出世

道歉 其实不意味着道歉的人错了 而是他认为这段关系 比自己的尊严更重要 失败了 不是说你有多差 而是说 你需要更努力了 写代码最重要的一个选择就是选哪个IDE了&#xff0c;目前主流的选择是vscode和IDEA了。 但是vscode虽然轻量&#xff0c;但是对于大型的项目仍然显得…

[Meachines][Hard]Napper

Main $ nmap -p- -sC -sV 10.10.11.240 --min-rate 1000 $ curl http://10.10.11.240 $ gobuster dir -u "https://app.napper.htb" -w /usr/share/wordlists/seclists/Discovery/Web-Content/raft-small-words-lowercase.txt -k 博客 $ ffuf -c -w /usr/share/se…

某盾BLACKBOX逆向关键点

需要准备的东西&#xff1a; 1、原JS码 2、AST解混淆码 3、token(来源于JSON) 一、原JS码很好获取&#xff0c;每次页面刷新&#xff0c;混淆的代码都会变&#xff0c;这是正常&#xff0c;以下为部分代码 while (Qooo0) {switch (Qooo0) {case 110 14 - 55: {function O0…

Lib city笔记:TrajectoryDataset

1 AbstractDataset 抽象类&#xff0c;所有数据集的基类 2 TrajectoryDataset 2.1 __init__ 2.2 get_data 2.3 cutter_filter 2.3.1 按照时间间隔切割 2.3.2 按照同一天切割 2.3.3 按照固定窗口长度切割 cut完的轨迹样子 每一个key是一个轨迹的id&#xff0c;对应的value内容…

class与对象的关系

经典的&#xff0c;房子图纸&#xff0c;和创建的房子之间的关系&#xff0c; 类实例化出对象就像现实中使用建筑设计图建造出房子&#xff0c;类就像是设计图&#xff0c;只设计出需要什么东西&#xff0c;但是并没有实体的建筑存在&#xff0c;同样类也只是一个设计&#xf…

Rust读写CSV文件 一维Vec类型元素、二维Vec类型元素写入CSV文件

本文主要介绍Rust读写CSV文件方法&#xff0c; Vec类型元素基本操作方法&#xff0c;Rust把一维Vec类型元素、二维Vec类型元素写入CSV文件方法。 实例测试&#xff1a; 要求读“log.csv”文件数据&#xff0c;把“时间”列数据和“次数”列数据写入日志处理结果1.csv文件&…

暴力破解【1】

1.c/s架构暴力破解 1.1 c/s架构暴力破解前提条件 知道目标地址&#xff0c;端口&#xff0c;协议&#xff0c;无后端验证、用户名字典、密码字典 1.2 c/s架构暴力破解工具 hydra、bruter、medusa爆破 2.b/s架构暴力破解 2.1 无验证码绕过 不带验证码无测试次数的直接使…

[微信小程序] 入门笔记1-滚动视图组件

[微信小程序] 入门笔记1-滚动视图组件 1.页面&组件&渲染 在小程序是由一个个页面page组成, 而页面又是由一个个组件component组成.和网页类似,这里的组件指的就是输入框<input>,按钮<button>,文本<text>,图片<image>等元素.如果你学过网页一…

快速排序(java细节实现)

目录 快速排序: Hoare版: 挖坑法 快速排序的优化 快速排序的非递归实现 小结 从小到大排序 快速排序: 基本思想为&#xff1a;任取待排序元素序列中的某元素作为基准值&#xff0c;按照该排序码将待排序集合分割成两子序列&#xff0c;左子序列中所有元素均小于基准值&…

二叉树的基础遍历2.0

1.0入口&#xff1a;二叉树的基础遍历-CSDN博客 在1.0中使用的是简单的结构体建树&#xff0c;本文注重用二维vector建树。 前序&#xff0c;中序和后序的分析1.0已给出&#xff0c;本文不做过多介绍&#xff0c;本文重点讲二叉树的层序遍历。 先奉上前中后序的代码&#xf…

只允许内网访问时,如何设置hosts

1、Hosts文件简介 hosts文件是一个没有扩展名的计算机文件&#xff0c;用于将主机名与对应的 IP 地址关联起来。在操作系统中&#xff0c;hosts文件通常用于在本地解析域名&#xff0c;以便将域名映射到特定的IP地址。这个文件可以用来屏蔽广告、加速访问特定网站、解决DNS解析…

计算机网络技术主要学什么内容,有哪些课程

计算机网络技术专业是一个涉及理论与实践紧密结合的学科&#xff0c;主要学习内容有计算机网络基础、网络设备技术、网络编程等内容&#xff0c;以下是上大学网&#xff08;www.sdaxue.com&#xff09;整理的计算机网络技术主要学什么内容&#xff0c;供大家参考&#xff01; 基…

服务运维问题

2024-05-01&#xff08;docker 部署的 jar包自动关闭&#xff09; 查询运行情况&#xff1a;处于退出状态 docker ps -a 查询日志&#xff1a;看不出问题 docker logs -f --tail1000 demo-java 查询关于java服务日志&#xff1a;Out of memory: Kill process 16236 (java) …

学习大数据,所需更要的shell基础(2)

文章目录 read读取控制台输入函数系统函数bashnamedirname 自定义函数Shell工具&#xff08;重点&#xff09;cutawk 正则表达式入门常规匹配常用特殊字符 read读取控制台输入 1&#xff09;基本语法 read (选项) (参数) ①选项&#xff1a; -p&#xff1a;指定读取值时的提示…

使用 Parallels Desktop 在 Mac 上畅玩 PC 游戏

我们不再需要接受 “Mac 不是为游戏而打造” 这一事实&#xff1b;Parallels Desktop 通过将电脑变成高性能的游戏设备&#xff0c;从而改变了一切。 Parallels Desktop 充分利用 Mac 硬件的强大功能&#xff0c;让您无缝畅玩 Windows 专享游戏。 性能得到提升&#xff0c;可玩…

顺序栈的操作

归纳编程学习的感悟&#xff0c; 记录奋斗路上的点滴&#xff0c; 希望能帮到一样刻苦的你&#xff01; 如有不足欢迎指正&#xff01; 共同学习交流&#xff01; &#x1f30e;欢迎各位→点赞 &#x1f44d; 收藏⭐ 留言​&#x1f4dd;既然选择了远方&#xff0c;当不负青春…

国产PLC海为如何与电脑通信

前言 这几天接触到了国产海为PLC&#xff0c;做一个记录&#xff01;学习一下&#xff01; 串口联机 步骤 1&#xff1a;使用 USB 转 485 线连接 A8&#xff08;RS485 通讯口&#xff09;和电脑&#xff1b; 步骤 2&#xff1a;打开 Haiwell happy PLC 编程软件&#xff0c…

【C++】C++11--- 列表初始化|关键字

目录 前言 列表初始化 创建对象时的列表初始化 单参数隐式类型转换 多参数的隐式类型转换 new表达式中使用列表初始化 列表初始化适用于STL 容器 模板类initializer_list 关键字auto 关键字decltype 关键字nullptr 前言 C标准10年磨一剑&#xff0c;第二个真正意义上…