实验三:A*算法

一、实验目的

掌握游戏中寻路算法尤其是目前产用的A*算法原理

二、实验仪器

Microsoft Visual Studio2019

三、实验原理及过程

//描述A*的算法原理

//描述程序实现时的思路包括对每个调用的API进行详细说明

A*(A-Star)算法是一种静态路网中求解最短路径最有效的直接搜索方法,也是许多其他问题的常用启发式算法。注意——是最有效的直接搜索算法,之后涌现了很多预处理算法(如ALT,CH,HL等等),在线查询效率是A*算法的数千甚至上万倍。

公式表示为: f*(n)=g*(n)+h*(n),

其中, f*(n) 是从初始状态经由状态n到目标状态的最小代价估计,

g*(n) 是在状态空间中从初始状态到状态n的最小代价,

h*(n) 是从状态n到目标状态的路径的最小估计代价。

(对于路径搜索问题,状态就是图中的节点,代价就是距离)

真实h(n)的选取:

保证找到最短路径(最优解的)条件,关键在于估价函数f(n)的选取(或者说h(n)的选取)。

以h(n)表达状态n到目标状态估计的距离,那么h(n)的选取大致有如下三种情况:

       1.如果h(n)< h*(n),这种情况下,搜索的点数多,搜索范围大,效率低。但能得到最优解。

       2.如果h(n)=h*(n),此时的搜索效率是最高的。

       3.如果 h(n)>h*(n),搜索的点数少,搜索范围小,效率高,但不能保证得到最优解。

例:

 

步骤1.从起点A开始,把A作为一个等待检查的方格,放入到“开启列表”中,开启列表就是一个存放等待检车方格的列表

 步骤2.寻找起点A周围可以到达的方格(最多八个),将它们放入到“开启列表”,并设置它们的父方格为A

 步骤3.从“开启列表”中删除点A,并将A放入到“关闭列表”中,“关闭列表”存放的是不再需要检查的方格

 步骤4.计算每个方格的F值

  F=G+H:

  G 表示从起点A移动到指定方格的移动消耗,我们假设横向移动一个格子消耗10,斜向移动一个格子消耗14(具体值可以根据情况修改)

  H 表示从指定的方格移动到目标B点的预计消耗,我们假设H的计算方法,忽略障碍物,只可以纵横向计算

 步骤5.从“开启列表”中选择F值最低的方格C,将其从“开启列表”中删除,放入到“关闭列表”中

 步骤6.检查C所有临近并且可达的方格(障碍物和“关闭列表”中的方格不考虑),如果这些方格还不在“开启列表”中的话,将它们加入到开启列表,并且计算这些方格的F值,并设置父方格为C。

 步骤7.如果某相邻的方格D已经在“开启列表”,计算新的路径从A到达方格D(即经过C的路径),G值是否更低一点,如果新的G值更低,则修改父方格为方格C,重新计算F值,H值不需要改变,因为方格到达目标点的预计消耗是固定的。但如果新的G值比较高,则说明新的路径消耗更高,则值不做改变。

 步骤8.继续从“开启列表”中找出F值最小的,从“开启列表”中删除,添加到“关闭列表”,再继续找出周围可以到达的方块,如此循环

 步骤9.当“开启列表”中出现目标方块B时,说明路径已经找到。除了起始方块A,每一个曾经或者现在还在“开启列表”中的方块,都存在一个“父方格”,可以从目标点B通过父方格索引到起始方块,这就是路径。

四、实验结果

这里通过简单的java代码来实现A*算法

五、实验心得(需包括有何不足如何改进)

//你认为目前的A*算法有什么不足之处,如何改进

A*算法通过比较当前路径栅格的8个邻居的启发式函数值F来逐步确定下一个路径栅格,当存在多个最小值时A*算法不能保证搜索的路径最优。

有些资料介绍将稀疏A-Star算法扩展到三维空间,提出了一种动态的稀疏A-Star算法。

A*算法的搜索效率很大程度上取决于估价函数h(n)。一般来说,在满足h(n) <=h* (n)的前提下,

h(n)的值越大越好。h(n) 的值越大,说明它携带的启发性信息越多,A*算法搜索时扩展的节点就越

少,搜索效率也越高。这-特性称为信息性。

通过本次实验,学习到了A*算法原理,以及能更好的明白游戏中的寻路算法,收获颇多,对今后的学习有了进一步的帮助。

六、主要代码

//本次实验主要main代码

#pragma warning (disable:4786)

#include <windows.h>

#include <time.h>

//need to include this for the toolbar stuff

#include <commctrl.h>

#pragma comment(lib, "comctl32.lib")

#include "constants.h"

#include "misc/utils.h"

#include "Time/PrecisionTimer.h"

#include "Pathfinder.h"

#include "resource.h"

#include "misc/Cgdi.h"

#include "misc/WindowUtils.h"

//need to define a custom message so that the backbuffer can be resized to

//accomodate the toolbar

#define UM_TOOLBAR_HAS_BEEN_CREATED (WM_USER + 33)

//--------------------------------- Globals ------------------------------

//

//------------------------------------------------------------------------

const char* g_szApplicationName = "PathFinder";

const char*     g_szWindowClassName = "MyWindowClass";

Pathfinder* g_Pathfinder;

//global toolbar handle

HWND g_hwndToolbar;

//------------------------- RedrawDisplay ---------------------------------

