#include "BoardPanel.h"
BEGIN_EVENT_TABLE(BoardPanel, wxPanel)
EVT_ERASE_BACKGROUND(BoardPanel::OnEraseBackground)
EVT_SIZE(BoardPanel::OnSize)
EVT_PAINT(BoardPanel::OnPaint)
EVT_LEFT_DOWN(BoardPanel::OnLeftClick)
EVT_RIGHT_DOWN(BoardPanel::OnRightClick)
EVT_MOTION(BoardPanel::OnMouse)
END_EVENT_TABLE()
BoardPanel::BoardPanel(wxWindow *parent, wxBitmap blackBmp, wxBitmap whiteBmp)
:wxPanel(parent)
{
this->blackBmp = blackBmp;
this->whiteBmp = whiteBmp;
//创建右键菜单
popMenu = new wxMenu;
popMenu->Append(wxID_ANY, _("Item1"));
popMenu->Append(wxID_ANY, _("Item2"));
popMenu->Append(wxID_ANY, _("Item3"));
popMenu->Append(wxID_ANY, _("Item4"));
//初始化游戏数据
gomoku = new Gomoku;
playerCnt = 2;
chessR = 15;
chessSize = wxSize(30, 30);
wxSize boardSize = GetSize();
xSide = (boardSize.GetWidth() - chessSize.GetWidth() * 15) / 2 + 15;
ySide = (boardSize.GetHeight() - chessSize.GetHeight() * 15) / 2 + 15;
}
BoardPanel::~BoardPanel()
{
delete popMenu;
delete gomoku;
}
void BoardPanel::SetPlayerCount(int cnt)
{
playerCnt = cnt;
}
int BoardPanel::GetPlayerCount()
{
return playerCnt;
}
void BoardPanel::Rollback()
{
wxClientDC dc(this);
ChessInfo info;
int n = playerCnt == 1 ? 2 : 1;
for (int i = 0; i < n; ++ i) {
if(gomoku->Rollback()) {
DrawOneChess(dc, downLoc);
if (gomoku->GetLastLoc(downLoc)) {
DrawDownChess(dc, downLoc);
} else {
downLoc.SetFalse();
}
}
}
}
void BoardPanel::Forward()
{
wxClientDC dc(this);
ChessInfo info;
int n = playerCnt == 1 ? 2 : 1;
for (int i = 0; i < n; ++ i) {
if(gomoku->Forward()) {
DrawOneChess(dc, downLoc);
if (gomoku->GetLastLoc(downLoc)) {
DrawOneChess(dc, downLoc);
DrawDownChess(dc, downLoc);
}
}
}
}
void BoardPanel::Restart()
{
gomoku->Restart();
downLoc.SetFalse();
Refresh();
}
void BoardPanel::Import()
{
wxFileDialog fileDlg(this, "选择棋局", wxEmptyString, wxEmptyString, "gmk files(*.gmk)|*.gmk", wxFD_OPEN|wxFD_FILE_MUST_EXIST);
if (fileDlg.ShowModal() == wxID_CANCEL) {
return ;
}
Gomoku *gomoku_new = gomoku->Import(fileDlg.GetPath());
if (!gomoku_new) {
wxMessageBox("打开文件失败!", "提示", wxOK|wxCENTRE, this);
return;
} else {
delete gomoku;
gomoku = gomoku_new;
if (gomoku->GetLastLoc(downLoc)) {
//
} else {
downLoc.SetFalse();
}
Refresh ();
}
}
void BoardPanel::Export()
{
wxFileDialog fileDlg(this, "保存棋局", wxEmptyString, wxEmptyString, "gmk file(*.gmk)|*.gmk", wxFD_SAVE|wxFD_OVERWRITE_PROMPT);
if (fileDlg.ShowModal() == wxID_CANCEL) {
return ;
}
if (!gomoku->Export(fileDlg.GetPath())) {
wxMessageBox("保存文件失败!", "提示", wxOK|wxCENTRE, this);
return;
}
}
void BoardPanel::OnEraseBackground(wxEraseEvent &event)
{
//Erase Background
}
void BoardPanel::OnSize(wxSizeEvent &event)
{
wxSize boardSize = GetSize();
xSide = (boardSize.GetWidth() - chessSize.GetWidth() * 15) / 2 + 15;
ySide = (boardSize.GetHeight() - chessSize.GetHeight() * 15) / 2 + 15;
//Refresh();
}
wxSize BoardPanel::DoGetBestSize () const
{
return wxSize(600, 550);
}
void BoardPanel::OnPaint(wxPaintEvent &event)
{
/* wxPaintDC */
wxPaintDC dc(this);
/* 准备wxMemoryDC */
wxMemoryDC memDC;
wxRect rect = this->GetRect();
wxBitmap bitmap(rect.GetSize());
memDC.SelectObject(bitmap);
/* 开始绘图 */
memDC.SetBackground(wxColor(128, 128, 128));
memDC.Clear();
memDC.SetPen(*wxBLACK_PEN);
memDC.DrawRectangle(xSide - chessR - 1, ySide - chessR - 1,
chessSize.GetWidth() * 15 + 2, chessSize.GetHeight() * 15 + 2);
ChessLoc loc;
int width = ChessBoard::GetWidth(), height = ChessBoard::GetHeight();
for (loc.y = 0; loc.y < width; ++ loc.y) {
for (loc.x = 0; loc.x < height; ++ loc.x) {
DrawOneChess(memDC, loc);
}
}
DrawDownChess(memDC, downLoc);
DrawMouseChess(memDC, focusLoc);
/* 绘图完毕 */
/* 复制到wxPaintDC */
dc.Blit(wxPoint(0, 0), rect.GetSize(), &memDC, wxPoint(0, 0));
}
void BoardPanel::DrawOneChess(wxDC &dc, const ChessLoc &loc)
{
if (!loc.Check()) {
return ;
}
wxCoord x = xSide + chessSize.GetWidth() * loc.x;
wxCoord y = ySide + chessSize.GetHeight() * loc.y;
ChessType type = gomoku->board.GetData(loc);
dc.SetPen(*wxTRANSPARENT_PEN);
dc.SetBrush(wxColor(240, 210, 110));
dc.DrawRectangle(x - chessR, y - chessR, chessSize.GetWidth(), chessSize.GetHeight());
if (type == CT_NONE) {
dc.SetPen(*wxBLACK_PEN);
//竖线
if (loc.y == 0) {
dc.DrawLine(x, y, x, y + chessR);
} else if (loc.y == 14) {
dc.DrawLine(x, y - chessR, x, y);
} else {
dc.DrawLine(x, y - chessR, x, y + chessR);
}
//横线
if (loc.x == 0) {
dc.DrawLine(x, y, x + chessR, y);
} else if (loc.x == 14) {
dc.DrawLine(x - chessR, y, x, y);
} else {
dc.DrawLine(x - chessR, y, x + chessR, y);
}
if ((loc.x == 3 && loc.y == 3)
|| (loc.x == 3 && loc.y == 11)
|| (loc.x == 11 && loc.y == 3)
|| (loc.x == 11 && loc.y == 11)
|| (loc.x == 7 && loc.y == 7)
) {
dc.SetBrush(*wxBLACK_BRUSH);
dc.DrawCircle(x, y, 3);
}
} else if (type == CT_WHITE) {
dc.DrawBitmap(whiteBmp, x - chessR, y - chessR);
} else {
dc.DrawBitmap(blackBmp, x - chessR, y - chessR);
}
}
void BoardPanel::DrawDownChess(wxDC &dc, const ChessLoc &loc)
{
if (!loc.Check()) {
return ;
}
wxCoord x = xSide + chessSize.GetWidth() * loc.x;
wxCoord y = ySide + chessSize.GetHeight() * loc.y;
wxPen pen(wxColour(128, 128, 128), 1, wxPENSTYLE_DOT);
dc.SetPen(pen);
dc.SetBrush(*wxTRANSPARENT_BRUSH);
dc.DrawRectangle(x - chessR, y - chessR, chessSize.GetWidth(), chessSize.GetHeight());
}
void BoardPanel::DrawMouseChess(wxDC &dc, const ChessLoc &loc)
{
if (!loc.Check()) {
return ;
}
wxCoord x = xSide + chessSize.GetWidth() * loc.x;
wxCoord y = ySide + chessSize.GetHeight() * loc.y;
if (gomoku->GetHolder() == CT_WHITE) {
wxPen pen(wxColour(255, 255, 255), 1, wxPENSTYLE_DOT);
dc.SetPen(pen);
} else {
wxPen pen(wxColour(0, 0, 0), 1, wxPENSTYLE_DOT);
dc.SetPen(pen);
}
wxBrush brush(*wxTRANSPARENT_BRUSH);
dc.SetBrush(brush);
dc.DrawCircle(x, y, chessR - 1);
}
void BoardPanel::AfterDownChess(const ChessLoc &loc)
{
wxClientDC dc(this);
if (downLoc.Check()) {
DrawOneChess(dc, downLoc);
}
DrawOneChess(dc, loc);
downLoc = loc;
DrawDownChess(dc, downLoc);
if (gomoku->IsOver()) {
ChessType winer = gomoku->GetWiner();
if (winer == CT_WHITE) {
wxMessageBox(("游戏结束:白棋胜!"), ("提示"));
} else if (winer == CT_BLACK) {
wxMessageBox(("游戏结束:黑棋胜!"), ("提示"));
} else {
wxMessageBox(("游戏结束:和棋!"), ("提示"));
}
}
}
void BoardPanel::OnLeftClick(wxMouseEvent& event)
{
if (gomoku->IsOver()) {
return ;
} else {
wxPoint pt = event.GetPosition();
ChessLoc loc(
(pt.x - xSide + chessR)/chessSize.GetW