Peter
Peter Campbell Smith

Count numbers and bombs

Weekly challenge 126 — 16 August 2021

Week 126: 16 Aug 2021

Task 2

Task — Minesweeper game

You are given a rectangle with points marked with either x or *. Please consider the x as a land mine. Write a script to print a rectangle with numbers and x as in the Minesweeper game. A number in a square of the minesweeper game indicates the number of mines within the neighbouring squares (usually 8), also implies that there are no bombs on that square.

Examples


Example 1:
Input:
    x * * * x * x x x x
    * * * * * * * * * x
    * * * * x * x * x *
    * * * x x * * * * *
    x * * * x * * * * x
Output:
    x 1 0 1 x 2 x x x x
    1 1 0 2 2 4 3 5 5 x
    0 0 1 3 x 3 x 2 x 2
    1 1 1 x x 4 1 2 2 2
    x 1 1 3 x 2 0 0 1 x

Analysis

I did not submit a solution at the time, but have written this later.

The essence of my solution is:

  • Loop over all the cells
  • If this one is a bomb:
    • Loop over up to 8 neighbouring cells
    • Increase their bomb-near count by 1 unless they are also a bomb

That sounds easy, but it amounts to quite a few lines of code.

One arguable aspect is that I worked with the cells in a 1-dimensional array with index of $x + $y * $width. My reason for doing that is that passing multidimensional arrays as subroutine arguments is a bit messy in Perl, and the ($x, $y) <-> $j conversion is cheap.

I have, separately, coded Minesweeper as a game in Perl and Jscript: if you would like a copy drop me an email.

Try it 

Try running the script with any input:



example: '* * x *','x * * *','* x * *'

Script


#!/usr/bin/perl

# Blog: http://ccgi.campbellsmiths.force9.co.uk/challenge

use v5.26;    # The Weekly Challenge - 2021-08-16
use utf8;     # Week 126 - task 2 - Minesweeper game
use warnings; # Peter Campbell Smith
binmode STDOUT, ':utf8';

minesweeper_game('x * * * x * x x x x',
                 '* * * * * * * * * x',
                 '* * * * x * x * x *',
                 '* * * x x * * * * *',
                 'x * * * x * * * * x');
                 
minesweeper_game('* * x * x', 
                 '* x * x *', 
                 '* * x x x', 
                 'x x * * *', 
                 'x * x x x', 
                 'x x x * x', 
                 '* x x x x');

sub minesweeper_game {
    
    my (@input, @cell, $height, $width, $g, $x, $y, $xx, $yy, $c, $j);
    
    # preliminaries - build $cell and change all * to 0
    $height = @_;
    for $y (@_) {
        $cell[$j ++] = $1 while $y =~ m|([^ ])|g;
    }
    $width = $j / $height;
    show_grid('Input:', $height, $width, \@cell);
    $cell[$_] = $cell[$_] eq '*' ? 0 : 'x' for 0 .. $height * $width - 1;
    
    # loop over all cells
    for $x (0 .. $width - 1) {
        for $y (0 .. $height - 1) {
            $j = $x + $y * $width;
            
            # skip unless this is a bomb
            next unless $cell[$j] eq 'x';
            
            # loop over neighbouring cells
            for ($xx = $x - 1; $xx <= $x + 1; $xx ++) {
                for ($yy = $y - 1; $yy <= $y + 1; $yy ++) {
                    
                    # check not this cell and not off grid
                    if ($xx != $x || $yy != $y) {
                        if ($xx >= 0 && $xx < $width && $yy >= 0 && $yy < $height) {
                            
                            # add to neighbouring bomb count
                            $j = $xx + $yy * $width;
                            $cell[$j] ++ unless $cell[$j] eq 'x';
                        }
                    }
                }
            }
        }
    }
    show_grid('Output:', $height, $width,  \@cell)
}

sub show_grid {
    
    my ($cell, $height, $width, $x, $y, $j, $title);
    
    # print grid nicely
    ($title, $height, $width, $cell) = @_;
    say $title;
    for $y (0 .. $height - 1) {
        for $x (0 .. $width - 1) {
            print $cell->[$x + $y * $width] . ' ';
        }
        say '';
    }
}

Output


Input:
x * * * x * x x x x
* * * * * * * * * x
* * * * x * x * x *
* * * x x * * * * *
x * * * x * * * * x
Output:
x 1 0 1 x 2 x x x x
1 1 0 2 2 4 3 5 5 x
0 0 1 3 x 3 x 2 x 2
1 1 1 x x 4 1 2 2 2
x 1 1 3 x 2 0 0 1 x

Input:
* * x * x
* x * x *
* * x x x
x x * * *
x * x x x
x x x * x
* x x x x
Output:
1 2 x 3 x
1 x 5 x 4
3 4 x x x
x x 5 6 4
x 7 x x x
x x x 8 x
3 x x x x


 

Any content of this website which has been created by Peter Campbell Smith is in the public domain