
-----------------------------------
Nathan4102
Sat Jul 06, 2013 4:48 pm

Grade 10 ICS Summative - Minesweeper
-----------------------------------
Hey guys,

This is my final summative for grade 10 ICS this year. The task was to make a game, with most people doing a graphical Rock Paper Scissors. I'm really only posting this to see what I could improve on in my code, but I'll post the full package aswell so you can try it out.

Let me know what you think of it!

Note: There is a cheat constant at the top of the program used for bug testing. If all the cells are highlighted, thats why!

Code:

%Nathaniel Woodthorpe
%May 17, 2013
%Minesweeper.t
%Create Minesweeper in Turing - ICS2OI Summative

const CHEAT := true

var background1 := Pic.FileNew ("background1.bmp") %Title screen Image
var background2 := Pic.FileNew ("background2.bmp") %Gameplay background Image
var losescreen := Pic.FileNew ("Losescreen.bmp") %Lose screen
var winscreen := Pic.FileNew ("Winscreen.bmp") %Win screen
var minescreen := Pic.FileNew ("SelectMines.bmp") %Select Mines screen
var flag := Pic.FileNew ("flag.jpg") %Flag
var font1 : int := Font.New ("Ariel:15") %Normal Font
var font2 : int := Font.New ("David:20") %Title Font
var loading_Bar : int := 150 %Variable for loading bar
var x, y, button, lastbutton, lastbutton1 : int := 0 %For Mousewhere, and to prevent dragging
var clock_Start, seconds : int %Used in Clock function
var fail : boolean := false %Used in random mine placement
var winOrLose : int := 0 %Used in retry? section
var retry : boolean := false %Used in retry? section
var numberOfMines := 60 %Set number of mines


const OFFSET := 13 %Used in cell placement


type Cells : %Record to store data for each cell
    record
	x1, y1 : int
	clicked, mine : boolean
	number, icon : int
    end record

type Mines : %Holds mine location, used in random mine placement
    record
	x, y : int
    end record

var cell_Array : array 1 .. 16, 1 .. 16 of Cells %Array of records, 1 per cell
var mine : array 1 .. numberOfMines of Mines %Used for random mine placement

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%FUNCTIONS/PROCEDURES BEGIN%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Function Name: Clock                                       %
%Function Desc.: Outputs time since start in string format  %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function Clock : string
    var minutes, hours : int := 0
    var elapsed : string

    seconds := round ((Time.Elapsed - clock_Start) div 1000)
    loop
	if seconds > 59 then
	    minutes += 1
	    seconds -= 60
	end if

	if minutes > 59 then
	    hours += 1
	    minutes -= 60
	end if
	exit when seconds  42 and x < 110 and y > 20 and y < 80 and button = 1 then
	    result 20
	elsif x > 140 and x < 210 and y > 95 and y < 160 and button = 1 then
	    result 30
	elsif x > 275 and x < 340 and y > 85 and y < 160 and button = 1 then
	    result 40
	elsif x > 370 and x < 440 and y > 22 and y < 85 and button = 1 then
	    result 60
	end if
    end loop
end HowManyMines

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Procedure Name: PlaceMines                          %
%Procedure Desc.: Randomly generates mine positions  %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
procedure PlaceMines
    for i : 1 .. numberOfMines
	loop
	    fail := false
	    mine (i).x := Rand.Int (1, 16)
	    mine (i).y := Rand.Int (1, 16)
	    for ii : 1 .. i - 1
		if mine (i).x = mine (ii).x and mine (i).y = mine (ii).y then
		    fail := true
		end if
	    end for
	    if fail = false then
		exit
	    end if
	end loop
    end for

    for i : 1 .. numberOfMines
	cell_Array (mine (i).x, mine (i).y).mine := true
    end for
end PlaceMines

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Procedure Name: GenerateNumber                          %
%Procedure Desc.: Find how many mines are near each cell %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
procedure GenerateNumber
    var num : int := 0
    for i : 1 .. 16
	for ii : 1 .. 16
	    if cell_Array (i, ii).mine = false then
		for j : max (i - 1, 1) .. min (i + 1, 16)
		    for k : max (ii - 1, 1) .. min (ii + 1, 16)
			if cell_Array (j, k).mine = true then
			    num := num + 1
			    cell_Array (i, ii).number := num
			end if
		    end for
		end for
	    end if
	    num := 0
	end for
    end for
    num := 0
end GenerateNumber

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Procedure Name: FindZeros                    %
%Procedure Desc.: Clicks all cells around 0's.%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
procedure FindZeros
    for i : 1 .. 16
	for ii : 1 .. 16
	    if cell_Array (i, ii).mine = false and
		    cell_Array (i, ii).clicked = true and
		    cell_Array (i, ii).number = 0 then
		for j : max (i - 1, 1) .. min (i + 1, 16)
		    for k : max (ii - 1, 1) .. min (ii + 1, 16)
			cell_Array (j, k).clicked := true
		    end for
		end for
	    end if
	end for
    end for
