本文章由cartzhang编写,转载请注明出处。 所有权利保留。

文章链接:http://blog.csdn.net/cartzhang/article/details/49818953

作者:cartzhang

一、Unity 打印日志

Unity中,在其编辑器上有个专门的Console,快捷键:shift + Ctrl+ c 。

代码中的Debug.Log("this is a test");就会打印到这里。

但是在打包后,只有从Log中找到,能不能找到一个可以实时显示的工具呢?

很明显,必须有啊!!要不写这篇不就是瞎扯了么?!!

我辗转腾挪,到处寻觅,我肯定不是第一个有这个想法的人。

终于有一天,我来到了七环!!!找到了几种方法,与君共享!!

二、我想有个控制台

之前说的Debug.Log();此函数是打印Unity控制台的。

好办,有高人已经重新把控制台给换了地方,打印到界面的控制台上。

就是类似控制台的一个界面。

先放结果图样:

1.问题来了,怎么实现的呢?

上代码:

我给改了名字叫TestConsole.cs了,因为之前名字为Console,这样想我这样都在一个工程中为大家测试,容易造成混乱。

  1. //#define USE_TESTCONSOLE
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4.  
  5. namespace Consolation
  6. {
  7. /// <summary>
  8. /// A console to display Unity's debug logs in-game.
  9. /// </summary>
  10. class TestConsole : MonoBehaviour
  11. {
  12. #if USE_TESTCONSOLE
  13. struct Log
  14. {
  15. public string message;
  16. public string stackTrace;
  17. public LogType type;
  18. }
  19.  
  20. #region Inspector Settings
  21.  
  22. /// <summary>
  23. /// The hotkey to show and hide the console window.
  24. /// </summary>
  25. public KeyCode toggleKey = KeyCode.BackQuote;
  26.  
  27. /// <summary>
  28. /// Whether to open the window by shaking the device (mobile-only).
  29. /// </summary>
  30. public bool shakeToOpen = true;
  31.  
  32. /// <summary>
  33. /// The (squared) acceleration above which the window should open.
  34. /// </summary>
  35. public float shakeAcceleration = 3f;
  36.  
  37. /// <summary>
  38. /// Whether to only keep a certain number of logs.
  39. ///
  40. /// Setting this can be helpful if memory usage is a concern.
  41. /// </summary>
  42. public bool restrictLogCount = false;
  43.  
  44. /// <summary>
  45. /// Number of logs to keep before removing old ones.
  46. /// </summary>
  47. public int maxLogs = 1000;
  48.  
  49. #endregion
  50.  
  51. readonly List<Log> logs = new List<Log>();
  52. Vector2 scrollPosition;
  53. bool visible;
  54. bool collapse;
  55.  
  56. // Visual elements:
  57.  
  58. static readonly Dictionary<LogType, Color> logTypeColors = new Dictionary<LogType, Color>
  59. {
  60. { LogType.Assert, Color.white },
  61. { LogType.Error, Color.red },
  62. { LogType.Exception, Color.red },
  63. { LogType.Log, Color.white },
  64. { LogType.Warning, Color.yellow },
  65. };
  66.  
  67. const string windowTitle = "Console";
  68. const int margin = 20;
  69. static readonly GUIContent clearLabel = new GUIContent("Clear", "Clear the contents of the console.");
  70. static readonly GUIContent collapseLabel = new GUIContent("Collapse", "Hide repeated messages.");
  71.  
  72. readonly Rect titleBarRect = new Rect(0, 0, 10000, 20);
  73. Rect windowRect = new Rect(margin, margin, Screen.width - (margin * 2), Screen.height - (margin * 2));
  74.  
  75. void OnEnable()
  76. {
  77. #if UNITY_5
  78. Application.logMessageReceived += HandleLog;
  79. #else
  80. Application.RegisterLogCallback(HandleLog);
  81. #endif
  82. }
  83.  
  84. void OnDisable()
  85. {
  86. #if UNITY_5
  87. Application.logMessageReceived -= HandleLog;
  88. #else
  89. Application.RegisterLogCallback(null);
  90. #endif
  91. }
  92.  
  93. void Update()
  94. {
  95. if (Input.GetKeyDown(toggleKey))
  96. {
  97. visible = !visible;
  98. }
  99.  
  100. if (shakeToOpen && Input.acceleration.sqrMagnitude > shakeAcceleration)
  101. {
  102. visible = true;
  103. }
  104. }
  105.  
  106. void OnGUI()
  107. {
  108. if (!visible)
  109. {
  110. return;
  111. }
  112.  
  113. windowRect = GUILayout.Window(123456, windowRect, DrawConsoleWindow, windowTitle);
  114. }
  115.  
  116. /// <summary>
  117. /// Displays a window that lists the recorded logs.
  118. /// </summary>
  119. /// <param name="windowID">Window ID.</param>
  120. void DrawConsoleWindow(int windowID)
  121. {
  122. DrawLogsList();
  123. DrawToolbar();
  124.  
  125. // Allow the window to be dragged by its title bar.
  126. GUI.DragWindow(titleBarRect);
  127. }
  128.  
  129. /// <summary>
  130. /// Displays a scrollable list of logs.
  131. /// </summary>
  132. void DrawLogsList()
  133. {
  134. scrollPosition = GUILayout.BeginScrollView(scrollPosition);
  135.  
  136. // Iterate through the recorded logs.
  137. for (var i = 0; i < logs.Count; i++)
  138. {
  139. var log = logs[i];
  140.  
  141. // Combine identical messages if collapse option is chosen.
  142. if (collapse && i > 0)
  143. {
  144. var previousMessage = logs[i - 1].message;
  145.  
  146. if (log.message == previousMessage)
  147. {
  148. continue;
  149. }
  150. }
  151.  
  152. GUI.contentColor = logTypeColors[log.type];
  153. GUILayout.Label(log.message);
  154. }
  155.  
  156. GUILayout.EndScrollView();
  157.  
  158. // Ensure GUI colour is reset before drawing other components.
  159. GUI.contentColor = Color.white;
  160. }
  161.  
  162. /// <summary>
  163. /// Displays options for filtering and changing the logs list.
  164. /// </summary>
  165. void DrawToolbar()
  166. {
  167. GUILayout.BeginHorizontal();
  168.  
  169. if (GUILayout.Button(clearLabel))
  170. {
  171. logs.Clear();
  172. }
  173.  
  174. collapse = GUILayout.Toggle(collapse, collapseLabel, GUILayout.ExpandWidth(false));
  175.  
  176. GUILayout.EndHorizontal();
  177. }
  178.  
  179. /// <summary>
  180. /// Records a log from the log callback.
  181. /// </summary>
  182. /// <param name="message">Message.</param>
  183. /// <param name="stackTrace">Trace of where the message came from.</param>
  184. /// <param name="type">Type of message (error, exception, warning, assert).</param>
  185. void HandleLog(string message, string stackTrace, LogType type)
  186. {
  187. logs.Add(new Log
  188. {
  189. message = message,
  190. stackTrace = stackTrace,
  191. type = type,
  192. });
  193.  
  194. TrimExcessLogs();
  195. }
  196.  
  197. /// <summary>
  198. /// Removes old logs that exceed the maximum number allowed.
  199. /// </summary>
  200. void TrimExcessLogs()
  201. {
  202. if (!restrictLogCount)
  203. {
  204. return;
  205. }
  206.  
  207. var amountToRemove = Mathf.Max(logs.Count - maxLogs, 0);
  208.  
  209. if (amountToRemove == 0)
  210. {
  211. return;
  212. }
  213.  
  214. logs.RemoveRange(0, amountToRemove);
  215. }
  216. #endif
  217. }
  218. }

