五子棋人机对弈——VC API实现!

 

// gobang.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "resource.h"
#include  "math.h"

#define MAX_LOADSTRING 100

//全局变量:
HINSTANCE hInst;
HBITMAP chess[2];
HDC  hdc,mdc,bufdc;
HWND hWnd;
DWORD tPre,tNow;

int  board[10][10];
bool ptab[10][10][192];
bool ctab[10][10][192];
int  win[2][192];
int  num[2];
bool turn,over;
int  winner;
        
//TCHAR szTitle[MAX_LOADSTRING];       
//TCHAR szWindowClass[MAX_LOADSTRING];       

// Foward declarations of functions included in this code module:
ATOM    MyRegisterClass(HINSTANCE hInstance);
BOOL    InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
//函数声明
void       MyPaint(HDC hdc);
void                InitGame();
void    ComTurn();


//****WIN MIAN*************************************
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
 MSG msg;
 
 MyRegisterClass(hInstance);
 
 //
 if (!InitInstance (hInstance, nCmdShow))
 {
  return FALSE;
 }
 
 //
    while( msg.message!=WM_QUIT )
    {
        if( PeekMessage( &msg, NULL, 0,0 ,PM_REMOVE) )
        {
            TranslateMessage( &msg );
            DispatchMessage( &msg );
        }
  else
  {
   tNow = GetTickCount();
   if(tNow-tPre >= 100)
    MyPaint(hdc);
  }
    }
 
 return msg.wParam;
}


//
//  FUNCTION: MyRegisterClass()
//
//  PURPOSE: Registers the window class.
//
//  COMMENTS:
//
//    This function and its usage is only necessary if you want this code
//    to be compatible with Win32 systems prior to the 'RegisterClassEx'
//    function that was added to Windows 95. It is important to call this function
//    so that the application will get 'well formed' small icons associated
//    with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
 WNDCLASSEX wcex;

 wcex.cbSize = sizeof(WNDCLASSEX);

 wcex.style   = CS_HREDRAW | CS_VREDRAW;
 wcex.lpfnWndProc = (WNDPROC)WndProc;
 wcex.cbClsExtra  = 0;
 wcex.cbWndExtra  = 0;
 wcex.hInstance  = hInstance;
 wcex.hIcon   = LoadIcon(hInstance, (LPCTSTR)IDI_GOBANG);
 wcex.hCursor  = LoadCursor(NULL, IDC_ARROW);
 wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
 wcex.lpszMenuName = (LPCSTR)IDC_GOBANG;
 wcex.lpszClassName = "canvas";//窗口名称
 wcex.hIconSm  = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);

 return RegisterClassEx(&wcex);
}

//
//   FUNCTION: InitInstance(HANDLE, int)
//
//   PURPOSE: Saves instance handle and creates main window
//
//   COMMENTS:
//
//        In this function, we save the instance handle in a global variable and
//        create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
 HBITMAP tile,bmp;
 int rowNum,colNum;
 int i,x,y;
 
 hInst = hInstance;
 hWnd = CreateWindow("canvas",
                  "五子棋人机对弈" ,
      WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT,
      0,
      CW_USEDEFAULT,
      0,
      NULL,
      NULL,
      hInstance,
      NULL);
 
 if (!hWnd)
 {
  return FALSE;
 }
 
 MoveWindow(hWnd,10,10,480,520,true);
 ShowWindow(hWnd,nCmdShow);
 UpdateWindow(hWnd);
 
 hdc = GetDC(hWnd);
 mdc = CreateCompatibleDC(hdc);
 bufdc = CreateCompatibleDC(hdc);
 
 bmp = CreateCompatibleBitmap(hdc,450,450);
 SelectObject(mdc,bmp);
 
 tile = (HBITMAP)LoadImage(NULL,"tile.bmp",IMAGE_BITMAP,45,45,LR_LOADFROMFILE);
 chess[0] = (HBITMAP)LoadImage(NULL,"chess0.bmp",IMAGE_BITMAP,38,38,LR_LOADFROMFILE);
 chess[1] = (HBITMAP)LoadImage(NULL,"chess1.bmp",IMAGE_BITMAP,38,38,LR_LOADFROMFILE);
 
 //地图拼接
 for (i=0;i<100;i++)
 {
  rowNum = i / 10;
  colNum = i % 10;
  x = colNum * 45;
  y = rowNum * 45;
  
  SelectObject(bufdc,tile);
  BitBlt(mdc,x,y,45,45,bufdc,0,0,SRCCOPY);
 }
 
 InitGame();
 MyPaint(hdc);
 
 return TRUE;
}

