棋盘的绘制和走棋参看博文:中国象棋游戏Chess(1) - 棋盘绘制以及棋子的绘制中国象棋游戏Chess(2)
- 走棋

现在重新整理之前写的代码,并且对于每个棋子的走棋规则都进行了限制,不像之前那样每个棋子都可以走到任意位置。

也实现了红先黑后,并且每一方走一步,交替走棋的功能。

直接看代码:

// Board.h
// Board类实现了棋盘的绘制以及显示
//

#ifndef BOARD_H
#define BOARD_H

#include <QFrame>
#include "Stone.h"
#include "Step.h"
#include <QVector>

class Board : public QFrame
{
    Q_OBJECT
public:
    explicit Board(QWidget *parent = 0);
    ~Board();

    /*===> 游戏数据 <===*/
    Stone _s[32]; // 定义32个棋子
    int _r; // 棋子的半径
    QPoint _off;
    bool _bSide;

    QVector<Step*> _steps; // 悔棋时使用

    /*===> 游戏状态 <===*/
    int _selectid;
    bool _bRedTurn;
    void init(bool bRedSide);

    /*===> 绘图函数 <===*/
    virtual void paintEvent(QPaintEvent *);
    void DrawBackground(); // 设置背景颜色
    void drawPlate(QPainter& p); // 绘制棋盘
    void drawPlace(QPainter& p); // 绘制九宫格
    void drawInitPosition(QPainter& p); // 绘制炮兵位置上的十字
    void drawInitPosition(QPainter& p, int row, int col);
    void drawStone(QPainter &p); // 绘制棋子
    void drawStone(QPainter &p, int id);

    /*===> 坐标转换相关函数 <===*/
    QPoint center(int row, int col); // 返回棋盘行列对应的像素坐标
    QPoint center(int id);
    QPoint topLeft(int row, int col);
    QPoint topLeft(int id);
    QRect cell(int row, int col);
    QRect cell(int id);

    bool getClickRowCol(QPoint pt, int &row, int &col);

    /*===> 帮助函数 <===*/
    QString name(int id);
    bool red(int id);
    bool sameColor(int id1, int id2);
    int getStoneId(int row, int col); // 获取行row列col上的棋子id
    void killStone(int id);
    void reliveStone(int id);
    void moveStone(int moveid, int row, int col);
    bool isDead(int id); // 判断id棋子是否死亡

    /*===> 移动相关函数 <===*/
    virtual void mouseReleaseEvent(QMouseEvent *ev); // 鼠标点击象棋并释放鼠标时候触发
    void click(QPoint pt);
    virtual void click(int id, int row, int col);
    void trySelectStone(int id);
    void tryMoveStone(int killid, int row, int col);
    void moveStone(int moveid, int killid, int row, int col);
    void saveStep(int moveid, int killid, int row, int col, QVector<Step*>& steps);
    void backOne();
    void back(Step* step);
    virtual void back();

    /*===> 移动规则 <===*/
    bool canMove(int moveid, int killid, int row, int col);
    bool canMoveJiang(int moveid, int killid, int row, int col);
    bool canMoveShi(int moveid, int, int row, int col);
    bool canMoveXiang(int moveid, int, int row, int col);
    bool canMoveChe(int moveid, int, int row, int col);
    bool canMoveMa(int moveid, int killid, int row, int col);
    bool canMovePao(int moveid, int killid, int row, int col);
    bool canMoveBing(int moveid, int killid, int row, int col);

    bool canSelect(int id);

    /*===> 移动规则相关的几个帮助函数 <===*/
    int relation(int row1, int col1, int row, int col); // 得到两点之间的关系值
    bool isBottomSide(int id); // 判断id棋子是否在棋盘下方
    // 判断两个点是否在同一条直线上,炮和车走棋的时候需要用到
    int getStoneCountAtLine(int row1, int col1, int row2, int col2);

signals:

public slots:
    void slotBack();
};

#endif // BOARD_H
// Board.cpp

#include "Board.h"
#include <QPainter> // 绘制棋盘需要
#include <QMouseEvent>
#include <QDebug>
#define GetRowCol(__row, __col, __id) \
    int __row = _s[__id]._row;\
    int __col = _s[__id]._col

