五子棋

// chess.cpp : 定义应用程序的入口点。
//

#include "stdafx.h"
#include "chess.h"
#include "math.h"

#define MAX_LOADSTRING 100

// 全局变量:
HINSTANCE hInst;        // 当前实例
TCHAR szTitle[MAX_LOADSTRING];     // 标题栏文本
TCHAR szWindowClass[MAX_LOADSTRING];   // 主窗口类名

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;

// 此代码模块中包含的函数的前向声明:
ATOM    MyRegisterClass(HINSTANCE hInstance);
BOOL    InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);

void MyPaint(HDC hdc);
void InitGame();
void ComTurn();

int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
 UNREFERENCED_PARAMETER(hPrevInstance);
 UNREFERENCED_PARAMETER(lpCmdLine);

  // TODO: 在此放置代码。
 MSG msg;
 HACCEL hAccelTable;

 // 初始化全局字符串
 LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
 LoadString(hInstance, IDC_CHESS, szWindowClass, MAX_LOADSTRING);
 MyRegisterClass(hInstance);

 // 执行应用程序初始化:
 if (!InitInstance (hInstance, nCmdShow))
 {
  return FALSE;
 }

 hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_CHESS));

 // 主消息循环:
/* while (GetMessage(&msg, NULL, 0, 0))
 {
  if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
  {
   TranslateMessage(&msg);
   DispatchMessage(&msg);
  }
 }*/
 while(TRUE)
 {
  if (GetMessage(&msg,NULL,0,0))
  {
   if (msg.message!=WM_QUIT)
   {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
    MyPaint(hdc);
   }
  }
  else
   break;
 }

 return (int) msg.wParam;
}

//
//  函数: MyRegisterClass()
//
//  目的: 注册窗口类。
//
//  注释:
//
//    仅当希望
//    此代码与添加到 Windows 95 中的“RegisterClassEx”
//    函数之前的 Win32 系统兼容时,才需要此函数及其用法。调用此函数十分重要,
//    这样应用程序就可以获得关联的
//    “格式正确的”小图标。
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
 WNDCLASSEX wcex;

 wcex.cbSize = sizeof(WNDCLASSEX);

 wcex.style   = CS_HREDRAW | CS_VREDRAW;
 wcex.lpfnWndProc = WndProc;
 wcex.cbClsExtra  = 0;
 wcex.cbWndExtra  = 0;
 wcex.hInstance  = hInstance;
 wcex.hIcon   = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_CHESS));
 wcex.hCursor  = LoadCursor(NULL, IDC_ARROW);
 wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
 wcex.lpszMenuName = MAKEINTRESOURCE(IDC_CHESS);
 wcex.lpszClassName = szWindowClass;
 wcex.hIconSm  = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

 return RegisterClassEx(&wcex);
}

//
//   函数: InitInstance(HINSTANCE, int)
//
//   目的: 保存实例句柄并创建主窗口
//
//   注释:
//
//        在此函数中,我们在全局变量中保存实例句柄并
//        创建和显示主程序窗口。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;
   HBITMAP tile,bmp;
   int rowNum,colNum;
   int i,x,y;

   hInst = hInstance; // 将实例句柄存储在全局变量中

   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

   if (!hWnd)
   {
      return FALSE;
   }

   ShowWindow(hWnd, nCmdShow);
   MoveWindow(hWnd,0,0,600,600,TRUE);
   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);
   }
   //BitBlt(hdc,0,0,640,480,mdc,0,0,SRCCOPY);

   InitGame();
   MyPaint(hdc);
   return TRUE;
}

//
//  函数: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  目的: 处理主窗口的消息。
//
//  WM_COMMAND - 处理应用程序菜单
//  WM_PAINT - 绘制主窗口
//  WM_DESTROY - 发送退出消息并返回
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
 int wmId, wmEvent;
 PAINTSTRUCT ps;
 HDC hdc;
 int x,y,m,n,i;

 switch (message)
 {
 case WM_COMMAND:
  wmId    = LOWORD(wParam);
  wmEvent = HIWORD(wParam);
  // 分析菜单选择:
  switch (wmId)
  {
  case IDM_ABOUT:
   DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
   break;
  case IDM_EXIT:
   DestroyWindow(hWnd);
   break;
  default:
   return DefWindowProc(hWnd, message, wParam, lParam);
  }
  break;
 case WM_PAINT:
  hdc = BeginPaint(hWnd, &ps);
  // TODO: 在此添加任意绘图代码...
  EndPaint(hWnd, &ps);
  break;
 case WM_KEYDOWN:
  switch(wParam)
  {
  case VK_ESCAPE:
   PostQuitMessage(0);
   break;
  case VK_F1:
   InitGame();
   break;
  }
 case WM_LBUTTONDOWN:
  if(!over)
   if (turn)
   {
    x=LOWORD(lParam);
    y=HIWORD(lParam);
    if (x>10&&x<460&&y>10&&y<460)
    {
     m=(int)floor((double)((x-10)/45));
     n=(int)floor((double)((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]);
  PostQuitMessage(0);
  break;
 default:
  return DefWindowProc(hWnd, message, wParam, lParam);
 }
 return 0;
}

// “关于”框的消息处理程序。
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
 UNREFERENCED_PARAMETER(lParam);
 switch (message)
 {
 case WM_INITDIALOG:
  return (INT_PTR)TRUE;

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

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<10;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="您赢了!";
   break;
  case 1:
   str="计算机赢了!";
   break;
  case 2:
   str="不分胜负!";
   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();
}

原文地址:https://www.cnblogs.com/batman425/p/3268333.html