我在代码最前面添加了宏定义,使用的时候屏蔽此宏定义即可

2.怎么使用呢?


恩。我写的使用很简单。
随便写个C#代码,在Update中测试的。
  1. // Update is called once per frame
  2. void Update ()
  3. {
  4. //DebugConsole.Log(" test s");
  5. Debug.Log("Debug log test");
  6. Console.WriteLine("this is Console Write line test ");
  7. ///
  8. //DebugConsole.instance.AddMessage("this is instance AddMessage test by cartzhang", "warning");
  9. //DebugConsole.Log("this is debug console log test cartzhang");
  10. }

3.结果上面已经说明了。

这里就不重复了。

4.这怎么实现的呢?

原理很简单。写一个面板,往上面写字啊!

说下啊,这个有个切换按键,就是可以控制是否显示这个面板的,按键为BackQuote,你也可以修改,BackQuote这个键呢,在ESC按键的下面就是这个“~”。

三、这不是我想要的,我要显示在屏幕上。

我想要显示在控制台上,就是CMD出来的那样。

可以啊!

1. 直接写在屏幕上的代码

不过,我先赠送一个显示在屏幕上的。
这样我觉得大部分的人就会满足了,最起码不用自己写GUI .Label()了啊。

说明这个是国外友人好早之前写的,我只改变了其中某些不符合现在Unity 5 的语句,其他没有动。