Board::Board(QWidget *parent) : QFrame(parent)
{
    this->_r = 20;
    setMinimumSize(_r * 18 + 1, _r * 20 + 1);
    init(true);
}

Board::~Board()
{

}

void Board::init(bool bRedSide)
{
    for (int i = 0; i < 32; ++i) {
        _s[i].init(i);
    }
    if (bRedSide) {
        for (int i = 0; i < 32; ++i) {
            _s[i].rotate();
        }
    }

    _selectid = -1;
    _bRedTurn = true;
    _bSide = bRedSide;
    update();
}

// 绘制棋盘
void Board::paintEvent(QPaintEvent *)
{
    DrawBackground(); // 绘制背景颜色

    int r = height() / 20;
    _r = r;
    _off = QPoint(r + 1, r + 1);

    QPainter p(this);
    p.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);

    p.save();
    drawPlate(p);
    p.restore();

    p.save();
    drawPlace(p);
    p.restore();

    p.save();
    drawInitPosition(p);
    p.restore();

    p.save();
    drawStone(p);
    p.restore();
}

// 设置背景颜色
void Board::DrawBackground()
{
    QPalette p = this->palette();
    p.setColor(QPalette::Window, QColor(224, 255, 255));
    this->setPalette(p);
}

// 绘制棋盘
void Board::drawPlate(QPainter &p)
{
    // 绘制10条横线
    for (int i = 0; i < 10; ++i) {
        if (i == 0 || i == 9) { // 上下边框画笔设置的粗一些
            p.setPen(QPen(Qt::black, 3, Qt::SolidLine));
        }
        else {
            p.setPen(QPen(Qt::black, 1, Qt::SolidLine));
        }
        p.drawLine(center(i, 0), center(i, 8));
    }

    // 绘制9条竖线
    for (int i = 0; i < 9; ++i) {
        if (i == 0 || i == 8) { // 中间有楚河汉界,不能画通
            p.setPen(QPen(Qt::black, 3, Qt::SolidLine));
            p.drawLine(center(0, i), center(9, i));
        }
        else {
            p.setPen(QPen(Qt::black, 1, Qt::SolidLine));
            p.drawLine(center(0, i), center(4, i));
            p.drawLine(center(5, i), center(9, i));
        }
    }
}

// 绘制九宫格
void Board::drawPlace(QPainter &p)
{
    p.drawLine(center(0, 3), center(2, 5));
    p.drawLine(center(2, 3), center(0, 5));

    p.drawLine(center(9, 3), center(7, 5));
    p.drawLine(center(7, 3), center(9, 5));
}

// 绘制炮兵位置上的十字
void Board::drawInitPosition(QPainter &p)
{
    drawInitPosition(p, 3, 0);
    drawInitPosition(p, 3, 2);
    drawInitPosition(p, 3, 4);
    drawInitPosition(p, 3, 6);
    drawInitPosition(p, 3, 8);

    drawInitPosition(p, 6, 0);
    drawInitPosition(p, 6, 2);
    drawInitPosition(p, 6, 4);
    drawInitPosition(p, 6, 6);
    drawInitPosition(p, 6, 8);

    drawInitPosition(p, 2, 1);
    drawInitPosition(p, 2, 7);

    drawInitPosition(p, 7, 1);
    drawInitPosition(p, 7, 7);
}

void Board::drawInitPosition(QPainter& p, int row, int col)
{
    QPoint pt = center(row, col);
    QPoint off = QPoint(_r / 6, _r / 6);
    int len = _r / 3;

    QPoint ptStart;
    QPoint ptEnd;

    if (col != 0) {
        // 左上角
        ptStart = QPoint(pt.x() - off.x(), pt.y() - off.y());
        ptEnd = ptStart + QPoint(-len, 0);
        p.drawLine(ptStart, ptEnd);
        ptEnd = ptStart + QPoint(0, -len);
        p.drawLine(ptStart, ptEnd);

        // 左下角
        ptStart = QPoint(pt.x() - off.x(), pt.y() + off.y());
        ptEnd = ptStart + QPoint(-len, 0);
        p.drawLine(ptStart, ptEnd);
        ptEnd = ptStart + QPoint(0, +len);
        p.drawLine(ptStart, ptEnd);
    }

    if (col != 8) {
        // 右下角
        ptStart = QPoint(pt.x() + off.x(), pt.y() + off.y());
        ptEnd = ptStart + QPoint(+len, 0);
        p.drawLine(ptStart, ptEnd);
        ptEnd = ptStart + QPoint(0, +len);
        p.drawLine(ptStart, ptEnd);

        // 右上角
        ptStart = QPoint(pt.x() + off.x(), pt.y() - off.y());
        ptEnd = ptStart + QPoint(+len, 0);
        p.drawLine(ptStart, ptEnd);
        ptEnd = ptStart + QPoint(0, -len);
        p.drawLine(ptStart, ptEnd);
    }
}

