1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 01:07:36 +00:00

Hearts: Add support for playing more than one hand

This changes the game so that more than one hand can be played. Once
one player has 100 or more points the game ends. A score card is shown
between each hand.

Fixes #7374.
This commit is contained in:
Gunnar Beutner 2021-05-24 22:54:47 +02:00 committed by Andreas Kling
parent e636ed43eb
commit 87ace131bc
6 changed files with 226 additions and 33 deletions

View file

@ -0,0 +1,89 @@
/*
* Copyright (c) 2021, Gunnar Beutner <gbeutner@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "ScoreCard.h"
#include <LibGUI/Button.h>
#include <LibGUI/Painter.h>
#include <LibGUI/Window.h>
#include <LibGfx/Font.h>
namespace Hearts {
ScoreCard::ScoreCard(Player (&players)[4], bool game_over)
: m_players(players)
, m_game_over(game_over)
{
set_min_size(recommended_size());
resize(recommended_size());
}
Gfx::IntSize ScoreCard::recommended_size()
{
auto& card_font = font().bold_variant();
return Gfx::IntSize {
4 * column_width + 3 * cell_padding,
16 * card_font.glyph_height() + 15 * cell_padding
};
}
void ScoreCard::paint_event(GUI::PaintEvent& event)
{
GUI::Widget::paint_event(event);
GUI::Painter painter(*this);
painter.add_clip_rect(frame_inner_rect());
painter.add_clip_rect(event.rect());
auto& font = painter.font().bold_variant();
auto cell_rect = [this, &font](int x, int y) {
return Gfx::IntRect {
frame_inner_rect().left() + x * column_width + x * cell_padding,
frame_inner_rect().top() + y * font.glyph_height() + y * cell_padding,
column_width,
font.glyph_height(),
};
};
VERIFY(!m_players[0].scores.is_empty());
int leading_score = -1;
for (size_t player_index = 0; player_index < 4; player_index++) {
auto& player = m_players[player_index];
auto cumulative_score = player.scores[player.scores.size() - 1];
if (leading_score == -1 || cumulative_score < leading_score)
leading_score = cumulative_score;
}
for (int player_index = 0; player_index < 4; player_index++) {
auto& player = m_players[player_index];
auto cumulative_score = player.scores[player.scores.size() - 1];
auto leading_color = m_game_over ? Color::Magenta : Color::Blue;
auto text_color = cumulative_score == leading_score ? leading_color : Color::Black;
dbgln("text_rect: {}", cell_rect(player_index, 0));
painter.draw_text(cell_rect(player_index, 0),
player.name,
font, Gfx::TextAlignment::Center,
text_color);
for (int score_index = 0; score_index < (int)player.scores.size(); score_index++) {
auto text_rect = cell_rect(player_index, 1 + score_index);
auto score_text = String::formatted("{}", player.scores[score_index]);
auto score_text_width = font.width(score_text);
if (score_index != (int)player.scores.size() - 1) {
painter.draw_line(
{ text_rect.left() + text_rect.width() / 2 - score_text_width / 2 - 3, text_rect.top() + font.glyph_height() / 2 },
{ text_rect.right() - text_rect.width() / 2 + score_text_width / 2 + 3, text_rect.top() + font.glyph_height() / 2 },
text_color);
}
painter.draw_text(text_rect,
score_text,
font, Gfx::TextAlignment::Center,
text_color);
}
}
}
}