//

//  Call this to refresh the client window

//------------------------------------------------------------------------

void RedrawDisplay(HWND hwnd)

{

  InvalidateRect(hwnd, NULL, TRUE);

  UpdateWindow(hwnd);

}

//----------------------- ResizeToCorrectClientArea ---------------------------

//

//  resizes the client are taking into account any toolbars and any menus

//-----------------------------------------------------------------------------

void ResizeToCorrectClientArea(HWND hwnd, int AccumulativeToolbarHeight, RECT ClientArea)

{

  AdjustWindowRectEx(&ClientArea,

                     WS_OVERLAPPED | WS_VISIBLE | WS_CAPTION | WS_SYSMENU,

                     true,

                     NULL);

  SetWindowPos(hwnd,

               NULL,

               0,

               0,

               ClientArea.right,

               ClientArea.bottom + AccumulativeToolbarHeight,

               SWP_NOMOVE|SWP_NOZORDER);

}

//---------------------------- WindowProc ---------------------------------

//    

//     This is the callback function which handles all the windows messages

//-------------------------------------------------------------------------

LRESULT CALLBACK WindowProc (HWND   hwnd,

                             UINT   msg,

                             WPARAM wParam,

                             LPARAM lParam)

{

   //these hold the dimensions of the client window area

        static int cxClient, cyClient;

        //used to create the back buffer

   static HDC       hdcBackBuffer;

   static HBITMAP     hBitmap = NULL;

   static HBITMAP     hOldBitmap = NULL;

   static int ToolBarHeight;

   //to grab filenames

   static TCHAR   szFileName[MAX_PATH],

                  szTitleName[MAX_PATH];

   static RECT rectClientWindow;

   static int CurrentSearchButton = 0;

    switch (msg)

    {

      

              //A WM_CREATE msg is sent when your application window is first

              //created

    case WM_CREATE:

      {

         //seed random number generator

         srand((unsigned) time(NULL));  

        

         //---------------create a surface to render to(backbuffer)

         //create a memory device context

         hdcBackBuffer = CreateCompatibleDC(NULL);

         //get the DC for the front buffer

         HDC hdc = GetDC(hwnd);

         hBitmap = CreateCompatibleBitmap(hdc,

                                          cxClient,

                                          cyClient);

                      

         //select the bitmap into the memory device context

                        hOldBitmap = (HBITMAP)SelectObject(hdcBackBuffer, hBitmap);

         //don't forget to release the DC

         ReleaseDC(hwnd, hdc); 

        

         //create the controller

         g_Pathfinder = new Pathfinder();

         CheckMenuItemAppropriately(hwnd, IDM_VIEW_TILES, g_Pathfinder->isShowTilesOn());

         CheckMenuItemAppropriately(hwnd, IDM_VIEW_GRAPH, g_Pathfinder->isShowGraphOn());

      }

      break;

      case UM_TOOLBAR_HAS_BEEN_CREATED:

      {

       

          //get the height of the toolbar

         RECT rectToolbar;

         GetWindowRect(g_hwndToolbar, &rectToolbar);

         ToolBarHeight =  abs(rectToolbar.bottom - rectToolbar.top);

         rectClientWindow.left = 0;

         rectClientWindow.right = ClientWidth;

         rectClientWindow.top = 0;

         rectClientWindow.bottom = ClientHeight + InfoWindowHeight;

        ResizeToCorrectClientArea(hwnd, ToolBarHeight, rectClientWindow);

        

        //let the toolbar know about the resize

        SendMessage(g_hwndToolbar, WM_SIZE, wParam, lParam);

        //this defines the area to be redrawn (to prevent the toolbar flickering)

        GetClientRect(hwnd, &rectClientWindow);

        rectClientWindow.bottom = ClientHeight - ToolBarHeight - 1;

         //create a memory device context

         hdcBackBuffer = CreateCompatibleDC(NULL);

         //get the DC for the front buffer

         HDC hdc = GetDC(hwnd);

         hBitmap = CreateCompatibleBitmap(hdc,

                                          rectClientWindow.right,

                                          rectClientWindow.bottom);

                      

         //select the bitmap into the memory device context

                        hOldBitmap = (HBITMAP)SelectObject(hdcBackBuffer, hBitmap);

         //don't forget to release the DC

         ReleaseDC(hwnd, hdc);     

      }

      break;

    case WM_KEYUP:

      {

        switch(wParam)

        {

         case VK_ESCAPE:

                     

            SendMessage(hwnd, WM_DESTROY, NULL, NULL); break;

          case 'G':

                    

            g_Pathfinder->ToggleShowGraph(); break;

          case 'T':

                    

            g_Pathfinder->ToggleShowTiles(); break;

        }//end switch

        RedrawWindowRect(hwnd, false, rectClientWindow);

      }

      break;

     

    case WM_LBUTTONDOWN:

    {

      g_Pathfinder->PaintTerrain(MAKEPOINTS(lParam));

      RedrawWindowRect(hwnd, false, rectClientWindow);

    

    }

   

    break;

    case WM_MOUSEMOVE:

    {

      switch(wParam)

      {

      case MK_LBUTTON:

        {

          g_Pathfinder->PaintTerrain(MAKEPOINTS(lParam));

          RedrawWindowRect(hwnd, false, rectClientWindow);

        }

        break;

      }

    }

    case WM_COMMAND:

    {

      switch(wParam)

      {

      case ID_BUTTON_STOP:

        g_Pathfinder->ChangeBrush(Pathfinder::target);

        break;

      case ID_BUTTON_START:

        g_Pathfinder->ChangeBrush(Pathfinder::source);

        break;

      case ID_BUTTON_OBSTACLE:

        g_Pathfinder->ChangeBrush(Pathfinder::obstacle);

        break;

      case ID_BUTTON_WATER:

        g_Pathfinder->ChangeBrush(Pathfinder::water);

        break;

      case ID_BUTTON_MUD:

        g_Pathfinder->ChangeBrush(Pathfinder::mud);

        break;

      case ID_BUTTON_NORMAL:

        g_Pathfinder->ChangeBrush(Pathfinder::normal);

        break;

      case ID_BUTTON_DFS:

        g_Pathfinder->CreatePathDFS(); CurrentSearchButton = ID_BUTTON_DFS; break;

        break;

      case ID_BUTTON_BFS:

        g_Pathfinder->CreatePathBFS(); CurrentSearchButton = ID_BUTTON_BFS; break;

        break;

      case ID_BUTTON_DIJKSTRA:

        g_Pathfinder->CreatePathDijkstra(); CurrentSearchButton = ID_BUTTON_DIJKSTRA; break;

        break;

      case ID_BUTTON_ASTAR:

        g_Pathfinder->CreatePathAStar(); CurrentSearchButton = ID_BUTTON_ASTAR; break;

        break;

      case ID_MENU_LOAD:

         

          FileOpenDlg(hwnd, szFileName, szTitleName, "pathfinder files (*.map)", "map");

          if (strlen(szTitleName) > 0)

          {

            g_Pathfinder->Load(szTitleName);

          }

          //uncheck the current search toolbar button

          SendMessage(g_hwndToolbar,

                     TB_CHECKBUTTON,

                     (WPARAM) CurrentSearchButton,

                     (LPARAM) false);

          break;

      case ID_MENU_SAVEAS:

        FileSaveDlg(hwnd, szFileName, szTitleName, "pathfinder files (*.map)", "map");

        if (strlen(szTitleName) > 0)

        {

          g_Pathfinder->Save(szTitleName);

        }

       

        break;

      case ID_MENU_NEW:

       

         //create the graph

         g_Pathfinder->CreateGraph(NumCellsX, NumCellsY);

          //uncheck the current search toolbar button

          SendMessage(g_hwndToolbar,

                     TB_CHECKBUTTON,

                     (WPARAM) CurrentSearchButton,

                     (LPARAM) false);

         break;

       case IDM_VIEW_GRAPH:

          if (GetMenuState(GetMenu(hwnd), IDM_VIEW_GRAPH, MFS_CHECKED) && MF_CHECKED)

          {

            ChangeMenuState(hwnd, IDM_VIEW_GRAPH, MFS_UNCHECKED);

            g_Pathfinder->SwitchGraphOff();

          }

          else

          {

            ChangeMenuState(hwnd, IDM_VIEW_GRAPH, MFS_CHECKED);

            g_Pathfinder->SwitchGraphOn();

          }

          break;

        case IDM_VIEW_TILES:

          if (GetMenuState(GetMenu(hwnd), IDM_VIEW_TILES, MFS_CHECKED) && MF_CHECKED)

          {

            ChangeMenuState(hwnd, IDM_VIEW_TILES, MFS_UNCHECKED);

            g_Pathfinder->SwitchTilesOff();

          }

          else

          {

            ChangeMenuState(hwnd, IDM_VIEW_TILES, MFS_CHECKED);

            g_Pathfinder->SwitchTilesOn();

          }

          break;

      }//end switch

      RedrawWindowRect(hwnd, false, rectClientWindow);

    }

   

    case WM_PAINT:

      {

                   

         PAINTSTRUCT ps;

         

         BeginPaint (hwnd, &ps);

        //fill the backbuffer with white

         BitBlt(hdcBackBuffer,

                0,

                0,

                cxClient,

                cyClient,

                NULL,

                NULL,

                NULL,

                WHITENESS);

         

        gdi->StartDrawing(hdcBackBuffer);

        g_Pathfinder->Render();

        gdi->StopDrawing(hdcBackBuffer);

         //now blit backbuffer to front

                        BitBlt(ps.hdc, 0, 0, cxClient, cyClient, hdcBackBuffer, 0, 0, SRCCOPY);

         

         EndPaint (hwnd, &ps);

      }

      break;

              case WM_SIZE:

                {

                       cxClient = LOWORD(lParam);

                       cyClient = HIWORD(lParam);

        //now to resize the backbuffer accordingly. First select

        //the old bitmap back into the DC

                       SelectObject(hdcBackBuffer, hOldBitmap);

        //don't forget to do this or you will get resource leaks

        DeleteObject(hBitmap);

                       //get the DC for the application

        HDC hdc = GetDC(hwnd);

                       //create another bitmap of the same size and mode

        //as the application

       hBitmap = CreateCompatibleBitmap(hdc,

                                        rectClientWindow.right,

                                        rectClientWindow.bottom);

                       ReleaseDC(hwnd, hdc);

                      

                       //select the new bitmap into the DC

        SelectObject(hdcBackBuffer, hBitmap);

      }

      break;

         

               case WM_DESTROY:

                      {

         //clean up our backbuffer objects

         SelectObject(hdcBackBuffer, hOldBitmap);

         DeleteDC(hdcBackBuffer);

         DeleteObject(hBitmap);

         DeleteObject(hOldBitmap);

        

         // kill the application, this sends a WM_QUIT message 

                             PostQuitMessage (0);

                      }

       break;

     }//end switch

     //this is where all the messages not specifically handled by our

               //winproc are sent to be processed

               return DefWindowProc (hwnd, msg, wParam, lParam);

}