// 绘制棋子
void Board::drawStone(QPainter &p)
{
    for (int i = 0; i < 32; ++i) {
        drawStone(p, i);
    }
}

void Board::drawStone(QPainter &p, int id)
{
    if (isDead(id)) {
        return;
    }

    QColor color;
    if (red(id)) {
        color = Qt::red;
    }
    else {
        color = Qt::black;
    }

    p.setPen(QPen(QBrush(color), 2));

    if (id == _selectid) {
        p.setBrush(Qt::gray);
    }
    else {
        p.setBrush(Qt::yellow);
    }

    p.drawEllipse(cell(id));

    p.setFont(QFont("system", _r * 1.2, 700)); // 设置字体大小和类型
    p.drawText(cell(id), name(id), QTextOption(Qt::AlignCenter));
}

// 返回棋盘行列对应的像素坐标
QPoint Board::center(int row, int col)
{
    QPoint pt(_r * col * 2, _r * row * 2);
    return pt + _off;
}

// 重载center函数,方便调用
QPoint Board::center(int id)
{
    return center(_s[id]._row, _s[id]._col);
}

QPoint Board::topLeft(int row, int col)
{
    return center(row, col) - QPoint(_r, _r);
}

QPoint Board::topLeft(int id)
{
    return center(id) - QPoint(_r, _r);
}

QRect Board::cell(int row, int col)
{
    return QRect(topLeft(row, col), QSize(_r * 2 - 1, _r * 2 - 1));
}

QRect Board::cell(int id)
{
    return QRect(topLeft(id), QSize(_r * 2 - 1, _r * 2 - 1));
}

// 判断点击位置属于哪个顶点
// 返回值为bool类型是为了处理点击在棋盘外的情况
bool Board::getClickRowCol(QPoint pt, int &row, int &col)
{
    row = pt.y() / (2 * _r) - 1;
    col = pt.x() / (2 * _r) - 1;

    QPoint c = center(row, col);
    int dx = c.x() - pt.x();
    int dy = c.y() - pt.y();
    int dist = dx * dx + dy * dy; // 和鼠标所处矩形左上顶点的距离
    if (dist < _r * _r) {
        return true;
    }

    row += 1;
    c = center(row, col);
    dx = c.x() - pt.x();
    dy = c.y() - pt.y();
    dist = dx * dx + dy * dy; // 和鼠标所处矩形左下顶点的距离
    if (dist < _r * _r) {
        return true;
    }

    row -= 1;
    col += 1;
    c = center(row, col);
    dx = c.x() - pt.x();
    dy = c.y() - pt.y();
    dist = dx * dx + dy * dy; // 和鼠标所处矩形右上顶点的距离
    if (dist < _r * _r) {
        return true;
    }

    row += 1;
    c = center(row, col);
    dx = c.x() - pt.x();
    dy = c.y() - pt.y();
    dist = dx * dx + dy * dy; // 和鼠标所处矩形右下顶点的距离
    if (dist < _r * _r) {
        return true;
    }

    return false;
}

QString Board::name(int id)
{
    return _s[id].name();
}

bool Board::red(int id)
{
    return _s[id]._red;
}

bool Board::sameColor(int id1, int id2)
{
    if (id1 == -1 || id2 == -1) {
        return false;
    }
    return red(id1) == red(id2);
}

int Board::getStoneId(int row, int col)
{
    for (int i = 0; i < 32; ++i) {
        if (_s[i]._row == row &&
            _s[i]._col == col && !isDead(i)) {
            return i;
        }
    }
    return -1; // 如果不是棋子返回-1
}

void Board::killStone(int id)
{
    if (id == -1) {
        return;
    }
    _s[id]._dead = true;
}