还是代码:
  1. /*==== DebugConsole.cs ====================================================
  2. * Class for handling multi-line, multi-color debugging messages.
  3. * Original Author: Jeremy Hollingsworth
  4. * Based On: Version 1.2.1 Mar 02, 2006
  5. *
  6. * Modified: Simon Waite
  7. * Date: 22 Feb 2007
  8. *
  9. * Modification to original script to allow pixel-correct line spacing
  10. *
  11. * Setting the boolean pixelCorrect changes the units in lineSpacing property
  12. * to pixels, so you have a pixel correct gui font in your console.
  13. *
  14. * It also checks every frame if the screen is resized to make sure the
  15. * line spacing is correct (To see this; drag and let go in the editor
  16. * and the text spacing will snap back)
  17. *
  18. * USAGE:
  19. * ::Drop in your standard assets folder (if you want to change any of the
  20. * default settings in the inspector, create an empty GameObject and attach
  21. * this script to it from you standard assets folder. That will provide
  22. * access to the default settings in the inspector)
  23. *
  24. * ::To use, call DebugConsole.functionOrProperty() where
  25. * functionOrProperty = one of the following:
  26. *
  27. * -Log(string message, string color) Adds "message" to the list with the
  28. * "color" color. Color is optional and can be any of the following: "error",
  29. * "warning", or "normal". Default is normal.
  30. *
  31. * Clear() Clears all messages
  32. *
  33. * isVisible (true,false) Toggles the visibility of the output. Does _not_
  34. * clear the messages.
  35. *
  36. * isDraggable (true, false) Toggles mouse drag functionality
  37. * =========================================================================*/
  38. //#define USE_DEBUGCONSOLE
  39.  
  40. using UnityEngine;
  41. using System.Collections;
  42.  
  43. public class DebugConsole : MonoBehaviour
  44. {
  45. #if USE_DEBUGCONSOLE
  46. public GameObject DebugGui = null; // The GUI that will be duplicated
  47. public Vector3 defaultGuiPosition = new Vector3(0.01F, 0.98F, 0F);
  48. public Vector3 defaultGuiScale = new Vector3(0.5F, 0.5F, 1F);
  49. public Color normal = Color.green;
  50. public Color warning = Color.yellow;
  51. public Color error = Color.red;
  52. public int maxMessages = 30; // The max number of messages displayed
  53. public float lineSpacing = 0.02F; // The amount of space between lines
  54. public ArrayList messages = new ArrayList();
  55. public ArrayList guis = new ArrayList();
  56. public ArrayList colors = new ArrayList();
  57. public bool draggable = true; // Can the output be dragged around at runtime by default?
  58. public bool visible = true; // Does output show on screen by default or do we have to enable it with code?
  59. public bool pixelCorrect = false; // set to be pixel Correct linespacing
  60. public static bool isVisible
  61. {
  62. get
  63. {
  64. return DebugConsole.instance.visible;
  65. }
  66.  
  67. set
  68. {
  69. DebugConsole.instance.visible = value;
  70. if (value == true)
  71. {
  72. DebugConsole.instance.Display();
  73. }
  74. else if (value == false)
  75. {
  76. DebugConsole.instance.ClearScreen();
  77. }
  78. }
  79. }
  80.  
  81. public static bool isDraggable
  82. {
  83. get
  84. {
  85. return DebugConsole.instance.draggable;
  86. }
  87.  
  88. set
  89. {
  90. DebugConsole.instance.draggable = value;
  91.  
  92. }
  93. }
  94.  
  95. private static DebugConsole s_Instance = null; // Our instance to allow this script to be called without a direct connection.
  96. public static DebugConsole instance
  97. {
  98. get
  99. {
  100. if (s_Instance == null)
  101. {
  102. s_Instance = FindObjectOfType(typeof(DebugConsole)) as DebugConsole;
  103. if (s_Instance == null)
  104. {
  105. GameObject console = new GameObject();
  106. console.AddComponent<DebugConsole>();
  107. console.name = "DebugConsoleController";
  108. s_Instance = FindObjectOfType(typeof(DebugConsole)) as DebugConsole;
  109. DebugConsole.instance.InitGuis();
  110. }
  111.  
  112. }
  113.  
  114. return s_Instance;
  115. }
  116. }
  117.  
  118. void Awake()
  119. {
  120. s_Instance = this;
  121. InitGuis();
  122.  
  123. }
  124.  
  125. protected bool guisCreated = false;
  126. protected float screenHeight =-1;
  127. public void InitGuis()
  128. {
  129. float usedLineSpacing = lineSpacing;
  130. screenHeight = Screen.height;
  131. if(pixelCorrect)
  132. usedLineSpacing = 1.0F / screenHeight * usedLineSpacing;
  133.  
  134. if (guisCreated == false)
  135. {
  136. if (DebugGui == null) // If an external GUIText is not set, provide the default GUIText
  137. {
  138. DebugGui = new GameObject();
  139. DebugGui.AddComponent<GUIText>();
  140. DebugGui.name = "DebugGUI(0)";
  141. DebugGui.transform.position = defaultGuiPosition;
  142. DebugGui.transform.localScale = defaultGuiScale;
  143. }
  144.  
  145. // Create our GUI objects to our maxMessages count
  146. Vector3 position = DebugGui.transform.position;
  147. guis.Add(DebugGui);
  148. int x = 1;
  149.  
  150. while (x < maxMessages)
  151. {
  152. position.y -= usedLineSpacing;
  153. GameObject clone = null;
  154. clone = (GameObject)Instantiate(DebugGui, position, transform.rotation);
  155. clone.name = string.Format("DebugGUI({0})", x);
  156. guis.Add(clone);
  157. position = clone.transform.position;
  158. x += 1;
  159. }
  160.  
  161. x = 0;
  162. while (x < guis.Count)
  163. {
  164. GameObject temp = (GameObject)guis[x];
  165. temp.transform.parent = DebugGui.transform;
  166. x++;
  167. }
  168. guisCreated = true;
  169. } else {
  170. // we're called on a screensize change, so fiddle with sizes
  171. Vector3 position = DebugGui.transform.position;
  172. for(int x=0;x < guis.Count; x++)
  173. {
  174. position.y -= usedLineSpacing;
  175. GameObject temp = (GameObject)guis[x];
  176. temp.transform.position= position;
  177. }
  178. }
  179. }
  180.  
  181. bool connectedToMouse = false;
  182. void Update()
  183. {
  184. // If we are visible and the screenHeight has changed, reset linespacing
  185. if (visible == true && screenHeight != Screen.height)
  186. {
  187. InitGuis();
  188. }
  189. if (draggable == true)
  190. {
  191. if (Input.GetMouseButtonDown(0))
  192. {
  193. if (connectedToMouse == false && DebugGui.GetComponent<GUIText>().HitTest((Vector3)Input.mousePosition) == true)
  194. {
  195. connectedToMouse = true;
  196. }
  197. else if (connectedToMouse == true)
  198. {
  199. connectedToMouse = false;
  200. }
  201.  
  202. }
  203.  
  204. if (connectedToMouse == true)
  205. {
  206. float posX = DebugGui.transform.position.x;
  207. float posY = DebugGui.transform.position.y;
  208. posX = Input.mousePosition.x / Screen.width;
  209. posY = Input.mousePosition.y / Screen.height;
  210. DebugGui.transform.position = new Vector3(posX, posY, 0F);
  211. }
  212. }
  213.  
  214. }
  215. //+++++++++ INTERFACE FUNCTIONS ++++++++++++++++++++++++++++++++
  216. public static void Log(string message, string color)
  217. {
  218. DebugConsole.instance.AddMessage(message, color);
  219.  
  220. }
  221. //++++ OVERLOAD ++++
  222. public static void Log(string message)
  223. {
  224. DebugConsole.instance.AddMessage(message);
  225. }
  226.  
  227. public static void Clear()
  228. {
  229. DebugConsole.instance.ClearMessages();
  230. }
  231. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  232.  
  233. //---------- void AddMesage(string message, string color) ------
  234. //Adds a mesage to the list
  235. //--------------------------------------------------------------
  236.  
  237. public void AddMessage(string message, string color)
  238. {
  239. messages.Add(message);
  240. colors.Add(color);
  241. Display();
  242. }
  243. //++++++++++ OVERLOAD for AddMessage ++++++++++++++++++++++++++++
  244. // Overloads AddMessage to only require one argument(message)
  245. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  246. public void AddMessage(string message)
  247. {
  248. messages.Add(message);
  249. colors.Add("normal");
  250. Display();
  251. }
  252.  
  253. //----------- void ClearMessages() ------------------------------
  254. // Clears the messages from the screen and the lists
  255. //---------------------------------------------------------------
  256. public void ClearMessages()
  257. {
  258. messages.Clear();
  259. colors.Clear();
  260. ClearScreen();
  261. }
  262.  
  263. //-------- void ClearScreen() ----------------------------------
  264. // Clears all output from all GUI objects
  265. //--------------------------------------------------------------
  266. void ClearScreen()
  267. {
  268. if (guis.Count < maxMessages)
  269. {
  270. //do nothing as we haven't created our guis yet
  271. }
  272. else
  273. {
  274. int x = 0;
  275. while (x < guis.Count)
  276. {
  277. GameObject gui = (GameObject)guis[x];
  278. gui.GetComponent<GUIText>().text = "";
  279. //increment and loop
  280. x += 1;
  281. }
  282. }
  283. }
  284.  
  285. //---------- void Prune() ---------------------------------------
  286. // Prunes the array to fit within the maxMessages limit
  287. //---------------------------------------------------------------
  288. void Prune()
  289. {
  290. int diff;
  291. if (messages.Count > maxMessages)
  292. {
  293. if (messages.Count <= 0)
  294. {
  295. diff = 0;
  296. }
  297. else
  298. {
  299. diff = messages.Count - maxMessages;
  300. }
  301. messages.RemoveRange(0, (int)diff);
  302. colors.RemoveRange(0, (int)diff);
  303. }
  304.  
  305. }
  306.  
  307. //---------- void Display() -------------------------------------
  308. // Displays the list and handles coloring
  309. //---------------------------------------------------------------
  310. void Display()
  311. {
  312. //check if we are set to display
  313. if (visible == false)
  314. {
  315. ClearScreen();
  316. }
  317. else if (visible == true)
  318. {
  319.  
  320. if (messages.Count > maxMessages)
  321. {
  322. Prune();
  323. }
  324.  
  325. // Carry on with display
  326. int x = 0;
  327. if (guis.Count < maxMessages)
  328. {
  329. //do nothing as we havent created our guis yet
  330. }
  331. else
  332. {
  333. while (x < messages.Count)
  334. {
  335. GameObject gui = (GameObject)guis[x];
  336.  
  337. //set our color
  338. switch ((string)colors[x])
  339. {
  340. case "normal": gui.GetComponent<GUIText>().material.color = normal;
  341. break;
  342. case "warning": gui.GetComponent<GUIText>().material.color = warning;
  343. break;
  344. case "error": gui.GetComponent<GUIText>().material.color = error;
  345. break;
  346. }
  347.  
  348. //now set the text for this element
  349. gui.GetComponent<GUIText>().text = (string)messages[x];
  350.  
  351. //increment and loop
  352. x += 1;
  353. }
  354. }
  355.  
  356. }
  357. }
  358. #endif
  359.  
  360. }// End DebugConsole Class