//----------------------------- CreateToolBar ----------------------------

//------------------------------------------------------------------------

HWND CreateToolBar(HWND hwndParent, HINSTANCE hinstMain)

{

  const int NumButtons = 11;

 

  //load in the common ctrls from the dll

  INITCOMMONCONTROLSEX cc;

  cc.dwSize = sizeof(INITCOMMONCONTROLSEX);

  cc.dwICC = ICC_BAR_CLASSES;

  if (!InitCommonControlsEx(&cc))

  {

    MessageBox(NULL, "Failed to load common ctrls!", "Error!", MB_OK);

    return 0;

  }

   

  //create the toolbar

  HWND hwndToolBar = CreateWindowEx(NULL,               

                             TOOLBARCLASSNAME,  

                             (LPSTR) NULL,          

                             WS_CHILD | WS_VISIBLE | CCS_BOTTOM, 

                             0,

                             0,                   

                             0,          

                             0,         

                             hwndParent,                

                             (HMENU) IDR_TOOLBAR1,                 

                             hinstMain,           

                             NULL);              

  //make sure the window creation has gone OK

  if(!hwndToolBar)

  {

    MessageBox(NULL, "CreateWindowEx Failed!", "Error!", 0);

  }

  //let the toolbar know the size of the buttons to be added

  SendMessage(hwndToolBar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);

  //add bitmaps to the buttons

  TBADDBITMAP tb;

  tb.hInst = NULL;

  tb.nID = (UINT_PTR)LoadBitmap((HINSTANCE)GetWindowLong(hwndParent, GWL_HINSTANCE),MAKEINTRESOURCE(IDR_TOOLBAR1));

  int idx = SendMessage (hwndToolBar, TB_ADDBITMAP, NumButtons, (LPARAM)&tb);

  //create the buttons

  TBBUTTON button[NumButtons];

  button[0].iBitmap   = 0;

  button[0].idCommand = ID_BUTTON_STOP;

  button[0].fsState   = TBSTATE_ENABLED;

  button[0].fsStyle   = TBSTYLE_CHECKGROUP;

  button[0].dwData    = NULL;

  button[0].iString   = NULL;

  button[1].iBitmap   = 1;

  button[1].idCommand = ID_BUTTON_START;

  button[1].fsState   = TBSTATE_ENABLED;

  button[1].fsStyle   = TBSTYLE_CHECKGROUP;

  button[1].dwData    = NULL;

  button[1].iString   = NULL;

  button[2].iBitmap   = 2;

  button[2].idCommand = ID_BUTTON_OBSTACLE;

  button[2].fsState   = TBSTATE_ENABLED;

  button[2].fsStyle   = TBSTYLE_CHECKGROUP;

  button[2].dwData    = NULL;

  button[2].iString   = NULL;

  button[3].iBitmap   = 3;

  button[3].idCommand = ID_BUTTON_MUD;

  button[3].fsState   = TBSTATE_ENABLED;

  button[3].fsStyle   = TBSTYLE_CHECKGROUP;

  button[3].dwData    = NULL;

  button[3].iString   = NULL;

  button[4].iBitmap   = 4;

  button[4].idCommand = ID_BUTTON_WATER;

  button[4].fsState   = TBSTATE_ENABLED;

  button[4].fsStyle   = TBSTYLE_CHECKGROUP;

  button[4].dwData    = NULL;

  button[4].iString   = NULL;

  button[5].iBitmap   = 5;

  button[5].idCommand = ID_BUTTON_NORMAL;

  button[5].fsState   = TBSTATE_ENABLED;

  button[5].fsStyle   = TBSTYLE_CHECKGROUP;

  button[5].dwData    = NULL;

  button[5].iString   = NULL;

  //this creates a separater

  button[6].iBitmap   = 265;

  button[6].idCommand = 0;

  button[6].fsState   = NULL;

  button[6].fsStyle   = TBSTYLE_SEP;

  button[6].dwData    = NULL;

  button[6].iString   = NULL;

  button[7].iBitmap   = 6;

  button[7].idCommand = ID_BUTTON_DFS;

  button[7].fsState   = TBSTATE_ENABLED;

  button[7].fsStyle   = TBSTYLE_CHECKGROUP;

  button[7].dwData    = NULL;

  button[7].iString   = NULL;

  button[8].iBitmap   = 7;

  button[8].idCommand = ID_BUTTON_BFS;

  button[8].fsState   = TBSTATE_ENABLED;

  button[8].fsStyle   = TBSTYLE_CHECKGROUP;

  button[8].dwData    = NULL;

  button[8].iString   = NULL;

  button[9].iBitmap   = 8;

  button[9].idCommand = ID_BUTTON_DIJKSTRA;

  button[9].fsState   = TBSTATE_ENABLED;

  button[9].fsStyle   = TBSTYLE_CHECKGROUP;

  button[9].dwData    = NULL;

  button[9].iString   = NULL;

  button[10].iBitmap   = 9;

  button[10].idCommand = ID_BUTTON_ASTAR;

  button[10].fsState   = TBSTATE_ENABLED;

  button[10].fsStyle   = TBSTYLE_CHECKGROUP;

  button[10].dwData    = NULL;

  button[10].iString   = NULL;

  //add the buttons to the toolbar

  SendMessage(hwndToolBar, TB_ADDBUTTONS, (WPARAM)NumButtons, (LPARAM)(LPTBBUTTON)&button);

  return hwndToolBar;

}