void Board::reliveStone(int id)
{
    if (id == -1) {
        return;
    }
    _s[id]._dead = false;
}

void Board::moveStone(int moveid, int row, int col)
{
    _s[moveid]._row = row;
    _s[moveid]._col = col;

    _bRedTurn = !_bRedTurn;
}

bool Board::isDead(int id)
{
    if (id == -1) {
        return true;
    }
    return _s[id]._dead;
}

void Board::saveStep(int moveid, int killid, int row, int col, QVector<Step*>& steps)
{
    GetRowCol(row1, col1, moveid);
    Step* step = new Step;
    step->_colFrom = col1;
    step->_colTo = col;
    step->_rowFrom = row1;
    step->_rowTo = row;
    step->_moveid = moveid;
    step->_killid = killid;

    steps.append(step);
}

void Board::backOne()
{
    if (this->_steps.size() == 0) {
        return;
    }

    Step* step = this->_steps.last();
    _steps.removeLast();
    back(step);

    update();
    delete step;
}

void Board::back(Step* step)
{
    reliveStone(step->_killid);
    moveStone(step->_moveid, step->_rowFrom, step->_colFrom);
}

void Board::back()
{
    backOne();
}

void Board::mouseReleaseEvent(QMouseEvent *ev)
{
    if (ev->button() != Qt::LeftButton) { // 排除鼠标右键点击
        return;
    }

    click(ev->pos());
}

void Board::click(QPoint pt)
{
    // 看有没有点中象棋
    // 将pt转化成象棋的行列值
    // 判断这个行列值上面有没有棋子
    int row, col;
    bool bClicked = getClickRowCol(pt, row, col);
    if (!bClicked) {
        return;
    }

    int id = getStoneId(row, col);
    click(id, row, col);

}

void Board::click(int id, int row, int col)
{
    if (this->_selectid == -1) { // 如果点中的棋子之前未被选中
        trySelectStone(id);
    }
    else {
        tryMoveStone(id, row, col);
    }
}

void Board::trySelectStone(int id)
{
    if (id == -1) {
        return;
    }

    if (!canSelect(id)) {
        return;
    }

    _selectid = id;
    update();
}

void Board::tryMoveStone(int killid, int row, int col)
{
    if (killid != -1 && sameColor(killid, _selectid)) {
        trySelectStone(killid);
        return;
    }

    bool ret = canMove(_selectid, killid, row, col);
    if (ret) {
        moveStone(_selectid, killid, row, col);
        _selectid = -1;
        update();
    }
}

void Board::moveStone(int moveid, int killid, int row, int col)
{
    saveStep(moveid, killid, row, col, _steps);

    killStone(killid);
    moveStone(moveid, row, col);
}

bool Board::canMove(int moveid, int killid, int row, int col)
{
    // 如果moveid和killid颜色相同,则不能移动,还需要换选择
    if (_s[moveid]._red == _s[killid]._red) {
        _selectid = killid;
        update();
        return false;
    }

    switch (_s[moveid]._type) {
    case Stone::JIANG:
        return canMoveJiang(moveid, killid, row, col);

    case Stone::SHI:
        return canMoveShi(moveid, killid, row, col);

    case Stone::XIANG:
        return canMoveXiang(moveid, killid, row, col);

    case Stone::CHE:
        return canMoveChe(moveid, killid, row, col);

    case Stone::MA:
        return canMoveMa(moveid, killid, row, col);

    case Stone::PAO:
        return canMovePao(moveid, killid, row, col);

    case Stone::BING:
        return canMoveBing(moveid, killid, row, col);
    }

    return true;

}

bool Board::canMoveJiang(int moveid, int killid, int row, int col)
{
    // 可直接吃对方将
    if (killid != -1 && _s[killid]._type == Stone::JIANG)
    {
        return canMoveChe(moveid, killid, row, col);
    }

    GetRowCol(row1, col1, moveid);
    int r = relation(row1, col1, row, col);
    if (r != 1 || r != 10) {
        return false;
    }

    if (col < 3 || col > 5) {
        return false;
    }

    if (isBottomSide(moveid)) {
        if (row < 7) {
            return false;
        }
    }
    else {
        if (row > 2) {
            return false;
        }
    }

    return true;
}

