Games-Minesweeper
view release on metacpan or search on metacpan
lib/Games/Minesweeper.pm view on Meta::CPAN
sub full_expose() {
my $update_rect = new Gtk2::Gdk::Rectangle (0, 0, $field_width*$tile_width, $field_height*$tile_height);
$d->window->invalidate_rect ($update_rect, 0);
}
sub draw_xy($$$;$) {
my ($x, $y, $img, $expose) = @_;
$img->copy_area(0, 0, $tile_width, $tile_height, $frame, $x*$tile_width, $y*$tile_height);
if ($expose) {
my $update_rect = new Gtk2::Gdk::Rectangle ($x*$tile_width, $y*$tile_height, $tile_width, $tile_height);
$d->window->invalidate_rect ($update_rect, 0);
}
}
sub open_all() {
for my $x (0..$field_width-1) {
for my $y (0..$field_height-1) {
my $f = $mine_field[$x][$y];
next unless $f;
if ($f & IS_MINE) {
if ($f & IS_FLAGGED) {
draw_xy ($x, $y, $mine_flag, 0)
} else { # mine not flagged
if ($f & IS_OPEN) {
draw_xy ($x, $y, $mine_red, 0);
} else {
draw_xy ($x, $y, $mine, 0)
}
}
} else { # not a mine but open or flagged
draw_xy ($x, $y, $mine_wrong, 0) if $f & IS_FLAGGED;
}
}
}
full_expose;
}
sub cleanup_cb {
undef $watcher;
}
my $timer = 0;
sub timeout () {
$l->set_text(sprintf "%.4d ", ++$timer);
1;
}
sub stop_timer () {
undef $watcher;
$timer;
}
sub start_timer () {
$timer = 0;
$watcher = AnyEvent->timer (after => 1.0, interval => 1, cb => sub { timeout; });
}
sub update_mine_count() {
$mc->set_text ( sprintf " %.3d", $mine_count);
}
sub expose_cb {
my ($w, $e) = @_;
#warn "expose: ".$e->area->x." ". $e->area->y." ".$e->area->width." ".$e->area->height;
$frame->render_to_drawable ($w->window, $w->style->black_gc,
$e->area->x, $e->area->y,
$e->area->x, $e->area->y,
$e->area->width, $e->area->height,
'normal',
$e->area->x, $e->area->y);
1;
}
sub around(&$$;$) {
my ($func, $x, $y, $data) = @_;
my $ret;
$ret = $func->($x-1, $y-1, $data) if $x > 0 && $y > 0;
$ret |= $func->($x, $y-1, $data) if $y > 0;
$ret |= $func->($x+1, $y-1, $data) if $x < $field_width -1 && $y >0;
$ret |= $func->($x-1, $y, $data) if $x >0;
$ret |= $func->($x+1, $y, $data) if $x < $field_width - 1;
$ret |= $func->($x-1, $y+1, $data) if $x > 0 && $y < $field_height -1;
$ret |= $func->($x, $y+1, $data) if $y < $field_height -1;
$ret |= $func->($x+1, $y+1, $data) if $x < $field_width - 1 && $y < $field_height -1;
$ret;
}
my @event;
my @undo;
sub button_press_cb {
return 1 if $game_over;
my ($w, $e) = @_;
play("mouse_press") if $audio;
my ($x, $y, $b) = (int $e->x / $tile_width, int $e->y / $tile_height, $e->button);
$event[$b] = [ $x, $y ];
#warn "press x=$x y=$y b=$b mc=".count_mines($x, $y)."is_mine=".($mine_field[$x][$y] & IS_MINE)."\n";
if($b == 3) {
return 1 if $mine_field[$x][$y] & IS_OPEN;
if ($mine_field[$x][$y] & IS_FLAGGED) {
$mine_field[$x][$y] &= ~IS_FLAGGED;
$mine_count++;
draw_xy ($x, $y, $mine_hidden, 1);
} else {
$mine_field[$x][$y] |= IS_FLAGGED;
$mine_count--;
draw_xy ($x, $y, $mine_flag, 1);
}
update_mine_count;
} elsif ($b == 2) {
$smiley->set_image ($smiley_stress_img);
@undo = ();
return 1 unless $mine_field[$x][$y] & IS_OPEN;
around ( sub {
my ($x, $y) = @_;
if ($mine_field[$x][$y] < 2) { # empty or nonflagged
( run in 2.036 seconds using v1.01-cache-2.11-cpan-600a1bdf6e4 )