⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 reversiboard.cpp

📁 MONA是为数不多的C++语言编写的一个很小的操作系统
💻 CPP
字号:
// This file's encoding is UTF-8.#include "ReversiBoard.h"using namespace MonAPI;/** * コンストラクタ */ReversiBoard::ReversiBoard() {    init();}/** * 指定された駒が盤面上にいくつあるかを数える * @param  piece <code>ReversiBoard.WHITE, ReversiBoard.BLACK, ReversiBoard.EMPTY</code> * @return 駒の個数 */int ReversiBoard::countPieces(int piece) {    int result = 0;    // 駒の個数を数える    for (int x = 0; x < BOARDW; x++) {        for (int y = 0; y < BOARDH; y++) {            if (this->board[x][y] == piece) result++;        }    }    return result;}/** * 指定された位置の駒を返す * @param  x (x, y) 駒の位置 * @param  y (x, y) 駒の位置 * @return 駒 盤面の範囲外の場合は<code>ReversiBoard.EMPTY</code> */int ReversiBoard::getPiece(int x, int y) {    // x, yの範囲をチェック   if (!checkRange(x, y)) return EMPTY;    // 駒を返す    return board[x][y];}/** * 指定された位置の駒を返す * @param  point 駒の位置 * @return 駒 盤面の範囲外の場合は<code>ReversiBoard.EMPTY</code> */int ReversiBoard::getPiece(Point2D* point) {    return getPiece(point->x, point->y);}/** * 現在の手番のプレイヤーを返す<code>ReversiBoard.EMPTY</code>を返したときは勝負の決着がついている状態<BR> * @return 現在の手番のプレイヤー <code>ReversiBoard.BLACK, WHITE, EMPTY</code> */int ReversiBoard::getCurrentHand() const {    return this->currentHand;}/** * 指定された位置に駒を置く。<BR> * 駒が置けた場合、置いた場所を示す。<BR> * <code>Point2D</code>がnotifyObserversで<BR> * 監視元に通知される * @param x (x, y) 駒の位置 * @param y (x, y) 駒の位置 * @param piece 置く駒 * @return 駒が置けたら<code>true</code>, 駒が置けなかったら<code>false</code> */bool ReversiBoard::setPiece(int x, int y, int piece) {    int numReversiblePieces; // 裏返すことのできる駒数    // 現在の手と照合    if (currentHand != piece) return false;    // 前手が完全に終了したかどうかをチェック    if (existNotReversedPieces()) return false;    // そこに置けるかどうかを調べる    numReversiblePieces = countReversiblePieces(x, y, piece);    if (numReversiblePieces <= 0) return false;    // pieceを(x, y)に置いたときに、裏返す駒をすべて記憶    recordReversiblePieces(x, y, piece);    // 駒を置く    board[x][y] = piece;    // ターンを記憶    allTurns->add(new Point3D(x, y, piece));    turn++;    // 変更をObserverに通知    this->setChanged();    Point2D* p = new Point2D(x, y);    this->notifyObservers(p);    delete p;    this->clearChanged();    return true;}/** * <code>setPiece()</code>した後に、裏返してない駒が存在するかを返す<BR> * <pre> *    使用方法 *      board.setPiece(3, 5, OthlloBoard::BLACK); *      while (existNotReversedPieces()) { *          reverseNext(); *          // 描画用処理 *      } * </pre> * @return 裏返してない駒が存在する場合<code>true</code> */bool ReversiBoard::existNotReversedPieces() {    return allNotReversedPieces->size() > 0;}/** * 次の駒を裏返す<BR> * 裏返した場所を示す<code>Point2D</code>がnotifyObserversで監視元に通知される * existNotReversedPieces()の使用方法を参照 */void ReversiBoard::reverseNext() {    // 裏返す位置を取得    Point2D* point = allNotReversedPieces->get(0);    // 裏返す    reversePiece(point->x, point->y);    // 変更を通知    this->setChanged();    notifyObservers(new Point2D(point));    this->clearChanged();    // 裏返したので位置を消去    allNotReversedPieces->removeAt(0);    return;}/** * 現在ターンを返す * @return 現在ターン */int ReversiBoard::getTurn() const {    return this->turn;}/** * undo機能 * 1手戻る */void ReversiBoard::undo() {    // 1手前に戻れない場合    if (getTurn() < 1) return;    // 盤面初期化    initBoard();    // 盤面並べなおし    for (int i = 0; i < allTurns->size() -1; i++) {        // 駒を置く        Point3D* p = allTurns->get(i);        setPiece(p->x, p->y, p->z);        while (existNotReversedPieces()) {            reverseNext();        }    }    // 最後のターンを消去    allTurns->removeAt(allTurns->size() -1);    return;}/** * 指定された位置に駒を置いたときに、いくつ駒が裏返せるかを返す * @param x * @param y * @param piece 置く駒 * @return 裏返せる駒数 */int ReversiBoard::countReversiblePieces(int x, int y, int piece) {    int result = 0;    // x, yの範囲をチェック    if (!checkRange(x, y)) return 0;    // すでに駒が置かれているかをチェック    if (board[x][y] != EMPTY) return 0;    // (x, y)にpieceを置いた場合に裏返すことのできる駒を8方向に探索    result += countReversiblePieceToOneAngle(x, y,  1,  0, piece, false);    result += countReversiblePieceToOneAngle(x, y,  1,  1, piece, false);    result += countReversiblePieceToOneAngle(x, y,  0,  1 ,piece, false);    result += countReversiblePieceToOneAngle(x, y, -1,  1, piece, false);    result += countReversiblePieceToOneAngle(x, y, -1,  0, piece, false);    result += countReversiblePieceToOneAngle(x, y, -1, -1, piece, false);    result += countReversiblePieceToOneAngle(x, y,  0, -1, piece, false);    result += countReversiblePieceToOneAngle(x, y,  1, -1, piece, false);    return result;}/** * リバーシ盤をリセットする */void ReversiBoard::resetBoard() {    delete (this->allTurns);    this->allTurns = new HList<Point3D*>();    initBoard();    // 変更を通知    this->setChanged();    this->notifyObservers(NULL);    this->clearChanged();    return;}/** * ReversiBoard生成と初期化を行う */void ReversiBoard::init() {    // 盤面初期化    initBoard();    // すべてのターンを記憶するHList初期化    allTurns = new HList<Point3D*>();    return;}/** * 盤面初期化行う */void ReversiBoard::initBoard() {    // 現在ターンを設定    this->turn = 0;    // 先手は黒    this->currentHand = BLACK;    // 盤面を空にする    for (int x = 0; x < BOARDW; x++) {        for (int y = 0; y < BOARDH; y++) board[x][y] = EMPTY;    }    // 初期状態で置かれている駒をセット    board[3][3] = BLACK;    board[4][4] = BLACK;    board[4][3] = WHITE;    board[3][4] = WHITE;    // 裏返すべき駒のすべて位置を記憶するList初期化    allNotReversedPieces = new HList<Point2D*>();    return;}/** * 指定した駒を裏返す */void ReversiBoard::reversePiece(int x, int y) {    // x, yの範囲をチェック    if (!checkRange(x, y)) return;    // 駒を裏返す、もし空なら何もしない    board[x][y] = turnColor(board[x][y]);    return;}/** * 入力された値が盤面上に存在するかチェックする */bool ReversiBoard::checkRange(int x, int y) {    // 盤面上にあるという条件    bool xRange = x >= 0 && x < BOARDW;    bool yRange = y >= 0 && y < BOARDH;    // 盤面上にある    if (xRange && yRange) return true;    // 盤面上にない    return false;}/** *  指定されたベクトル(toX, toY)の方向へ裏返せる駒数を数える *  reordFlagがtrueの時は位置を記憶 */int ReversiBoard::countReversiblePieceToOneAngle(int x, int y, int toX,int toY                                                 , int piece, bool recordFlag) {    int result = 0;    // 隣の駒へ移動    x += toX;    y += toY;    // 盤面の端まで探索を続ける    while (x >= 0 && y >= 0 && x < BOARDW && y < BOARDH) {        // 探索中の駒が裏返しの色なら裏返せる        if (board[x][y] == turnColor(piece)) {            // 裏返せる駒の位置を記憶            if (recordFlag) allNotReversedPieces->add(new Point2D(x, y));            // 駒数インクリメント            result++;        }        // 同じ色だったら、そこまであった裏返し色を裏返すことができる        else if (board[x][y] == piece) return result;        // 空なら裏返せない        else if (board[x][y] == EMPTY) {            if (recordFlag) {                // 記憶していた駒の位置                for (int i = 0; i < result; i++) {                    allNotReversedPieces->removeAt(allNotReversedPieces->size() - 1);                }            }            return 0;        }        // さらに隣の駒へ移動        x += toX;        y += toY;    }    if (recordFlag) {        // 記憶していた駒の位置        for (int i = 0; i < result; i++) {            allNotReversedPieces->removeAt(allNotReversedPieces->size() - 1);        }    }    return 0;}/** * 裏返した色を返す */int ReversiBoard::turnColor(int piece) {    return piece * -1;}/** * pieceを(x, y)に置いたときに、裏返す駒をすべて記憶 */bool ReversiBoard::recordReversiblePieces(int x, int y, int piece) {    // x, yの範囲をチェック    if (!checkRange(x, y)) return false;    // すでに駒が置かれているかをチェック    if (board[x][y] != EMPTY) return false;    // 駒位置記憶オブジェクトを初期化    delete allNotReversedPieces;    allNotReversedPieces = new HList<Point2D*>();    // 裏返せる位置を記憶    countReversiblePieceToOneAngle(x, y,  1,  0, piece, true);    countReversiblePieceToOneAngle(x, y,  1,  1, piece, true);    countReversiblePieceToOneAngle(x, y,  0,  1 ,piece, true);    countReversiblePieceToOneAngle(x, y, -1,  1, piece, true);    countReversiblePieceToOneAngle(x, y, -1,  0, piece, true);    countReversiblePieceToOneAngle(x, y, -1, -1, piece, true);    countReversiblePieceToOneAngle(x, y,  0, -1, piece, true);    countReversiblePieceToOneAngle(x, y,  1, -1, piece, true);    return true;}// 次手のプレイヤーを判断void ReversiBoard::setNextHand() {    if (isTherePlace(turnColor(currentHand))) {        currentHand = turnColor(currentHand);    } else if (isTherePlace(currentHand)) {        // 続けてもう1手    } else {        // 両プレイヤー共に置く場所がない        currentHand = EMPTY;    }    return;}// 盤面上に指定されたpieceをおくことができるかを判断bool ReversiBoard::isTherePlace(int piece) {    int result = 0;    // 駒の個数を数える    for (int x = 0; x < BOARDW; x++) {        for (int y = 0; y < BOARDH; y++) {            result += countReversiblePieces(x, y, piece);        }    }    return result > 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -