From 4f0d7a9012d8900dbea8035c8b0a38f2d6436a70 Mon Sep 17 00:00:00 2001 From: Alexey Mostovoy <1931904+AMurkin@users.noreply.github.com> Date: Mon, 27 Apr 2020 20:35:33 +0400 Subject: [PATCH] Refactor iuse_software_lightson Use points instead of int pairs, point arithmetics. Several helper methods added. --- src/iuse_software_lightson.cpp | 83 ++++++++++++++++++++-------------- src/iuse_software_lightson.h | 13 ++++-- 2 files changed, 58 insertions(+), 38 deletions(-) diff --git a/src/iuse_software_lightson.cpp b/src/iuse_software_lightson.cpp index a91c901c21589..87708ff8f6ac1 100644 --- a/src/iuse_software_lightson.cpp +++ b/src/iuse_software_lightson.cpp @@ -23,10 +23,10 @@ void lightson_game::new_level() const int half_perimeter = rng( 8, 11 ); const int lvl_width = rng( 4, 6 ); const int lvl_height = half_perimeter - lvl_width; - level_size = std::make_pair( lvl_height, lvl_width ); + level_size = point( lvl_width, lvl_height ); level.resize( lvl_height * lvl_width ); - const int steps_rng = half_perimeter / 2.0 + rng_float( 0, 2 ); + const int steps_rng = half_perimeter / 2.0 + rng_float( 0.0, 2.0 ); generate_change_coords( steps_rng ); reset_level(); @@ -37,26 +37,41 @@ void lightson_game::reset_level() std::fill( level.begin(), level.end(), true ); // change level - std::for_each( change_coords.begin(), change_coords.end(), [this]( std::pair &p ) { - this->position = std::make_pair( p.first, p.second ); - toggle_lights(); + std::for_each( change_coords.begin(), change_coords.end(), [this]( point & p ) { + toggle_lights_at( p ); } ); - position = std::make_pair( 0, 0 ); + position = point_zero; werase( w ); draw_border( w ); } +bool lightson_game::get_value_at( const point &pt ) +{ + return level[pt.y * level_size.x + pt.x]; +} + +void lightson_game::set_value_at( const point &pt, bool value ) +{ + level[pt.y * level_size.x + pt.x] = value; +} + +void lightson_game::toggle_value_at( const point &pt ) +{ + set_value_at( pt, !get_value_at( pt ) ); +} + void lightson_game::draw_level() { - for( int i = 0; i < level_size.first; i++ ) { - for( int j = 0; j < level_size.second; j++ ) { - bool selected = position.first == i && position.second == j; - bool on = level[i * level_size.second + j]; + for( int i = 0; i < level_size.y; i++ ) { + for( int j = 0; j < level_size.x; j++ ) { + point current = point( j, i ); + bool selected = position == current; + bool on = get_value_at( current ); const nc_color fg = on ? c_white : c_dark_gray; const char symbol = on ? '#' : '-'; - mvwputch( w, point( j + 1, i + 1 ), selected ? hilite( c_white ) : fg, symbol ); + mvwputch( w, current + point_south_east, selected ? hilite( c_white ) : fg, symbol ); } } wrefresh( w ); @@ -65,16 +80,15 @@ void lightson_game::draw_level() void lightson_game::generate_change_coords( int changes ) { change_coords.resize( changes ); - const int size = level_size.first * level_size.second; + const int size = level_size.y * level_size.x; - std::pair< int, int > candidate; + point candidate; for( int k = 0; k < changes; k++ ) { do { const int candidate_index = rng( 0, size - 1 ); - const int col = candidate_index % level_size.second; - const int row = ( candidate_index - col ) / level_size.second; - candidate = std::make_pair( row, col ); + candidate.x = candidate_index % level_size.x; + candidate.y = ( candidate_index - candidate.x ) / level_size.x; // not accept repeatable coordinates } while( !( k == 0 || std::find( change_coords.begin(), change_coords.end(), candidate ) == change_coords.end() ) ); @@ -91,24 +105,25 @@ bool lightson_game::check_win() void lightson_game::toggle_lights() { - const int row = position.first; - const int col = position.second; - const int height = level_size.first; - const int width = level_size.second; + toggle_lights_at( position ); +} + +void lightson_game::toggle_lights_at( const point &pt ) +{ + toggle_value_at( pt ); - if( row > 0 ) { - level[( row - 1 ) * width + col] = !level[( row - 1 ) * width + col]; // N + if( pt.y > 0 ) { + toggle_value_at( pt + point_north ); } - level[row * width + col] = !level[row * width + col]; // x - if( row < height - 1 ) { - level[( row + 1 ) * width + col] = !level[( row + 1 ) * width + col]; // S + if( pt.y < level_size.y - 1 ) { + toggle_value_at( pt + point_south ); } - if( col > 0 ) { - level[row * width + ( col - 1 )] = !level[row * width + ( col - 1 )]; // W + if( pt.x > 0 ) { + toggle_value_at( pt + point_west ); } - if( col < width - 1 ) { - level[row * width + ( col + 1 )] = !level[row * width + ( col + 1 )]; // E + if( pt.x < level_size.x - 1 ) { + toggle_value_at( pt + point_east ); } } @@ -129,9 +144,9 @@ int lightson_game::start_game() ctxt.register_action( "QUIT" ); std::vector shortcuts; - shortcuts.push_back( _( " toggle lights" ) ); // '5': toggle - shortcuts.push_back( _( "eset" ) ); // 'r': reset - shortcuts.push_back( _( "uit" ) ); // 'q': quit + shortcuts.push_back( _( " toggle lights" ) ); + shortcuts.push_back( _( "eset" ) ); + shortcuts.push_back( _( "uit" ) ); int iWidth = 0; for( auto &shortcut : shortcuts ) { @@ -168,8 +183,8 @@ int lightson_game::start_game() } std::string action = ctxt.handle_input(); if( const cata::optional vec = ctxt.get_direction( action ) ) { - position.first = std::min( std::max( position.first + vec->y, 0 ), level_size.first - 1 ); - position.second = std::min( std::max( position.second + vec->x, 0 ), level_size.second - 1 ); + position.y = clamp( position.y + vec->y, 0, level_size.y - 1 ); + position.x = clamp( position.x + vec->x, 0, level_size.x - 1 ); } else if( action == "TOGGLE_SPACE" || action == "TOGGLE_5" ) { toggle_lights(); win = check_win(); diff --git a/src/iuse_software_lightson.h b/src/iuse_software_lightson.h index f4b4f7c7e7a11..0de4a57ef835b 100644 --- a/src/iuse_software_lightson.h +++ b/src/iuse_software_lightson.h @@ -6,6 +6,7 @@ #include #include "cursesdef.h" +#include "point.h" class lightson_game { @@ -13,11 +14,11 @@ class lightson_game catacurses::window w_border; catacurses::window w; // rows, columns - std::pair< int, int > level_size; - std::vector< bool > level; - std::vector< std::pair< int, int > > change_coords; + point level_size; + std::vector level; + std::vector change_coords; // row, column - std::pair< int, int > position; + point position; bool win; void new_level(); @@ -26,6 +27,10 @@ class lightson_game void draw_level(); bool check_win(); void toggle_lights(); + void toggle_lights_at( const point &pt ); + bool get_value_at( const point &pt ); + void set_value_at( const point &pt, bool value ); + void toggle_value_at( const point &pt ); public: int start_game();