2.使用方法


  1. //DebugConsole.instance.AddMessage("this is instance AddMessage test by cartzhang", "warning");
  2. //DebugConsole.Log("this is debug console log test cartzhang");

3.结果如图




四、这还不是我想要的,我要显示在控制台上,就是CMD出来的那样。

好吧,你赢了!!

你往下看吧!


-----------THE END ---------------

若有问题,请随时联系!
非常感谢!
--------

由于担心篇幅过长,写成下一篇吧。
再次感谢各位!

Unity 实现Log实时输出到屏幕或控制台上<一>的更多相关文章

  1. Unity 实现Log实时输出到屏幕或控制台上<二>

    本文章由cartzhang编写,转载请注明出处. 所有权利保留. 文章链接:http://blog.csdn.net/cartzhang/article/details/49884507 作者:car ...

  2. unity收集log工具

    参考 yusong:http://www.xuanyusong.com/archives/2477 凉鞋     :https://www.cnblogs.com/liangxiegame/p/Uni ...

  3. [Linux]屏幕输出控制

    专门的术语叫做ANSI Escape sequences(ANSI Escape codes),题目并不恰当,与其说是屏幕输出控制,不如说是通过bash在兼容VT100的终端上进行输出. 主要有以下类 ...

  4. .NET Core下的日志(3):如何将日志消息输出到控制台上

    当我们利用LoggerFactory创建一个Logger对象并利用它来实现日志记录,这个过程会产生一个日志消息,日志消息的流向取决于注册到LoggerFactory之上的LoggerProvider. ...

  5. java 在控制台上输入密码时,密码不显示在控制台上

    用下面的方法可以实现在控制台上输入密码时,密码不显示在控制台上:Console cons=System.console(); System.out.print(" 密码:"); c ...

  6. 大数据调错系列之hadoop在开发工具控制台上打印不出日志的解决方法

    (1)在windows环境上配置HADOOP_HOME环境变量 (2)在eclipse上运行程序 (3)注意:如果eclipse打印不出日志,在控制台上只显示 1.log4j:WARN No appe ...

  7. eclipse:eclipse for java EE环境下如何配置tomcat服务器,并让tomcat服务器显示在控制台上,将Web应用部署到tomcat中

    eclipse环境下如何配置tomcat 打开Eclipse,单击"Window"菜单,选择下方的"Preferences".  单击"Server& ...

  8. Ubuntu上运行Blender,在控制台上查看运行结果

    1.首先在控制台打开Blender. 具体操作:找到Blender的安装路径,我的是:/home/lcx/下载/blender-2.78c-linux-glibc219-x86_64 $cd /hom ...

  9. Java:IO流的综合用法(从键盘录入数据并打印在控制台上)

    import java.io.*; public class IOTestDouble { public static void main(String[] args)throws Exception ...

随机推荐

  1. ACM POJ 1146 ID Codes

    题目大意:输入一个字符串.输出它的下一个字典序排列. 字典序算法思想: 1.从右向左寻找字符串找出第一个a[i]<a[i+1]的位置i; 2.从右向左找出第一个大于a[i]的元素a[j]; 3. ...

  2. Android 购物车的实现

    实现了购物车的全选 全不选  选中删除   选中状态下数量添加时总价随之添加等基本功能. watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L ...

  3. 1.Swift教程翻译系列——关于Swift

    英文版PDF下载地址http://download.csdn.net/detail/tsingheng/7480427 我本来是做JAVA的.可是有一颗折腾的心,苹果公布Swift以后就下载了苹果的开 ...

  4. blog_html

    <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE html> <html b:v ...

  5. What's the difference between Unicode and UTF-8?

    https://stackoverflow.com/questions/3951722/whats-the-difference-between-unicode-and-utf-8 If asked ...

  6. hpuoj--1695--一道签到题(KMP)

    1695: 一道签到题 时间限制: 2 Sec  内存限制: 128 MB 提交: 72  解决: 36 [提交][状态][讨论版] 题目描述 我想说这是一道签到题,意思就是本次测试中最水的一道,不过 ...

  7. Eval函数知识总结

    说道Json,我们先来聊聊eval 一.eval是什么?(解析器) eval是一个函数,看本质function  eval() { [native code] } 二.怎样使用eval? 语法:str ...

  8. Spring项目的配置文件们(web.xml context servlet springmvc)

    我们的spring项目目前用到的配置文件包括1--web.xml文件,这是java的web项目的配置文件.我理解它是servlet的配置文件,也就是说,与spring无关.即使你开发的是一个纯粹jsp ...

  9. HDU 1240 Asteroids!【BFS】

    题意:给出一个三维的空间,给出起点和终点,问是否能够到达终点 和上一题一样,只不过这一题的坐标是zxy输入的, 因为题目中说的是接下来的n行中分别是由n*n的矩形组成的,所以第一个n该是Z坐标,n*n ...

  10. Debian9.5下sftp配置和scp用法

    基于 ssh 的 sftp 服务相比 ftp 有更好的安全性(非明文帐号密码传输)和方便的权限管理(限制用户的活动目录). 1.如果只想让某些用户只能使用 sftp 操作文件, 而不能通过ssh进行服 ...