end FindZeros

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Function Name: CycleIcon                         %
%Function Desc.: Alternates between 1 and 0, used %
%for flags.                                       %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function CycleIcon (CurrentIcon : int) : int
    case CurrentIcon of
	label 0 :
	    result 1
	label 1 :
	    result 0
    end case
end CycleIcon

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Procedure Name: CheckWin                          %
%Procedure Desc.: Checks to see if user has won    %
%Note: 1 is win, 0 is no win                       %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function CheckWin : int
    var clicked : int := 0
    for i : 1 .. 16
	for ii : 1 .. 16
	    if cell_Array (i, ii).clicked = true then
		clicked := clicked + 1
	    end if
	end for
    end for

    if clicked = 256 - numberOfMines then
	result 1
    else
	result 0
    end if
end CheckWin

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Procedure Name: Initialise                        %
%Procedure Desc.: Initialises all program stuff    %
%Note: Used to keep code main loop neater          %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
procedure Initialise
    setscreen ("graphics:500;530")
    View.Set ("offscreenonly")
    buttonchoose ("multibutton")

    Pic.Draw (background1, 0, 0, picMerge) %Draw Title Background

    drawfillbox (150, 180, 350, 195, white)
    drawbox (150, 180, 350, 195, black)
    Draw.Text ("Loading...", 210, 200, font1, black) %Draw loading bar

    loop %Fake loading screen
	if loading_Bar > 335 then
	    loading_Bar := 350
	else
	    loading_Bar += Rand.Int (2, 15)
	end if
	drawfillbox (150, 180, loading_Bar, 195, cyan)
	drawbox (150, 180, loading_Bar, 195, black)
	delay (Rand.Int (10, 200))
	View.Update
	exit when loading_Bar = 350
    end loop

    cls
    clock_Start := Time.Elapsed %Begin clock
    Pic.Draw (background2, 0, 0, picMerge)
    Draw.Text ("Minesweeper", 175, 485, font2, black)

    for i : 1 .. 16 %Initialise cell boundories and properties
	for ii : 1 .. 16
	    cell_Array (i, ii).x1 := ((i - 1) * 30) + OFFSET
	    cell_Array (i, ii).y1 := ((ii - 1) * 30) + OFFSET
	    cell_Array (i, ii).clicked := false
	    cell_Array (i, ii).mine := false
	    cell_Array (i, ii).number := 0
	    cell_Array (i, ii).icon := 0
	end for
    end for
end Initialise

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Procedure Name: Reset%%%%%%%%%%%%%%%%%%%%%%
%Procedure Desc.: Resets variables%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
procedure Reset
    for i : 1 .. 16
	for ii : 1 .. 16
	    cell_Array (i, ii).clicked := false
	    cell_Array (i, ii).mine := false
	    cell_Array (i, ii).number := 0
	    cell_Array (i, ii).icon := 0
	end for
    end for

    winOrLose := 0
    clock_Start := Time.Elapsed
    lastbutton := 1
end Reset

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%FUNCTIONS/PROCEDURES END%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%MAIN LOOP BEGIN%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