//-------------------------------- WinMain -------------------------------

//

//     The entry point of the windows program

//------------------------------------------------------------------------

int WINAPI WinMain (HINSTANCE hInstance,

                    HINSTANCE hPrevInstance,

                    LPSTR     szCmdLine,

                    int       iCmdShow)

{

     //handle to our window

               HWND                                    hWnd;

   

               //our window class structure

               WNDCLASSEX     winclass;

               

     // first fill in the window class stucture

          winclass.cbSize        = sizeof(WNDCLASSEX);

          winclass.style         = CS_HREDRAW | CS_VREDRAW;

     winclass.lpfnWndProc   = WindowProc;

     winclass.cbClsExtra    = 0;

     winclass.cbWndExtra    = 0;

     winclass.hInstance     = hInstance;

     winclass.hIcon         = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));

     winclass.hCursor       = LoadCursor(NULL, IDC_ARROW);

     winclass.hbrBackground = NULL;

     winclass.lpszMenuName  = MAKEINTRESOURCE(IDR_MENU1);

     winclass.lpszClassName = g_szWindowClassName;

          winclass.hIconSm       = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));

               //register the window class

              if (!RegisterClassEx(&winclass))

              {

                     MessageBox(NULL, "Registration Failed!", "Error", 0);

                     //exit the application

                     return 0;

              }

               //create the window   

     hWnd = CreateWindowEx (NULL,                 // extended style

                            g_szWindowClassName,  // window class name

                            g_szApplicationName,  // window caption

                            WS_OVERLAPPED | WS_VISIBLE | WS_CAPTION | WS_SYSMENU,  // window style

                            GetSystemMetrics(SM_CXSCREEN)/2 - WindowWidth/2,

                            GetSystemMetrics(SM_CYSCREEN)/2 - WindowHeight/2,                   

                            WindowWidth,           // initial x size

                            WindowHeight,          // initial y size

                            NULL,                 // parent window handle

                            NULL,                 // window menu handle

                            hInstance,            // program instance handle

                            NULL);                // creation parameters

  //make sure the window creation has gone OK

  if(!hWnd)

  {

    MessageBox(NULL, "CreateWindowEx Failed!", "Error!", 0);

  }

  //create the toolbar

  g_hwndToolbar = CreateToolBar(hWnd, hInstance);

  SendMessage(hWnd, UM_TOOLBAR_HAS_BEEN_CREATED, NULL, NULL);

  //create the graph

  g_Pathfinder->CreateGraph(NumCellsX, NumCellsY);

    

  //enter the message loop

  //this will hold any windows messages

  MSG msg;

    

      //entry point of our message handler

       while (GetMessage (&msg, NULL, 0, 0))

  {

     TranslateMessage (&msg);

     DispatchMessage (&msg);

  }

  delete g_Pathfinder;

  UnregisterClass( g_szWindowClassName, winclass.hInstance );

  return msg.wParam;

}