//*******棋局初始函数*********************************

void InitGame()
{
 int i,j,k;
 int count=0;
 
 over = false;
 num[0] = num[1] = 0;
 
 //设定玩家与计算机在各个获胜组合中的棋子数
 for(i=0;i<192;i++)
 {
  win[0][i] = 0;
  win[1][i] = 0;
 }
 
 //初始化棋盘状态
 for(i=0;i<10;i++)         
  for(j=0;j<10;j++)
   board[i][j] = 2;
  
  //设定水平方向的获胜组合
  for(i=0;i<10;i++)         
   for(j=0;j<6;j++)
   {
    for(k=0;k<5;k++)
    {
     ptab[i][j+k][count] = true;
     ctab[i][j+k][count] = true;
    }
    count++;
   }
   
   //设定垂直方向的获胜组合
   for(i=0;i<10;i++)         
    for(j=0;j<6;j++)
    {
     for(k=0;k<5;k++)
     {
      ptab[j+k][i][count] = true;
      ctab[j+k][i][count] = true;
     }
     count++;
    }
    
    //设定正对角线方向的获胜组合
    for(i=0;i<6;i++)          
     for(j=0;j<6;j++)
     {
      for(k=0;k<5;k++)
      {
       ptab[j+k][i+k][count] = true;
       ctab[j+k][i+k][count] = true;
      }
      count++;
     }
     
     //设定反对角线上的获胜组合
     for(i=0;i<6;i++)          
      for(j=9;j>=4;j--)
      {
       for(k=0;k<5;k++)
       {
        ptab[j-k][i+k][count] = true;
        ctab[j-k][i+k][count] = true;
       }
       count++;
      }
      
      //随机数决定由那一方先下
      srand(GetTickCount());
      if(rand()%2 == 0)
       turn = true;
      else
       turn = false;
}


//*******计算机下棋函数*******************************

void ComTurn()
{
 int grades[2][10][10];
 int m,n,i,max=0;
 int u,v;

 for(m=0;m<10;m++)
  for(n=0;n<10;n++)
  {
   grades[0][m][n] = 0;
   grades[1][m][n] = 0;

   if(board[m][n] == 2)
   {
    for(i=0;i<192;i++)
    {
     //计算玩家在空位置上的获胜分数
     if(ptab[m][n][i] && win[0][i] != 7)
     {
      switch(win[0][i])
      {
       case 0:
        grades[0][m][n]+=1;
        break;
       case 1:
        grades[0][m][n]+=200;
        break;
       case 2:
        grades[0][m][n]+=400;
        break;
       case 3:
        grades[0][m][n]+=2000;
        break;
       case 4:
        grades[0][m][n]+=10000;
        break;
      }
     }

     //计算计算机在空位置上的获胜分数
     if(ctab[m][n][i] && win[1][i] != 7)
     {
      switch(win[1][i])
      {
       case 0:
        grades[1][m][n]+=1;
        break;
       case 1:
        grades[1][m][n]+=220;
        break;
       case 2:
        grades[1][m][n]+=420;
        break;
       case 3:
        grades[1][m][n]+=2100;
        break;
       case 4:
        grades[1][m][n]+=20000;
        break;
      }
     }
    }

    if(max == 0)
    {
     u = m;
     v = n;
    }

    if(grades[0][m][n] > max)
    {
     max = grades[0][m][n];
     u = m;
     v = n;
    }
    else if(grades[0][m][n] == max)
    {
     if(grades[1][m][n] > grades[1][u][v])
     {
      u = m;
      v = n;
     }
    }

    if(grades[1][m][n] > max)
    {
     max = grades[1][m][n];
     u = m;
     v = n;
    }
    else if(grades[1][m][n] == max)
    {
     if(grades[0][m][n] > grades[0][u][v])
     {
      u = m;
      v = n;
     }
    }
   }
  }

 board[u][v] = 1;      //设定为计算机的棋子数
 num[1]++;

 if(num[0] == 50 && num[1] == 50)
 {
  winner = 2;   //平手
  over = true;
 }
 else
  for(i=0;i<192;i++)
  {
   if(ctab[u][v][i])
   {
    win[1][i]++;
    ptab[u][v][i] = false;
    win[0][i] = 7;

    if(win[1][i] == 5)
    {
     winner = 1;
     over = true;
    }
   }
  }
 turn = true;   //换由玩家下
}

 

