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 )