//这里是关于A*算法的简单的java代码

import java.util.ArrayList;

import java.util.List;

//A*寻路算法简单实现————>四方向(上下左右)

public class Maze_A_ManHaDun {

   

    //简单的迷宫模拟——利用二维数组,其中 1 表示障碍,不可通过。

    public static final int[][] MAZE= {

    {0, 1, 0, 0, 0, 0, 0},//7

    {0, 0, 1, 0, 0, 0, 0},

    {1, 0, 0, 1, 0, 0, 0},

    {0, 1, 0, 1, 1, 1, 1},

    {0, 0, 0, 0, 0, 0, 0},

    {0, 0, 0, 0, 0, 0, 0},

    {0, 0, 0, 1, 1, 1, 0},

    //7

    };

   

    //定义 方格节点——grid

    static class Grid{

        public int x;//结点

        public int y;

        public int f;//fn

        public int g;//gn

        public int h;//hn

        public Grid parent;

       

       

        public Grid(int x,int y) {

            this.x=x;

            this.y=y;

        }

       

        //实例化一个方格节点

        public void initGrid(Grid parent, Grid end) {

            //parent赋值

            this.parent=parent;

           

            //计算g的大小

            if(parent!=null) {

                this.g=parent.g+1;

                //this.g=0;

            }

            else

            {

                this.g=1;

            }

           

            //计算h的大小

            this.h=Math.abs(this.x-end.x)+Math.abs(this.y-end.y);

            //this.h=Math.abs(this.x-end.x)*Math.abs(this.y-end.y);     

            //计算f的大小

            this.f=this.g+this.h;

        }

    }

   

    //寻路算法核心实现过程

    public static Grid aStarSearch(Grid start, Grid end) {

       

        //准备两个链表,分别存储 将要选择的节点    已经走过的节点

        ArrayList<Grid> openlist=new ArrayList<Grid>();

        ArrayList<Grid> closelist=new ArrayList<Grid>();

       

        //将起点加入链表,准备开始寻路。

        openlist.add(start);

       

        //只要链表不为空,就重复这个寻路的过程

        while(openlist.size()>0) {

           

            //找到 openlist F值最小的那个 方格(节点)

            Grid currentgrid=findMinGrid(openlist);

           

            // openlist中删除找到的那个  F 最小的那个节点

            openlist.remove(currentgrid);

           

            //将这个  F 最小的节点,加入到  closelist

            closelist.add(currentgrid);

           

            //寻找  当前找到的这个 F值最小的节点的  邻居节点 ——上下左右,四个方向上的节点,要判断它们是否为合法可用的节点。

            List<Grid> neighbors=findNeighbors(currentgrid, openlist, closelist);

           

            //对合法可用的邻居节点进行初始化,并加入到  openlist

            for(Grid grid : neighbors) {

                if(!openlist.contains(grid)) {

                   grid.initGrid(currentgrid,end);

                   openlist.add(grid);

                }

            }

           

            //邻居节点加入  openlist 后,判断openlist中,是否包含  终点节点,如果包含终点,直接返回并退出。

            for(Grid grid : openlist) {

                if((grid.x==end.x) && (grid.y==end.y)) {

                   return grid;

                }

            }

        }

       

        return null;

    }

   

   

    //寻找邻居节点的方法,返回值为  链表  ——创建一个合理的邻居链表

    private static ArrayList<Grid> findNeighbors(Grid grid, List<Grid> openlist, List<Grid> closelist) {

        // TODO Auto-generated method stub

       

        ArrayList<Grid> gridlist=new ArrayList<Grid>();

       

        //判断上下左右邻居节点的合理性,没问题就加入到邻居链表中。

        if(isValidGrid(grid.x, grid.y-1, openlist, closelist)) {//

            gridlist.add(new Grid(grid.x, grid.y-1));

        }

       

        if(isValidGrid(grid.x, grid.y+1, openlist, closelist)) {//

            gridlist.add(new Grid(grid.x, grid.y+1));

        }

       

        if(isValidGrid(grid.x-1, grid.y, openlist, closelist)) {//

            gridlist.add(new Grid(grid.x-1, grid.y));

        }

       

        if(isValidGrid(grid.x+1, grid.y, openlist, closelist)) {//

            gridlist.add(new Grid(grid.x+1, grid.y));

        }

       

       

        return gridlist;

    }

    //判断当前位置的节点是否合理

    private static boolean isValidGrid(int x, int y, List<Grid> openlist, List<Grid> closelist) {

        // TODO Auto-generated method stub

       

        //当前节点是否越界,不再MAZE数组范围内了,注意二位数组的长度计算方法及含意

        //MAZElength表示行的长度

        //MAZE[0]length表示列的长度

        if(x<0 || x>=MAZE.length || y<0 || y>=MAZE[0].length) {

            return false;

        }

       

        //当前节点是否为障碍节点

        if(MAZE[x][y]==1) {

            return false;

        }

       

       

        //判断当前节点是否在 openlist

        if(containgrid(openlist, x, y)) {

            return false;

        }

       

        //判断当前节点是否在 closelist

        if(containgrid(closelist, x, y)) {

            return false;

        }

       

        return true;

    }

    //判断当前链表中是否包含当前的节点

    private static boolean containgrid(List<Grid> grids, int x, int y) {

        // TODO Auto-generated method stub

       

        for(Grid grid : grids) {

            if((grid.x==x) && (grid.y==y)) {

                return true;

            }

        }

       

        return false;

    }

    //寻找当前链表中的节点F 最小的那个节点,并返回这个节点。

    private static Grid findMinGrid(ArrayList<Grid> openlist) {

        // TODO Auto-generated method stub

       

        Grid tempgrid=openlist.get(0);

        for(Grid grid : openlist) {

            if(grid.f<tempgrid.f) {

                tempgrid=grid;

            }

        }

       

        return tempgrid;

    }

    public static void main(String[] args) {

        // TODO Auto-generated method stub

        int b1=0,b2=0;//起始坐标

        int c1=0,c2=6;

        Grid startgrid=new Grid(b2,b1);

        System.out.println("起点坐标为:"+"("+b1+","+b2+")");

       

        Grid endgrid=new Grid(c2,c1);

        System.out.println("终点坐标为:"+"("+c1+","+c2+")");

        Grid resultgrid=aStarSearch(startgrid,endgrid);

       

        //创建回溯链表

        ArrayList<Grid> path=new ArrayList<Grid>();

        while(resultgrid!=null) {

            path.add(new Grid(resultgrid.x, resultgrid.y));

            resultgrid=resultgrid.parent;

        }

       

        //打印输出当前寻路路径

        int count=0;

        for(int i=0; i<MAZE.length; i++) {

            for(int j=0; j<MAZE[0].length; j++) {

                if(containgrid(path, i, j)) {

                   System.out.print(", ");

                   count++;

                }

                else

                {

                   System.out.print(MAZE[i][j]+ ", ");

                }

            }

            System.out.println();

           

        }

        System.out.println("最短路径长度为:"+count);

    }

}

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

