Games::Bingo::Card - a helper class for Games::Bingo


Games-Bingo documentation Contained in the Games-Bingo distribution.

Index


Code Index:

NAME

Top

Games::Bingo::Card - a helper class for Games::Bingo

SYNOPSIS

Top

	use Games::Bingo::Card;

	my $b = Games::Bingo-E<gt>new(90);
	my $card = Games::Bingo::Card-E<gt>new($b);

	my $bingo = Games::Bingo-E<gt>new(90);
	$card-E<gt>validate($bingo);

	use Games::Bingo::Card;

	my $p = Games::Bingo::Card-E<gt>new();
	$p-E<gt>populate();

DESCRIPTION

Top

The Games::Bingo::Card class suits the simple purpose of being able to generate bingo cards and validating whether they are valid in during a game where a player indicate victory.

It is also used by Games::Bingo::Print to hold the generated bingo cards before they are printed.

METHODS

Top

new

This method generates an object representing a bingo card.

The constructor, takes no arguments.

populate

This method is the main method of the class. It populates the card objects with a predefined number of randomly picked numbers which can be printed using the Games::Bingo::Print class.

_init

Init uses the function in Games::Bingo::Column and Games::Bingo::ColumnCollection, which are use to generate the necessary random numbers to generate the card and set the them in the necessary columns.

_insert

This is the private method which is used to insert numbers onto the card in the Bingo::Games::Card class.

Populate takes to arguments, the row and the number, it resolves the column using _resolve_column.

_resolve_column

Resolve column is method used to resolve where on the card a specified number should go. It takes a number and returns an integer indicating a column.

_integrity_check

This method is a part of the work-around, which was made in the populate method, it checks whether the populated card holds 12 numbers return a boolean value indicating succes or failure.

validate

This method can validate a bingo card against a game. So it easily can be examined whether a player/card has bingo.

The method takes one argument, the Games::Bingo object of the current game.

This method does not hold the same flaw as the method above though.

_flush

This method can be used to flush the contents of the Card object.

get_all_numbers

Returns all the numbers contained in the _array attribute as an array.

BUGS

Top

This class contains a bug in populate, which is regarded a design flaw. A work-around have implemented. See the BUGS file.

No other bugs are known at the time of writing.

SEE ALSO

Top

Games::Bingo
Games::Bingo::Bot
Games::Bingo::Column
Games::Bingo::Column::Collection
Games::Bingo::Constants
Games::Bingo::Print

TODO

Top

The TODO file contains a complete list for the whole Games::Bingo project.

AUTHOR

Top

jonasbn <jonasbn@cpan.org>

COPYRIGHT

Top


Games-Bingo documentation Contained in the Games-Bingo distribution.

package Games::Bingo::Card;

# $Id: Card.pm 1869 2007-08-12 15:52:36Z jonasbn $

use strict;
use integer;
use vars qw($VERSION);
use Games::Bingo::Column;
use Games::Bingo::ColumnCollection;
use Games::Bingo::Constants qw(
	NUMBER_OF_NUMBERS_IN_CARD
	NUMBER_OF_COLUMNS_IN_CARD
	NUMBER_OF_ROWS_IN_CARD
	NUMBER_OF_NUMBERS_IN_ROW
	NUMBER_OF_NUMBERS
);

$VERSION = '0.04';

sub new {
	my ($class) = @_;
	
	my $self = bless [], $class;
	
	return $self;
}

sub get_all_numbers {
	my $self = shift;
	
	my @numbers = ();
	foreach my $row (@{$self}) {		
		foreach my $number (@{$row}) {
			push(@numbers, $number) if $number;
		}
	}
	return @numbers;
}

sub validate {
	my ($self, $bingo) = @_;
	
	my $rv = 0;
	my $trv = NUMBER_OF_NUMBERS_IN_CARD;
	
	if ($bingo->{game}) {
		my @numbers = $self->get_all_numbers();
		
		foreach my $number (@numbers) {
			++$rv if $bingo->pulled($number); 
		}
		$trv = NUMBER_OF_NUMBERS_IN_CARD;
	} else {
		warn "bingo game not defined?\n";
	}
	
	if ($rv == $trv) { 
		$bingo->{game}--;
		return 1;
	} else {
		return 0;
	}
}

