Skip to content
This repository has been archived by the owner on Jul 7, 2024. It is now read-only.

Commit

Permalink
refactor: refactor some code
Browse files Browse the repository at this point in the history
  • Loading branch information
ShenMian committed Mar 31, 2023
1 parent f8a348c commit 656c183
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 85 deletions.
161 changes: 83 additions & 78 deletions src/board.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,27 +17,15 @@ enum class Chess
class Board
{
public:
Board(sf::Vector2i size = {15, 15}) : size_(size) { reset(); }

/**
* @brief 将棋盘绘制在指定的窗口中.
*
* @param window 窗口.
*/
void draw(sf::RenderWindow& window) const
{
draw_board(window);
draw_chesses(window);
draw_mark(window);
}
Board(const sf::Vector2i& size = {15, 15}) : size_(size) { reset(); }

/**
* @brief 在指定位置下棋.
*
* @param position 落子位置.
* @param chess 棋子类型.
*/
void place_chess(sf::Vector2i position, Chess chess)
void place(const sf::Vector2i& position, Chess chess)
{
board_[position.x][position.y] = chess;
if(chess != Chess::Black && chess != Chess::White)
Expand All @@ -49,7 +37,7 @@ class Board
{
if(histories_.empty())
return;
place_chess(histories_.back(), Chess::Null);
place(histories_.back(), Chess::Null);
histories_.pop_back();
}

Expand All @@ -65,19 +53,19 @@ class Board
*
* @return 若存在则返回连成一线的五子, 否则返回空.
*/
std::optional<std::vector<sf::Vector2i>> get_five_in_a_row(sf::Vector2i position)
std::optional<std::vector<sf::Vector2i>> get_five_in_a_row(const sf::Vector2i& position) const
{
const Chess chess = board_[position.x][position.y];

const sf::Vector2i directions[8] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}, {-1, -1}, {1, 1}, {-1, 1}, {1, -1}};
for(int i = 0; i < 8; i += 2)
for(int direction_index = 0; direction_index < 8; direction_index += 2)
{
std::vector<sf::Vector2i> chesses;

auto add_chesses_on_direction = [&](sf::Vector2i direction) {
for(int j = 1; j <= 4; j++)
auto add_chesses_on_direction = [&](const sf::Vector2i& direction) {
for(int i = 1; i <= 4; i++)
{
const sf::Vector2i pos = position + direction * j;
const sf::Vector2i pos = position + direction * i;
if(pos.x < 0 || pos.x >= size_.x || pos.y < 0 || pos.y >= size_.y)
break;

Expand All @@ -88,8 +76,8 @@ class Board
}
};

add_chesses_on_direction(directions[i]);
add_chesses_on_direction(directions[i + 1]);
add_chesses_on_direction(directions[direction_index]);
add_chesses_on_direction(directions[direction_index + 1]);

if(chesses.size() >= 4)
{
Expand All @@ -102,13 +90,16 @@ class Board
}

/**
* @brief 获取指定位置的棋子.
*
* @param position 要获取棋子的位置.
* @brief 将棋盘绘制在指定的窗口中.
*
* @return 返回棋子.
* @param window 窗口.
*/
Chess get_chess(sf::Vector2i position) const { return board_[position.x][position.y]; }
void draw(sf::RenderWindow& window) const
{
draw_board(window);
draw_chesses(window);
draw_mark(window);
}

/**
* @brief 重置棋盘.
Expand All @@ -123,6 +114,15 @@ class Board
histories_.clear();
}

/**
* @brief 获取指定位置的棋子.
*
* @param position 要获取棋子的位置.
*
* @return 返回棋子.
*/
Chess get_chess(const sf::Vector2i& position) const { return board_[position.x][position.y]; }

/**
* @brief 将窗口坐标转为棋盘坐标.
*
Expand All @@ -143,6 +143,16 @@ class Board
return position;
}

/**
* @brief 将棋盘坐标转为窗口坐标.
*
* @return 返回对应的窗口坐标.
*/
sf::Vector2f board_to_window_position(const sf::Vector2f& position) const noexcept
{
return {position_.x + position.x * chess_offset_, position_.y + position.y * chess_offset_};
}

const auto& position() const noexcept { return position_; }
const auto& size() const noexcept { return size_; }

Expand All @@ -159,27 +169,54 @@ class Board
board_shape.setPosition(position_);
window.draw(board_shape);

sf::RectangleShape horizontal_line(sf::Vector2f((size_.x - 1) * chess_offset_, line_thickness));
sf::RectangleShape horizontal_line({(size_.x - 1) * chess_offset_, line_thickness});
horizontal_line.setOrigin(0, horizontal_line.getSize().y / 2);
horizontal_line.setFillColor(sf::Color::Black);
for(int y = 0; y < size_.y; y++)
{
horizontal_line.setPosition(board_to_window_position(sf::Vector2f(0, y)));
horizontal_line.setPosition(board_to_window_position({0.f, static_cast<float>(y)}));
window.draw(horizontal_line);
}

sf::RectangleShape vertical_line(sf::Vector2f(line_thickness, (size_.y - 1) * chess_offset_));
sf::RectangleShape vertical_line({line_thickness, (size_.y - 1) * chess_offset_});
vertical_line.setOrigin(vertical_line.getSize().x / 2, 0);
vertical_line.setFillColor(sf::Color::Black);
for(int x = 0; x < size_.x; x++)
{
vertical_line.setPosition(board_to_window_position(sf::Vector2f(x, 0)));
vertical_line.setPosition(board_to_window_position({static_cast<float>(x), 0.f}));
window.draw(vertical_line);
}

draw_stars(window);
}

/**
* @brief 绘制天元和星.
*/
void draw_stars(sf::RenderWindow& window) const
{
sf::CircleShape star(5.f, 10);
star.setOrigin(star.getRadius(), star.getRadius());
star.setFillColor(sf::Color::Black);

// 绘制星
star.setPosition(board_to_window_position({3.f, 3.f}));
window.draw(star);

star.setPosition(board_to_window_position({size_.x - 4.f, 3.f}));
window.draw(star);

star.setPosition(board_to_window_position({3.f, size_.y - 4.f}));
window.draw(star);

star.setPosition(board_to_window_position({size_.x - 4.f, size_.y - 4.f}));
window.draw(star);

// 绘制天元
star.setPosition(board_to_window_position({(size_.x - 1.f) / 2.f, (size_.y - 1.f) / 2.f}));
window.draw(star);
}

void draw_chesses(sf::RenderWindow& window) const
{
for(int y = 0; y < board_.size(); y++)
Expand All @@ -188,36 +225,18 @@ class Board
draw_chess(window, {x, y}, board_[x][y]);
}

/**
* @brief 绘制最后落子标记.
*
* @param window 要绘制的窗口.
*/
void draw_mark(sf::RenderWindow& window) const
{
if(histories_.empty())
return;
if(histories_.back().x < 0 || histories_.back().y < 0)
return;
sf::CircleShape mark(chess_diameter_ / 4.f / 2.f, 3);
mark.setOrigin(mark.getRadius(), mark.getRadius());
mark.setPosition(board_to_window_position(sf::Vector2f(histories_.back())));
mark.setFillColor(sf::Color::Red);
window.draw(mark);
}

/**
* @brief 绘制棋子.
*
* @param window 要绘制的窗口.
* @param position 棋子的位置.
* @param chess 棋子.
*/
void draw_chess(sf::RenderWindow& window, sf::Vector2i position, Chess chess) const
void draw_chess(sf::RenderWindow& window, const sf::Vector2i& position, Chess chess) const
{
sf::CircleShape chess_shape(chess_diameter_ / 2.f, 50);
chess_shape.setOrigin(chess_shape.getRadius(), chess_shape.getRadius());
chess_shape.setPosition(board_to_window_position(sf::Vector2f(position.x, position.y)));
chess_shape.setPosition(board_to_window_position({static_cast<float>(position.x), static_cast<float>(position.y)}));

switch(chess)
{
Expand All @@ -241,35 +260,21 @@ class Board
}

/**
* @brief 绘制天元和星.
* @brief 绘制最后落子标记.
*
* @param window 要绘制的窗口.
*/
void draw_stars(sf::RenderWindow& window) const
{
sf::CircleShape star(5.f, 10);
star.setOrigin(star.getRadius(), star.getRadius());
star.setFillColor(sf::Color::Black);

// 绘制星
star.setPosition(board_to_window_position({3.f, 3.f}));
window.draw(star);

star.setPosition(board_to_window_position({size_.x - 4.f, 3.f}));
window.draw(star);

star.setPosition(board_to_window_position({3.f, size_.y - 4.f}));
window.draw(star);

star.setPosition(board_to_window_position({size_.x - 4.f, size_.y - 4.f}));
window.draw(star);

// 绘制天元
star.setPosition(board_to_window_position({(size_.x - 1.f) / 2.f, (size_.y - 1.f) / 2.f}));
window.draw(star);
}

sf::Vector2f board_to_window_position(sf::Vector2f position) const noexcept
void draw_mark(sf::RenderWindow& window) const
{
return {position_.x + position.x * chess_offset_, position_.y + position.y * chess_offset_};
if(histories_.empty())
return;
if(histories_.back().x < 0 || histories_.back().y < 0)
return;
sf::CircleShape mark(chess_diameter_ / 4.f / 2.f, 3);
mark.setOrigin(mark.getRadius(), mark.getRadius());
mark.setPosition(board_to_window_position(sf::Vector2f(histories_.back())));
mark.setFillColor(sf::Color::Red);
window.draw(mark);
}

std::vector<std::vector<Chess>> board_;
Expand Down
14 changes: 7 additions & 7 deletions src/gomoku.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ class Gomoku
sf::Vector2i position;
packet >> position;

board_.place_chess(position, chess_ == Chess::Black ? Chess::White : Chess::Black);
board_.place(position, chess_ == Chess::Black ? Chess::White : Chess::Black);

status_ = Status::Ready;
handle_over(position);
Expand Down Expand Up @@ -187,7 +187,7 @@ class Gomoku

void reset()
{
status_ = Status::Initial;
status_ = Status::Initial;
chess_ = Chess::Null;
cursor_position_ = board_.size() / 2;
board_.reset();
Expand All @@ -198,7 +198,7 @@ class Gomoku
sf::CircleShape cursor(40 / 2.f, 50);
cursor.setOrigin(cursor.getRadius(), cursor.getRadius());
cursor.setFillColor(sf::Color(255 / 2, 255 / 2, 255 / 2, 150));
cursor.setPosition(board_.position().x + cursor_position_.x * 46, board_.position().y + cursor_position_.y * 46);
cursor.setPosition(board_.board_to_window_position(sf::Vector2f(cursor_position_)));
window_.draw(cursor);
}

Expand All @@ -209,7 +209,7 @@ class Gomoku
window_.close();
}

void handle_over(sf::Vector2i position)
void handle_over(const sf::Vector2i& position)
{
if(board_.is_full())
{
Expand All @@ -231,8 +231,8 @@ class Gomoku
for(int i = 0; i < 10; i++)
{
for(const auto& pos : chesses.value())
board_.place_chess(pos, i % 2 == 0 ? Chess::Green : winner_chess);
board_.place_chess(position, i % 2 == 0 ? Chess::Green : winner_chess);
board_.place(pos, i % 2 == 0 ? Chess::Green : winner_chess);
board_.place(position, i % 2 == 0 ? Chess::Green : winner_chess);

window_.clear(sf::Color(242, 208, 75));
board_.draw(window_);
Expand Down Expand Up @@ -304,7 +304,7 @@ class Gomoku
if(chess_ == Chess::Null)
chess_ = Chess::Black;

board_.place_chess(cursor_position_, chess_);
board_.place(cursor_position_, chess_);

return true;
}
Expand Down

0 comments on commit 656c183

Please sign in to comment.