void MyPaint(HDC hdc)
{
 int m,n;
 char *str;
 
 if(over)
 {
  switch(winner)
  {
  case 0:
   str = "您赢了!        按下[F1]键可重新开始..";
   break;
  case 1:
   str = "计算机赢了!    按下[F1]键可重新开始..";
   break;
  case 2:
   str = "平局!          按下[F1]键可重新开始..";
   break;
  }
  TextOut(hdc,10,470,str,strlen(str));
 }
 else if(!turn)      //计算机下棋
 {
  str = "计算机思考中... ";
  TextOut(hdc,10,470,str,strlen(str));
  ComTurn();                
 }
 else
 {
  str = "该您下了... ";
  TextOut(hdc,10,470,str,strlen(str));
 }
 
 for(m=0;m<10;m++)
  for(n=0;n<10;n++)
  {
   if(board[m][n] == 0)   //贴上玩家棋子
   {
    SelectObject(bufdc,chess[0]);
    BitBlt(mdc,m*45+3,n*45+3,38,38,bufdc,0,0,SRCCOPY);
   }
   else if(board[m][n] == 1)      //贴上计算机棋子
   {
    SelectObject(bufdc,chess[1]);
    BitBlt(mdc,m*45+3,n*45+3,38,38,bufdc,0,0,SRCCOPY);
   }
   else       //贴上空格
   {
    SelectObject(bufdc,chess[1]);
    BitBlt(mdc,m*45+3,n*45+3,38,38,bufdc,0,0,WHITENESS);
   }
  }
  
  BitBlt(hdc,10,10,450,450,mdc,0,0,SRCCOPY);
  
  tPre = GetTickCount();
}

 

 

 


//
//  FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
//
//  PURPOSE:  Processes messages for the main window.
//
//  WM_COMMAND - process the application menu
//  WM_PAINT - Paint the main window
//  WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
 int x,y,m,n,i;
 
 switch (message)
 {
 case WM_KEYDOWN:      //按下按键消息
  switch (wParam)
  {
  case VK_ESCAPE:           //按下ESC键
   PostQuitMessage( 0 );
   break;
  case VK_F1:      //按下F1键
   InitGame();
   break;
  }
  case WM_LBUTTONDOWN:     //单击鼠标左键消息
   if(!over)
    if(turn)
    {
        x = LOWORD(lParam);  //取得鼠标X坐标
        y = HIWORD(lParam);  //取得鼠标Y坐标
     
     if(x> 10 && x < 460 && y> 10 && y < 460)
     {
         m = (int)floor((x-10)/45);
      n = (int)floor((y-10)/45);
      
      if(board[m][n] == 2)
      {
       board[m][n] = 0;   //设定为玩家下的棋子
       num[0]++;
       
       if(num[0] == 50 && num[1] == 50)
       {
        winner = 2;    //判断平局
        over = true;
       }
       else
        for(i=0;i<192;i++)
        {
         if(ptab[m][n][i])
         {
          win[0][i]++;
          ctab[m][n][i] = false;
          win[1][i] = 7;
          
          if(win[0][i] == 5)
          {
           winner = 0;
           over = true;
          }
         }
        }
        turn = false;       //换由计算机下
      }
     }
    }
    break;
  case WM_DESTROY:     //窗口结束消息
   DeleteDC(mdc);
   DeleteDC(bufdc);
   DeleteObject(chess[0]);
   DeleteObject(chess[1]);
   
   ReleaseDC(hWnd,hdc);
   
   PostQuitMessage(0);
   break;
  default:       //其他消息
   return DefWindowProc(hWnd, message, wParam, lParam);
 }
 return 0;
}

// Mesage handler for about box.
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
 switch (message)
 {
  case WM_INITDIALOG:
    return TRUE;

  case WM_COMMAND:
   if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
   {
    EndDialog(hDlg, LOWORD(wParam));
    return TRUE;
   }
   break;
 }
    return FALSE;
}

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值