function gameRandAll = suds(v)
% Generate completed instance of 4 x 4 Sudoku game
% logical v selects valid game (true) or invalid game (false)

% Author: Charles Riedesel
% Date:   September 8, 2018

% -----------------------------------------------------------------------
% carefully crafted valid game
gameOriginal = [1 2 3 4;4 3 1 2;2 1 4 3;3 4 2 1];

% -----------------------------------------------------------------------
if ~v                                  % (false) invalidate the original game
   if randi([false,true],1)            % invalidate by row/column or by quadrant?
      swapCol = randi(3,1);            % (by row/column) swap pair of elements on
      t = gameOriginal(1,swapCol);     % first row (col 1-3 with col 4) to
      gameOriginal(1,swapCol) = gameOriginal(1,4);  % induce a duplicate in
      gameOriginal(1,4) = t;           % corresponding columns
   else
      swapCol1 = randi([1,2],1);       % (by quadrant) swap pair of columns between 
      swapCol2 = randi([3,4],1);       % left side quadrants and right side
      t = gameOriginal(:,swapCol1);    % quadrants to induce a duplicate in
      gameOriginal(:,swapCol1) = gameOriginal(:,swapCol2);  % at least one
      gameOriginal(:,swapCol2) = t;    % quadrant
   end
end

% -----------------------------------------------------------------------
if randi([false,true],1)               % increase variety (but not affect validity)
   gameOriginal = gameOriginal';       % by transposing original game
end

% -----------------------------------------------------------------------
% all the ways to scramble rows/columns without affecting validity
% (all swaps leave quadrants intact) 
seq = [1 2 3 4; 1 2 4 3; 2 1 3 4; 2 1 4 3; 3 4 1 2;4 3 1 2;3 4 2 1; 4 3 2 1];

% -----------------------------------------------------------------------
% randomly reorder rows, then columns (both safely)
gameRandRows = gameOriginal(seq(randi(8,1),:),:);
gameRandAll  = gameRandRows(:,seq(randi(8,1),:));

end

