How to resolve the algorithm Minesweeper game step by step in the Perl programming language

Published on 12 May 2024 09:40 PM

How to resolve the algorithm Minesweeper game step by step in the Perl programming language

Table of Contents

Problem Statement

There is an n by m grid that has a random number (between 10% to 20% of the total number of tiles, though older implementations may use 20%..60% instead) of randomly placed mines that need to be found. Positions in the grid are modified by entering their coordinates where the first coordinate is horizontal in the grid and the second vertical. The top left of the grid is position 1,1; the bottom right is at n,m. The Task is to create a program that allows you to play minesweeper on a 6 by 4 grid, and that assumes all user input is formatted correctly and so checking inputs for correct form may be omitted. You may also omit all GUI parts of the task and work using text input and output. Note: Changes may be made to the method of clearing mines to more closely follow a particular implementation of the game so long as such differences and the implementation that they more accurately follow are described. C.F: wp:Minesweeper (computer game)

Let's start with the solution:

Step by Step solution about How to resolve the algorithm Minesweeper game step by step in the Perl programming language

Source code in the perl programming language

#!/usr/bin/perl
use warnings;
use strict;

{   package Local::Field;

    use constant {
        REAL  => 0,
        SHOW  => 1,
        COUNT => 2,
    };

    sub new {
        my ($class, $width, $height, $percent) = @_;
        my $field;
        for my $x (1 .. $width) {
            for my $y (1 .. $height) {
                $field->[$x - 1][$y - 1][REAL] = ' ';
                $field->[$x - 1][$y - 1][SHOW] = '.';
            }
        }
        for (1 .. $percent / 100 * $width * $height) {
            my ($x, $y) = map int rand $_, $width, $height;
            redo if 'm' eq $field->[$x][$y][REAL];
            $field->[$x][$y][REAL] = 'm';
            for my $i ($x - 1 .. $x + 1) {
                for my $j ($y - 1 .. $y + 1) {
                    $field->[$i][$j][COUNT]++
                        if $i >= 0 and $j >= 0
                        and $i <= $#$field and $j <= $#{ $field->[0] };
                }
            }
        }
        bless $field, $class;
    }


    sub show {
        my ($self) = @_;
        print "\n  ";
        printf '%2d ', $_ + 1 for 0 .. $#$self;
        print "\n";

        for my $row (0 .. $#{ $self->[0] }) {
            printf '%2d ', 1 + $row;
            for my $column (0 .. $#$self) {
                print $self->[$column][$row][SHOW], '  ';
            }
            print "\n";
        }
    }


    sub mark {
        my ($self, $x, $y) = @_;
        $_-- for $x, $y;

        if ('.' eq $self->[$x][$y][SHOW]) {
            $self->[$x][$y][SHOW] = '?';

        } elsif ('?' eq $self->[$x][$y][SHOW]) {
            $self->[$x][$y][SHOW] = '.';
        }
    }


    sub end {
        my $self = shift;
        for my $y (0 .. $#{ $self->[0] }) {
            for my $x (0 .. $#$self) {
                $self->[$x][$y][SHOW] = '!' if '.' eq $self->[$x][$y][SHOW]
                    and 'm' eq $self->[$x][$y][REAL];
                $self->[$x][$y][SHOW] = 'x' if '?' eq $self->[$x][$y][SHOW]
                    and 'm' ne $self->[$x][$y][REAL];
            }
        }
        $self->show;
        exit;
    }

    sub _declassify {
        my ($self, $x, $y) = @_;
        return if '.' ne $self->[$x][$y][SHOW];
        if (' ' eq $self->[$x][$y][REAL] and '.' eq $self->[$x][$y][SHOW]) {
            $self->[$x][$y][SHOW] = $self->[$x][$y][COUNT] || ' ';
        }
        return if ' ' ne $self->[$x][$y][SHOW];

        for my $i ($x - 1 .. $x + 1) {
            next if $i < 0 or $i > $#$self;
            for my $j ($y - 1 .. $y + 1) {
                next if $j < 0 or $j > $#{ $self->[0] };
                no warnings 'recursion';
                $self->_declassify($i, $j);
            }
        }
    }


    sub clear {
        my ($self, $x, $y) = @_;
        $_-- for $x, $y;
        return unless '.' eq $self->[$x][$y][SHOW];

        print "You lost.\n" and $self->end if 'm' eq $self->[$x][$y][REAL];

        $self->_declassify($x, $y);
    }


    sub remain {
        my $self = shift;
        my $unclear = 0;
        for my $column (@$self) {
            for my $cell (@$column) {
                $unclear++ if '.' eq $cell->[SHOW];
            }
        }
        return $unclear;
    }

}

sub help {
    print << '__HELP__';
Commands:
h     ... help
q     ... quit
m X Y ... mark/unmark X Y
c X Y ... clear X Y
__HELP__
}


my ($width, $height, $percent) = @ARGV;
$width   ||= 6;
$height  ||= 4;
$percent ||= 15;

my $field = 'Local::Field'->new($width, $height, $percent);

my $help = 1;
while (1) {
    $field->show;
    help() if $help;
    $help = 0;
    my $remain = $field->remain;
    last if 0 == $remain;
    print "Cells remaining: $remain.\n";
    my $command = <STDIN>;
    exit if $command =~ /^q/i;

    if ($command =~ /^m.*?([0-9]+).*?([0-9]+)/i) {
        $field->mark($1, $2);

    } elsif ($command =~ /^c.*?([0-9]+).*?([0-9]+)/i) {
        $field->clear($1, $2);

    } elsif ($command =~ /^h/i) {
        $help = 1;

    } else {
        print "Huh?\n";
    }
}
print "You won!\n";


  

You may also check:How to resolve the algorithm Loops/Break step by step in the BASIC programming language
You may also check:How to resolve the algorithm Sorting algorithms/Shell sort step by step in the AArch64 Assembly programming language
You may also check:How to resolve the algorithm Strip a set of characters from a string step by step in the Draco programming language
You may also check:How to resolve the algorithm Perfect shuffle step by step in the Perl programming language
You may also check:How to resolve the algorithm Array concatenation step by step in the Frink programming language