<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Game of Life (naive Implementierung)]]></title><description><![CDATA[<p>Naive Implementierung des Game of Life. Mags mir bitte jemand um die Ohren hauen?</p>
<pre><code>#include &lt;cstddef&gt;
#include &lt;stdexcept&gt;
#include &lt;algorithm&gt;
#include &lt;chrono&gt;
#include &lt;random&gt;
#include &lt;array&gt;
#include &lt;vector&gt;
#include &lt;string&gt;
#include &lt;sstream&gt;
#include &lt;iostream&gt;

#include &lt;tchar.h&gt;
#include &lt;conio.h&gt;

#define _WIN32_WINNT 0x0500
#define WIN32_LEAN_AND_MEAN 
#define NOMINMAX
#include &lt;windows.h&gt;

class console_t {

	HWND      window_handle;
	HANDLE    output_handle;

	unsigned  max_width;
	unsigned  max_height;

	unsigned  width;
	unsigned  height;

	HANDLE    original_buffer;
	HANDLE    front_buffer;
	HANDLE    back_buffer;

	public:
		console_t();
		console_t( unsigned width, unsigned height );

		console_t( console_t const &amp; other ) = delete;
		console_t &amp; operator=( console_t other ) = delete;

		~console_t();

		unsigned get_max_width()  const { return max_width;  }
		unsigned get_max_height() const { return max_height; }

		unsigned get_width()  const { return width;  }
		unsigned get_height() const { return height; }

		void set_title( std::string const &amp; title );
		void move_window( unsigned x, unsigned y );
		void resize( unsigned new_width, unsigned new_height );
		void set_font_size( unsigned size );
		void gotoxy( unsigned x, unsigned y );

		void toggle_double_buffering();
		HANDLE get_front_buffer() const;
		HANDLE get_back_buffer() const;
		void flip();
};

console_t::console_t()
: window_handle   { GetConsoleWindow() },
  output_handle   {},
  max_width       {},
  max_height      {},
  width           {},
  height          {},
  original_buffer {},
  front_buffer    {},
  back_buffer     {}
{
	if( !window_handle ) {

		if( !AllocConsole() )
			throw std::runtime_error{ &quot;An attempt to allocate a console for this process failed!&quot; };

		window_handle = GetConsoleWindow();
	}

	output_handle = GetStdHandle( STD_OUTPUT_HANDLE );

	if( !output_handle || output_handle == INVALID_HANDLE_VALUE )
		throw std::runtime_error{ &quot;Couldn't get standard output handle!&quot; };

	COORD max_size( GetLargestConsoleWindowSize( output_handle ) );
	max_width  = max_size.X;
	max_height = max_size.Y;

	CONSOLE_SCREEN_BUFFER_INFOEX csbiex{ sizeof csbiex };
	GetConsoleScreenBufferInfoEx( output_handle, &amp;csbiex );
	width  = csbiex.srWindow.Right  - csbiex.srWindow.Left + 1;
	height = csbiex.srWindow.Bottom - csbiex.srWindow.Top  + 1;

	resize( width, height );
}

console_t::console_t( unsigned width, unsigned height )
: console_t{}
{
	resize( width, height );
}

console_t::~console_t()
{
	if( original_buffer )
		toggle_double_buffering();
}

void console_t::set_title( std::string const &amp; title )
{
	SetConsoleTitleA( title.c_str() );
}

void console_t::move_window( unsigned x, unsigned y )
{
	SetWindowPos( window_handle, nullptr, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER );
}

void console_t::resize( unsigned new_width, unsigned new_height )
{
	if( !new_width || !new_height || new_width &gt; max_width || new_height &gt; max_height )
		throw std::runtime_error{ &quot;New dimensions for console window exceed system limits!&quot; };

	CONSOLE_SCREEN_BUFFER_INFOEX csbiex{ sizeof csbiex };
	GetConsoleScreenBufferInfoEx( output_handle, &amp;csbiex );

	csbiex.srWindow.Left   = 0;
	csbiex.srWindow.Top    = 0;
	csbiex.srWindow.Right  = 1;
	csbiex.srWindow.Bottom = 1;
	SetConsoleWindowInfo( output_handle, TRUE, &amp;csbiex.srWindow );

	csbiex.dwSize.X = new_width;
	csbiex.dwSize.Y = new_height;
	SetConsoleScreenBufferInfoEx( output_handle, &amp;csbiex );

	csbiex.srWindow.Left   = 0;
	csbiex.srWindow.Top    = 0;
	csbiex.srWindow.Right  = new_width  - 1;
	csbiex.srWindow.Bottom = new_height - 1;
	SetConsoleWindowInfo( output_handle, TRUE, &amp;csbiex.srWindow );

	width  = new_width;
	height = new_height;
}

void console_t::set_font_size( unsigned size )
{
	if( size &lt; 2 )
		throw std::runtime_error{ &quot;Can't set a console font size smaller than 2!&quot; };

	CONSOLE_FONT_INFOEX cfiex{ sizeof cfiex };
	GetCurrentConsoleFontEx( GetStdHandle( STD_OUTPUT_HANDLE ), FALSE, &amp;cfiex );
	cfiex.dwFontSize.Y = size;
	SetCurrentConsoleFontEx( GetStdHandle( STD_OUTPUT_HANDLE ), FALSE, &amp;cfiex );

	COORD max_size( GetLargestConsoleWindowSize( output_handle ) );
	max_width  = max_size.X;
	max_height = max_size.Y;
}

void console_t::gotoxy( unsigned x, unsigned y )
{
	if( !SetConsoleCursorPosition( output_handle, COORD{ x, y } ) )
		throw std::runtime_error{ &quot;gotoxy() failed!&quot; };
}

void console_t::toggle_double_buffering()
{
	if( !front_buffer ) {

		front_buffer = original_buffer = CreateFile( _T( &quot;CONOUT$&quot; ), GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr );
		back_buffer = CreateConsoleScreenBuffer( GENERIC_READ | GENERIC_WRITE, 0, nullptr, CONSOLE_TEXTMODE_BUFFER, nullptr );

	} else {

		SetConsoleActiveScreenBuffer( original_buffer );
		CloseHandle( original_buffer == front_buffer ? back_buffer : front_buffer );

		original_buffer = front_buffer = back_buffer = nullptr;
	}
}

HANDLE console_t::get_front_buffer() const
{
	return front_buffer;
}

HANDLE console_t::get_back_buffer() const
{
	return back_buffer;
}

void console_t::flip()
{
	std::swap( front_buffer, back_buffer );
	SetConsoleActiveScreenBuffer( front_buffer );
}

class ruleset_t
{
	std::array&lt; std::size_t, 9 &gt;  birth;
	std::array&lt; std::size_t, 9 &gt;  survival;

	public:
		ruleset_t();
		ruleset_t( std::vector&lt; unsigned &gt; &amp; birth_neighbours,
		           std::vector&lt; unsigned &gt; &amp; survival_neighbours );

		bool dead_or_alive( bool cell, std::size_t neighbours_alive ) const;
};

ruleset_t::ruleset_t()
: birth    ( { 0, 0, 0, 1, 0, 0, 0, 0, 0 } ),  // {    3 }
  survival ( { 0, 0, 1, 1, 0, 0, 0, 0, 0 } )   // { 2, 3 }
{}

ruleset_t::ruleset_t( std::vector&lt; unsigned &gt; &amp; birth_neighbours,
                      std::vector&lt; unsigned &gt; &amp; survival_neighbours )
: birth    (),
  survival ()
{
	for( auto i : birth_neighbours )
		birth[ 1 &lt;&lt; i ] = 1;

	for( auto i : survival_neighbours )
		survival[ 1 &lt;&lt; i ] = 1;
}

bool ruleset_t::dead_or_alive( bool cell, std::size_t neighbours_alive ) const
{
	return cell &amp;&amp; survival[ neighbours_alive ] || birth[ neighbours_alive ];
}

struct point_t
{
	std::size_t x;
	std::size_t y;
};

class life_t
{
	private:
		typedef std::vector&lt; char &gt; state_t;

		std::size_t  generation;
		std::size_t  population;
		std::size_t  width;
		std::size_t  height;
		state_t      curr;
		state_t      next;
		ruleset_t	 ruleset;
		std::string  static_title_part;

		std::size_t get_moore_neighbours( std::size_t i ) const;

	public:
		life_t( std::size_t width, std::size_t height, ruleset_t const &amp; ruleset = ruleset_t() );
		void reset();

		template&lt; typename Engine &gt;
		void randomize( double probability_of_life, Engine &amp; engine )
		{
			std::bernoulli_distribution distribution( probability_of_life );
			std::transform( curr.begin(), curr.end(), curr.begin(), [&amp;]( char i ){ return distribution( engine ); } );
		}

		void iterate();
		void print( console_t &amp; console ) const;
};

life_t::life_t( std::size_t width, std::size_t height, ruleset_t const &amp; ruleset )
: generation (),
  population (),
  width      ( width ),
  height     ( height ),
  curr       ( width * height, 0 ),
  next       ( width * height, 0 ),
  ruleset    ( ruleset )
{
	std::stringstream ss{ &quot;Game of Life   [ &quot; };
	ss.seekp( 0, std::ios::end );
	ss &lt;&lt; width &lt;&lt; &quot; x &quot; &lt;&lt; height &lt;&lt; &quot; | Population: &quot;;
	static_title_part = ss.str();
}

std::size_t life_t::get_moore_neighbours( std::size_t i ) const
{
	std::size_t neighbours{};

	bool const has_top_neighbour    { i &gt;= width };
	bool const has_bottom_neighbour { i &lt; curr.size() - width };
	bool const has_left_neighbour   { i &amp;&amp; i % width };
	bool const has_right_neighbour  { ( i + 1 ) % width != 0 };

	if( has_top_neighbour ) {

		if( curr[ i - width ] )
			++neighbours;

		if( has_right_neighbour &amp;&amp; curr[ i - width + 1 ] )
			++neighbours;

		if( has_left_neighbour &amp;&amp; curr[ i - width - 1 ] )
			++neighbours;
	}

	if( has_left_neighbour &amp;&amp; curr[ i - 1 ] )
		++neighbours;

	if( has_right_neighbour &amp;&amp; curr[ i + 1 ] )
		++neighbours;

	if( has_bottom_neighbour ) {

		if( curr[ i + width ] )
			++neighbours;

		if( has_left_neighbour &amp;&amp; curr[ i + width - 1 ] )
			++neighbours;

		if( has_right_neighbour &amp;&amp; curr[ i + width + 1 ] )
			++neighbours;
	}

	return neighbours;
}

void life_t::reset()
{
	generation = 0;
	population = 0;

	std::fill( curr.begin(), curr.end(), 0 );
	std::fill( next.begin(), next.end(), 0 );
}

void life_t::iterate()
{
	population = 0;

	for( std::size_t i{}; i &lt; width * height; ++i )
		next[ i ] = ruleset.dead_or_alive( curr[ i ] != 0, get_moore_neighbours( i ) ) &amp;&amp; ++population;

	std::swap( curr, next );
	++generation;
}

void life_t::print( console_t &amp; console ) const
{
	static std::stringstream ss{};

	DWORD written;
	WriteConsoleOutputCharacterA( console.get_back_buffer(), &amp;curr[ 0 ], static_cast&lt; DWORD &gt;( curr.size() ), { 0, 0 }, &amp;written );

	ss.str( static_title_part );
	ss.seekp( 0, std::ios::end );
	ss &lt;&lt; population &lt;&lt; &quot; | Generation: &quot; &lt;&lt; generation &lt;&lt; &quot; ]&quot;;
	console.set_title( ss.str() );

	console.flip();
}

int main()
{
	try {
		console_t console{};
		console.set_font_size( 5 );
		console.resize( console.get_max_width() - 4, console.get_max_height() - 4 );
		console.move_window( 0, 0 );
		console.toggle_double_buffering();

		life_t life{ console.get_width(), console.get_height() };

		std::mt19937 random_engine{ static_cast&lt; unsigned &gt;(
			std::chrono::high_resolution_clock::now().time_since_epoch().count() ) };

		double life_chances{ 0.1 };

		life.randomize( life_chances, random_engine );

		bool run{ true };
		DWORD delay = 0;

		do {
			if( _kbhit() ) {

				switch( _getch() ) {

					case 'r':
						life.reset();
						life.randomize( life_chances, random_engine );
						break;

					case 0x20:  // space
						_ungetch( _getch() );
						break;

					case 0x1b:  // esc
						run = false;
						break;

					case '+':
						if( delay )
							delay -= 10;
						break;

					case '-':
							delay += 10;
						break;
				}

			} else {

				life.iterate();
				life.print( console );
				Sleep( delay );
			}

		} while( run );

	} catch( std::runtime_error &amp; exception ) {

		std::cerr &lt;&lt; exception.what() &lt;&lt; &quot;\n\n&quot;;
		return EXIT_FAILURE;

	} catch( ... ) {

		std::cerr &lt;&lt; &quot;An unknown error occured!\n\n&quot;;
		return EXIT_FAILURE;
	}
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/topic/328833/game-of-life-naive-implementierung</link><generator>RSS for Node</generator><lastBuildDate>Tue, 07 Jul 2026 07:58:49 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/328833.rss" rel="self" type="application/rss+xml"/><pubDate>Tue, 28 Oct 2014 19:11:06 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Game of Life (naive Implementierung) on Wed, 29 Oct 2014 18:11:35 GMT]]></title><description><![CDATA[<p>Naive Implementierung des Game of Life. Mags mir bitte jemand um die Ohren hauen?</p>
<pre><code>#include &lt;cstddef&gt;
#include &lt;stdexcept&gt;
#include &lt;algorithm&gt;
#include &lt;chrono&gt;
#include &lt;random&gt;
#include &lt;array&gt;
#include &lt;vector&gt;
#include &lt;string&gt;
#include &lt;sstream&gt;
#include &lt;iostream&gt;

#include &lt;tchar.h&gt;
#include &lt;conio.h&gt;

#define _WIN32_WINNT 0x0500
#define WIN32_LEAN_AND_MEAN 
#define NOMINMAX
#include &lt;windows.h&gt;

class console_t {

	HWND      window_handle;
	HANDLE    output_handle;

	unsigned  max_width;
	unsigned  max_height;

	unsigned  width;
	unsigned  height;

	HANDLE    original_buffer;
	HANDLE    front_buffer;
	HANDLE    back_buffer;

	public:
		console_t();
		console_t( unsigned width, unsigned height );

		console_t( console_t const &amp; other ) = delete;
		console_t &amp; operator=( console_t other ) = delete;

		~console_t();

		unsigned get_max_width()  const { return max_width;  }
		unsigned get_max_height() const { return max_height; }

		unsigned get_width()  const { return width;  }
		unsigned get_height() const { return height; }

		void set_title( std::string const &amp; title );
		void move_window( unsigned x, unsigned y );
		void resize( unsigned new_width, unsigned new_height );
		void set_font_size( unsigned size );
		void gotoxy( unsigned x, unsigned y );

		void toggle_double_buffering();
		HANDLE get_front_buffer() const;
		HANDLE get_back_buffer() const;
		void flip();
};

console_t::console_t()
: window_handle   { GetConsoleWindow() },
  output_handle   {},
  max_width       {},
  max_height      {},
  width           {},
  height          {},
  original_buffer {},
  front_buffer    {},
  back_buffer     {}
{
	if( !window_handle ) {

		if( !AllocConsole() )
			throw std::runtime_error{ &quot;An attempt to allocate a console for this process failed!&quot; };

		window_handle = GetConsoleWindow();
	}

	output_handle = GetStdHandle( STD_OUTPUT_HANDLE );

	if( !output_handle || output_handle == INVALID_HANDLE_VALUE )
		throw std::runtime_error{ &quot;Couldn't get standard output handle!&quot; };

	COORD max_size( GetLargestConsoleWindowSize( output_handle ) );
	max_width  = max_size.X;
	max_height = max_size.Y;

	CONSOLE_SCREEN_BUFFER_INFOEX csbiex{ sizeof csbiex };
	GetConsoleScreenBufferInfoEx( output_handle, &amp;csbiex );
	width  = csbiex.srWindow.Right  - csbiex.srWindow.Left + 1;
	height = csbiex.srWindow.Bottom - csbiex.srWindow.Top  + 1;

	resize( width, height );
}

console_t::console_t( unsigned width, unsigned height )
: console_t{}
{
	resize( width, height );
}

console_t::~console_t()
{
	if( original_buffer )
		toggle_double_buffering();
}

void console_t::set_title( std::string const &amp; title )
{
	SetConsoleTitleA( title.c_str() );
}

void console_t::move_window( unsigned x, unsigned y )
{
	SetWindowPos( window_handle, nullptr, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER );
}

void console_t::resize( unsigned new_width, unsigned new_height )
{
	if( !new_width || !new_height || new_width &gt; max_width || new_height &gt; max_height )
		throw std::runtime_error{ &quot;New dimensions for console window exceed system limits!&quot; };

	CONSOLE_SCREEN_BUFFER_INFOEX csbiex{ sizeof csbiex };
	GetConsoleScreenBufferInfoEx( output_handle, &amp;csbiex );

	csbiex.srWindow.Left   = 0;
	csbiex.srWindow.Top    = 0;
	csbiex.srWindow.Right  = 1;
	csbiex.srWindow.Bottom = 1;
	SetConsoleWindowInfo( output_handle, TRUE, &amp;csbiex.srWindow );

	csbiex.dwSize.X = new_width;
	csbiex.dwSize.Y = new_height;
	SetConsoleScreenBufferInfoEx( output_handle, &amp;csbiex );

	csbiex.srWindow.Left   = 0;
	csbiex.srWindow.Top    = 0;
	csbiex.srWindow.Right  = new_width  - 1;
	csbiex.srWindow.Bottom = new_height - 1;
	SetConsoleWindowInfo( output_handle, TRUE, &amp;csbiex.srWindow );

	width  = new_width;
	height = new_height;
}

void console_t::set_font_size( unsigned size )
{
	if( size &lt; 2 )
		throw std::runtime_error{ &quot;Can't set a console font size smaller than 2!&quot; };

	CONSOLE_FONT_INFOEX cfiex{ sizeof cfiex };
	GetCurrentConsoleFontEx( GetStdHandle( STD_OUTPUT_HANDLE ), FALSE, &amp;cfiex );
	cfiex.dwFontSize.Y = size;
	SetCurrentConsoleFontEx( GetStdHandle( STD_OUTPUT_HANDLE ), FALSE, &amp;cfiex );

	COORD max_size( GetLargestConsoleWindowSize( output_handle ) );
	max_width  = max_size.X;
	max_height = max_size.Y;
}

void console_t::gotoxy( unsigned x, unsigned y )
{
	if( !SetConsoleCursorPosition( output_handle, COORD{ x, y } ) )
		throw std::runtime_error{ &quot;gotoxy() failed!&quot; };
}

void console_t::toggle_double_buffering()
{
	if( !front_buffer ) {

		front_buffer = original_buffer = CreateFile( _T( &quot;CONOUT$&quot; ), GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr );
		back_buffer = CreateConsoleScreenBuffer( GENERIC_READ | GENERIC_WRITE, 0, nullptr, CONSOLE_TEXTMODE_BUFFER, nullptr );

	} else {

		SetConsoleActiveScreenBuffer( original_buffer );
		CloseHandle( original_buffer == front_buffer ? back_buffer : front_buffer );

		original_buffer = front_buffer = back_buffer = nullptr;
	}
}

HANDLE console_t::get_front_buffer() const
{
	return front_buffer;
}

HANDLE console_t::get_back_buffer() const
{
	return back_buffer;
}

void console_t::flip()
{
	std::swap( front_buffer, back_buffer );
	SetConsoleActiveScreenBuffer( front_buffer );
}

class ruleset_t
{
	std::array&lt; std::size_t, 9 &gt;  birth;
	std::array&lt; std::size_t, 9 &gt;  survival;

	public:
		ruleset_t();
		ruleset_t( std::vector&lt; unsigned &gt; &amp; birth_neighbours,
		           std::vector&lt; unsigned &gt; &amp; survival_neighbours );

		bool dead_or_alive( bool cell, std::size_t neighbours_alive ) const;
};

ruleset_t::ruleset_t()
: birth    ( { 0, 0, 0, 1, 0, 0, 0, 0, 0 } ),  // {    3 }
  survival ( { 0, 0, 1, 1, 0, 0, 0, 0, 0 } )   // { 2, 3 }
{}

ruleset_t::ruleset_t( std::vector&lt; unsigned &gt; &amp; birth_neighbours,
                      std::vector&lt; unsigned &gt; &amp; survival_neighbours )
: birth    (),
  survival ()
{
	for( auto i : birth_neighbours )
		birth[ 1 &lt;&lt; i ] = 1;

	for( auto i : survival_neighbours )
		survival[ 1 &lt;&lt; i ] = 1;
}

bool ruleset_t::dead_or_alive( bool cell, std::size_t neighbours_alive ) const
{
	return cell &amp;&amp; survival[ neighbours_alive ] || birth[ neighbours_alive ];
}

struct point_t
{
	std::size_t x;
	std::size_t y;
};

class life_t
{
	private:
		typedef std::vector&lt; char &gt; state_t;

		std::size_t  generation;
		std::size_t  population;
		std::size_t  width;
		std::size_t  height;
		state_t      curr;
		state_t      next;
		ruleset_t	 ruleset;
		std::string  static_title_part;

		std::size_t get_moore_neighbours( std::size_t i ) const;

	public:
		life_t( std::size_t width, std::size_t height, ruleset_t const &amp; ruleset = ruleset_t() );
		void reset();

		template&lt; typename Engine &gt;
		void randomize( double probability_of_life, Engine &amp; engine )
		{
			std::bernoulli_distribution distribution( probability_of_life );
			std::transform( curr.begin(), curr.end(), curr.begin(), [&amp;]( char i ){ return distribution( engine ); } );
		}

		void iterate();
		void print( console_t &amp; console ) const;
};

life_t::life_t( std::size_t width, std::size_t height, ruleset_t const &amp; ruleset )
: generation (),
  population (),
  width      ( width ),
  height     ( height ),
  curr       ( width * height, 0 ),
  next       ( width * height, 0 ),
  ruleset    ( ruleset )
{
	std::stringstream ss{ &quot;Game of Life   [ &quot; };
	ss.seekp( 0, std::ios::end );
	ss &lt;&lt; width &lt;&lt; &quot; x &quot; &lt;&lt; height &lt;&lt; &quot; | Population: &quot;;
	static_title_part = ss.str();
}

std::size_t life_t::get_moore_neighbours( std::size_t i ) const
{
	std::size_t neighbours{};

	bool const has_top_neighbour    { i &gt;= width };
	bool const has_bottom_neighbour { i &lt; curr.size() - width };
	bool const has_left_neighbour   { i &amp;&amp; i % width };
	bool const has_right_neighbour  { ( i + 1 ) % width != 0 };

	if( has_top_neighbour ) {

		if( curr[ i - width ] )
			++neighbours;

		if( has_right_neighbour &amp;&amp; curr[ i - width + 1 ] )
			++neighbours;

		if( has_left_neighbour &amp;&amp; curr[ i - width - 1 ] )
			++neighbours;
	}

	if( has_left_neighbour &amp;&amp; curr[ i - 1 ] )
		++neighbours;

	if( has_right_neighbour &amp;&amp; curr[ i + 1 ] )
		++neighbours;

	if( has_bottom_neighbour ) {

		if( curr[ i + width ] )
			++neighbours;

		if( has_left_neighbour &amp;&amp; curr[ i + width - 1 ] )
			++neighbours;

		if( has_right_neighbour &amp;&amp; curr[ i + width + 1 ] )
			++neighbours;
	}

	return neighbours;
}

void life_t::reset()
{
	generation = 0;
	population = 0;

	std::fill( curr.begin(), curr.end(), 0 );
	std::fill( next.begin(), next.end(), 0 );
}

void life_t::iterate()
{
	population = 0;

	for( std::size_t i{}; i &lt; width * height; ++i )
		next[ i ] = ruleset.dead_or_alive( curr[ i ] != 0, get_moore_neighbours( i ) ) &amp;&amp; ++population;

	std::swap( curr, next );
	++generation;
}

void life_t::print( console_t &amp; console ) const
{
	static std::stringstream ss{};

	DWORD written;
	WriteConsoleOutputCharacterA( console.get_back_buffer(), &amp;curr[ 0 ], static_cast&lt; DWORD &gt;( curr.size() ), { 0, 0 }, &amp;written );

	ss.str( static_title_part );
	ss.seekp( 0, std::ios::end );
	ss &lt;&lt; population &lt;&lt; &quot; | Generation: &quot; &lt;&lt; generation &lt;&lt; &quot; ]&quot;;
	console.set_title( ss.str() );

	console.flip();
}

int main()
{
	try {
		console_t console{};
		console.set_font_size( 5 );
		console.resize( console.get_max_width() - 4, console.get_max_height() - 4 );
		console.move_window( 0, 0 );
		console.toggle_double_buffering();

		life_t life{ console.get_width(), console.get_height() };

		std::mt19937 random_engine{ static_cast&lt; unsigned &gt;(
			std::chrono::high_resolution_clock::now().time_since_epoch().count() ) };

		double life_chances{ 0.1 };

		life.randomize( life_chances, random_engine );

		bool run{ true };
		DWORD delay = 0;

		do {
			if( _kbhit() ) {

				switch( _getch() ) {

					case 'r':
						life.reset();
						life.randomize( life_chances, random_engine );
						break;

					case 0x20:  // space
						_ungetch( _getch() );
						break;

					case 0x1b:  // esc
						run = false;
						break;

					case '+':
						if( delay )
							delay -= 10;
						break;

					case '-':
							delay += 10;
						break;
				}

			} else {

				life.iterate();
				life.print( console );
				Sleep( delay );
			}

		} while( run );

	} catch( std::runtime_error &amp; exception ) {

		std::cerr &lt;&lt; exception.what() &lt;&lt; &quot;\n\n&quot;;
		return EXIT_FAILURE;

	} catch( ... ) {

		std::cerr &lt;&lt; &quot;An unknown error occured!\n\n&quot;;
		return EXIT_FAILURE;
	}
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2424590</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2424590</guid><dc:creator><![CDATA[Swordfish]]></dc:creator><pubDate>Wed, 29 Oct 2014 18:11:35 GMT</pubDate></item><item><title><![CDATA[Reply to Game of Life (naive Implementierung) on Tue, 28 Oct 2014 22:41:37 GMT]]></title><description><![CDATA[<p>Viel Kapselung ist da nicht. live_t ruft WriteConsoleOutputCharacterA auf, nimmt aber trotzdem eine allgemeine console_t entgegen. Ausserdem sollten Simulation und Ausgabe völlig getrennt sein, was hier irgendwie nicht der Fall ist.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2424619</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2424619</guid><dc:creator><![CDATA[kapsel]]></dc:creator><pubDate>Tue, 28 Oct 2014 22:41:37 GMT</pubDate></item><item><title><![CDATA[Reply to Game of Life (naive Implementierung) on Tue, 28 Oct 2014 23:08:33 GMT]]></title><description><![CDATA[<p>Guter Punkt. Ich hab' mich da bis zum Ende noch mit mehreren Ausgabemöglichkeiten gespielt und es ist was halbgares übrig geblieben. Gehört überarbeitet.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2424620</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2424620</guid><dc:creator><![CDATA[Swordfish]]></dc:creator><pubDate>Tue, 28 Oct 2014 23:08:33 GMT</pubDate></item><item><title><![CDATA[Reply to Game of Life (naive Implementierung) on Tue, 28 Oct 2014 23:21:21 GMT]]></title><description><![CDATA[<p>Nur um sicherzugehen, kennste Golly nebst <a href="http://en.wikipedia.org/wiki/Hashlife" rel="nofollow">http://en.wikipedia.org/wiki/Hashlife</a> ?<br />
Ist einfach frech, wie er in 20 Sekunden den Status eines Brüters nach 568,369,413,039,756,162,463,293,997,882,080,960,114,807,029,482,683,105,646,244,545,020,753,710,871,466,714,894,912 Generationen berechnet hat.<br />
<img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f62e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_with_open_mouth"
      title=":open_mouth:"
      alt="😮"
    /> <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f62e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_with_open_mouth"
      title=":open_mouth:"
      alt="😮"
    /> <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f62e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_with_open_mouth"
      title=":open_mouth:"
      alt="😮"
    /> <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f62e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_with_open_mouth"
      title=":open_mouth:"
      alt="😮"
    /> <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f62e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_with_open_mouth"
      title=":open_mouth:"
      alt="😮"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2424621</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2424621</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Tue, 28 Oct 2014 23:21:21 GMT</pubDate></item><item><title><![CDATA[Reply to Game of Life (naive Implementierung) on Tue, 28 Oct 2014 23:48:23 GMT]]></title><description><![CDATA[<p>Der ctor</p>
<pre><code class="language-cpp">ruleset_t::ruleset_t( std::vector&lt; unsigned &gt; &amp; birth_neighbours,
                      std::vector&lt; unsigned &gt; &amp; survival_neighbours )
: birth    (),
  survival ()
{
    for( auto i : birth_neighbours )
        birth[ 1 &lt;&lt; i ] = 1;

    for( auto i : survival_neighbours )
        survival[ 1 &lt;&lt; i ] = 1;
}
</code></pre>
<p>ist kaputt. Behaupte ich mal. <code>1 &lt;&lt; i</code> macht hier keinen Sinn. Und nachdem es nicht Performance-kritisch ist wäre mMn. <code>.at()</code> statt <code>[]</code> angebracht.</p>
<p><code>get_moore_neighbours</code> kannst du deutlich vereinfachen, auf eine von zwei Arten:</p>
<ol>
<li>Erweitere das Array auf allen vier Seiten um je eine Zelle die immer 0 bleibt. Das würde ich machen.<br />
Oder</li>
<li>Bastel dir eine <code>at(x, y)</code> Funktion die 0 für &quot;out of bounds&quot; Zellen zurückliefert und ruf diese in der <code>get_moore_neighbours</code> auf.</li>
</ol>
<p>Der <code>&amp;&amp; ++population;</code> Trick ist grauenhaft. Ich will lieber nicht genauer darauf eingehen was ich davon halte - will dich nicht beleidigen.</p>
<p>Wenn du Output und Simulation wirklich trennen willst, dann gehört die <code>print</code> Funktion aus der <code>life_t</code> Klasse raus. Statt dessen wirst du dann irgend eine generische Möglichkeit brauchen in ein <code>life_t</code> reinzugucken bzw. das aktuelle &quot;Frame&quot; zu extrahieren.</p>
<p>Die Initialisierung von Skalaren mit <code>{...}</code> finde ich ebenso furchtbar, aber das ist ne Stilfrage, darum geht's ja weniger.</p>
<p>Und - nochmal Stil - ... was soll das <code>_t</code> als Suffix bei den Klassennamen? Verwende statt dessen lieber vernünftige Namen.<br />
<code>life_t</code> =&gt; <code>game_of_life</code><br />
<code>ruleset_t</code> =&gt; <code>game_of_life::ruleset</code><br />
<code>point_t</code> =&gt; <code>point</code><br />
<code>console_t</code> =&gt; <code>console_utility/console_window</code></p>
<p>Und dann die Variablennamen... alles sehr einsilbig. Das geht auch besser (klarer, eindeutiger, leichter zu verstehen).</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2424622</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2424622</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Tue, 28 Oct 2014 23:48:23 GMT</pubDate></item><item><title><![CDATA[Reply to Game of Life (naive Implementierung) on Wed, 29 Oct 2014 18:50:39 GMT]]></title><description><![CDATA[<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/106">@volkard</a>: ja, kenn ich natürlich <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
<p>hustbaer schrieb:</p>
<blockquote>
<p>Der ctor [ <code>ruleset()</code> ] ist kaputt. Behaupte ich mal. <code>1 &lt;&lt; i</code> macht hier keinen Sinn. [...]</p>
</blockquote>
<p>Sorry, da steh' ich auf irgendwelchen Leitungen rum ... was ist da kaputt? Bitte sag noch ein bisschen was dazu, damit mir vielleicht ein Licht aufgeht.</p>
<p>hustbaer schrieb:</p>
<blockquote>
<p>[...] Und nachdem es nicht Performance-kritisch ist wäre mMn. <code>.at()</code> statt <code>[]</code> angebracht.</p>
</blockquote>
<p>Angenommen. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f44d.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--thumbs_up"
      title=":+1:"
      alt="👍"
    /></p>
<p>hustbaer schrieb:</p>
<blockquote>
<p><code>get_moore_neighbours</code> kannst du deutlich vereinfachen, auf eine von zwei Arten:</p>
<ol>
<li>Erweitere das Array auf allen vier Seiten um je eine Zelle die immer 0 bleibt. Das würde ich machen.<br />
Oder [...]</li>
</ol>
</blockquote>
<p>Erledigt. Sieht besser aus. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f44d.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--thumbs_up"
      title=":+1:"
      alt="👍"
    /></p>
<p>hustbaer schrieb:</p>
<blockquote>
<p>Der <code>&amp;&amp; ++population;</code> Trick ist grauenhaft. Ich will lieber nicht genauer darauf eingehen was ich davon halte - will dich nicht beleidigen.</p>
</blockquote>
<p>Keine Angst, dafür könntest mich mit keiner Aussage beleidigen. Ich tipp mal auf Fehlerträchtig und bzw. weil leicht zu übersehen?<br />
In der jetzigen Version wirst mich halt für die Zuweisung im <code>if</code> haun ...</p>
<p>hustbaer schrieb:</p>
<blockquote>
<p>Wenn du Output und Simulation wirklich trennen willst, dann gehört die <code>print</code> Funktion aus der <code>life_t</code> Klasse raus. Statt dessen wirst du dann irgend eine generische Möglichkeit brauchen in ein <code>life_t</code> reinzugucken bzw. das aktuelle &quot;Frame&quot; zu extrahieren.</p>
</blockquote>
<p>Erledigt. Aber ob das nicht auch eleganter geht?</p>
<p>hustbaer schrieb:</p>
<blockquote>
<p>[...] Und dann die Variablennamen... alles sehr einsilbig. Das geht auch besser (klarer, eindeutiger, leichter zu verstehen).</p>
</blockquote>
<p>Hm. Welche sind denn besonders schlimm?</p>
<p>Aktuelle Version:</p>
<pre><code>#include &lt;cstddef&gt;
#include &lt;stdexcept&gt;
#include &lt;algorithm&gt;
#include &lt;chrono&gt;
#include &lt;random&gt;
#include &lt;array&gt;
#include &lt;vector&gt;
#include &lt;string&gt;
#include &lt;sstream&gt;
#include &lt;iostream&gt;

#define _WIN32_WINNT 0x0500
#define WIN32_LEAN_AND_MEAN 
#define NOMINMAX
#include &lt;windows.h&gt;
#include &lt;conio.h&gt;

class console_window
{
	HWND      window_handle;
	HANDLE    output_handle;
	unsigned  max_width;
	unsigned  max_height;
	unsigned  width;
	unsigned  height;
	HANDLE    original_buffer;
	HANDLE    front_buffer;
	HANDLE    back_buffer;

	public:
		console_window( console_window const &amp; )      = delete;
		console_window &amp; operator=( console_window )  = delete;

		console_window()
		: window_handle    { GetConsoleWindow() },
		  output_handle    {},
		  max_width        {},
		  max_height       {},
		  width            {},
		  height           {},
		  original_buffer  {},
		  front_buffer     {},
		  back_buffer      {}
		{
			if( !window_handle ) {

				if( !AllocConsole() )
					throw std::runtime_error{ &quot;An attempt to allocate a console for this process failed!&quot; };

				window_handle = GetConsoleWindow();
			}

			output_handle = GetStdHandle( STD_OUTPUT_HANDLE );

			if( !output_handle || output_handle == INVALID_HANDLE_VALUE )
				throw std::runtime_error{ &quot;Couldn't get standard output handle!&quot; };

			COORD max_size( GetLargestConsoleWindowSize( output_handle ) );
			max_width  = max_size.X;
			max_height = max_size.Y;

			CONSOLE_SCREEN_BUFFER_INFOEX csbiex{ sizeof csbiex };
			GetConsoleScreenBufferInfoEx( output_handle, &amp;csbiex );
			width  = csbiex.srWindow.Right  - csbiex.srWindow.Left + 1;
			height = csbiex.srWindow.Bottom - csbiex.srWindow.Top  + 1;

			resize( width, height );
		}

		console_window( unsigned width, unsigned height )
		: console_window{}
		{
			resize( width, height );
		}

		~console_window()
		{
			if( original_buffer )
				toggle_double_buffering();
		}

		unsigned get_max_width()  const { return max_width;  }
		unsigned get_max_height() const { return max_height; }

		unsigned get_width()  const { return  width; }
		unsigned get_height() const { return height; }

		void set_title( std::string const &amp; title ) { SetConsoleTitleA( title.c_str() ); }

		void move_window( unsigned x, unsigned y )
		{
			SetWindowPos( window_handle, nullptr, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER );
		}

		void resize( unsigned new_width, unsigned new_height )
		{
			if( !new_width || !new_height || new_width &gt; max_width || new_height &gt; max_height )
				throw std::runtime_error{ &quot;New dimensions for console window exceed system limits!&quot; };

			CONSOLE_SCREEN_BUFFER_INFOEX csbiex{ sizeof csbiex };
			GetConsoleScreenBufferInfoEx( output_handle, &amp;csbiex );

			csbiex.srWindow = { 0, 0, 1, 1 };
			SetConsoleWindowInfo( output_handle, TRUE, &amp;csbiex.srWindow );

			csbiex.dwSize = { new_width, new_height };
			SetConsoleScreenBufferInfoEx( output_handle, &amp;csbiex );

			csbiex.srWindow = { 0, 0, new_width - 1, new_height - 1 };
			SetConsoleWindowInfo( output_handle, TRUE, &amp;csbiex.srWindow );

			width  = new_width;
			height = new_height;
		}

		void set_font_size( unsigned size )
		{
			if( size &lt; 2 )
				throw std::runtime_error{ &quot;Can't set a console font size smaller than 2!&quot; };

			CONSOLE_FONT_INFOEX cfiex{ sizeof cfiex };
			GetCurrentConsoleFontEx( output_handle, FALSE, &amp;cfiex );

			cfiex.dwFontSize.Y = size;
			SetCurrentConsoleFontEx( output_handle, FALSE, &amp;cfiex );

			COORD max_size( GetLargestConsoleWindowSize( output_handle ) );
			max_width  = max_size.X;
			max_height = max_size.Y;
		}

		void gotoxy( unsigned x, unsigned y )
		{
			if( !SetConsoleCursorPosition( output_handle, COORD{ x, y } ) )
				throw std::runtime_error{ &quot;gotoxy() failed!&quot; };
		}

		void write_buffer( char const * buffer, std::size_t length, std::size_t x, std::size_t y )
		{
			DWORD written;
			WriteConsoleOutputCharacterA( front_buffer ? back_buffer : front_buffer,
			                              buffer, length, { x, y }, &amp;written );
		}

		bool  kbhit   ()  const { return _kbhit() != 0; }
		int   getch   ()  const { return _getch(); }
		int   ungetch ( int key  ) const { return _ungetch( key ); }
		void  sleep   ( DWORD ms ) const { Sleep( ms ); }

		void toggle_double_buffering()
		{
			if( !front_buffer ) {

				front_buffer = original_buffer = CreateFileA( &quot;CONOUT$&quot;, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr );
				back_buffer = CreateConsoleScreenBuffer( GENERIC_READ | GENERIC_WRITE, 0, nullptr, CONSOLE_TEXTMODE_BUFFER, nullptr );

			} else {

				SetConsoleActiveScreenBuffer( original_buffer );
				CloseHandle( original_buffer == front_buffer ? back_buffer : front_buffer );
				original_buffer = front_buffer = back_buffer = nullptr;
			}
		}

		HANDLE get_front_buffer() const { return front_buffer; }
		HANDLE get_back_buffer()  const { return  back_buffer; }

		void flip()
		{
			std::swap( front_buffer, back_buffer );
			SetConsoleActiveScreenBuffer( front_buffer );
		}
};

class game_of_life
{
	public:
		class ruleset
		{
			std::array&lt; std::size_t, 9 &gt; birth;
			std::array&lt; std::size_t, 9 &gt; survival;

			public:
				ruleset()
				: birth     ({ 0, 0, 0, 1, 0, 0, 0, 0, 0 }),  // {    3 }
				  survival  ({ 0, 0, 1, 1, 0, 0, 0, 0, 0 })   // { 2, 3 }
				{}

				ruleset( std::vector&lt; unsigned &gt; &amp;     birth_neighbours,
				         std::vector&lt; unsigned &gt; &amp;  survival_neighbours )
				: birth     {},
				  survival  {}
				{
					for( auto i : birth_neighbours )
						birth.at( 1 &lt;&lt; i ) = 1;

					for( auto i : survival_neighbours )
						survival.at( 1 &lt;&lt; i ) = 1;
				}

				bool dead_or_alive( bool cell, std::size_t neighbours_alive ) const
				{
					return cell &amp;&amp; survival[ neighbours_alive ] || birth[ neighbours_alive ];
				}
		};

	private:
		typedef std::vector&lt; char &gt; state;

		static char const *  caption;
		static char const *  caption_seperator;
		static char const *  stats_title;
		static char const *  stats_seperator;
		static char const *  stats_generation_title;
		static char const *  stats_population_title;

		std::size_t const    width;
		std::size_t const    height;
		std::size_t          generation;
		std::size_t          population;
		state                current_state;
		state                next_state;
		ruleset              rules;

		std::size_t get_moore_neighbours( std::size_t i ) const
		{
			return current_state[ i - width - 1 ]
				 + current_state[ i - width     ]
				 + current_state[ i - width + 1 ]
				 + current_state[ i - 1 ]
				 + current_state[ i + 1 ]
				 + current_state[ i + width - 1 ]
				 + current_state[ i + width     ]
				 + current_state[ i + width + 1 ];
		}

	public:
		game_of_life( std::size_t field_width, std::size_t field_height, ruleset const &amp; rules = game_of_life::ruleset{} )
		: width		     { field_width  + 2 },
		  height	     { field_height + 2 },
		  generation     {},
		  population     {},
		  current_state  { width * height, 0 },
		  next_state     { width * height, 0 },
		  rules          { rules }
		{}

		std::size_t get_width()  const { return  width - 2; }
		std::size_t get_height() const { return height - 2; }

		state::const_pointer operator[]( std::size_t y ) const
		{
			if( y &gt; height - 2 )
				throw std::runtime_error{ &quot;Line number out of range!&quot; };

			return &amp;current_state[ ( y + 1 ) * width + 2 ];
		}

		std::size_t get_generation() const { return generation; }
		std::size_t get_population() const { return population; }

		std::string generate_stats_line() const
		{
			std::stringstream ss{ caption };
			ss.seekp( 0, std::ios::end );

			ss &lt;&lt; caption_seperator &lt;&lt; stats_title
			   &lt;&lt; get_width() &lt;&lt; &quot; x &quot; &lt;&lt; get_height() &lt;&lt; stats_seperator
			   &lt;&lt; stats_population_title &lt;&lt; population &lt;&lt; stats_seperator
			   &lt;&lt; stats_generation_title &lt;&lt; generation;

			return ss.str();

		}

		void reset()
		{
			generation = population = 0;
			std::fill( std::begin( current_state ), std::end( current_state ), 0 );
			std::fill( std::begin(    next_state ), std::end(    next_state ), 0 );
		}		

		template&lt; typename Engine &gt;
		void randomize( double probability_of_life, Engine &amp; engine )
		{
			std::bernoulli_distribution distribution( probability_of_life );

			std::transform( std::begin( current_state ) + width, std::end( current_state ) - width,
				std::begin( current_state ) + width, [&amp;]( state::value_type ){ return distribution( engine ); } );

			for( std::size_t i{ width }; i &lt; current_state.size() - width; ++i ) {

				current_state[ i ] = 0;
				current_state[ i += width - 1 ] = 0;
			}
		}

		void iterate()
		{
			population = 0;

			for( std::size_t y{ 1 }; y &lt; height - 1; ++y ) {
				for( std::size_t x{ 1 }; x &lt; width - 1; ++x ) {

					std::size_t i{ y * width + x };
					if( next_state[ i ] = rules.dead_or_alive( current_state[ i ] != 0, get_moore_neighbours( i ) ) )
						++population;
				}
			}

			std::swap( current_state, next_state );
			++generation;
		}
};

char const * game_of_life::caption                { &quot;Game of Life&quot; };
char const * game_of_life::caption_seperator      { &quot; - &quot; };
char const * game_of_life::stats_title            { &quot;Stats: &quot; };
char const * game_of_life::stats_seperator        { &quot; | &quot; };
char const * game_of_life::stats_generation_title { &quot;Generation: &quot; };
char const * game_of_life::stats_population_title { &quot;Population: &quot; };

int main()
{
	try {
		console_window console{};

		console.set_font_size( 5 );
		console.resize( console.get_max_width() - 4, console.get_max_height() - 4 );
		console.move_window( 0, 0 );
		console.toggle_double_buffering();

		game_of_life life{ console.get_width(), console.get_height() };

		std::mt19937 random_engine{ static_cast&lt; unsigned &gt;(
			std::chrono::high_resolution_clock::now().time_since_epoch().count() ) };

		double const life_chances{ 0.1 };
		life.randomize( life_chances, random_engine );

		bool run{ true };
		DWORD delay{};

		do {
			if( console.kbhit() ) {

				switch( console.getch() ) {

					case 'r':
						life.reset();
						life.randomize( life_chances, random_engine );
						break;

					case ' ':
						if( console.ungetch( console.getch() ) == ' ' )
							console.getch();
						break;

					case 0x1b:  // esc
						run = false;
						break;

					case '+':
						if( delay )
							delay -= 10;
						break;

					case '-':
						delay += 10;
						break;
				}

			} else {

				life.iterate();

				for( std::size_t y{}; y &lt; life.get_height(); ++y )
					console.write_buffer( life[ y ], life.get_width(), 0, y );					

				console.flip();
				console.set_title( life.generate_stats_line() );
				console.sleep( delay );
			}

		} while( run );

	} catch( std::runtime_error &amp; exception ) {

		std::cerr &lt;&lt; exception.what() &lt;&lt; &quot;\n\n&quot;;
		return EXIT_FAILURE;

	} catch( ... ) {

		std::cerr &lt;&lt; &quot;An unknown error occured!\n\n&quot;;
		return EXIT_FAILURE;
	}
}
</code></pre>
<p>// edit: Code updated.<br />
// edit: und auf &lt; Romanlänge gekürzt.<br />
// edit: dacht' ich zumindest <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f615.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--confused_face"
      title=":/"
      alt="😕"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2424719</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2424719</guid><dc:creator><![CDATA[Swordfish]]></dc:creator><pubDate>Wed, 29 Oct 2014 18:50:39 GMT</pubDate></item></channel></rss>