Task: Minesweeper game


C++: #include <iostream>
#include <string>
#include <windows.h>
using namespace std;
typedef unsigned char byte;

enum fieldValues : byte { OPEN, CLOSED = 10, MINE, UNKNOWN, FLAG, ERR };

class fieldData
{
public:
    fieldData() : value( CLOSED ), open( false ) {}
    byte value;
    bool open, mine;
};

class game
{
public:
    ~game()
    { if( field ) delete [] field; }

    game( int x, int y )
    {
        go = false; wid = x; hei = y;
	field = new fieldData[x * y];
	memset( field, 0, x * y * sizeof( fieldData ) );
	oMines = ( ( 22 - rand() % 11 ) * x * y ) / 100;
	mMines = 0;
	int mx, my, m = 0;
	for( ; m < oMines; m++ )
	{
	    do
	    { mx = rand() % wid; my = rand() % hei; }
	    while( field[mx + wid * my].mine );
	    field[mx + wid * my].mine = true;
	}
	graphs[0] = ' '; graphs[1] = '.'; graphs[2] = '*'; 
	graphs[3] = '?'; graphs[4] = '!'; graphs[5] = 'X'; 
    }
	
    void gameLoop()
    {
	string c, r, a;
	int col, row;
	while( !go )
	{
	    drawBoard();
	    cout << "Enter column, row and an action( c r a ):\nActions: o => open, f => flag, ? => unknown\n";
	    cin >> c >> r >> a;
	    if( c[0] > 'Z' ) c[0] -= 32; if( a[0] > 'Z' ) a[0] -= 32;
	    col = c[0] - 65; row = r[0] - 49;
	    makeMove( col, row, a );
	}
    }

private:
    void makeMove( int x, int y, string a )
    {
	fieldData* fd = &field[wid * y + x];
	if( fd->open && fd->value < CLOSED )
	{
	    cout << "This cell is already open!";
	    Sleep( 3000 ); return;
	}
	if( a[0] == 'O' ) openCell( x, y );
	else if( a[0] == 'F' ) 
	{
	    fd->open = true;
	    fd->value = FLAG;
	    mMines++;
	    checkWin();
	}
	else
	{
	    fd->open = true;
	    fd->value = UNKNOWN;
	}
    }

    bool openCell( int x, int y )
    {
	if( !isInside( x, y ) ) return false;
	if( field[x + y * wid].mine ) boom();
	else 
	{
	    if( field[x + y * wid].value == FLAG )
	    {
		field[x + y * wid].value = CLOSED;
		field[x + y * wid].open = false;
		mMines--;
	    }
	    recOpen( x, y );
	    checkWin();
	}
	return true;
    }

    void drawBoard()
    {
	system( "cls" );
	cout << "Marked mines: " << mMines << " from " << oMines << "\n\n";		
	for( int x = 0; x < wid; x++ )
	    cout << "  " << ( char )( 65 + x ) << " "; 
	cout << "\n"; int yy;
	for( int y = 0; y < hei; y++ )
	{
	    yy = y * wid;
	    for( int x = 0; x < wid; x++ )
		cout << "+---";

	    cout << "+\n"; fieldData* fd;
	    for( int x = 0; x < wid; x++ )
	    {
		fd = &field[x + yy]; cout<< "| ";
		if( !fd->open ) cout << ( char )graphs[1] << " ";
		else 
		{
		    if( fd->value > 9 )
			cout << ( char )graphs[fd->value - 9] << " ";
		    else
		    {
			if( fd->value < 1 ) cout << "  ";
			    else cout << ( char )(fd->value + 48 ) << " ";
		    }
		}
	    }
	    cout << "| " << y + 1 << "\n";
	}
	for( int x = 0; x < wid; x++ )
	    cout << "+---";

	cout << "+\n\n";
    }

    void checkWin()
    {
	int z = wid * hei - oMines, yy;
	fieldData* fd;
	for( int y = 0; y < hei; y++ )
	{
	    yy = wid * y;
	    for( int x = 0; x < wid; x++ )
	    {
		fd = &field[x + yy];
		if( fd->open && fd->value != FLAG ) z--;
	    }
	}
	if( !z ) lastMsg( "Congratulations, you won the game!");
    }

    void boom()
    {
	int yy; fieldData* fd;
	for( int y = 0; y < hei; y++ )
	{
	    yy = wid * y;
	    for( int x = 0; x < wid; x++ )
	    {
		fd = &field[x + yy];
		if( fd->value == FLAG )
		{
		    fd->open = true;
		    fd->value = fd->mine ? MINE : ERR;
		}
		else if( fd->mine )
		{
		    fd->open = true;
		    fd->value = MINE;
		}
	    }
	}
	lastMsg( "B O O O M M M M M !" );
    }

    void lastMsg( string s )
    {
	go = true; drawBoard();
	cout << s << "\n\n";
    }

    bool isInside( int x, int y ) { return ( x > -1 && y > -1 && x < wid && y < hei ); }

    void recOpen( int x, int y )
    {
	if( !isInside( x, y ) || field[x + y * wid].open ) return;
	int bc = getMineCount( x, y );
	field[x + y * wid].open = true;
	field[x + y * wid].value = bc;
	if( bc ) return;

	for( int yy = -1; yy < 2; yy++ )
	    for( int xx = -1; xx < 2; xx++ )
	    {
		if( xx == 0 && yy == 0 ) continue;
		recOpen( x + xx, y + yy );
	    }
    }

    int getMineCount( int x, int y )
    {
	int m = 0;
	for( int yy = -1; yy < 2; yy++ )
	    for( int xx = -1; xx < 2; xx++ )
	    {
		if( xx == 0 && yy == 0 ) continue;
		if( isInside( x + xx, y + yy ) && field[x + xx + ( y + yy ) * wid].mine ) m++;
	    }
		
	return m;
    }
	
    int wid, hei, mMines, oMines;
    fieldData* field; bool go;
    int graphs[6];
};

int main( int argc, char* argv[] )
{
    srand( GetTickCount() );
    game g( 4, 6 ); g.gameLoop();
    return system( "pause" );
}






Python: 


gridsize  = (6, 4)
minerange = (0.2, 0.6)


try:
    raw_input
except:
    raw_input = input
    
import random
from itertools import product
from pprint import pprint as pp


def gridandmines(gridsize=gridsize, minerange=minerange):
    xgrid, ygrid = gridsize
    minmines, maxmines = minerange
    minecount = xgrid * ygrid    
    minecount = random.randint(int(minecount*minmines), int(minecount*maxmines))
    grid = set(product(range(xgrid), range(ygrid)))
    mines = set(random.sample(grid, minecount))
    show = {xy:'.' for xy in grid}
    return grid, mines, show

def printgrid(show, gridsize=gridsize):
    xgrid, ygrid = gridsize
    grid = '\n'.join(''.join(show[(x,y)] for x in range(xgrid))
                     for y in range(ygrid))
    print( grid )

def resign(showgrid, mines, markedmines):
    for m in mines:
        showgrid[m] = 'Y' if m in markedmines else 'N'

def clear(x,y, showgrid, grid, mines, markedmines):
    if showgrid[(x, y)] == '.':
        xychar = str(sum(1
                         for xx in (x-1, x, x+1)
                         for yy in (y-1, y, y+1)
                         if (xx, yy) in mines ))
        if xychar == '0': xychar = '.'
        showgrid[(x,y)] = xychar
        for xx in (x-1, x, x+1):
            for yy in (y-1, y, y+1):
                xxyy = (xx, yy)
                if ( xxyy != (x, y)
                     and xxyy in grid
                     and xxyy not in mines | markedmines ):
                    clear(xx, yy, showgrid, grid, mines, markedmines)

if __name__ == '__main__':
    grid, mines, showgrid = gridandmines()
    markedmines = set([])
    print( __doc__ )
    print( '\nThere are %i true mines of fixed position in the grid\n' % len(mines) )
    printgrid(showgrid)
    while markedmines != mines:
        inp = raw_input('m x y/c x y/p/r: ').strip().split()
        if inp:
            if inp[0] == 'm':
                x, y = [int(i)-1 for i in inp[1:3]]
                if (x,y) in markedmines:
                    markedmines.remove((x,y))
                    showgrid[(x,y)] = '.'
                else:
                    markedmines.add((x,y))
                    showgrid[(x,y)] = '?'
            elif inp[0] == 'p':
                printgrid(showgrid)
            elif inp[0] == 'c':
                x, y = [int(i)-1 for i in inp[1:3]]
                if (x,y) in mines | markedmines:
                    print( '\nKLABOOM!! You hit a mine.\n' )
                    resign(showgrid, mines, markedmines)
                    printgrid(showgrid)
                    break
                clear(x,y, showgrid, grid, mines, markedmines)
                printgrid(showgrid)
            elif inp[0] == 'r':
                print( '\nResigning!\n' )
                resign(showgrid, mines, markedmines)
                printgrid(showgrid)
                break
    
    print( '\nYou got %i and missed %i of the %i mines'
           % (len(mines.intersection(markedmines)),
              len(markedmines.difference(mines)),
              len(mines)) )