Just another update
This commit is contained in:
parent
a25938f123
commit
00a190b0a6
6591 changed files with 94363 additions and 23227 deletions
|
|
@ -11,7 +11,7 @@ Positions in the grid are modified by entering their coordinates where the first
|
|||
:* If the point is free space then it is cleared, as are any adjacent points that are also free space- this is repeated recursively for subsequent adjacent free points unless that point is marked as a mine or is a mine.
|
||||
::* Points marked as a mine show as a '?'.
|
||||
::* Other free points show as an integer count of the number of adjacent true mines in its immediate neighbourhood, or as a single space ' ' if the free point is not adjacent to any true mines.
|
||||
* Of course you lose if you try to clear space that has a hidden mine.
|
||||
* Of course you lose if you try to cjhlear space that has a hidden mine.
|
||||
* You win when you have correctly identified all mines.
|
||||
|
||||
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.
|
||||
|
|
|
|||
223
Task/Minesweeper-game/C++/minesweeper-game.cpp
Normal file
223
Task/Minesweeper-game/C++/minesweeper-game.cpp
Normal file
|
|
@ -0,0 +1,223 @@
|
|||
#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" );
|
||||
}
|
||||
117
Task/Minesweeper-game/Julia/minesweeper-game-1.julia
Normal file
117
Task/Minesweeper-game/Julia/minesweeper-game-1.julia
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
# Minesweeper:
|
||||
|
||||
type Field
|
||||
size::(Int, Int)
|
||||
numbers::Array{Int, 2}
|
||||
possible_mines::Array{Bool, 2}
|
||||
actual_mines::Array{Bool, 2}
|
||||
visible::Array{Bool, 2}
|
||||
end
|
||||
|
||||
function Field(x, y)
|
||||
size = (x, y)
|
||||
actual_mines = convert(Array{Bool, 2}, rand(x, y) .< 0.15)
|
||||
possible_mines = zeros(Bool, x, y)
|
||||
numbers = zeros(Int, x, y)
|
||||
visible = zeros(Bool, x, y)
|
||||
for i = 1:x
|
||||
for j = 1:y
|
||||
n = 0
|
||||
for di = -1:1
|
||||
for dj = -1:1
|
||||
n += (0 < di+i <= x && 0 < dj+j <= y) ?
|
||||
(actual_mines[di+i, dj+j] ? 1 : 0) : 0
|
||||
end
|
||||
end
|
||||
numbers[i, j] = n
|
||||
end
|
||||
end
|
||||
return Field(size, numbers, possible_mines, actual_mines, visible)
|
||||
end
|
||||
|
||||
function printfield(f::Field; showall = false)
|
||||
spaces = int(floor(log(10, f.size[2])))
|
||||
|
||||
str = " "^(4+spaces)
|
||||
for i in 1:f.size[1]
|
||||
str *= string(" ", i, " ")
|
||||
end
|
||||
str *= "\n" * " "^(4+spaces) * "___"^f.size[1] * "\n"
|
||||
for j = 1:f.size[2]
|
||||
str *= " " * string(j) * " "^(floor(log(10, j)) > 0 ? 1 : spaces+1) * "|"
|
||||
for i = 1:f.size[1]
|
||||
if showall
|
||||
str *= f.actual_mines[i, j] ? " * " : " "
|
||||
else
|
||||
if f.visible[i, j]
|
||||
str *= " " * string(f.numbers[i, j] > 0 ? f.numbers[i, j] : " ") * " "
|
||||
elseif f.possible_mines[i, j]
|
||||
str *= " ? "
|
||||
else
|
||||
str *= " . "
|
||||
end
|
||||
end
|
||||
end
|
||||
str *= "\r\n"
|
||||
end
|
||||
println("Found " * string(length(f.possible_mines[f.possible_mines.==true])) *
|
||||
" of " * string(length(f.actual_mines[f.actual_mines.==true])) * " mines.\n")
|
||||
print(str)
|
||||
end
|
||||
|
||||
function parse_input(str::ASCIIString)
|
||||
input = split(chomp(str), " ")
|
||||
mode = input[1]
|
||||
coords = length(input) > 1 ? (int(input[2]), int(input[3])) : (0, 0)
|
||||
return mode, coords
|
||||
end
|
||||
|
||||
function eval_input(f::Field, str::ASCIIString)
|
||||
mode, coords = parse_input(str)
|
||||
(coords[1] > f.size[1] || coords[2] > f.size[2]) && return true
|
||||
if mode == "o"
|
||||
reveal(f, coords...) || return false
|
||||
elseif mode == "m" && f.visible[coords...] == false
|
||||
f.possible_mines[coords...] = !f.possible_mines[coords...]
|
||||
elseif mode == "close"
|
||||
error("You closed the game.")
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function reveal(f::Field, x::Int, y::Int)
|
||||
(x > f.size[1] || y > f.size[2]) && return true # check for index out of bounds
|
||||
f.actual_mines[x, y] && return false # check for mines
|
||||
f.visible[x, y] = true
|
||||
if f.numbers[x, y] == 0
|
||||
for di = -1:1
|
||||
for dj = -1:1
|
||||
if (0 < di+x <= f.size[1] && 0 < dj+y <= f.size[2]) &&
|
||||
f.actual_mines[x+di, y+dj] == false &&
|
||||
f.visible[x+di, y+dj] == false
|
||||
reveal(f, x+di, y+dj)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function play()
|
||||
print("\nWelcome to Minesweeper\n\nEnter the gridsize (x y):\n")
|
||||
s = split(readline(), " ")
|
||||
f = Field(int(s[1]), int(s[2]))
|
||||
won = false
|
||||
while true
|
||||
printfield(f)
|
||||
print("\nWhat do you do? (\"o x y\" to reveal a field; \"m x y\" to toggle a mine; close)\n")
|
||||
eval_input(f, readline()) || break
|
||||
print("_"^80 * "\n")
|
||||
(f.actual_mines == f.possible_mines ||
|
||||
f.visible == !f.actual_mines) && (won = true; break)
|
||||
end
|
||||
println(won ? "You won the game!" : "You lost the game:\n")
|
||||
printfield(f, showall = true)
|
||||
end
|
||||
|
||||
play()
|
||||
83
Task/Minesweeper-game/Julia/minesweeper-game-2.julia
Normal file
83
Task/Minesweeper-game/Julia/minesweeper-game-2.julia
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
julia> include("minesweeper.jl")
|
||||
|
||||
Welcome to Minesweeper
|
||||
|
||||
Enter the gridsize (x y):
|
||||
6 4
|
||||
Found 0 of 5 mines.
|
||||
|
||||
1 2 3 4 5 6
|
||||
__________________
|
||||
1 | . . . . . .
|
||||
2 | . . . . . .
|
||||
3 | . . . . . .
|
||||
4 | . . . . . .
|
||||
|
||||
What do you do? ("o x y" to reveal a field; "m x y" to toggle a mine; close)
|
||||
o 1 1
|
||||
________________________________________________________________________________
|
||||
|
||||
Found 0 of 5 mines.
|
||||
|
||||
1 2 3 4 5 6
|
||||
__________________
|
||||
1 | 1 . . . . .
|
||||
2 | . . . . . .
|
||||
3 | . . . . . .
|
||||
4 | . . . . . .
|
||||
|
||||
What do you do? ("o x y" to reveal a field; "m x y" to toggle a mine; close)
|
||||
o 1 2
|
||||
________________________________________________________________________________
|
||||
|
||||
Found 0 of 5 mines.
|
||||
|
||||
1 2 3 4 5 6
|
||||
__________________
|
||||
1 | 1 . . . . .
|
||||
2 | 2 . . . . .
|
||||
3 | . . . . . .
|
||||
4 | . . . . . .
|
||||
|
||||
What do you do? ("o x y" to reveal a field; "m x y" to toggle a mine; close)
|
||||
o 2 1
|
||||
________________________________________________________________________________
|
||||
|
||||
Found 0 of 5 mines.
|
||||
|
||||
1 2 3 4 5 6
|
||||
__________________
|
||||
1 | 1 2 . . . .
|
||||
2 | 2 . . . . .
|
||||
3 | . . . . . .
|
||||
4 | . . . . . .
|
||||
|
||||
What do you do? ("o x y" to reveal a field; "m x y" to toggle a mine; close)
|
||||
o 6 4
|
||||
________________________________________________________________________________
|
||||
|
||||
Found 0 of 5 mines.
|
||||
|
||||
1 2 3 4 5 6
|
||||
__________________
|
||||
1 | 1 2 . . . .
|
||||
2 | 2 . 2 1 1 1
|
||||
3 | . . 2
|
||||
4 | . . 1
|
||||
|
||||
What do you do? ("o x y" to reveal a field; "m x y" to toggle a mine; close)
|
||||
m 2 2
|
||||
________________________________________________________________________________
|
||||
|
||||
Found 1 of 5 mines.
|
||||
|
||||
1 2 3 4 5 6
|
||||
__________________
|
||||
1 | 1 2 . . . .
|
||||
2 | 2 ? 2 1 1 1
|
||||
3 | . . 2
|
||||
4 | . . 1
|
||||
|
||||
What do you do? ("o x y" to reveal a field; "m x y" to toggle a mine; close)
|
||||
close
|
||||
ERROR: You closed the game.
|
||||
243
Task/Minesweeper-game/MATLAB/minesweeper-game.m
Normal file
243
Task/Minesweeper-game/MATLAB/minesweeper-game.m
Normal file
|
|
@ -0,0 +1,243 @@
|
|||
function Minesweeper
|
||||
|
||||
% Game parameters (should be modified by user)
|
||||
nRows = 6;
|
||||
nCols = 4;
|
||||
percentMines = 0.15;
|
||||
|
||||
% Create minefield
|
||||
nMines = ceil(percentMines*nRows*nCols);
|
||||
field = makeGrid(nRows, nCols, nMines);
|
||||
|
||||
% Create timer for updating in axes title
|
||||
stopwatch = timer('TimerFcn', {@updateTime, field}, ...
|
||||
'ExecutionMode', 'fixedRate', 'Period', 1, 'StartDelay', 1, ...
|
||||
'TasksToExecute', 999);
|
||||
|
||||
% Specify callbacks
|
||||
set(gcf, 'CloseRequestFcn', {@cleanUp, stopwatch})
|
||||
set(gca, 'ButtonDownFcn', {@onClick, field, stopwatch})
|
||||
|
||||
|
||||
end
|
||||
|
||||
function field = makeGrid(nRows, nCols, nMines)
|
||||
% Create minefield with unit squares
|
||||
% Use quadrant IV to make indexing semi-consistent
|
||||
% i.e. square in ith row, jth column has lower-right corner at (j, -i)
|
||||
figure
|
||||
set(gcf, 'Color', [1 1 1])
|
||||
axis([0 nCols -nRows 0])
|
||||
axis square
|
||||
axis manual
|
||||
hold on
|
||||
set(gca, 'GridLineStyle', '-')
|
||||
grid on
|
||||
set(gca, 'XTick', 0:nCols)
|
||||
set(gca, 'YTick', -nRows:0)
|
||||
set(gca, 'XTickLabel', [])
|
||||
set(gca, 'YTickLabel', [])
|
||||
set(gca, 'Color', [0.6 0.6 0.6])
|
||||
setTitle(nMines, ': )', 0)
|
||||
xlabel('left-click to dig, right-click to mark')
|
||||
|
||||
% Set up field structure
|
||||
% text will contain the handles to the labels in each square
|
||||
% One character per square (or other functions will break)
|
||||
% . Nothing noted
|
||||
% M Marked as mine
|
||||
% ? Marked as unknown
|
||||
% 1-8 Digits indicate how many mines this square touches
|
||||
% * Mine (game over)
|
||||
% (blank) Square has been (dug) and is not mined nor touching any mines
|
||||
% squares will contain handles to the colored "fill" objects
|
||||
% fill objects will be deleted once square is "dug"
|
||||
% Use ishandle() to determine if square is not yet dug
|
||||
% mines will contain a logical array indicating positions of mines
|
||||
% true Mine
|
||||
% false No mine
|
||||
% Later versions of MATLAB use gobjects() to preallocate text and squares
|
||||
field = struct('text', zeros(nRows, nCols), ...
|
||||
'squares', zeros(nRows, nCols), ...
|
||||
'mines', false(nRows, nCols));
|
||||
|
||||
% Create individual square color and label objects
|
||||
for r = 1:nRows
|
||||
for c = 1:nCols
|
||||
field.squares(r, c) = ...
|
||||
fill([c-1 c-1 c c c-1], [-r+1 -r -r -r+1 -r+1], [0.9 0.9 0.9]);
|
||||
set(field.squares(r, c), 'HitTest', 'off')
|
||||
field.text(r, c) = text(c-0.5, -r+0.5, '.');
|
||||
set(field.text(r, c), 'FontSize', 12, 'FontWeight', 'bold', ...
|
||||
'HorizontalAlignment', 'center', 'HitTest', 'off');
|
||||
end
|
||||
end
|
||||
|
||||
% Place mines randomly without repeats
|
||||
k = 0;
|
||||
while k < nMines
|
||||
idx = randi(nRows*nCols);
|
||||
if ~field.mines(idx)
|
||||
field.mines(idx) = true;
|
||||
k = k+1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function onClick(obj, event, field, stopwatch)
|
||||
if strcmp(stopwatch.Running, 'off')
|
||||
start(stopwatch)
|
||||
end
|
||||
|
||||
pt = get(obj, 'CurrentPoint');
|
||||
r = ceil(-pt(1, 2));
|
||||
c = ceil(pt(1, 1));
|
||||
|
||||
if r > 0 && c > 0 && r <= size(field.squares, 1) && ... % Not yet been "dug"
|
||||
c <= size(field.squares, 2) && ishandle(field.squares(r, c))
|
||||
buttons = {'normal' 'alt' 'extend'};
|
||||
btn = find(strcmp(get(get(obj, 'Parent'), 'SelectionType'), buttons));
|
||||
labels = '.M?'; % Unmarked, mine flag, unknown flag
|
||||
currLabel = get(field.text(r, c), 'String');
|
||||
|
||||
if btn == 1 % Left click
|
||||
if currLabel ~= labels(2); % Don't dig if flagged as mine
|
||||
if field.mines(r, c) % Mine there -> you lose
|
||||
gameLost(field, stopwatch, r, c)
|
||||
else % No mine -> free to dig
|
||||
minesLeft = countMineFlags(field);
|
||||
digSquare(field, r, c)
|
||||
if all(all(ishandle(field.squares) == field.mines))
|
||||
gameWon(field, stopwatch)
|
||||
else
|
||||
faceTimer = timer('StartDelay', 0.5, ...
|
||||
'StartFcn', {@setTitleOnTimer, minesLeft, ...
|
||||
': o', stopwatch.TasksExecuted}, ...
|
||||
'TimerFcn', {@setTitleOnTimer, minesLeft, ...
|
||||
': )', stopwatch.TasksExecuted}, ...
|
||||
'StopFcn', @deleteTimer);
|
||||
start(faceTimer)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
elseif btn == 2 % Right-click
|
||||
% Rotate through labels list to the next one
|
||||
switch find(currLabel == labels)
|
||||
case 1
|
||||
newLabel = labels(2);
|
||||
case 2
|
||||
newLabel = labels(3);
|
||||
case 3
|
||||
newLabel = labels(1);
|
||||
end
|
||||
set(field.text(r, c), 'String', newLabel);
|
||||
setTitle(countMineFlags(field), ': )', stopwatch.TasksExecuted)
|
||||
|
||||
elseif btn == 3 % Middle-click
|
||||
% Mark/unmark unknown flag
|
||||
if currLabel == labels(1)
|
||||
set(field.text(r, c), 'String', labels(3));
|
||||
elseif currLabel == labels(3)
|
||||
set(field.text(r, c), 'String', labels(1));
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function updateTime(obj, event, field)
|
||||
setTitle(countMineFlags(field), ': )', obj.TasksExecuted)
|
||||
end
|
||||
|
||||
function deleteTimer(obj, event)
|
||||
delete(obj)
|
||||
end
|
||||
|
||||
function setTitleOnTimer(obj, event, mines, face, time)
|
||||
setTitle(mines, face, time)
|
||||
end
|
||||
|
||||
function setTitle(mines, face, time)
|
||||
title(sprintf('%03d Mines %s Timer %03d', mines, face, time))
|
||||
end
|
||||
|
||||
function minesLeft = countMineFlags(field)
|
||||
% Determine how many mines are unmarked (negative means too many mines marked)
|
||||
minesLeft = sum(field.mines(:));
|
||||
for k = 1:numel(field.text)
|
||||
if get(field.text(k), 'String') % Not an empty string
|
||||
minesLeft = minesLeft-(get(field.text(k), 'String') == 'M');
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function digSquare(field, r, c)
|
||||
% If square is touching one or more mines then indicate the number
|
||||
% Otherwise indicate no mines and dig surrounding squares recursively
|
||||
% Assumes current square is clear of mines
|
||||
delete(field.squares(r, c))
|
||||
[nRows, nCols] = size(field.mines);
|
||||
surrR = [r-1 r r+1 r-1 r+1 r-1 r r+1];
|
||||
surrC = [c-1 c-1 c-1 c c c+1 c+1 c+1];
|
||||
toDelete = surrR < 1 | surrR > nRows | surrC < 1 | surrC > nCols;
|
||||
surrR(toDelete) = [];
|
||||
surrC(toDelete) = [];
|
||||
nearMines = sum(field.mines(sub2ind([nRows nCols], surrR, surrC)));
|
||||
label = sprintf('%d', nearMines);
|
||||
textColor = [0 0 0 ; 0 0 1 ; 0 1 0 ; 1 0 0 ; 0.5 0.1 0.9 ; ...
|
||||
0.6 0 0 ; 0.2 0.5 0.3 ; 0.2 0.2 0.1 ; 0 0 0];
|
||||
if ~nearMines
|
||||
label = '';
|
||||
for k = 1:length(surrR)
|
||||
if ~field.mines(surrR(k), surrC(k)) && ...
|
||||
ishandle(field.squares(surrR(k), surrC(k))) && ...
|
||||
~strcmp(get(field.text(k), 'String'), 'M')
|
||||
digSquare(field, surrR(k), surrC(k))
|
||||
end
|
||||
end
|
||||
end
|
||||
set(field.text(r, c), 'String', label, 'Color', textColor(nearMines+1, :))
|
||||
end
|
||||
|
||||
function gameLost(field, stopwatch, r, c)
|
||||
stop(stopwatch)
|
||||
setTitle(countMineFlags(field), 'X (', stopwatch.TasksExecuted)
|
||||
set(field.squares(r, c), 'FaceColor', [1 0 0])
|
||||
for k = 1:numel(field.text)
|
||||
if field.mines(k) && any(get(field.text(k), 'String') == '.?')
|
||||
set(field.text(k), 'String', '*', 'FontSize', 20)
|
||||
elseif ~field.mines(k) && ishandle(field.squares(k)) && ...
|
||||
get(field.text(k), 'String') == 'M'
|
||||
set(field.text(k), 'String', 'X', 'Color', [1 0 0])
|
||||
end
|
||||
end
|
||||
set(gca, 'HitTest', 'off')
|
||||
queryPlayAgain('Game over')
|
||||
end
|
||||
|
||||
function gameWon(field, stopwatch)
|
||||
% Flag any leftover mines and indicate win
|
||||
stop(stopwatch)
|
||||
set(field.text(ishandle(field.squares)), 'String', 'M')
|
||||
setTitle(0, 'B )', stopwatch.TasksExecuted)
|
||||
set(gca, 'HitTest', 'off')
|
||||
queryPlayAgain('Minefield cleared!')
|
||||
end
|
||||
|
||||
function queryPlayAgain(msg)
|
||||
% Ask player if they want to play again
|
||||
% Reset game by closing and reopening figure
|
||||
choice = questdlg(sprintf('%s\nWould you like to play again?', msg), ...
|
||||
'', 'Yes', 'No', 'No');
|
||||
if strcmp(choice, 'Yes')
|
||||
close
|
||||
Minesweeper
|
||||
end
|
||||
end
|
||||
|
||||
function cleanUp(obj, event, stopwatch)
|
||||
% Stop and close down all necessary processes
|
||||
stop(stopwatch)
|
||||
delete(stopwatch)
|
||||
delete(obj)
|
||||
end
|
||||
Loading…
Add table
Add a link
Reference in a new issue