[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 ,如需转载请自行联系原博主。

相关文章
|
网络协议 Unix 应用服务中间件
Nginx极简实战—Nginx服务器高性能优化配置,轻松实现10万并发访问量
如何使Nginx轻松实现10万并发访问量。通常来说,一个正常的 Nginx Linux 服务器可以达到 500,000 – 600,000 次/秒 的请求处理性能,如果Nginx服务器经过优化的话,则可以稳定地达到 904,000 次/秒 的处理性能,大大提高Nginx的并发访问量。
Nginx极简实战—Nginx服务器高性能优化配置,轻松实现10万并发访问量
|
小程序 开发者
微信小程序实现俄罗斯方块
微信小程序实现俄罗斯方块
741 0
|
6月前
|
人工智能 自然语言处理 负载均衡
排期延误预警:用AI预测项目风险的3层模型搭建教程
本文介绍了如何通过 AI 智能排期将项目排期误差减少 40% 以上。文章剖析了传统排期中常见的经验依赖、资源冲突、需求变更和进度滞后四大痛点,提出 AI 排期的三步落地方法:历史数据建模、动态适配需求、资源智能匹配,并推荐适配不同团队的 AI 排期工具。强调 AI 是辅助而非替代,核心在于用数据驱动提升排期准确性,帮助团队告别“拍脑袋估期”,实现高效、可控的项目管理。
排期延误预警:用AI预测项目风险的3层模型搭建教程
|
9月前
|
Docker 容器
在openEuler 22.03 LTS上安装Docker CE和Docker Compose
以上就是在openEuler 22.03 LTS上安装Docker CE和Docker Compose的过程。希望这个指南能帮助你顺利完成安装。
2285 12
|
11月前
|
人工智能 负载均衡 调度
COMET:字节跳动开源MoE训练加速神器,单层1.96倍性能提升,节省百万GPU小时
COMET是字节跳动推出的针对Mixture-of-Experts(MoE)模型的优化系统,通过细粒度的计算-通信重叠技术,显著提升分布式训练效率,支持多种并行策略和大规模集群部署。
688 9
【Java基础面试三十四】、接口中可以有构造函数吗?
这篇文章讨论了Java中接口不能包含构造函数的原因,主要解释了接口中的成员变量默认是public static final类型的常量,不需要通过构造函数初始化,且接口本身不能被实例化,因此构造函数在接口中没有意义。
|
10月前
|
机器学习/深度学习 人工智能 安全
从攻防演练到AI防护:网络安全服务厂商F5的全方位安全策略
从攻防演练到AI防护:网络安全服务厂商F5的全方位安全策略
305 8
|
11月前
|
人工智能
替代你的不是AI,而是会使用AI的人——生成式人工智能(GAI)认证成为职场新宠
在AI技术飞速发展的数字化时代,职场环境正经历深刻变革。生成式人工智能(GAI)认证的出现,为职场人士提供了提升自我、证明能力的新途径。由培生推出的GAI认证,涵盖核心技能与伦理知识,助力求职者脱颖而出。它不仅是职场晋升的加速器,还为企业认可的专业能力背书。拥抱AI、学习AI,通过GAI认证,让自己成为掌握AI技术的领先者,在竞争中保持优势。
|
弹性计算 运维 安全
自动化AutoTalk第十五期:自动化场景-多账号自动化场景下的AK管理方案
自动化AutoTalk第十五期探讨了多账号自动化场景下的AK管理方案。主要介绍了通过阿里云的实例角色和STS Token减少AK暴露风险,避免硬编码AK带来的安全隐患。最佳实践包括定期轮转AK、使用临时Token、分环境管理凭据,以及利用ECS实例角色实现安全的跨账号资源操作,确保在多账号架构中提升自动化程序的安全性和管理效率。
328 7