开发者社区> 李博 bluemind> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

[CareerCup] 8.8 Othello Game 黑白棋游戏

简介:
+关注继续查看

8.8 Othello is played as follows: Each Othello piece is white on one side and black on the other. When a piece is surrounded by its opponents on both the left and right sides, or both the top and bottom, it is said to be captured and its color is flipped. On your turn, you must capture at least one of your opponent's pieces. The game ends when either user has no more valid moves. The win is assigned to the person with the most pieces. Implement the object-oriented design for Othello.

这道题是经典的黑白棋游戏,我最早接触到这个游戏是在文曲星上,当年文曲星很火的时候,上面的各种游戏我都爱不释手啊,什么英雄坛说,华容道,汉诺塔啊,黑白棋啊都是我常玩的游戏,尤其这道黑白棋,总是玩不过困难模式的电脑,后来想想玩不过也应该,电脑应该可以把所有可以走的步骤都计算一遍,每次都选择最优的解,下不赢电脑也很正常嘛。今天才算深入了解这个游戏的设计原理啊,可参见下面代码:

enum Direction { Left, Right, Up, Down };
enum Color { White, Black };
class Piece {
public:
    Piece(Color c): _color(c) {}
    void flip() {
        if (_color == Color::Black) _color = Color::White;
        else _color = Color::Black;
    }
    Color getColor() { return _color; }

private:
    Color _color;
};

class Location {
public:
    Location(int r, int c): _row(r), _col(c) {}
    bool isSameAs(int r, int c) {
        return _row == r && _col == c;
    }
    int getRow() { return _row; }
    int getCol() { return _col; }
    
private:
    int _row;
    int _col;
};

class Board {
public:
    Board(int rows, int cols) {
        _board.resize(rows, vector<Piece*>(cols));
    }
    void initialize() {
        int midRow = _board.size() / 2;
        int midCol = _board[midRow].size() / 2;
        _board[midRow][midCol] = new Piece(Color::White);
        _board[midRow + 1][midCol] = new Piece(Color::Black);
        _board[midRow + 1][midCol + 1] = new Piece(Color::White);
        _board[midRow][midCol + 1] = new Piece(Color::Black);
        _blackCnt = 2;
        _whiteCnt = 2;
    } 
    bool placeColor(int row, int col, Color color) {
        if (_board[row][col] != nullptr) {
            return false;
        }
        vector<int> res(4, 0);
        res[0] = flipSection(row - 1, col, color, Direction::Up);
        res[1] = flipSection(row + 1, col, color, Direction::Down);
        res[2] = flipSection(row, col + 1, color, Direction::Right);
        res[3] = flipSection(row, col - 1, color, Direction::Left);
        int flipped = 0;
        for (auto a : res) {
            if (a > 0) flipped += a;
        }
        if (flipped < 0) return false;
        _board[row][col] = new Piece(color);
        updateScore(color, flipped + 1);
        return true;
    } 
    int getScoreForColor(Color c) {
        if (c == Color::Black) return _blackCnt;
        else return _whiteCnt;
    }
    void updateScore(Color newColor, int newPieces) {
        if (newColor == Color::Black) {
            _whiteCnt -= newPieces - 1;
            _blackCnt += newPieces;
        } else {
            _blackCnt -= newPieces - 1;
            _whiteCnt += newPieces;
        }
    } 
    void printBoard() {
        for (int r = 0; r < _board.size(); ++r) {
            for (int c = 0; c < _board[r].size(); ++c) {
                if (_board[r][c] == nullptr) {
                    cout << "_";
                } else if (_board[r][c]->getColor() == Color::White) {
                    cout << "W";
                } else {
                    cout << "B";
                }
            }
            cout << endl;
        }
    }

private:
    int _blackCnt = 0;
    int _whiteCnt = 0;
    vector<vector<Piece*> > _board;
    int flipSection(int row, int col, Color color, Direction d) {
        int r = 0, c = 0;
        switch (d) {
            case Direction::Up: r = -1; break;
            case Direction::Down: r = 1; break;
            case Direction::Left: c = -1; break;
            case Direction::Right: c = 1; break;
        }
        if (row < 0 || row >= _board.size() || col < 0 || col >= _board[row].size() || _board[row][col] == nullptr) {
            return -1;
        }
        if (_board[row][col]->getColor() == color) {
            return 0;
        }
        int flipped = flipSection(row + r, col + c, color, d);
        if (flipped < 0) return -1;
        _board[row][col]->flip();
        return flipped + 1;
    } 
};

class Player {
public:
    Player(Color c): _color(c) {}
    int getScore() {
    
    } // ...
    bool playPiece(int r, int c) {
        return Game::getInstance()->getBoard()->placeColor(r, c, _color);
    }

private:
    Color _color;
};

class Game {
public:
    static Game* getInstance() {
        if (_instance == nullptr) {
            _instance = new Game();
        }
        return _instance;
    }
    Board* getBoard() { return _board; }

private:
    vector<Player*> _players;
    static Game *_instance;
    Board *_board;
    const int _ROWS = 10;
    const int _COLUMNS = 10;
    Game() {
        _board = new Board(_ROWS, _COLUMNS);
        _players.resize(2, nullptr);
        _players[0] = new Player(Color::Black);
        _players[1] = new Player(Color::White);
    }
};

本文转自博客园Grandyang的博客,原文链接:黑白棋游戏[CareerCup] 8.8 Othello Game ,如需转载请自行联系原博主。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
LeetCode 390. Elimination Game
给定一个从1 到 n 排序的整数列表。 首先,从左到右,从第一个数字开始,每隔一个数字进行删除,直到列表的末尾。 第二步,在剩下的数字中,从右到左,从倒数第一个数字开始,每隔一个数字进行删除,直到列表开头。 我们不断重复这两步,从左到右和从右到左交替进行,直到只剩下一个数字。 返回长度为 n 的列表中,最后剩下的数字。
0 0
+关注
李博 bluemind
云栖社区Java、Redis、MongoDB运营小编,有意合作请联系钉钉:15810436147
文章
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载