相关文章

  1. WebSocket笔记+SpringBoot整合WebSocke

    WebSocket笔记 webSocket&#xff1a;HTML5 WebSocket设计出来的目的就是取代轮询和长连接&#xff0c;使客户端浏览器具备像C/S框架下桌面系统的即时通讯能力&#xff0c;实现了浏览器和服务器全双工通信&#xff0c;建立在TCP之上&#xff0c;虽然WebSocket和HTTP一样通过TCP…...

    2024/4/14 10:04:35
  2. 关于NullPointerException空指针异常的解决办法

    在spring学习过程中很容易碰到.NullPointerException的异常 ava.lang.NullPointerExceptionat com.itheima.controller.RoleController.list(RoleController.java:23)at com.itheima.controller.RoleController.test1(RoleController.java:32)at sun.reflect.NativeMethodAcc…...

    2024/4/20 1:28:18
  3. MC(c++)转载

    #include<bits/stdc.h> #include<time.h> #include<conio.h> #include<Windows.h> using namespace std; string name,gname,wqm"手",hjm"空"; long long gly,hjnx-1,hjz0,pg0,s20,ssx,csg1,wq0,gjzcsgwq,t,z0,l0,x0,y60,u,sy2,dy…...

    2024/4/27 23:38:44
  4. nginx反向代理后页面内嵌入的iframe无法打开

    通过nginx反向代理的方式代理一个系统的资源&#xff0c;但是访问代理后的地址后登录报错500&#xff0c;因为系统比较久远无人维护&#xff0c;无法查看应用的日志&#xff0c;无法得知具体的报错信息。 经过多次排查&#xff0c;确认是接口校验了请求的referren请求头&#x…...

    2024/4/14 10:04:45
  5. Spring Boot 中使用 @Async 注解导致循环依赖的原因及解决方案

    前言 在写这篇文章之前&#xff0c;我写了一篇关于循环依赖的文章&#xff0c;为什么这篇文章我又说和循环依赖有关的话题呢&#xff0c;其实&#xff0c;是因为我原本想写一篇关于 Async 原理分析的文章的&#xff0c;后来为了能更深入理解 Async 以便我接下来的写的文章&…...

    2024/4/28 3:38:44
  6. NLP综合

    实验要求 完成对中文搜狗新闻语料库的LDA主题提取。 实验内容 一、训练关键词提取算法 &#xff08;1&#xff09;加载已有的文档数据集。 为了解决编码错误&#xff0c;将编码改为GB18030&#xff1a; 能读取的文件数量从17678&#xff0c;增加到了17910。 打印文件内容…...

    2024/4/14 10:04:35
  7. 资深程序员参加面试因穿着被认为是实习生,拿下帽子后,被当场录取

    在职场上&#xff0c;面试几乎是每一个行业从业人员都必要要经历的过程。对于很多的职场新手来说&#xff0c;在面试的时候很容易因不懂“行业潜规则”而遗憾的被面试官淘汰&#xff01; 最近&#xff0c;一个资深程序员应聘的视频引起了网友的热烈讨论&#xff0c;对于程序员的…...

    2024/4/20 9:18:45
  8. vscode配置 SSH 链接服务器

    什么是SSH Secure Shell&#xff08;安全外壳协议&#xff0c;简称SSH&#xff09;是一种加密的网络传输协议&#xff0c;可在不安全的网络中为网络服务提供安全的传输环境。SSH通过在网络中创建安全隧道来实现SSH客户端与服务器之间的连接。SSH最常见的用途是远程登录系统&am…...

    2024/4/25 3:13:14
  9. Flink 实践教程-进阶(7):基础运维

    流计算 Oceanus 简介 流计算 Oceanus 是大数据产品生态体系的实时化分析利器&#xff0c;是基于 Apache Flink 构建的具备一站开发、无缝连接、亚秒延时、低廉成本、安全稳定等特点的企业级实时大数据分析平台。流计算 Oceanus 以实现企业数据价值最大化为目标&#xff0c;加速…...

    2024/4/14 10:04:40
  10. springboot学习笔记1(idea快速创建项目,隐藏文件,运行项目,修改端口)

    1.通过idea中的spring initializr可快速生成项目&#xff0c;若idea无法联网&#xff0c;则可去https://start.spring.io或http://start.aliyun.com访问&#xff0c;当然也可以自己制作&#xff0c;不过手工制作好像有点复杂&#xff0c;这里我就不介绍了&#xff0c;可以去网上…...

    2024/4/7 15:29:11
  11. 华为、TCL、大疆,高级android面试答案

    面经、真题 华为 一面 1.自我介绍 2.应用启动流程&#xff0c;activity 启动流程&#xff0c;为什么要每个应用有一个自己的虚拟机&#xff0c;这个虚拟机和JVM的关系。 3.hashmap的基本原理 4.来说一说&#xff0c;在5.0以上和4.0加载dex时的方式有什么区别&#xff1f; 5.说…...

    2024/4/19 15:56:34
  12. 元宇宙是什么,如何看待未来元宇宙的发展?

    元宇宙&#xff08;Metaverse&#xff09;这个听起来宏大遥远的词汇&#xff0c;最初由科幻作家Neal Stephenson于1992年在其著作《雪崩》中提出。它的英文前缀Meta&#xff0c;指「超级​的​、大地」&#xff1b;后缀verse和宇宙&#xff08;universe&#xff09;相同&#x…...

    2024/4/28 5:13:48
  13. C++ Primer Plus(第6版)---编程作业完成(第四,五章)

    第四章 #include <iostream> #include <string> #include <cstring> #include <array> using namespace std; //函数原型 void grade(void); void code(void); void name(void); void name_string(void); void candy(void); void candy_array(void); …...

    2024/4/14 10:04:40
  14. Mysql中的条件函数

    1.CASE函数 是一种多分支的函数&#xff0c;可以根据条件列表的值返回多个可能的结果表达式中的一个。 可用在任何允许使用表达式的地方&#xff0c;但不能单独作为一个语句执行。分为简单CASE函数和搜索CASE函数 1.1简单case函数 CASE 测试表达式 WHEN 简单表达式1 THEN 结…...

    2024/4/14 10:05:10
  15. 小程序 获取当前城市位置-高德地图

    微信小程序 wx.getLocation 只能获取到经纬度&#xff0c;想要获取具体城市信息&#xff0c;需要使用地图插件。公司要求使用 高德地图&#xff0c;在使用上&#xff0c;几个地图的代码步骤都差不多。 目录 1. 查看官方文档 1.1 申请高德地图Key&#xff0c;点击查看申请key…...

    2024/4/20 8:33:07
  16. 32位C程序在64位上使用遇到的问题记录

    1.返回值是指针。 注意当函数的返回值是指针时&#xff0c;需要注意显示声明&#xff01;如果隐式声明会被默认截断为32位数据&#xff0c;指针就会出问题&#xff0c;导致崩溃轻而易举。...

    2024/4/20 0:14:48
  17. 北京Android 3年开发,二本学历,历时半年终斩获腾讯offer

    10、Activity A启动B生命周期回调 11、列表卡顿 12、找出字符串的最长不重复子串 13、线程池 14、原理&#xff1a; ThreadPoolExecutor Executors 15、组件化流程 16、进程方法调用( Binder原理) 17、Activity启动流程 18、HTTPS … 小总结&#xff1a;首先是根据…...

    2024/4/14 15:12:55
  18. 网友爆出鹅厂和猫厂的程序员工资表,看完心动了...

    近日有网友曝出腾讯和阿里巴巴的员工待遇架构&#xff0c;我们先来一睹为快&#xff1a; 腾讯员工工资表中可以看出&#xff0c;级别较低的员工工资在一万左右&#xff0c;虽然不算是太高&#xff0c;但对于刚毕业的应届生来说还是可以满足一定的生活需求。随着级别的提高&…...

    2024/4/23 23:52:33
  19. linux12企业实战 -- 40全网日常巡检

    日常巡检 #!/bin/bash # Author: sys_op # Date: 2022-1-12 0:00:00 # Last Modified by: sys_op # Last Modified time: 2022-1-12 0:00:00 # E-mail: fengmmshait.com.cn #!/bin/bash #1、主机信息每日巡检IPADDR$(ifconfig eth0|grep inet addr|awk -F [ :] {print $13…...

    2024/4/20 0:00:15
  20. SocketIO介绍+SpringBoot整合SocketIO完成实时通信

    Socket.IO笔记 ​ 即时通信是基于TCP长连接&#xff0c;建立连接之后&#xff0c;客户段/服务器可以无限次随时向对端发送数据&#xff0c;实现服务器数据发送的即时性 HTTP HTTP是短链接&#xff0c;设计的目的是减少服务器的压力 HTTP伪即时通讯 轮询 emmet长轮询 long pull…...

    2024/4/7 15:29:04