bool Board::canMoveShi(int moveid, int, int row, int col)
{

    // 移动步长一个格子对角线
    GetRowCol(row1, col1, moveid);
    int r = relation(row1, col1, row, col);
    if (r != 11) {
        return false;
    }

    if (col < 3 || col > 5) {
        return false;
    }

    if (isBottomSide(moveid)) {
        if (row < 7) {
            return false;
        }
    }
    else {
        if (row > 2) {
            return false;
        }
    }

    return true;
}

bool Board::canMoveXiang(int moveid, int, int row, int col)
{
    GetRowCol(row1, col1, moveid);
    int r = relation(row1, col1, row, col);
    if (r != 22) { // 象走田,所以r应该等于22
        return false;
    }

    // 看象眼有没有棋子
    int rEye = (row + row1) / 2;
    int cEye = (col + col1) / 2;
    if (getStoneId(rEye, cEye) != -1) {
        return false;
    }

    // 判断是否在棋盘的下方
    if (isBottomSide(moveid)) {
        if (row < 4) {
            return false;
        }
    }
    else {
        if (row > 5) {
            return false;
        }
    }

    return true;
}

bool Board::canMoveChe(int moveid, int, int row, int col)
{
    GetRowCol(row1, col1, moveid);
    int ret = getStoneCountAtLine(row1, col1, row, col);
    if (ret == 0) { // 在一行,并且中间没有棋子
        return true;
    }

    return false;
}

bool Board::canMoveMa(int moveid, int, int row, int col)
{
    GetRowCol(row1, col1, moveid);
    int r = relation(row1, col1, row, col);
    // 首先判断马要走马字
    if (r != 12 && r != 21) {
        return false;
    }

    // 判断有没有蹩马腿的情况
    if (r == 12) { // 列相差等于2
        if (getStoneId(row1, (col + col1) / 2) != -1) {
            return false;
        }
    }
    else { // 行相差等于2
        if (getStoneId((row + row1) / 2, col1) != -1) {
            return false;
        }
    }
    return true;
}

bool Board::canMovePao(int moveid, int killid, int row, int col)
{
    GetRowCol(row1, col1, moveid);
    int ret = getStoneCountAtLine(row, col, row1, col1);
    if (killid != -1) { // 如果炮要吃对方的棋子
        if (ret == 1) { // 中间有一个棋子,可以走
            return true;
        }
    }
    else { // 如果炮不吃棋子
        if (ret == 0) { // 中间没有棋子,可以走
            return true;
        }
    }

    return false;
}

bool Board::canMoveBing(int moveid, int, int row, int col)
{
    GetRowCol(row1, col1, moveid);
    int r = relation(row1, col1, row, col);
    // 首先判断兵只能走一步
    if (r != 1 && r != 10) {
        return false;
    }

    if (isBottomSide(moveid)) { // 下面一方的棋子
        if (row > row1) { // 如果目标行大于原始行,相当于并在后退
            return false;
        }
        if (row1 >= 5 && row == row1) { // 还没有过河就想横着走
            return false;
        }
    }
    else { // 上面一方的棋子
        if (row1 > row) { // 如果目标行小于原始行,相当于兵在后退
            return false;
        }
        if (row <= 4 && row == row1) { // 还没有过河就想横着走
            return false;
        }
    }
    return true;
}

bool Board::canSelect(int id)
{
    return _bRedTurn == _s[id]._red;
}

int Board::relation(int row1, int col1, int row, int col)
{
    return qAbs(row1 - row) * 10 + qAbs(col1 - col);
}

bool Board::isBottomSide(int id)
{
    return _bSide == _s[id]._red;
}

int Board::getStoneCountAtLine(int row1, int col1, int row2, int col2)
{
    int ret = 0;

    // 首先判断两个棋子是否在同一条直线上,如果不在同一条直线上,直接返回-1
    if (row1 != row2 && col1 != col2) {
        return -1;
    }
    if (row1 == row2 && col1 == col2) {
        return -1;
    }

    // 计算两个棋子之间的有多少个棋子
    if (row1 == row2) { // 在同一行
        int min = col1 < col2 ? col1 : col2;
        int max = col1 > col2 ? col1 : col2;
        for (int col = min + 1; col < max; ++col) {
            if (getStoneId(row1, col) != -1) {
                ++ret;
            }
        }
    }
    else { // 在同一列
        int min = row1 < row2 ? row1 : row2;
        int max = row1 > row2 ? row1 : row2;
        for (int row = min + 1; row < max; ++row) {
            if (getStoneId(row, col1) != -1) {
                ++ret;
            }
        }
    }

    return ret;
}

