?? reversiboard.cpp
字號:
// This file's encoding is UTF-8.#include "ReversiBoard.h"using namespace MonAPI;/** * コンストラクタ */ReversiBoard::ReversiBoard() { init();}/** * 指定された駒が盤面上にいくつあるかを數(shù)える * @param piece <code>ReversiBoard.WHITE, ReversiBoard.BLACK, ReversiBoard.EMPTY</code> * @return 駒の個數(shù) */int ReversiBoard::countPieces(int piece) { int result = 0; // 駒の個數(shù)を數(shù)える 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 駒 盤面の範(fàn)囲外の場合は<code>ReversiBoard.EMPTY</code> */int ReversiBoard::getPiece(int x, int y) { // x, yの範(fàn)囲をチェック if (!checkRange(x, y)) return EMPTY; // 駒を返す return board[x][y];}/** * 指定された位置の駒を返す * @param point 駒の位置 * @return 駒 盤面の範(fàn)囲外の場合は<code>ReversiBoard.EMPTY</code> */int ReversiBoard::getPiece(Point2D* point) { return getPiece(point->x, point->y);}/** * 現(xiàn)在の手番のプレイヤーを返す<code>ReversiBoard.EMPTY</code>を返したときは勝負(fù)の決著がついている狀態(tài)<BR> * @return 現(xiàn)在の手番のプレイヤー <code>ReversiBoard.BLACK, WHITE, EMPTY</code> */int ReversiBoard::getCurrentHand() const { return this->currentHand;}/** * 指定された位置に駒を置く。<BR> * 駒が置けた場合、置いた場所を示す。<BR> * <code>Point2D</code>がnotifyObserversで<BR> * 監(jiān)視元に通知される * @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; // 裏返すことのできる駒數(shù) // 現(xiàn)在の手と照合 if (currentHand != piece) return false; // 前手が完全に終了したかどうかをチェック if (existNotReversedPieces()) return false; // そこに置けるかどうかを調(diào)べる 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で監(jiān)視元に通知される * 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;}/** * 現(xiàn)在ターンを返す * @return 現(xiàn)在ターン */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 裏返せる駒數(shù) */int ReversiBoard::countReversiblePieces(int x, int y, int piece) { int result = 0; // x, yの範(fàn)囲をチェック 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() { // 現(xiàn)在ターンを設(shè)定 this->turn = 0; // 先手は黒 this->currentHand = BLACK; // 盤面を空にする for (int x = 0; x < BOARDW; x++) { for (int y = 0; y < BOARDH; y++) board[x][y] = EMPTY; } // 初期狀態(tài)で置かれている駒をセット 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の範(fàn)囲をチェック 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)の方向へ裏返せる駒數(shù)を數(shù)える * 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)); // 駒數(shù)インクリメント 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の範(fàn)囲をチェック 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; // 駒の個數(shù)を數(shù)える for (int x = 0; x < BOARDW; x++) { for (int y = 0; y < BOARDH; y++) { result += countReversiblePieces(x, y, piece); } } return result > 0;}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -