Tic Tac Toe 
	 
	
		| Author | 
		Message | 
	 
		 
		metachief
 
  
 
    
		 | 
		
		
			
				  Posted: Wed Sep 16, 2009 9:25 pm    Post subject: Tic Tac Toe  | 
	
				
				 | 
			 
			 
				
  | 
			 
			
				What can be done more efficiently?
 
 
	  | Turing: | 	 		  
% Meta Chief
% May 20, 2009
% TicTacToe
/*
 
 A two player game of tic tac toe
 
 */
var mouseX, mouseY, mouseB  : int % Stores mouse properties
type BoardType  : array 1 ..  3,  1 ..  3 of int % Grid points type
var board  : BoardType  %Stores grid points
const squareSize  := 40 % Size of each square on the board
proc InitBoard  % Assigns all grid points to a value of zero
    for a  : lower (board ) ..  upper (board )
        for b  : lower (board ) ..  upper (board )
            board  (a, b ) := 0
        end for
    end for
end InitBoard
 proc DrawBoard  % Depending on the value of a grid point, the board is drawn
    for a  : lower (board ) ..  upper (board )
        for b  : lower (board ) ..  upper (board )
            drawbox (a  * squareSize, b  * squareSize, a  * squareSize + squareSize, b  * squareSize + squareSize,  black)
            if board  (a, b ) = 1 then  % If the grid point value is 1 an x is drawn
                drawline (a  * squareSize, b  * squareSize, a  * squareSize + squareSize, b  * squareSize + squareSize,  black)
                drawline (a  * squareSize + squareSize, b  * squareSize, a  * squareSize, b  * squareSize + squareSize,  black)
            elsif board  (a, b ) = 2 then % If the grid point value is 2 a circle is drawn
                drawoval (a  * squareSize + squareSize  div 2, b  * squareSize + squareSize  div 2, squareSize  div 2, squareSize  div 2,  black)
            end if
        end for
    end for
end DrawBoard
 var turn  : int := 1 % Stores the players' turn
var turnCount  : int := 0 % Counts the number of turns in total
proc UseMouse  % Allow the user to use the mouse to change the value on the grid
    for a  : lower (board ) ..  upper (board )
        for b  : lower (board ) ..  upper (board )
            var x, y  : int
            if Mouse.ButtonMoved ("down") then
                var buttonnumber, buttonupdown  : int
                Mouse.ButtonWait ("down", x, y, buttonnumber,
 
                    buttonupdown )
                if mouseX  div squareSize <=  upper (board ) and mouseY  div squareSize <=  upper (board ) and mouseX  div squareSize >=  lower (board ) and mouseY  div squareSize >=  lower (board ) then
                    % If the mouse in on the board (to prevent out of range error)
                    if board  (mouseX  div squareSize, mouseY  div squareSize ) = 0 then
                        board  (mouseX  div squareSize, mouseY  div squareSize ) := turn  % Turn represents an x or a cricle depending on the turn
                        if turn  = 1 then
                            turn  := 2
                        elsif turn  = 2 then
                            turn  := 1
                        end if
                        turnCount + = 1
                    end if
                end if
            end if
        end for
    end for
end UseMouse
 fcn CheckWin  : int % Checks possivle win conditions
    for i  : 1 ..  2
        if board  (1,  1) = i  and board  (2,  2) = i  and board  (3,  3) = i  then
            result i
         elsif board  (1,  1) = i  and board  (1,  2) = i  and board  (1,  3) = i  then
            result i
         elsif board  (1,  1) = i  and board  (2,  1) = i  and board  (3,  1) = i  then
            result i
         elsif board  (2,  1) = i  and board  (2,  2) = i  and board  (2,  3) = i  then
            result i
         elsif board  (3,  1) = i  and board  (3,  2) = i  and board  (3,  3) = i  then
            result i
         elsif board  (3,  1) = i  and board  (2,  2) = i  and board  (1,  3) = i  then
            result i
         elsif board  (1,  3) = i  and board  (2,  3) = i  and board  (3,  3) = i  then
            result i
         elsif board  (1,  2) = i  and board  (2,  2) = i  and board  (3,  2) = i  then
            result i
         end if
    end for
    result 0
end CheckWin
 proc DrawWord  (x, y, c  : int, word  : string) % Draws words with specified position and color
    var fontID  : int
    fontID  := Font.New ("mono:12:bold")
    Font.Draw (word, x -  (Font.Width (word, fontID ) div 2), y, fontID, c )
    Font.Free (fontID )
end DrawWord
 proc ShowTurn  % Displays the turn of the players
    DrawWord  (maxx div 2,  maxy -  20,  black,  "Player " +  intstr (turn ))