void Board::slotBack()
{
    back();
}
#ifndef STEP_H
#define STEP_H

#include <QObject>

class Step : public QObject
{
    Q_OBJECT
public:
    explicit Step(QObject *parent = 0);
    ~Step();

    int _moveid;
    int _killid;
    int _rowFrom;
    int _colFrom;
    int _rowTo;
    int _colTo;

signals:

public slots:
};

#endif // STEP_H
// Stone.h
// 棋子类,存储了棋子的基础信息

#ifndef STONE_H
#define STONE_H

#include <QString>

class Stone
{
public:
    Stone();
    ~Stone();

    enum TYPE{JIANG, CHE, PAO, MA, BING, SHI, XIANG};
    int _row;
    int _col;
    TYPE _type;

    int _id;
    bool _dead;
    bool _red;

    // 棋子的初始化
    void init(int id);

    // 判断_type返回相应字符串
    QString name();

    void rotate(); // 翻转棋盘

};

#endif // STONE_H
// Stone.cpp

#include "Stone.h"
#include <QDebug>

Stone::Stone()
{

}

Stone::~Stone()
{

}

void Stone::init(int id)
{
    struct {
        int row, col;
        Stone::TYPE type;
    } pos[16] = {
    {0, 0, Stone::CHE},
    {0, 1, Stone::MA},
    {0, 2, Stone::XIANG},
    {0, 3, Stone::SHI},
    {0, 4, Stone::JIANG},
    {0, 5, Stone::SHI},
    {0, 6, Stone::XIANG},
    {0, 7, Stone::MA},
    {0, 8, Stone::CHE},

    {2, 1, Stone::PAO},
    {2, 7, Stone::PAO},
    {3, 0, Stone::BING},
    {3, 2, Stone::BING},
    {3, 4, Stone::BING},
    {3, 6, Stone::BING},
    {3, 8, Stone::BING},
    };

    //_id = id;
    _dead = false;
    _red = id < 16;

    if (id < 16) { // 上方的棋子
        this->_row = pos[id].row;
        this->_col = pos[id].col;
        this->_type = pos[id].type;
    }
    else { // 下方的棋子
        this->_row = 9 - pos[id - 16].row;
        this->_col = 8 - pos[id - 16].col;
        this->_type = pos[id - 16].type;
    }
}

QString Stone::name()
{
    switch (this->_type)
    {
    case CHE:
        return "车";
    case MA:
        return "马";
    case PAO:
        return "炮";
    case BING:
        return "兵";
    case JIANG:
        return "将";
    case SHI:
        return "士";
    case XIANG:
        return "相";
    }
    return "错误";
}

void Stone::rotate()
{
    this->_col = 8 - this->_col;
    this->_row = 9 - this->_row;
}
// main.cpp
// Chess游戏主程序
//
// Created by Lucifer Zhang on 2015-07-21.
// Copyright (c) 2015 Lucifer Zhang. All rights reserved.

#include <QApplication>
#include "Board.h"

int main(int argc, char* argv[])
{
    QApplication app(argc, argv);
    Board board;
    board.show();
    return app.exec();
}

工程代码详情:Github

