本帖最后由 zht_304 于 2009-09-28 00:40:05 编辑

解决方案 »

  1.   

    由于不知道问题出在什么地方,所以就把代码都贴上来了。 辛苦大家了。
    ----------------------
    Board.cpp
    #include "Board.h"Board::Board()
    {

    }Board::~Board()
    {
    releaseRes();
    }int Board::getCx() const
    {
    return cx;
    }int Board::getCy() const
    {
    return cy;
    }
    BOOL Board::initRes(HINSTANCE hInstance)
    {
    // Init Resources,
    //HINSTANCE hInstance;
    //hInstance = ((LPCREATESTRUCT)lParam)->hInstance;
    hBoard = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BOARD));
    hBlack = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BLACK));
    hWhite = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_WHITE));
    hBlackhand = LoadCursor(hInstance, MAKEINTRESOURCE(IDC_BLACKHAND));
    hWhitehand = LoadCursor(hInstance, MAKEINTRESOURCE(IDC_WHITEHAND));
    return TRUE;
    }BOOL Board::releaseRes()
    {
    BOOL bSuccess =  TRUE;
    bSuccess &= DeleteObject(hBoard);
    bSuccess &= DeleteObject(hBlack);
    bSuccess &= DeleteObject(hWhite);
    bSuccess &= DeleteObject(hBlackhand);
    bSuccess &= DeleteObject(hWhitehand);
    return bSuccess;
    }// 画棋板,
    BOOL Board::drawBoard(HWND hwnd)
    {
    //BOOL bSuccess = TRUE;
    //PAINTSTRUCT ps;
    HDC hdc = GetDC(hwnd);
    HDC hdcMem = CreateCompatibleDC(hdc); SelectObject(hdcMem, hBoard);
    BitBlt(hdc, 0, 0,BOARDSIZE,BOARDSIZE, hdcMem,0,0, SRCCOPY); DeleteDC(hdcMem);
    ReleaseDC(hwnd, hdc); return TRUE;

    }
    // 定位交叉点
    BOOL Board::findNearest(LPARAM lParam)
    {
    x = LOWORD(lParam);
    y = HIWORD(lParam); // calculate the nearest crossing point.
    if((x-HALFGRID)%GRID <= HALFGRID){
    x = x-(x-HALFGRID)%GRID;
    cx = (x-HALFGRID)/GRID;
    }
    else{
    x = x+(GRID-(x-HALFGRID)%GRID);
    cx = (x-HALFGRID)/GRID+1;
    }
    if((y-HALFGRID)%GRID <= HALFGRID){
    y = y-(y-HALFGRID)%GRID;
    cy = (y-HALFGRID)/GRID;
    }
    else{
    y = y+(GRID-(y-HALFGRID)%GRID);
    cy = (y-HALFGRID)/GRID+1;
    }
    return TRUE;
    }// 画棋子
    BOOL Board::drawStone(HWND hwnd, Player &p, Controller &ctrl)
    {
    if(p.isTurn() && ctrl.getStoneTable(cx, cy) == EMPTY){
    PAINTSTRUCT ps;
    HDC hdc = BeginPaint(hwnd, &ps);
    HDC hdcMem = CreateCompatibleDC(hdc);

    if(p.getColor()=='b'){ SetCursor(hBlackhand);
    SelectObject(hdcMem, hBlack);
    BitBlt(hdc,x-HALFGRID, y-HALFGRID, GRID,GRID, hdcMem, 0, 0, SRCCOPY);
    }
    else if(p.getColor()=='w'){
    SetCursor(hWhitehand);
    SelectObject(hdcMem, hWhite);
    BitBlt(hdc,x-HALFGRID, y-HALFGRID, GRID,GRID, hdcMem, 0, 0, SRCCOPY);
    }

    DeleteDC(hdcMem);
    EndPaint(hwnd, &ps);
    }
    return TRUE;
    }// this will send a WM_PAINT msg to paint the region
    BOOL Board::invalidateStoneArea(HWND hwnd, Controller &ctrl)
    {
    BOOL bHappened = FALSE;
    if(ctrl.getStoneTable(cx, cy) == EMPTY){
    RECT rect;
    rect.left = x-HALFGRID;
    rect.right = x+HALFGRID;
    rect.top = y-HALFGRID;
    rect.bottom = y+HALFGRID;
    HRGN hRgn = CreateEllipticRgnIndirect(&rect);

    InvalidateRgn(hwnd,hRgn, FALSE);
    bHappened = TRUE;
    }
    return bHappened;
    }
    --------------
    Controller.cpp
    #include "Controller.h"
    Controller::Controller()
    {
    for(int i = 0; i < GRIDNUM; ++i){
    for(int j = 0; j < GRIDNUM; ++j)
    stoneTable[i][j] = EMPTY;
    }
    }Controller::~Controller()
    {
    }int Controller::getStoneTable(int x, int y) const
    {
    return stoneTable[x][y];
    }// update the stoneTable for Player, using a Board object to get array's cursor
    void Controller::updateStoneTable(Player& pl, Board &bd) 
    {
    if(pl.isTurn() && stoneTable[bd.getCx()][bd.getCy()] == EMPTY){
    if(pl.getColor() == 'b')
    stoneTable[bd.getCx()][bd.getCy()] = BLACK_S;
    else if(pl.getColor() == 'w')
    stoneTable[bd.getCx()][bd.getCy()] = WHITE_S;
    }
    }void Controller::switchTurn(Player &b, Player &w)
    {
    b.reverseTurn();
    w.reverseTurn();
    }// judge if win.
    int Controller::judge(int stone, int x, int y)
    {
    int winner = 0; // no winner yet
    //directions
    int North = 0, NorthEast = 0, East = 0, SouthEast = 0; // North. Up first, then Down.
    for(int j = y; j > y-5 && j >= 0 && stoneTable[x][j]==stone; --j,++North );
    for(int j = y; j < y+5 && j < GRIDNUM && stoneTable[x][j]==stone; ++j, ++North); // NorthEast. Up-Right first, then Down-Left
    for(int i = x, j = y; i < x+5 && i < GRIDNUM && j > y-5 && j >= 0 && stoneTable[i][j]==stone; ++i,--j,++NorthEast );
    for(int i = x, j = y; i > x-5 && i >= 0 && j < y+5 && j < GRIDNUM && stoneTable[i][j]==stone; --i,++j, ++NorthEast); // East. Right first, then Left 
    for(int i = x; i < x+5 && i < GRIDNUM && stoneTable[i][y]==stone; ++i,++East );
    for(int i = x; i > x-5 && i >= 0 && stoneTable[i][y]==stone; --i, ++East); // SouthEast. Up-Left first, then Down-Right
    for(int i = x, j = y; i > x -5 && i >= 0 && j > y-5 && j >= 0 && stoneTable[i][j]==stone; --i,--j,++SouthEast );
    for(int i = x, j = y; i < x+5 && x < GRIDNUM && j < y+5 && j < GRIDNUM && stoneTable[i][j]==stone; ++i,++j, ++SouthEast);

    // if >=6 because (x,y) was calculated twice
    if (North >= 6 || NorthEast >= 6 || East >= 6 || SouthEast >=6)
    {
    winner = stone;
    }
    return winner;
    }------------------------
    Player.cpp
    ---#include "Player.h"Player::Player(unsigned int b, char color)
    {
    turn.flag = b;
    this->color = color;
    }Player::~Player(void)
    {
    }char Player::getColor() const
    {
    return color;
    }unsigned int Player::isTurn() const
    {
    return turn.flag;
    }void Player::setTurn(unsigned int b){
    turn.flag = b;
    }void Player::reverseTurn()
    {
    turn.flag = ~(turn.flag);
    }/*
    int Player::getStoneTable(int x, int y)
    {
    if (x <= 15 && x >= 0 && y <= 15 && y>=0)
    {
    return stoneTable[x][y];
    }
    else
    return -1;
    }void Player::setStoneTable(int x, int y, int value)
    {
    if (x <= 15 && x >= 0 && y <= 15 && y>=0)
    {
    stoneTable[x][y] = value;
    }
    }
    */
      

  2.   

    1. 画的棋子只能出现最近的一个。好像是被画棋盘的那个函数(Board.cpp中)重画掉显示区域了。 应该怎么处理? 可以让棋盘只载入、画一次吗? 这个不会只画一次的,OnPaint消息会经常调用的。这个需要你处理一下,每一次调OnPaint的时候都先画棋盘,再画棋子。这样就需要你先把已经下的棋子的位置和颜色记录下来。每一次重画的时候都重新画一下即可。这个可能需要加上双缓冲,要不会比较闪
      

  3.   

    搞一个cmemdc,在这个上面画,然后需要刷新时画到界面的dc上。
    同时要记录下所有已经下的棋子的状态,需要重画的时候需要逐个画上............
      

  4.   

    我也刚学windowsAPI编程,也写了个5子棋的,没用别的函数,直接3个函数,一个主函数,一个消息处理函数,一个算法函数。因为刚学,所以没太注意结构,楼主比我强多了,楼主参考的话可以直接Q我,大家互相学习嘛 302977769
      

  5.   

    谢谢各位! 特来结贴给分! xxcpqzm,我已加你qq,相互学习。我业余的。