sub _print_card {
	my $self  = shift;

	my $row = 0;
	for (my $m = 0; $m < 7; $m++) {
		my $column = 0;
		
		if ($m%2) {
			for (my $n = 1; $n < 20; $n++) {
				if ($n%2) {
					print "|";
				} else {
					if ($self->[$column][$row]) {
						printf("%2d",$self->[$column][$row]);
					} else {	
						print "  ";
					}
					++$column;
				}
			}
			$row++;
		} else {
			for (my $n = 1; $n < 20; $n++) {
				if ($n%2) {
					print "+";
				} else {
					print "--";
				}
			}
		}
		print "\n";
	}
	return 1;
}

sub _insert {
	my ($self, $row, $number) = @_;
	
	my $column = $self->_resolve_column($number);	
	$self->[$column]->[$row] = $number;

	return 1;
}

sub _integrity_check {
	my ($self) = @_;
	
	my $rv = NUMBER_OF_NUMBERS_IN_CARD;
	foreach my $row (@{$self})	{
		foreach my $cell (@{$row}) {
			if ($cell and $cell =~ m/^\d+$/o) {
				$rv--;
			}
		} 
	}
	if ($rv != 0) {
		return 0;
	} else {
		return 1;
	}
}

sub _resolve_column {
	my ($self, $number) = @_;
	
	my $result = ($number / 10);
	my ($column) = $result =~ m/^(\d{1})$/o;
		
	if ($result < 1) { #ones go in column 0
		$column = 0;
	} elsif ($result == NUMBER_OF_COLUMNS_IN_CARD) { #9 go in column 8
		$column = 8;
	}
	return $column;
}

sub _init {
	my ($self) = @_;
		
	my @numbers;
	my $bingo = Games::Bingo->new();
	$bingo->init(\@numbers, NUMBER_OF_NUMBERS);

	#Creating the numeric set to pick from
	my $temp_collection = Games::Bingo::ColumnCollection->new();
	$temp_collection->divide(NUMBER_OF_COLUMNS_IN_CARD, @numbers);
	
	my $final_collection = Games::Bingo::ColumnCollection->new();
	
	#Getting the first 9 numbers
	for (my $i = 0; $i < NUMBER_OF_COLUMNS_IN_CARD; $i++) {
		my $c = $temp_collection->get_column($i);
		my $n = $c->get_random_number(1);

		my $fc = Games::Bingo::Column->new($i);
		$fc->populate($n);
		
		$final_collection->add_column($fc);
	}

	#Getting the 3 extras so we have 12 numbers
	for (my $i = NUMBER_OF_NUMBERS_IN_CARD 
			- NUMBER_OF_COLUMNS_IN_CARD; $i > 0; $i--) {
		my $tc = $temp_collection->get_random_column(1);
		my $n = $tc->get_random_number(1);
		my $label = $tc->{label};	
		
		my $fc = $final_collection->get_column($label);
				
		$fc->populate($n);
	}			
	return $final_collection;
}

sub populate {
	my ($self) = @_;

	HACK:
	
	my $fcc = $self->_init();
		
	for (my $row = NUMBER_OF_ROWS_IN_CARD-1; $row >= 0; $row--) {
		my $tcc = Games::Bingo::ColumnCollection->new();

		for (my $i = NUMBER_OF_NUMBERS_IN_ROW; $i > 0; $i--) {

			my $c = $fcc->get_random_column(1);
			my $number = $c->get_highest_number(1);
						
			if ($c->count_numbers() > 0) {
					$fcc->add_column($c);
			} else {
				#implicitly discarding empty columns
			} 		
			$self->_insert($row, $number);
		}
		foreach my $column (@${fcc}) {
			$tcc->add_column($column);
		}		
		$fcc = $tcc;
	}	
	my $amount = scalar $self->get_all_numbers();
	
	unless ($self->_integrity_check) {
		
		warn "Incomplete trying again... ($amount)\n";
		
		#if the integrity check fails, meaning we don not have 
		#enough numbers to  print a card we simply try again,
		#please refer to the BUGS file or the B<BUGS> section below.
		
		$self = $self->_flush;
		
		goto HACK;	
	}		
	return $self;
}

sub _flush {
	my $self = shift;
		
	@{$self} = ();
	
	return $self;
}

1;

__END__