end ShowTurn
 proc Main
     var winID  : int
    winID  := Window.Open ("offscreenonly,graphics:200,200,position:centre,centre")
    InitBoard  % Initialises the game grid
    loop
        mousewhere (mouseX, mouseY, mouseB )
        UseMouse
 
        DrawBoard
 
        ShowTurn
         if CheckWin  = 1 then
            cls
            DrawWord  (maxx div 2,  maxy div 2,  black,  "Player " +  intstr (CheckWin ) +  " won!")
            exit
        elsif CheckWin  = 2 then
            cls
            DrawWord  (maxx div 2,  maxy div 2,  black,  "Player " +  intstr (CheckWin ) +  " won!")
            exit
        elsif turnCount  = 9 and CheckWin  = 0 then
            cls
            DrawWord  (maxx div 2,  maxy div 2,  black,  "Tie!")
            exit
        end if
        View.Update
        cls
    end loop
end Main
 % Main
Main
   | 	 
  | 
			 
			
				 | 
			 
		  | 
	 
	 
		 | 
		
		 | 
	 
	  
		  | 
	 
		 
		Sponsor Sponsor 
		 
  
		 | 
		
 | 
	 
	 
		  | 
	 
				 
		Zren
 
  
 
    
		 | 
		
		
			
				  Posted: Wed Sep 16, 2009 10:27 pm    Post subject: Re: Tic Tac Toe  | 
	
				
				 | 
			 
			 
				
  | 
			 
			
				Other than converting the CheckWin if statements into one long unreadable line. Though that would make it faster to type, and less readability.
 
It's nicely done for a simple game of tic tac toe.
 
 
Though I'm all about code shortening so we could make this:
 
	  | Turing: | 	 		  
if CheckWin  = 1 then 
            cls 
            DrawWord  (maxx div 2,  maxy div 2,  black,  "Player " +  intstr (CheckWin ) +  " won!") 
            exit 
        elsif CheckWin  = 2 then 
            cls 
            DrawWord  (maxx div 2,  maxy div 2,  black,  "Player " +  intstr (CheckWin ) +  " won!") 
            exit
end if
  | 	  
 
 
Into this:
 
	  | Turing: | 	 		  
if CheckWin  = 1 | CheckWin  = 2 then 
            cls 
            DrawWord  (maxx div 2,  maxy div 2,  black,  "Player " +  intstr (CheckWin ) +  " won!") 
            exit 
end if
  | 	  
 
 
| can be replaced with or by the way. | 
			 
			
				 | 
			 
		  | 
	 
	 
		 | 
		
		 | 
	 
	  
		  | 
	 
				 
		DemonWasp
 
 
 
    
		 | 
		
		
			
				  Posted: Wed Sep 16, 2009 11:56 pm    Post subject: RE:Tic Tac Toe  | 
	
				
				 | 
			 
			 
				
  | 
			 
			
				In InitBoard:
 
- Be aware that lower ( board ) and upper ( board ) will return only the length of the first dimension. While this code will work for square arrays (which is all you need), it won't work for anything non-square.
 
 
 
In CheckForWin:
 
- You don't need to check for both players, you just need to check that the parts of the array have the same value. If you compare (1,1) to (2,2) and find them to be equal and that (2,2) = (3,3), then you know that someone has won. You can then just use the value of any one of those squares to see who won.
 
- You could also use for loops over the array to shorten the amount of code you'd have to write.
 
 
 
In DrawWord:
 
- With frequently-used resources like fonts, it's probably best to create them once, cache them, then free them only when you're really done with them. Right now, every time you DrawWord, Turing has to load the requested font before it can draw.
 
 
 
Not bad though. | 
			 
			
				 | 
			 
		  | 
	 
	 
		 | 
		
		 | 
	 
	  
		  | 
	 
				 
		A.J
 
  
 
    
		 | 
		
		
			
				  Posted: Thu Sep 17, 2009 7:44 am    Post subject: RE:Tic Tac Toe  | 
	
				
				 | 
			 
			 
				
  | 
			 
			
				Good job, metachief 
 
 
Well, I would suggest that you store the tic tac toe board in a one dimensional array instead of a two dimensional array.
 
 
So, for example, the position (1, 1). would become 1, and the position (1, 2) would become 2, etc...
 
(something like this:
 
 ____________
 
|  1  |  2  |  3  |
 
|  4  |  5  |  6  |
 
|  7  |  8  |  9  |
 
 ____________
 
 
Using a simple hashing function to hash coordinates on the board to a single integer would be pretty easy (for example, in this case, given x and y, (x, y) on the board is y + 3*(x-1)). And, this can make it easier to work with. | 
			 
			
				 | 
			 
		  | 
	 
	 
		 | 
		
		 | 
	 
	  
		  | 
	 
				 
		 | 
	 
 
	
	
	 
	
	 |