Initialise
loop
    numberOfMines := HowManyMines
    PlaceMines
    GenerateNumber
    delay (200)
    loop
	Pic.Draw (background2, 0, 0, picMerge) %Draw background, clock, and title
	Draw.Text (Clock, 50, 495, font2, black)                            %
	Draw.Text ("Minesweeper", 175, 495, font2, black)                   %

	for i : 1 .. 16 %Draws black boxes behind cells
	    for ii : 1 .. 16
		drawfillbox (cell_Array (i, ii).x1 - 2, cell_Array (i, ii).y1 - 2, cell_Array (i, ii).x1 + 25, cell_Array (i, ii).y1 + 25, black)
	    end for
	end for

	mousewhere (x, y, button) %Gets mouse coords and button state

	for i : 1 .. 16 %Draws smaller blue box ontop of black creating a 1px border
	    for ii : 1 .. 16
		if x > cell_Array (i, ii).x1 - 3 and %If mouse is in cell boundries
			x < cell_Array (i, ii).x1 + 28 and %Then check if mouse is down
			y > cell_Array (i, ii).y1 - 5 and %If it is, check if mouse
			y < cell_Array (i, ii).y1 + 26 then %Button is down. If so,
		    if button = 1 then
			if lastbutton1 = 0 then
			    lastbutton1 := 1
			    if cell_Array (i, ii).mine = true then
				winOrLose := 2 %If we lose, set winOrLose to 2
			    end if
			    cell_Array (i, ii).clicked := true %Draw a light blue box
			    drawfillbox (cell_Array (i, ii).x1, cell_Array (i, ii).y1, cell_Array (i, ii).x1 + 25, cell_Array (i, ii).y1 + 25, blue)
			end if
		    else
			lastbutton1 := 0
			if button = 100 then %If right click, put/remove flag
			    if lastbutton = 0 then %Lastbutton prevents flickering
				lastbutton := 1 %Of flag
				cell_Array (i, ii).icon := CycleIcon (cell_Array (i, ii).icon)
			    end if
			else
			    lastbutton := 0
			end if

			if cell_Array (i, ii).clicked = true then %If a cell is clicked, display the number
			    drawfillbox (cell_Array (i, ii).x1, cell_Array (i, ii).y1, cell_Array (i, ii).x1 + 25, cell_Array (i, ii).y1 + 25, grey)
			    if cell_Array (i, ii).number not= 0 then
				Font.Draw (intstr (cell_Array (i, ii).number), cell_Array (i, ii).x1 + 8, cell_Array (i, ii).y1 + 6, font1, black)
			    end if
			else %Otherwise, display the blue box
			    drawfillbox (cell_Array (i, ii).x1, cell_Array (i, ii).y1, cell_Array (i, ii).x1 + 25, cell_Array (i, ii).y1 + 25, cyan)
			end if
		    end if
		else %Draw number if cell is clicked
		    if cell_Array (i, ii).clicked = true then
			drawfillbox (cell_Array (i, ii).x1, cell_Array (i, ii).y1, cell_Array (i, ii).x1 + 25, cell_Array (i, ii).y1 + 25, grey)
			if cell_Array (i, ii).number not= 0 then %Don't draw number if cell.number = 0
			    Font.Draw (intstr (cell_Array (i, ii).number), cell_Array (i, ii).x1 + 8, cell_Array (i, ii).y1 + 6, font1, black)
			end if
		    else
			if cell_Array (i, ii).mine = true and CHEAT = true then
			    drawfillbox (cell_Array (i, ii).x1, cell_Array (i, ii).y1, cell_Array (i, ii).x1 + 25, cell_Array (i, ii).y1 + 25, 5)
			else
			    drawfillbox (cell_Array (i, ii).x1, cell_Array (i, ii).y1, cell_Array (i, ii).x1 + 25, cell_Array (i, ii).y1 + 25, 150)
			end if
		    end if
		end if

		if cell_Array (i, ii).icon = 1 then %If cell's "icon" attribute is 1, draw flag
		    drawfillbox (cell_Array (i, ii).x1, cell_Array (i, ii).y1, cell_Array (i, ii).x1 + 25, cell_Array (i, ii).y1 + 25, grey)
		    Pic.Draw (flag, cell_Array (i, ii).x1 + 3, cell_Array (i, ii).y1 + 3, picMerge)
		end if
	    end for
	end for

	FindZeros %Look to see if we can expand any zeros

	if CheckWin = 1 then %If we've won, set winorLose to 1
	    winOrLose := 1
	end if

	View.Update %Update screen

	exit when winOrLose = 1 or winOrLose = 2 %Exit if we win or if we lose
    end loop

    case winOrLose of %DIsplay win/lose picture
	label 1 :
	    Pic.Draw (winscreen, 0, 0, picCopy)
	    Draw.Text (Clock, 370, 345, font1, black)

	label 2 :
	    Pic.Draw (losescreen, 0, 0, picCopy)
    end case

    View.Update
    delay (500) %Prevents buttons from being accidentally clicked

    loop
	mousewhere (x, y, button)
	if x > 100 and x < 400 and y > 50 and y < 125 and button = 1 then
	    retry := false %"No thanks!" button
	    exit
	elsif x > 100 and x < 400 and y > 145 and y < 215 and button = 1 then
	    retry := true %"Lets go!" button
	    exit
	end if
	View.Update
    end loop

    exit when retry = false %Exit loop/program if we don't want to retry

    Reset %Reset all variables since we want to play again

    delay (200) %Short delay so that we don't accidentally click cell
end loop

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%MAIN LOOP END%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%Personal Best - 2:26%%%%%%%%%%%%%%%%%%

-----------------------------------
Raknarg
Sat Jul 06, 2013 10:07 pm

RE:Grade 10 ICS Summative - Minesweeper
-----------------------------------
Just a cool way to write findzeroes: Recursion!


procedure FindZeros (x, y : int)  
    if cell (x, y).clicked = false and cell (x, y).numMines = 0 and x >= 1 and x = 1 and y 