共有回帖数  1  个 
	 
	
	
	
     
          
          
               
                  -  花了两个晚上一个白天写的windows五子棋人机对战,请大家多指教!
- 
													  只看楼主					  
                     
                       收藏
                      
                          
                           回复
                      
					  
					                     
					 
 
            
				   - 
						
						
							 
									
  
 写的时候是可以让计算机计算很多部的,采用3叉树的结构存储计算机计算的棋盘信息,但实际上计算9、10步电脑就有点不行了。可能因为没有剪枝吧!还有,计算多了以后,电脑下的棋反而不精确了,可能因为权值不精确,搜索广度不够吧!大家提点意见吧!
 先放resource.h
 #define IDR_MENU1                        101
 #define IDR_MENU                         101
 #define IDM_START                        40001
 #define IDM_RESTART                      40002
 #define IDM_ABOUT                        40003
 #define IDM_1STEP                        40004
 #define IDM_2STEP                        40005
 #define IDM_3STEP                        40006
 #define IDM_4STEP                        40007
 #define IDM_5STEP                        40008
 
 // Next default values for new objects
 //
 #ifdef APSTUDIO_INVOKED
 #ifndef APSTUDIO_READONLY_SYMBOLS
 #define _APS_NEXT_RESOURCE_VALUE         102
 #define _APS_NEXT_COMMAND_VALUE          40009
 #define _APS_NEXT_CONTROL_VALUE          1000
 #define _APS_NEXT_SYMED_VALUE            101
 #endif
 #endif
 
 资源文件
 //Microsoft Developer Studio generated resource script.
 //
 #include "resource.h"
 
 #define APSTUDIO_READONLY_SYMBOLS
 /////////////////////////////////////////////////////////////////////////////
 //
 // Generated from the TEXTINCLUDE 2 resource.
 //
 #include "afxres.h"
 
 /////////////////////////////////////////////////////////////////////////////
 #undef APSTUDIO_READONLY_SYMBOLS
 
 /////////////////////////////////////////////////////////////////////////////
 // Chinese (中国) resources
 
 #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
 #ifdef _WIN32
 LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
 #pragma code_page(936)
 #endif //_WIN32
 
 #ifdef APSTUDIO_INVOKED
 /////////////////////////////////////////////////////////////////////////////
 //
 // TEXTINCLUDE
 //
 
 1 TEXTINCLUDE DISCARDABLE
 BEGIN
 "resource.h "
 END
 
 2 TEXTINCLUDE DISCARDABLE
 BEGIN
 "#include ""afxres.h""rn"
 " "
 END
 
 3 TEXTINCLUDE DISCARDABLE
 BEGIN
 "rn"
 " "
 END
 
 #endif     // APSTUDIO_INVOKED
 
 
 /////////////////////////////////////////////////////////////////////////////
 //
 // Menu
 //
 
 IDR_MENU MENU DISCARDABLE
 BEGIN
 POPUP "游戏"
 BEGIN
 POPUP "开始游戏"
 BEGIN
 MENUITEM "计算一步",                     IDM_1STEP
 MENUITEM "计算两步",                     IDM_2STEP
 MENUITEM "计算三步",                     IDM_3STEP
 MENUITEM "计算四步",                     IDM_4STEP
 MENUITEM "计算五步",                     IDM_5STEP
 END
 MENUITEM "再来一次",                     IDM_RESTART
 END
 POPUP "帮助"
 BEGIN
 MENUITEM "关于...",                      IDM_ABOUT
 END
 END
 
 #endif     // Chinese (中国) resources
 /////////////////////////////////////////////////////////////////////////////
 
 
 
 #ifndef APSTUDIO_INVOKED
 /////////////////////////////////////////////////////////////////////////////
 //
 // Generated from the TEXTINCLUDE 3 resource.
 //
 
 
 /////////////////////////////////////////////////////////////////////////////
 #endif     // not APSTUDIO_INVOKED
 
 #include windows.h
 #include "resource.h"
 
 
 LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM) ;
 
 
 int Turn=1;
 int IsStart=0;
 int Steps=0;
 int TempBoard[15][15]={0};
 
 
 int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR szCmdLine,int iCmdShow)
 {
 static TCHAR szAppName[]=TEXT("五子棋");
 HWND hwnd;
 MSG msg;
 WNDCLASS wndclass ;
 wndclass.style            =CS_HREDRAW|CS_VREDRAW;
 wndclass.lpfnWndProc      =WndProc;
 wndclass.cbClsExtra       =0;
 wndclass.cbWndExtra       =0;
 wndclass.hInstance        =hInstance;
 wndclass.hIcon            =LoadIcon(NULL,IDI_APPLICATION);
 wndclass.hCursor          =LoadCursor(NULL,IDC_ARROW);
 wndclass.hbrBackground    =(HBRUSH)GetStockObject(GRAY_BRUSH);
 wndclass.lpszMenuName     =NULL;
 wndclass.lpszClassName    =szAppName;
 if (!RegisterClass(&wndclass))
 {
 MessageBox(NULL,TEXT("This program requires Windows NT!"),szAppName,MB_ICONERROR) ;
 return 0 ;
 }
 hwnd=CreateWindow(szAppName,
 TEXT("五子棋人机对战"),
 WS_OVERLAPPEDWINDOW,
 CW_USEDEFAULT,
 CW_USEDEFAULT,
 480,
 530,
 NULL,
 LoadMenu(hInstance,MAKEINTRESOURCE(IDR_MENU)),
 hInstance,
 NULL);
 ShowWindow(hwnd,SW_SHOWNORMAL);
 UpdateWindow(hwnd);
 while (GetMessage(&msg,NULL,0,0))
 {
 TranslateMessage(&msg);
 DispatchMessage(&msg);
 }
 return msg.wParam;
 }
 
 //判断是否胜利
 int win(int i,int j)
 {
 int s,t=0;
 
 
 for(s=1;s=4&&(i-s)=0;s++)
 {
 if(TempBoard[i-s][j]==TempBoard[j])
 t++;
 if(TempBoard[i-s][j]!=TempBoard[j])
 break;
 }
 for(s=1;s=4&&(i+s)=14;s++)
 {
 if(TempBoard[i+s][j]==TempBoard[j])
 t++;
 if(TempBoard[i+s][j]!=TempBoard[j])
 break;
 }
 if(t=4)
 return 1;
 
 
 t=0;
 for(s=1;s=4&&(j-s)=0;s++)
 {
 if(TempBoard[j-s]==TempBoard[j])
 t++;
 if(TempBoard[j-s]!=TempBoard[j])
 break;
 }
 for(s=1;s=4&&(j+s)=14;s++)
 {
 if(TempBoard[j+s]==TempBoard[j])
 t++;
 if(TempBoard[j+s]!=TempBoard[j])
 break;
 }
 if(t=4)
 return 1;
 
 
 t=0;
 for(s=1;s=4&&(i-s)=0&&(j-s)=0;s++)
 {
 if(TempBoard[i-s][j-s]==TempBoard[j])
 t++;
 if(TempBoard[i-s][j-s]!=TempBoard[j])
 break;
 }
 for(s=1;s=4&&(i+s)=14&&(j+s)=14;s++)
 {
 if(TempBoard[i+s][j+s]==TempBoard[j])
 t++;
 if(TempBoard[i+s][j+s]!=TempBoard[j])
 break;
 }
 if(t=4)
 return 1;
 
 
 t=0;
 for(s=1;s=4&&(i-s)=0&&(j+s)=14;s++)
 {
 if(TempBoard[i-s][j+s]==TempBoard[j])
 t++;
 if(TempBoard[i-s][j+s]!=TempBoard[j])
 break;
 }
 for(s=1;s=4&&(i+s)=14&&(j-s)=0;s++)
 {
 if(TempBoard[i+s][j-s]==TempBoard[j])
 t++;
 if(TempBoard[i+s][j-s]!=TempBoard[j])
 break;
 }
 if(t=4)
 return 1;
 
 
 return 0;
 }
 
 回复6楼
 2010-10-24 19:50
 举报 |个人企业举报垃圾信息举报
  
 //画棋子
 void Draw(HWND hwnd,int x,int y)
 {
 HDC hdc;
 hdc=GetDC(hwnd);
 if(Turn)
 SelectObject(hdc,GetStockObject(BLACK_BRUSH));
 else
 {
 SelectObject(hdc,GetStockObject(WHITE_BRUSH));
 SelectObject(hdc,GetStockObject(WHITE_PEN));
 }
 Ellipse(hdc,30*x+20,30*y+20,30*x+40,30*y+40);
 ReleaseDC(hwnd,hdc);
 }
 
 回复
 8楼
 2010-10-24 19:54
 举报 |个人企业举报垃圾信息举报
  
   
 
 阿宾和白洁
 超能力者9
 //画棋盘
 void DrawBoard(HDC hdc)
 {
 int i,j;
 HPEN hPen;
 HBRUSH hBrush;
 hPen=CreatePen(PS_SOLID,2,RGB(0,255,0));
 SelectObject(hdc,hPen);
 hBrush=CreateSolidBrush(RGB(255,255,0));
 SelectObject(hdc,hBrush);
 for(i=0;i14;i++)
 {
 for(j=0;j14;j++)
 {
 Rectangle(hdc,30+30*i,30+30*j,60+30*i,60+30*j);
 }
 }
 DeleteObject(hPen);
 DeleteObject(hBrush);
 hPen=CreatePen(PS_SOLID,2,RGB(255,0,0));
 SelectObject(hdc,hPen);
 hBrush=CreateSolidBrush(RGB(255,0,0));
 SelectObject(hdc,hBrush);
 Ellipse(hdc,235,235,245,245);
 Ellipse(hdc,115,115,125,125);
 Ellipse(hdc,355,115,365,125);
 Ellipse(hdc,115,355,125,365);
 Ellipse(hdc,355,355,365,365);
 DeleteObject(hPen);
 DeleteObject(hBrush);
 }
 
 
 
 //定义一个ai状态的结构
 struct AIStep
 {
 int flag;
 int EndFlag;
 int weight;
 struct AIStep *child1;
 struct AIStep *child2;
 struct AIStep *child3;
 int board[15][15];
 };
 //计算权值
 int CalWeight(int i,int j,struct AIStep *NowStep)
 {
 int Weight=0;
 int s,t;
 int a[2][8],b[2][8];
 if(NowStep-board[j]!=0)
 Weight=-1;
 else
 {
 for(s=0;s=7;s++)
 {
 a[0][s]=0;
 b[0][s]=0;
 a[1][s]=1;
 b[1][s]=1;
 }
 for(s=1;s=4&&(i-s)=0;s++)             //←
 {
 if(NowStep-board[i-s][j]==1)
 a[0][0]++;
 if(NowStep-board[i-s][j]==0)
 {
 a[1][0]=0;
 break;
 }
 if(NowStep-board[i-s][j]==2)
 {
 a[1][0]=1;
 break;
 }
 }
 for(s=1;s=4&&(i+s)=14;s++)         //→
 {
 if(NowStep-board[i+s][j]==1)
 a[0][1]++;
 if(NowStep-board[i+s][j]==0)
 {
 a[1][1]=0;
 
 
 
 break;
 }
 if(NowStep-board[i+s][j]==2)
 {
 a[1][1]=1;
 break;
 }
 }
 
 
 for(s=1;s=4&&(j-s)=0;s++)             //↑
 {
 if(NowStep-board[j-s]==1)
 a[0][2]++;
 if(NowStep-board[j-s]==0)
 {
 a[1][2]=0;
 break;
 }
 if(NowStep-board[j-s]==2)
 {
 a[1][2]=1;
 break;
 }
 }
 for(s=1;s=4&&(j+s)=14;s++)         //↓
 {
 if(NowStep-board[j+s]==1)
 a[0][3]++;
 if(NowStep-board[j+s]==0)
 {
 a[1][3]=0;
 break;
 }
 
 
 
 if(NowStep-board[j+s]==2)
 {
 a[1][3]=1;
 break;
 }
 }
 
 
 for(s=1;s=4&&(i-s)=0&&(j-s)=0;s++)         //↖
 {
 if(NowStep-board[i-s][j-s]==1)
 a[0][4]++;
 if(NowStep-board[i-s][j-s]==0)
 {
 a[1][4]=0;
 break;
 }
 if(NowStep-board[i-s][j-s]==2)
 {
 a[1][4]=1;
 break;
 }
 }
 for(s=1;s=4&&(i+s)=14&&(j+s)=14;s++)         //↘
 {
 if(NowStep-board[i+s][j+s]==1)
 a[0][5]++;
 if(NowStep-board[i+s][j+s]==0)
 {
 a[1][5]=0;
 break;
 }
 if(NowStep-board[i+s][j+s]==2)
 {
 
 
 
 a[1][5]=1;
 break;
 }
 }
 
 
 for(s=1;s=4&&(i-s)=0&&(j+s)=14;s++)         //↙
 {
 if(NowStep-board[i-s][j+s]==1)
 a[0][6]++;
 if(NowStep-board[i-s][j+s]==0)
 {
 a[1][6]=0;
 break;
 }
 if(NowStep-board[i-s][j+s]==2)
 {
 a[1][6]=1;
 break;
 }
 }
 for(s=1;s=4&&(i+s)=14&&(j-s)=0;s++)         //↗
 {
 if(NowStep-board[i+s][j-s]==1)
 a[0][7]++;
 if(NowStep-board[i+s][j-s]==0)
 {
 a[1][7]=0;
 break;
 }
 if(NowStep-board[i+s][j-s]==2)
 {
 a[1][7]=1;
 break;
 }
 }
 
 
 for(s=0;s=7;s+=2)                         //成五
 {
 if((a[0][s]+a[0][s+1])=4)
 Weight+=10000;
 }
 for(s=0;s=7;s+=2)                         //活四
 {
 if((a[0][s]+a[0][s+1])==3&&a[1][s]==0&&a[1][s+1]==0)
 Weight+=10000;
 }
 for(s=0;s=7;s+=2)
 {
 if((a[0][s]+a[0][s+1])==3&&((a[1][s]==0&&a[1][s+1]==1)||(a[1][s]==1&&a[1][s+1]==0)))
 {
 for(t=0;t=7;t+=2)
 {
 if((a[0][t]+a[0][t+1])==2&&a[1][t]==0&&a[1][t+1]==0)         //死四活三
 Weight+=10000;
 if(t!=s&&(a[0][t]+a[0][t+1])==3&&((a[1][t]==0&&a[1][t+1]==1)||(a[1][t]==1&&a[1][t+1]==0))) //双死四
 Weight+=5000;
 }
 Weight+=500;         //单死四
 }
 }
 for(s=0;s=7;s+=2)
 {
 
 
 if((a[0][s]+a[0][s+1]==2)&&a[1][s]==0&&a[1][s+1]==0)
 {
 for(t=0;t=7;t+=2)
 {
 if(s!=t&&(a[0][t]+a[0][t+1]==2)&&a[1][t]==0&&a[1][t+1]==0)         //双活三
 Weight+=2500;
 if(s!=t&&(a[0][t]+a[0][t+1])==2&&((a[1][t]==0&&a[1][t+1]==1)||(a[1][t]==1&&a[1][t+1]==0)))         //死三活三
 Weight+=1000;
 }
 Weight+=200;         //单活三
 }
 }
 for(s=0;s=7;s+=2)
 {
 if((a[0][s]+a[0][s+1])==2&&((a[1][s]==0&&a[1][s+1]==1)||(a[1][s]==1&&a[1][s+1]==0)))
 {
 for(t=0;t=7;t+=2)
 {
 if(s!=t&&(a[0][t]+a[0][t+1])==2&&((a[1][t]==0&&a[1][t+1]==1)||(a[1][t]==1&&a[1][t+1]==0)))     //双死三
 Weight+=50;
 }
 Weight+=50;         //单死三
 
 
 }
 }
 for(s=0;s=7;s+=2)
 {
 if((a[0][s]+a[0][s+1]==1)&&a[1][s]==0&&a[1][s+1]==0)
 {
 for(t=0;t=7;t+=2)
 {
 if(s!=t&&(a[0][t]+a[0][t+1]==1)&&a[1][t]==0&&a[1][t+1]==0)         //双活二
 Weight+=5;
 if(s!=t&&(a[0][t]+a[0][t+1])==1&&((a[1][t]==0&&a[1][t+1]==1)||(a[1][t]==1&&a[1][t+1]==0)))         //死二活二
 Weight+=7;
 }
 Weight+=5;         //单活二
 }
 }
 for(s=0;s=7;s+=2)
 {
 if((a[0][s]+a[0][s+1])==1&&((a[1][s]==0&&a[1][s+1]==1)||(a[1][s]==1&&a[1][s+1]==0)))
 {
 for(t=0;t=7;t+=2)
 {
 if(s!=t&&(a[0][t]+a[0][t+1])==1&&((a[1][t]==0&&a[1][t+1]==1)||(a[1][t]==1&&a[1][t+1]==0)))         //双死二
 Weight+=2;
 }
 Weight+=3;         //单死二
 }
 }
 
 for(s=1;s=4&&(i-s)=0;s++)             //←
 {
 if(NowStep-board[i-s][j]==2)
 b[0][0]++;
 if(NowStep-board[i-s][j]==0)
 {
 b[1][0]=0;
 break;
 }
 if(NowStep-board[i-s][j]==1)
 {
 b[1][0]=1;
 break;
 }
 }
 for(s=1;s=4&&(i+s)=14;s++)             //→
 {
 if(NowStep-board[i+s][j]==2)
 b[0][1]++;
 if(NowStep-board[i+s][j]==0)
 {
 b[1][1]=0;
 break;
 }
 if(NowStep-board[i+s][j]==1)
 {
 b[1][1]=1;
 break;
 }
 }
 
 
 for(s=1;s=4&&(j-s)=0;s++)             //↑
 
 
 {             if(NowStep-board[j-s]==2)                 b[0][2]++;             if(NowStep-board[j-s]==0)             {                 b[1][2]=0;                 break;             }             if(NowStep-board[j-s]==1)             {                 b[1][2]=1;                 break;             }         }         for(s=1;s=4&&(j+s)=14;s++)         //↓         {             if(NowStep-board[j+s]==2)                 b[0][3]++;             if(NowStep-board[j+s]==0)             {                 b[1][3]=0;                 break;             }             if(NowStep-board[j+s]==1)             {                 b[1][3]=1;                 break;             }         }
 
 for(s=1;s=4&&(i-s)=0&&(j-s)=0;s++)         //↖         {             if(NowStep-board[i-s][j-s]==2)
 
 b[0][4]++;
 if(NowStep-board[i-s][j-s]==0)
 {
 b[1][4]=0;
 break;
 }
 if(NowStep-board[i-s][j-s]==1)
 {
 b[1][4]=1;
 break;
 }
 }
 for(s=1;s=4&&(i+s)=14&&(j+s)=14;s++)         //↘
 {
 if(NowStep-board[i+s][j+s]==2)
 b[0][5]++;
 if(NowStep-board[i+s][j+s]==0)
 {
 b[1][5]=0;
 break;
 }
 if(NowStep-board[i+s][j+s]==1)
 {
 b[1][5]=1;
 break;
 }
 }
 
 
 for(s=1;s=4&&(i-s)=0&&(j+s)=14;s++)         //↙
 {
 if(NowStep-board[i-s][j+s]==2)
 b[0][6]++;
 if(NowStep-board[i-s][jj+s]==0)
 
 
 {
 b[1][6]=0;
 break;
 }
 if(NowStep-board[i-s][j+s]==1)
 {
 b[1][6]=1;
 break;
 }
 }
 for(s=1;s=4&&(i+s)=14&&(j-s)=0;s++)         //↗
 {
 if(NowStep-board[i+s][j-s]==2)
 b[0][7]++;
 if(NowStep-board[i+s][j-s]==0)
 {
 b[1][7]=0;
 break;
 }
 if(NowStep-board[i+s][j-s]==1)
 {
 b[1][7]=1;
 break;
 }
 }
 
 
 for(s=0;s=7;s++)                         //成五
 {
 if((b[0][s]+b[0][s+1])=4)
 Weight+=10000;
 }
 for(s=0;s=7;s+=2)                         //活四
 {
 if((b[0][s]+b[0][s+1])==3&&b[1][s]==0&&b[1][s+1]==0)
 Weight+=10000;
 }
 for(s=0;s=7;s+=2)
 {
 if((b[0][s]+b[0][s+1])==3&&((b[1][s]==0&&b[1][s+1]==1)||(b[1][s]==1&&b[1][s+1]==0)))
 {
 for(t=0;t=7;t+=2)
 {
 if((b[0][t]+b[0][t+1])==2&&b[1][t]==0&&b[1][t+1]==0)         //死四活三
 Weight+=10000;
 if(t!=s&&(b[0][t]+b[0][t+1])==3&&((b[1][t]==0&&b[1][t+1]==1)||(b[1][t]==1&&b[1][t+1]==0))) //双死四
 Weight+=5000;
 }
 Weight+=500;         //单死四
 }
 }
 for(s=0;s=7;s+=2)
 {
 
 
 if((b[0][s]+b[0][s+1]==2)&&b[1][s]==0&&b[1][s+1]==0)
 {
 for(t=0;t=7;t+=2)
 {
 if(s!=t&&(b[0][t]+b[0][t+1]==2)&&b[1][t]==0&&b[1][t+1]==0)         //双活三
 Weight+=2500;
 if(s!=t&&(b[0][t]+b[0][t+1])==2&&((b[1][t]==0&&b[1][t+1]==1)||(b[1][t]==1&&b[1][t+1]==0)))         //死三活三
 Weight+=1000;
 }
 Weight+=200;         //单活三
 }
 }
 for(s=0;s=7;s+=2)
 {
 if((b[0][s]+b[0][s+1])==2&&((b[1][s]==0&&b[1][s+1]==1)||(b[1][s]==1&&b[1][s+1]==0)))
 {
 for(t=0;t=7;t+=2)
 {
 if(s!=t&&(b[0][t]+b[0][t+1])==2&&((b[1][t]==0&&b[1][t+1]==1)||(b[1][t]==1&&b[1][t+1]==0)))     //双死三
 Weight+=50;
 }
 Weight+=50;         //单死三
 
 
 }
 }
 for(s=0;s=7;s+=2)
 {
 if((b[0][s]+b[0][s+1]==1)&&b[1][s]==0&&b[1][s+1]==0)
 {
 for(t=0;t=7;t+=2)
 {
 if(s!=t&&(b[0][t]+b[0][t+1]==1)&&b[1][t]==0&&b[1][t+1]==0)         //双活二
 Weight+=5;
 if(s!=t&&(b[0][t]+b[0][t+1])==1&&((b[1][t]==0&&b[1][t+1]==1)||(b[1][t]==1&&b[1][t+1]==0)))         //死二活二
 Weight+=7;
 }
 Weight+=5;         //单活二
 }
 }
 for(s=0;s=7;s+=2)
 {
 if((b[0][s]+b[0][s+1])==1&&((b[1][s]==0&&b[1][s+1]==1)||(b[1][s]==1&&b[1][s+1]==0)))
 {
 for(t=0;t=7;t+=2)
 {
 if(s!=t&&(b[0][t]+b[0][t+1])==1&&((b[1][t]==0&&b[1][t+1]==1)||(b[1][t]==1&&b[1][t+1]==0)))         //双死二
 Weight+=2;
 }
 Weight+=3;         //单死二
 }
 }
 }
 return Weight;
 }
 
 //计算下一步
 void NextStep(struct AIStep *parent)
 {
 if(parent-EndFlag=Steps)
 {
 int i,j;
 int Maxx=7,Maxy=7,Mediumx=7,Mediumy=7,Minx=7,Miny=7;
 int Weight=0,MaxWeight=0,MediumWeight=0,MinWeight=0;
 struct AIStep *next1,*next2,*next3;
 for(i=0;i=14;i++)
 {
 for(j=0;j=14;j++)
 {
 Weight=CalWeight(i,j,parent);
 if(WeightMaxWeight)
 {
 MaxWeight=Weight;
 Maxx=i;
 Maxy=j;
 }
 else if(WeightMediumWeight)
 {
 MediumWeight=Weight;
 Mediumx=i;楼主 2016-04-15 08:56 回复 
 
				    
					  
             
			 
                   - 
                        
                        
                             
									虽然不知道你在写什么 ,但是看起来好像很厉害的样子
 
							 								1楼 2016-04-19 14:10								  回复
							 
 
 
 
  
	Copyright © 2010~2015 直线网 版权所有,All Rights Reserved.沪ICP备10039589号
	
	意见反馈 | 
	关于直线 | 
	版权声明 | 
	会员须知