function ticgui()

global f

% Tic Tac Toe formed with non-Guide GUI
% Developed by Charles Riedesel, May 1, 2010
% Compare to Guide-based GUI and non-GUI versions

global board its mark wins count namesIn showNames showMsg showWins showBoard

% vvvvvvvvvvvvv NEXT 30+ LINES DO NOT APPEAR IN NON-GUI vvvvvvvvvvvvvvvvvv

% here is the window for the game
f = figure('Visible', 'off', 'color', 'white', 'Position', [360, 500, 550, 600]);
set (f, 'Name', 'TicTacToe');
movegui(f, 'center')

% these are coordinates for the 9 positions on the board
x = [100 200 300 100 200 300 100 200 300];
y = [300 300 300 200 200 200 100 100 100];

% each position on the board is a pushbutton
for ii = 1:9
   showBoard(ii) = uicontrol('style','pushbutton', 'position', [x(ii),y(ii),90,90], ...
      'Callback', @process, 'Fontsize', 30, 'UserData', ii, 'string', ' ');
end

% two edit boxes to enter and hold player names
showNames(1) = uicontrol('style', 'edit', 'position', [100, 500, 300, 50], ...
    'String', 'Enter name here', 'Callback', @addName, 'Fontsize', 20, ...
    'userData', 1);
showNames(2) = uicontrol('style', 'edit', 'position', [100, 425, 300, 50], ...
    'String', 'Enter name here', 'Callback', @addName, 'Fontsize', 20, ...
    'userData', 2);

% generic message box - enter names, whose turn, who won, etc.
showMsg = uicontrol('style', 'text', 'Position', [100, 25, 400, 50], ...
    'String', 'Please enter names above', 'Fontsize', 20);

% count of wins for each player
showWins(1) = uicontrol('style', 'text', 'Position', [400, 500, 50, 50], ...
    'Fontsize', 20, 'String', '0');
showWins(2) = uicontrol('style', 'text', 'Position', [400, 425, 50, 50], ...
    'Fontsize', 20, 'String', '0');

% reset button to start a new game
uicontrol('style', 'pushbutton', 'Position', [400, 200, 100, 50], ...
    'String', 'Reset', 'Fontsize', 20, 'Callback', @playAgain);

% vvvvvvvvvvvvvv (following same as non-gui) vvvvvvvvvvvvvvvvvvvvv
its = 1;                         % whose turn, 1 or 2
count = 0;                       % count the (up to) 9 plays
mark = 'XO';                     % playing pieces for players 1 and 2
board = ['   ';'   ';'   '];     % internal representation of board
wins = [0,0];                    % internal count of wins
% ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
namesIn = 0;                     % count as players enter names

set(f, 'Visible', 'on')
end

% ================= CALL BACK FOR ENTERING NAMES ==================
function addName(source, ~)
% Callback for entering names, when both in, indicate ready to play
global namesIn mark names its showMsg

%set(source, 'Editing', 'off');
names{get(source, 'userData')} = get(source, 'string');
namesIn = namesIn + 1;
if namesIn == 2
   set(showMsg, 'String', [names{its} ' (playing ' mark(its) ') your play!'])
end
end

% ---------------- ENTERED UPON CLICKING A BOARD PIECE -----------
function  process(source, ~)
% Callback for Buttons on the Game Board

global board its mark names wins count showMsg showWins
pos = get(source, 'userData');

% vvvvvvvvvvvvvvvvvvv VERY SIMILAR TO NON-GUI vvvvvvvvvvvvvvvvvvvvv
r = ceil(pos/3);
c = mod(pos-1,3)+1;

% Continue processing only if open position and game not done
if board(r, c) == ' ' && count < 9
    count = count + 1;             % Increment play count
    board(r, c) = mark(its);       % Update both internal and GUI board
    set(source, 'String', mark(its));
    if winner()                    % Winner - force game done, do updates
        count = 9;
        wins(its) = wins(its) + 1;
        set(showMsg, 'String', [names{its} ' (playing ' mark(its) ') wins!']);
        set(showWins(its), 'String', wins(its))
    elseif count == 9              % Board is full - game over with a tie
        set(showMsg, 'String', 'Cat game - Press RESET');
    else                           % Switch to other player
        its = 3 - its;
        set(showMsg, 'String', [names{its} ' (playing ' mark(its) ') your play!'])
    end
end
end

% ------------------------------------------------------------------
function win = winner()
% Check for win by current player - Could be optimized!
global board its mark
win = (board(1,1) == mark(its) && board(1,1) == board(1,2) && board(1,2) == board(1,3)) || ...
      (board(2,1) == mark(its) && board(2,1) == board(2,2) && board(2,2) == board(2,3)) || ...
      (board(3,1) == mark(its) && board(3,1) == board(3,2) && board(3,2) == board(3,3)) || ...
      (board(1,1) == mark(its) && board(1,1) == board(2,1) && board(2,1) == board(3,1)) || ...
      (board(1,2) == mark(its) && board(1,2) == board(2,2) && board(2,2) == board(3,2)) || ...
      (board(1,3) == mark(its) && board(1,3) == board(2,3) && board(2,3) == board(3,3)) || ...
      (board(1,1) == mark(its) && board(1,1) == board(2,2) && board(2,2) == board(3,3)) || ...
      (board(1,3) == mark(its) && board(1,3) == board(2,2) && board(2,2) == board(3,1));
end

% --------------------------------------------------------------------
function  playAgain(source, ~)
% Callback for Reset Button

   global board its count mark showBoard showMsg names
   count = 0;
   for ii = 1:9                      % Reset the GUI board
      set(showBoard(ii), 'String', ' ')
   end
   board = ['   ';'   ';'   '];      % Reset the internal board
   if strcmp(mark, 'XO')             % Swap who starts on new game
      mark = 'OX';
      its = 2;
   else
      mark = 'XO';
      its = 1;
   end
   set(showMsg, 'String', [names{its} ' (playing ' mark(its) ') your play!'])
end
% ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

