C#核心--实践小项目(贪吃蛇)

C#核心实践小项目 -- 贪吃蛇

必备知识点--多脚本文件

(可观看CSharp核心--52集进行了解)

必备知识点--UML类图

必备知识点--七大原则

贪吃蛇

项目展示

控制方向的是:WSAD

确定键是:J

需求分析(UML类图)

自个先写--贪吃蛇

结合自己所学进行开发(UML类图是老师提供的,因为自己暂时还不太会绘制,主要是代码逻辑还不够清晰)

补充知识点:

检测键盘是否激活

Console.KeyAvailable == true;

按照UML类图逐个去写逐个去实现(但是有些模块我没有用上)

主要精力是放在了功能实现上

下面是我实现的过程

一、万事开头难--游戏类

(我先确定了开始着手的地方--游戏类,因为它是所有类和方法的汇聚地)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;//游戏类namespace 自个先写CSharp核心小项目_贪吃蛇_
{enum E_Scene{BeginID,GamingID,FinishID,}class Game{public static int x;public static int y;public static E_Scene scene = new E_Scene();Begin begin = new Begin();Finish finish = new Finish();public Game(){x = 100;y = 30;scene = E_Scene.BeginID;}//初始化控制台public void Consoles(){//隐藏光标Console.CursorVisible = false;//设置舞台大小Console.SetWindowSize(x, y);Console.SetBufferSize(x, y);}//游戏主循环public void MajorCycle(){while (true){//思考一下,为什么把开始场景和结束场景的类申明放在外面,而游戏场景的类申明放循环里面//因为开始结束场景是一成不变的,只需申明一次就够用了//而游戏场景进入一次就会执行出结果出来,每次结果都将不一样,所以每次都得重新申明switch (scene){case E_Scene.BeginID:Console.Clear();begin.newers();break;case E_Scene.GamingID:Console.Clear();GameScene gameScene = new GameScene();gameScene.newers();break;case E_Scene.FinishID:Console.Clear();finish.newers();break;default:break;}}}//场景切换public void SceneMove(){}}
}
二、游戏帧更新接口
1.更新接口

2.开始和结束场景基类

开始场景类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;//开始场景namespace 自个先写CSharp核心小项目_贪吃蛇_
{class Begin : BeginAndFinish{public Begin(){str = "贪吃蛇";str1 = "开始游戏";str2 = "结束游戏";}//重写更新方法public override void newers(){Console.SetCursorPosition(48, 10);Console.ForegroundColor = ConsoleColor.White;Console.WriteLine(str);Console.SetCursorPosition(47, 13);Console.ForegroundColor = key == 1 ? ConsoleColor.Red : ConsoleColor.White;Console.WriteLine(str1);Console.SetCursorPosition(47, 15);Console.ForegroundColor = key == 2 ? ConsoleColor.Red : ConsoleColor.White;Console.WriteLine(str2);char c = Console.ReadKey(true).KeyChar;switch (c){case 'W':case 'w':key = 1;break;case 'S':case 's':key = 2;break;case 'J':case 'j':if (key == 2){//关闭控制台Environment.Exit(0);}Game.scene = (E_Scene)key;break;default:break;}}}
}
结束场景类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;//结束场景namespace 自个先写CSharp核心小项目_贪吃蛇_
{class Finish : BeginAndFinish{string str0;public static int num;public Finish(){key = 0;str = "游戏结束";str0 = "本次游戏的长度为:";str1 = "回到开始界面";str2 = "结束游戏";}//重写更新方法public override void newers(){Console.SetCursorPosition(47, 10);Console.ForegroundColor = ConsoleColor.White;Console.WriteLine(str);Console.SetCursorPosition(42, 12);Console.ForegroundColor = ConsoleColor.White;Console.WriteLine(str0 + num);Console.SetCursorPosition(45, 15);Console.ForegroundColor = key == 0 ? ConsoleColor.Red : ConsoleColor.White;Console.WriteLine(str1);Console.SetCursorPosition(47, 17);Console.ForegroundColor = key == 2 ? ConsoleColor.Red : ConsoleColor.White;Console.WriteLine(str2);char c = Console.ReadKey(true).KeyChar;switch (c){case 'W':case 'w':key = 0;break;case 'S':case 's':key = 2;break;case 'J':case 'j':if (key == 2){//关闭控制台Environment.Exit(0);}Game.scene = (E_Scene)key;break;default:break;}}}
}

(这里面其实可以把这些方法提取到开始和结束场景基类里面的,但我懒,没有去整!!!)

3.游戏场景类

(第二个大类,游戏里的墙壁、食物、蛇、各种方法等等都汇聚在这个类中)

三、游戏场景中的各类
1.绘制接口

2.游戏对象类

(讲真的这个类没怎么用上,具体怎么用我还得看看老师是怎么用的)

3.位置结构体

(这个是完全没有用上!!)

4.地图墙壁类

5.食物类

6.蛇类--(最复杂的类)

蛇身体类--没用上

蛇类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;//蛇类namespace 自个先写CSharp核心小项目_贪吃蛇_
{//移动方向枚举enum E_Move{Up,Down,Left,Right,}class Snake{string snakeHead = "●";string snakeBody = "◎";int x = 10;int y = 5;E_Move move = E_Move.Down;char c;Foods foods = new Foods();int bodyNum = 0;//标识符int[] num1 = new int[10000];int[] num2 = new int[10000];//打印出长度public string longs = "当前长度为:";//蛇绘制public void SnakePlan(){//打印长度Console.SetCursorPosition(2, 1);Console.ForegroundColor = ConsoleColor.Red;Console.WriteLine(longs + bodyNum);Finish.num = bodyNum;//蛇头的绘制Console.SetCursorPosition(x, y);Console.ForegroundColor = ConsoleColor.Yellow;Console.WriteLine(snakeHead);//蛇身的绘制for (int i = 0; i < bodyNum; i++){Console.SetCursorPosition(num1[i], num2[i]);Console.ForegroundColor = ConsoleColor.Green;Console.WriteLine(snakeBody);}}//蛇清除public void SnakeClear(){//打印长度清除Console.SetCursorPosition(2, 1);Console.WriteLine("               ");//蛇头的清除Console.SetCursorPosition(x, y);Console.WriteLine("  ");//蛇身的清除for (int i = 0; i < bodyNum; i++){Console.SetCursorPosition(num1[i], num2[i]);Console.WriteLine("  ");}}//蛇转向public void SnakeTurn(){//老师漏讲的知识点,Console.KeyAvailable -- 检测键盘是否被激活if (Console.KeyAvailable == true){c = Console.ReadKey(true).KeyChar;switch (c){case 'W':case 'w':if (move == E_Move.Down && bodyNum != 0){move = E_Move.Down;}else{move = E_Move.Up;}break;case 'S':case 's':if (move == E_Move.Up && bodyNum != 0){move = E_Move.Up;}else{move = E_Move.Down;}break;case 'A':case 'a':if (move == E_Move.Right && bodyNum != 0){move = E_Move.Right;}else{move = E_Move.Left;}break;case 'D':case 'd':if (move == E_Move.Left && bodyNum != 0){move = E_Move.Left;}else{move = E_Move.Right;}break;default:break;}}} //吃食物//死亡//蛇移动 -- (包含了蛇绘制、蛇转向、吃食物)public void SnakeMove(){if(foods.x == 0 || foods.y == 0){foods.Plan();}SnakeTurn();switch (move){case E_Move.Up:SnakeClear();y -= 1;//判断是否死亡//撞墙死亡if (y == 0){Game.scene = E_Scene.FinishID;GameScene.bo = false;break;}//撞身体死亡for (int i = 0; i < bodyNum; i++){if(num1[i] == x && num2[i] == y){Game.scene = E_Scene.FinishID;GameScene.bo = false;break;}}if (foods.x == x && foods.y == y){foods.Plan();//给个判断,让生成的food不会出现在有蛇身体的位置上for (int i = 0; i < bodyNum; i++){if (foods.x == num1[i] && foods.y == num2[i]){Console.SetCursorPosition(foods.x, foods.y);Console.WriteLine("  ");foods.Plan();i = 0;}}bodyNum += 1;for (int i = bodyNum - 1; i > 0; i--){num1[i] = num1[i - 1];num2[i] = num2[i - 1];}num1[0] = x;num2[0] = y + 1;}else{for (int i = bodyNum - 1; i > 0; i--){num1[i] = num1[i - 1];num2[i] = num2[i - 1];}num1[0] = x;num2[0] = y + 1;}SnakePlan();break;case E_Move.Down:SnakeClear();y += 1;//判断是否死亡//撞墙死亡if (y == 29){Game.scene = E_Scene.FinishID;GameScene.bo = false;break;}//撞身体死亡for (int i = 0; i < bodyNum; i++){if (num1[i] == x && num2[i] == y){Game.scene = E_Scene.FinishID;GameScene.bo = false;break;}}if (foods.x == x && foods.y == y){foods.Plan();//给个判断,让生成的food不会出现在有蛇身体的位置上for (int i = 0; i < bodyNum; i++){if (foods.x == num1[i] && foods.y == num2[i]){Console.SetCursorPosition(foods.x, foods.y);Console.WriteLine("  ");foods.Plan();i = 0;}}bodyNum += 1;for (int i = bodyNum - 1; i > 0; i--){num1[i] = num1[i - 1];num2[i] = num2[i - 1];}num1[0] = x;num2[0] = y - 1;}else{for (int i = bodyNum - 1; i > 0; i--){num1[i] = num1[i - 1];num2[i] = num2[i - 1];}num1[0] = x;num2[0] = y - 1;}SnakePlan();break;case E_Move.Left:SnakeClear();x -= 2;//判断是否死亡//撞墙死亡if (x == 0){Game.scene = E_Scene.FinishID;GameScene.bo = false;break;}//撞身体死亡for (int i = 0; i < bodyNum; i++){if (num1[i] == x && num2[i] == y){Game.scene = E_Scene.FinishID;GameScene.bo = false;break;}}if (foods.x == x && foods.y == y){foods.Plan();//给个判断,让生成的food不会出现在有蛇身体的位置上for (int i = 0; i < bodyNum; i++){if (foods.x == num1[i] && foods.y == num2[i]){Console.SetCursorPosition(foods.x, foods.y);Console.WriteLine("  ");foods.Plan();i = 0;}}bodyNum += 1;for (int i = bodyNum - 1; i > 0; i--){num1[i] = num1[i - 1];num2[i] = num2[i - 1];}num1[0] = x + 2;num2[0] = y;}else{for (int i = bodyNum - 1; i > 0; i--){num1[i] = num1[i - 1];num2[i] = num2[i - 1];}num1[0] = x + 2;num2[0] = y;}SnakePlan();break;case E_Move.Right:SnakeClear();x += 2;//判断是否死亡//撞墙死亡if (x == 98){Game.scene = E_Scene.FinishID;GameScene.bo = false;break;}//撞身体死亡for (int i = 0; i < bodyNum; i++){if (num1[i] == x && num2[i] == y){Game.scene = E_Scene.FinishID;GameScene.bo = false;break;}}if (foods.x == x && foods.y == y){foods.Plan();//给个判断,让生成的food不会出现在有蛇身体的位置上for (int i = 0; i < bodyNum; i++){if (foods.x == num1[i] && foods.y == num2[i]){Console.SetCursorPosition(foods.x, foods.y);Console.WriteLine("  ");foods.Plan();i = 0;}}bodyNum += 1;for (int i = bodyNum - 1; i > 0; i--){num1[i] = num1[i - 1];num2[i] = num2[i - 1];}num1[0] = x - 2;num2[0] = y;}else{for (int i = bodyNum - 1; i > 0; i--){num1[i] = num1[i - 1];num2[i] = num2[i - 1];}num1[0] = x - 2;num2[0] = y;}SnakePlan();break;default:break;}}}
}
全部代码文件:看资源
实现视频展示:

C#核心实践项目(自个先写)--贪吃蛇

总结:

代码有点屎山,but跑起来就好!!!

还是知识点运用的不够,很多没用上。

跟着老师实现--贪吃蛇

一.需求分析 -- 就是UML类图

二.游戏对象和场景更新接口
1.游戏类 ---- Game 

场景类型枚举 ---- E_SceneType

2.场景更新接口 ---- ISceneUpdate

三、实现多场景切换
1.游戏场景类

2.开始和结束场景基类

3.开始场景

将Game类中的nowScene 改为静态的

将Game类中的场景切换方法也改静态的

4.结束场景

Game中的调用也改

四、游戏场景逻辑实现
1.游戏对象基类的实现
绘制接口

游戏对象类

位置结构体

2.继承游戏对象基类的对象
地图墙壁类

食物类

蛇身子类

3.地图对象

在GameScene实现Map中的方法

到这里可以实现的功能有:三个场景

4.蛇对象

5.蛇对象移动 -- (Lesson7 部分)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using 贪吃蛇.Lesson3;
using 贪吃蛇.Lesson4;namespace 贪吃蛇.Lesson6
{/// <summary>/// 蛇的移动方向/// </summary>enum E_MoveDir{Up,Down,Left,Right,}class Snake : IDraw{SnakeBody[] bodys;//记录当前蛇的长度int nowNum;//当前移动方向E_MoveDir dir;public Snake(int x, int y){//粗暴的方法 直接申明200个空间 来装蛇身体的数组bodys = new SnakeBody[200];bodys[0] = new SnakeBody(E_SnakeBody_Type.Head, x, y);nowNum = 1;dir = E_MoveDir.Down;}public void Draw(){//画一节一节的身子for (int i = 0; i < nowNum; i++){bodys[i].Draw();}}#region Lesson7 蛇的移动public void Move(){//移动前//擦除最后一个位置Console.SetCursorPosition(bodys[nowNum - 1].pos.x, bodys[nowNum - 1].pos.y);Console.WriteLine("  ");//再移动switch (dir){case E_MoveDir.Up:--bodys[0].pos.y;break;case E_MoveDir.Down:++bodys[0].pos.y;break;case E_MoveDir.Left:bodys[0].pos.x -= 2;break;case E_MoveDir.Right:bodys[0].pos.x += 2;break;default:break;}}#endregion}
}

6.蛇对象改变移动方向(Lesson8 部分)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using 贪吃蛇.Lesson3;
using 贪吃蛇.Lesson4;namespace 贪吃蛇.Lesson6
{/// <summary>/// 蛇的移动方向/// </summary>enum E_MoveDir{Up,Down,Left,Right,}class Snake : IDraw{SnakeBody[] bodys;//记录当前蛇的长度int nowNum;//当前移动方向E_MoveDir dir;public Snake(int x, int y){//粗暴的方法 直接申明200个空间 来装蛇身体的数组bodys = new SnakeBody[200];bodys[0] = new SnakeBody(E_SnakeBody_Type.Head, x, y);nowNum = 1;dir = E_MoveDir.Down;}public void Draw(){//画一节一节的身子for (int i = 0; i < nowNum; i++){bodys[i].Draw();}}#region Lesson7 蛇的移动public void Move(){//移动前//擦除最后一个位置Console.SetCursorPosition(bodys[nowNum - 1].pos.x, bodys[nowNum - 1].pos.y);Console.WriteLine("  ");//再移动switch (dir){case E_MoveDir.Up:--bodys[0].pos.y;break;case E_MoveDir.Down:++bodys[0].pos.y;break;case E_MoveDir.Left:bodys[0].pos.x -= 2;break;case E_MoveDir.Right:bodys[0].pos.x += 2;break;default:break;}}#endregion#region Lesson8 改变方向public void ChangeDir(E_MoveDir dir){//只有头部的时候 可以直接左转右 右转左 上转下 下转上//有身体时 这些情况就不能直接转if (this.dir == dir || nowNum > 1 && (this.dir == E_MoveDir.Up && dir == E_MoveDir.Down || this.dir == E_MoveDir.Down && dir == E_MoveDir.Up || this.dir == E_MoveDir.Left && dir == E_MoveDir.Right || this.dir == E_MoveDir.Right && dir == E_MoveDir.Left)){return;}//只要没有 return 就记录外面传入的方向 之后就会按照这个方向去移动this.dir = dir;}#endregion}
}

在GameScene里面实现调用

7.撞墙撞身体结束游戏 -- (Lesson9 部分)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using 贪吃蛇.Lesson3;
using 贪吃蛇.Lesson4;
using 贪吃蛇.Lesson5;namespace 贪吃蛇.Lesson6
{/// <summary>/// 蛇的移动方向/// </summary>enum E_MoveDir{Up,Down,Left,Right,}class Snake : IDraw{SnakeBody[] bodys;//记录当前蛇的长度int nowNum;//当前移动方向E_MoveDir dir;public Snake(int x, int y){//粗暴的方法 直接申明200个空间 来装蛇身体的数组bodys = new SnakeBody[200];bodys[0] = new SnakeBody(E_SnakeBody_Type.Head, x, y);nowNum = 1;dir = E_MoveDir.Down;}public void Draw(){//画一节一节的身子for (int i = 0; i < nowNum; i++){bodys[i].Draw();}}#region Lesson7 蛇的移动public void Move(){//移动前//擦除最后一个位置Console.SetCursorPosition(bodys[nowNum - 1].pos.x, bodys[nowNum - 1].pos.y);Console.WriteLine("  ");//再移动switch (dir){case E_MoveDir.Up:--bodys[0].pos.y;break;case E_MoveDir.Down:++bodys[0].pos.y;break;case E_MoveDir.Left:bodys[0].pos.x -= 2;break;case E_MoveDir.Right:bodys[0].pos.x += 2;break;default:break;}}#endregion#region Lesson8 改变方向public void ChangeDir(E_MoveDir dir){//只有头部的时候 可以直接左转右 右转左 上转下 下转上//有身体时 这些情况就不能直接转if (this.dir == dir || nowNum > 1 && (this.dir == E_MoveDir.Up && dir == E_MoveDir.Down || this.dir == E_MoveDir.Down && dir == E_MoveDir.Up || this.dir == E_MoveDir.Left && dir == E_MoveDir.Right || this.dir == E_MoveDir.Right && dir == E_MoveDir.Left)){return;}//只要没有 return 就记录外面传入的方向 之后就会按照这个方向去移动this.dir = dir;}#endregion#region Lesson9 撞墙撞身体结束逻辑public bool CheckEnd(Map map){for (int i = 0; i < map.walls.Length; i++){if (bodys[0].pos == map.walls[i].pos){return true;}}for (int i = 1; i < nowNum; i++){if (bodys[0].pos == bodys[i].pos){return true;}}return false;}#endregion}
}

GameScene中调用

8.蛇吃食物

Snake类里面添加的相关方法 -- (Lesson10 部分)

GameScene类中调用

9.蛇长身体

Snake类中添加方法

(加了Lesson11--长身体AddBody方法,在Lesson10吃食物方法里面调用了AddBody方法,然后在Lesson7中添加了蛇尾跟着蛇头移动的逻辑处理)

至此跟着老师进行的制作的功能都已实现

视频展示

C#核心实践--贪吃蛇(老师实现的)

完整代码在资源里。

总结一下下

还是得多敲多练,多想想怎么让代码更精简,逻辑怎么更清晰!

多挤些时间啊!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

强化学习应用(三):基于Q-learning的无人机物流路径规划研究(提供Python代码)

一、Q-learning简介 Q-learning是一种强化学习算法&#xff0c;用于解决基于马尔可夫决策过程&#xff08;MDP&#xff09;的问题。它通过学习一个价值函数来指导智能体在环境中做出决策&#xff0c;以最大化累积奖励。 Q-learning算法的核心思想是通过不断更新一个称为Q值的…

Ubuntu server配置ssh远程登录

使用如下命令进行安装 apt-get install ssh 安装好后启动 service ssh start 然后查看运行状态 然后用本机ping虚拟机 关闭本机和虚拟机防火墙 ufw disable 然后打开Xshell进行连接

学习Vue封装的过渡与动画总结

今天学习了Vue封装的过渡与动画&#xff0c;接下来说一下Vue是如何实现的&#xff0c;首先原生的方法是在style元素中给指定元素添加过渡的过渡或动画&#xff0c;但Vue就不需要直接获取到需要过渡或动画的元素&#xff0c;而是使用一个<transition>的标签来包裹住想要过…

鸿蒙Harmony--LocalStorage--页面级UI状态存储详解

走的太急疼的是脚&#xff0c;逼的太紧累的是心&#xff0c;很多时候&#xff0c;慢一点也没关系&#xff0c;多给自己一些耐心和等待&#xff0c;保持热爱&#xff0c;当下即是未来&#xff0c;生活自有安排! 目录 一&#xff0c;定义 二&#xff0c;LocalStorageProp定义 三…

如何设置gitlab.rb 将所有数据运行目录放置到指定目录

如何设置gitlab.rb 将所有数据运行目录放置到指定目录 在GitLab中&#xff0c;要将所有数据目录&#xff08;包括仓库、日志和其他配置文件&#xff09;移动到一个自定义位置&#xff0c;你需要编辑GitLab的配置文件 /etc/gitlab/gitlab.rb。这里主要关注的是 git_data_dir 配置…

无心剑中译卡明斯《从未游历之地》

Somewhere I Have Never Travelled 从未游历之地 Edward Estlin Cummings 爱德华埃斯特林卡明斯 somewhere i have never traveled, gladly beyond any experience, your eyes have their silence: in your most frail gesture are things which enclose me or which i can…

【VRTK】【Unity】【游戏开发】更多技巧

课程配套学习项目源码资源下载 https://download.csdn.net/download/weixin_41697242/88485426?spm=1001.2014.3001.5503 【概述】 本篇将较为零散但常用的VRTK开发技巧集合在一起,主要内容: 创建物理手震动反馈高亮互动对象【创建物理手】 非物理手状态下,你的手会直接…

Python异步编程|PySimpleGUI界面读取PDF转换Excel

目录 实例要求 原始pdf文件格式 输出xls文件格式 运行界面 完整代码 代码分析 遍历表格 布局界面 控件简介 写入表格 表格排序 事件循环 异步编程 实例要求 使用PySimpleGUI做一个把单位考勤系统导出的pdf文件合并输出Excel的应用&#xff0c;故事出自&#xff1…

Playwright 结合 Selenium Grid - 1.windows 环境使用教程

Playwright 可以连接到运行 Selenium 4 的 Selenium Grid Hub 来启动 Google Chrome 或 Microsoft Edge 浏览器,而不是在本地机器上运行浏览器。 下载Selenium Grid 打开selenium官方https://www.selenium.dev/downloads/下载Selenium Server (Grid) 目前最新版本4.16.1 下…

FPGA高端项目:12G-SDI 视频编解码,提供工程源码和技术支持

目录 1、前言免责声明 2、相关方案推荐我这里已有的 GT 高速接口解决方案我目前已有的SDI编解码方案 3、详细设计方案设计框图UltraScale GTH 的SDI模式应用UltraScale GTH 基本结构参考时钟的选择和分配UltraScale GTH 发送和接收处理流程UltraScale GTH 发送接口UltraScale G…

73应急响应-Web分析phpjavaWeb自动化工具

我感觉学完渗透自然就会应急响应&#xff0c;之前又发过应急响应的文章 应急响应笔记就开始比较潦草 应急响应基础知识 应急响应流程 保护阶段&#xff08;断网&#xff0c;避免继续渗透&#xff1b;备份&#xff09;&#xff0c;分析阶段&#xff08;分析攻击行为&#xf…

C++|44.智能指针

文章目录 智能指针unique_ptr特点一——无法进行复制 shared_ptr特点一——可复制特点二——计数器&#xff08;用于确定删除的时机&#xff09; 其他 智能指针 通常的指针是需要特殊地去申请对应的空间&#xff0c;并在不使用的时候还需要人工去销毁。 而智能指针相对普通的指…

用模方软件进行模型的透明贴图,为什么翻出来透明部分是黑的?

答&#xff1a;透贴需要用PNG格式。 模方是一款针对实景三维模型的冗余碎片、水面残缺、道路不平、标牌破损、纹理拉伸模糊等共性问题研发的实景三维模型修复编辑软件。模方4.1新增自动单体化建模功能&#xff0c;支持一键自动提取房屋结构&#xff0c;平均1栋复杂建筑物只需3…

了解ASP.NET Core 中的文件提供程序

写在前面 ASP.NET Core 通过文件提供程序来抽象化文件系统访问。分为物理文件提供程序(PhysicalFileProvider)和清单嵌入的文件提供程序(ManifestEmbeddedFileProvider)还有复合文件提供程序(CompositeFileProvider )&#xff1b;其中PhysicalFileProvider 提供对物理文件系统…

1panel中的sftpgo webadmin 更新修改docker容器文件的配置教程

本篇文章主要讲解1panel中的sftpgo webadmin 更新修改docker容器文件的配置教程&#xff0c;适合sftpgo webadmin和1panel系统用户配置时使用。 作者&#xff1a;任聪聪 rccblogs.com 日期&#xff1a;2024年1月8日 sftpgo是无法直接直接更改容器内部的网站目录的&#xff0c;但…

uniapp 如何使用echarts 以及解决tooltip自定义不生效问题

使用的是echarts-for-wx插件&#xff1b; 正常写法案例&#xff1a;给tooltip数值加个% <template><view><uni-ec-canvas class"uni-ec-canvas"id"uni-ec-canvas"ref"canvas"canvas-id"uni-ec-canvas":ec"ec&quo…

使用nginx+HTML2canvas将任意html网页转为png图片自定义张数

文章目录 概述网页的转换html2canvas的使用导入导入HTML2canvas库函数定义 nginx部署编写控制截图网页代码iframe 网页控制代码 测试说明 概述 本文简述如何使用nginxhtml2canvas将任意网页html转为png图片 网页的转换 如果是本地网页&#xff0c;直接进行nginx反向代理就行…

vue3dLoader Cannot read properties of null (reading ‘setCrossOrigin‘)“这个报错怎么解决?

默认情况下crossOrigin默认值是“anonymous” 如果出现报错的情况 请设置crossOrigin为空字符串即可。如&#xff1a; <vue3dLoader crossOrigin""> 相关阅读 推荐&#xff1a;vue-3d-loader支持.dae/.fbx/.gltf/.glb/.obj/.ply/.stl/.json&#xff0c;并支…

5G前装搭载率即将迈过10%大关,车载通讯进入多层次增长通道

对于智能化来说&#xff0c;车载通讯性能的提升&#xff0c;对于相关功能的用户体验优化、进一步减少通讯时延以及打开应用新空间&#xff0c;至关重要。 目前&#xff0c;2G/3G正在进入运营商逐步关闭运营的阶段&#xff0c;4G依然是主力&#xff0c;但5G也在迎来新的增长机会…

vue3 生命周期

与 2.x 版本生命周期相对应的组合式 API beforeCreate -> 使用 setup() created -> 使用 setup() beforeMount -> onBeforeMount mounted -> onMounted beforeUpdate -> onBeforeUpdate updated -> onUpdated beforeDestroy -> onBeforeUnmount destroye…