Win32 API 五子棋画棋盘后,落子只能显示一个棋子 本帖最后由 zht_304 于 2009-09-28 00:40:05 编辑 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 由于不知道问题出在什么地方,所以就把代码都贴上来了。 辛苦大家了。----------------------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 regionBOOL 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 cursorvoid 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; }}*/ 1. 画的棋子只能出现最近的一个。好像是被画棋盘的那个函数(Board.cpp中)重画掉显示区域了。 应该怎么处理? 可以让棋盘只载入、画一次吗? 这个不会只画一次的,OnPaint消息会经常调用的。这个需要你处理一下,每一次调OnPaint的时候都先画棋盘,再画棋子。这样就需要你先把已经下的棋子的位置和颜色记录下来。每一次重画的时候都重新画一下即可。这个可能需要加上双缓冲,要不会比较闪 搞一个cmemdc,在这个上面画,然后需要刷新时画到界面的dc上。同时要记录下所有已经下的棋子的状态,需要重画的时候需要逐个画上............ 我也刚学windowsAPI编程,也写了个5子棋的,没用别的函数,直接3个函数,一个主函数,一个消息处理函数,一个算法函数。因为刚学,所以没太注意结构,楼主比我强多了,楼主参考的话可以直接Q我,大家互相学习嘛 302977769 谢谢各位! 特来结贴给分! xxcpqzm,我已加你qq,相互学习。我业余的。 求VC 用ASCII加密解密的函数,下面是C#的,我想改成VC的,谢谢。 请使用过CXImage的大侠们指教一下~有几个小问题。 如何在对话框中插入一个浏览器!在线等! CAsyncSocket和多线程 在class里又定义1个class,这是怎么回事,谁给说说? 又100 怎样画一条带箭头的直线?谢谢! 寻求 DriverStudio 2.5 下载地点! 请问高手,如何知道击键消息是否被重复? 如何在sdi窗口中建立子窗口? 请问该如何进一步的学习 关于位图背景问题
----------------------
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;
}
}
*/
同时要记录下所有已经下的棋子的状态,需要重画的时候需要逐个画上............