最新文章

  1. 自然语言处理的发展及归纳介绍

    NLP简介 自然语言处理&#xff08;Natural Language Processing&#xff0c;NLP&#xff09;是人工智能领域的一个重要分支&#xff0c;旨在使计算机理解、解释和生成人类语言。NLP的产生背景可以追溯到上世纪50年代&#xff0c;随着计算机科学和人工智能领域的发展&#xff0c…...

    2024/4/28 6:24:23
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/3/20 10:50:27
  3. K8S容器空间不足问题分析和解决

    如上图&#xff0c;今天测试环境的K8S平台出现了一个问题&#xff0c;其中的一个容器报错&#xff1a;Free disk space below threshold. Available: 3223552 bytes (threshold: 10485760B)&#xff0c;意思服务器硬盘空间不够了。这个问题怎么产生的&#xff0c;又怎么解决的呢…...

    2024/4/23 6:25:22
  4. Mybatis--TypeHandler使用手册

    TypeHandler使用手册 场景&#xff1a;想保存user时 teacher自动转String &#xff0c;不想每次保存都要手动去转String&#xff1b;从DB查询出来时&#xff0c;也要自动帮我们转换成Java对象 Teacher Data public class User {private Integer id;private String name;priva…...

    2024/4/23 16:06:48
  5. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/4/26 18:09:39
  6. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/4/28 3:28:32
  7. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/4/26 23:05:52
  8. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/4/27 4:00:35
  9. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/4/27 17:58:04
  10. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/4/27 14:22:49
  11. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/4/28 1:28:33
  12. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/4/27 9:01:45
  13. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/4/27 17:59:30
  14. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/4/25 18:39:16
  15. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/4/28 1:34:08
  16. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/4/26 19:03:37
  17. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/4/28 1:22:35
  18. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/4/25 18:39:14
  19. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/4/26 23:04:58
  20. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/4/27 23:24:42
  21. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/4/28 5:48:52
  22. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/4/26 19:46:12
  23. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/4/27 11:43:08
  24. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/4/27 8:32:30
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57