中国象棋游戏Chess(3) - 实现走棋规则的更多相关文章

  1. 中国象棋游戏Chess(2) - 走棋

    之前的文章请看:中国象棋游戏Chess(1) - 棋盘绘制以及棋子的绘制 现在实现走棋的功能. 首先需要获取点击到的棋子,用QWidget中的函数 mouseReleaseEvent 实现函数: vo ...

  2. 中国象棋游戏Chess(1) - 棋盘绘制以及棋子的绘制

    本项目都使用QT来实现绘图,没有任何第三方的资源. 工程详情:Github 首先将棋盘设计为一个类Board // Board.h // Board类实现了棋盘的绘制以及显示 // #ifndef B ...

  3. C/C++编程笔记:C语言打造中国象棋游戏,项目源代码分享!

    中国象棋是起源于中国的一种棋,属于二人对抗性游戏的一种,在中国有着悠久的历史.由于用具简单,趣味性强,成为流行极为广泛的棋艺活动. 它是中国棋文化,也是中华民族的文化瑰宝,它源远流长,趣味浓厚,基本规 ...

  4. 基于HTML5实现的中国象棋游戏

    棋类游戏在桌面游戏中已经非常成熟,中国象棋的版本也非常多.今天这款基于HTML5技术的中国象棋游戏非常有特色,我们不仅可以选择中国象棋的游戏难度,而且可以切换棋盘的样式.程序写累了,喝上一杯咖啡,和电 ...

  5. C#中国象棋+游戏大厅 服务器 + 客户端源码

    来源:www.ajerp.com/bbs C#中国象棋+游戏大厅 服务器 + 客户端源码 源码开源 C#版中国象棋(附游戏大厅) 基于前人大虾的修改版 主要用委托实现 服务器支持在线人数,大厅桌数的设 ...

  6. 【原创】使用HTML5+canvas+JavaScript开发的原生中国象棋游戏及源码分享

    目前已经实现的功能: V1.0 : 实现棋子的布局,画布及游戏场景的初始化V2.0 : 实现棋子的颜色改变V3.0 :实现所有象棋的走棋规则V4.0 : 实现所有棋子的吃子功能 GItHub源码下载地 ...

  7. GMchess Linux下的中国象棋游戏

    gmchess,一款Linux下的中国象棋程序

  8. cocos2dx 3.2 的中国象棋游戏

    改编来源:http://cn.cocos2d-x.org/tutorial/lists?id=103 在cocos2dx官网看到了这么个教程,是cocos2dx 2.x版本的,于是用 cocos2dx ...

  9. 亲自动手实现Python+pygame中国象棋游戏

    功能1:实现游戏整体界面显示 一.创建基本的结构 代码如下: import time import pygame def main(): # 初始化pygame pygame.init() # 创建用 ...

随机推荐

  1. cuda网格的限制

    限制于计算能力有关. 详情 http://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#compute-capabilities 只 ...

  2. [Centos]openvpn 服务端的安装(easy-rsa3)

    VPN在办公和fan墙领域有着广泛的应用,  我们小办公网最近可能会用到,先学学来着 vpn的server需要有公网ip,客户端可以在多种环境下使用 概念 PKI:Public Key Infrast ...

  3. Microsoft Dynamics CRM 2011 当您在 大型数据集上执行 RetrieveMultiple 查询很慢的解决方法

    症状 当您在 Microsoft Dynamics CRM 2011 年大型数据集上执行 RetrieveMultiple 查询时,您会比较慢. 原因 发生此问题是因为大型数据集缓存 Retrieve ...

  4. Swift函数柯里化(Currying)简谈

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 下面简单说说Swift语言中的函数柯里化.简单的说就是把接收多 ...

  5. python地理数据处理库geopy

    http://blog.csdn.net/pipisorry/article/details/52205266 python地理位置处理 python地理编码地址以及用来处理经纬度的库 GeoDjan ...

  6. FFmpeg源代码简单分析:libavdevice的gdigrab

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

  7. [ExtJS5学习笔记]第七节 Extjs5的组件components及其模板事件方法学习

    本文地址:http://blog.csdn.net/sushengmiyan/article/details/38487519 本文作者:sushengmiyan ------------------ ...

  8. JVM常量池和八种基本数据及字符串

    迄今为止看到的对常量池和字符串最为透彻的解释,赞一个! 常量池(constant_pool)指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据.它包括了关于类.方法.接口等中的常量, ...

  9. Shell在大数据时代的魅力:从一道百度大数据面试题想到的点滴

    对于在Linux下开发的同学来说,Shell可以说是一种基本功. 对于运维的同学来说,Shell可以说是一种必备的技能,而且应该要非常熟练的书写Shell.对于Release Team,软件配置管理的 ...

  10. Dynamics CRM 2013 SP1 客户表单界面上联系人subgrid上的添加现有联系人功能缺失

    CRM2013打了SP1的同学会发现一个问题,客户关联联系人的1:N关系,在表单subgrid中添加联系人时,只能新建而无法添加现有联系人,而这个现象在之前的版本中是没有的. 我们通过工具ribbon ...