Task: Flipping bits game





Java: import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;

public class FlippingBitsGame extends JPanel {
    final int maxLevel = 7;
    final int minLevel = 3;

    private Random rand = new Random();
    private int[][] grid, target;
    private Rectangle box;
    private int n = maxLevel;
    private boolean solved = true;

    FlippingBitsGame() {
        setPreferredSize(new Dimension(640, 640));
        setBackground(Color.white);
        setFont(new Font("SansSerif", Font.PLAIN, 18));

        box = new Rectangle(120, 90, 400, 400);

        startNewGame();

        addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                if (solved) {
                    startNewGame();
                } else {
                    int x = e.getX();
                    int y = e.getY();

                    if (box.contains(x, y))
                        return;

                    if (x > box.x && x < box.x + box.width) {
                        flipCol((x - box.x) / (box.width / n));

                    } else if (y > box.y && y < box.y + box.height)
                        flipRow((y - box.y) / (box.height / n));

                    if (solved(grid, target))
                        solved = true;

                    printGrid(solved ? "Solved!" : "The board", grid);
                }
                repaint();
            }
        });
    }

    void startNewGame() {
        if (solved) {

            n = (n == maxLevel) ? minLevel : n + 1;

            grid = new int[n][n];
            target = new int[n][n];

            do {
                shuffle();

                for (int i = 0; i < n; i++)
                    target[i] = Arrays.copyOf(grid[i], n);

                shuffle();

            } while (solved(grid, target));

            solved = false;
            printGrid("The target", target);
            printGrid("The board", grid);
        }
    }

    void printGrid(String msg, int[][] g) {
        System.out.println(msg);
        for (int[] row : g)
            System.out.println(Arrays.toString(row));
        System.out.println();
    }

    boolean solved(int[][] a, int[][] b) {
        for (int i = 0; i < n; i++)
            if (!Arrays.equals(a[i], b[i]))
                return false;
        return true;
    }

    void shuffle() {
        for (int i = 0; i < n * n; i++) {
            if (rand.nextBoolean())
                flipRow(rand.nextInt(n));
            else
                flipCol(rand.nextInt(n));
        }
    }

    void flipRow(int r) {
        for (int c = 0; c < n; c++) {
            grid[r][c] ^= 1;
        }
    }

    void flipCol(int c) {
        for (int[] row : grid) {
            row[c] ^= 1;
        }
    }

    void drawGrid(Graphics2D g) {
        g.setColor(getForeground());

        if (solved)
            g.drawString("Solved! Click here to play again.", 180, 600);
        else
            g.drawString("Click next to a row or a column to flip.", 170, 600);

        int size = box.width / n;

        for (int r = 0; r < n; r++)
            for (int c = 0; c < n; c++) {
                g.setColor(grid[r][c] == 1 ? Color.blue : Color.orange);
                g.fillRect(box.x + c * size, box.y + r * size, size, size);
                g.setColor(getBackground());
                g.drawRect(box.x + c * size, box.y + r * size, size, size);
                g.setColor(target[r][c] == 1 ? Color.blue : Color.orange);
                g.fillRect(7 + box.x + c * size, 7 + box.y + r * size, 10, 10);
            }
    }

    @Override
    public void paintComponent(Graphics gg) {
        super.paintComponent(gg);
        Graphics2D g = (Graphics2D) gg;
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);

        drawGrid(g);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame f = new JFrame();
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.setTitle("Flipping Bits Game");
            f.setResizable(false);
            f.add(new FlippingBitsGame(), BorderLayout.CENTER);
            f.pack();
            f.setLocationRelativeTo(null);
            f.setVisible(true);
        });
    }
}






Fortran: 
program flipping_bits
implicit none
character(len=*), parameter :: cfmt = "(A3)", ifmt = "(I3)"
integer :: N, i, j, io, seed(8), moves, input
logical, allocatable :: Brd(:,:), Trgt(:,:)
logical :: solved
double precision :: r

do
  write(*,*) 'Enter the number of squares (between 1 and 10) you would like: '
  read(*,*,iostat=io) N
  if(N.gt.0 .and. N.le.10 .and. io.eq.0) exit
  write(*,*) 'Please, an integer between 1 and 10'
end do

allocate(Brd(N,N),Trgt(N,N))
call date_and_time(values=seed)
call srand(1000*seed(7)+seed(8)+60000*seed(6))
do i = 1,N
  do j = 1,N
    r = rand()
    if(r.gt.0.5D0) then
      Brd(i,j) = .TRUE.
      Trgt(i,j) = .TRUE.
    else
      Brd(i,j) = .FALSE.
      Trgt(i,j) = .FALSE.
    end if
  end do
end do

moves = N
do i = 1,moves
  r = 1+2.0D0*dble(N)*rand() - 1.0D-17 
  if(floor(r).le.N) then
    do j = 1,N
      Trgt(floor(r),j) = .NOT.Trgt(floor(r),j)
    end do
  else
    r = r-N
    do j = 1,N
      Trgt(j,floor(r)) = .NOT.Trgt(j,floor(r))
    end do
  end if
end do


do
  input = N
  call next_move(Brd,Trgt,N,input,solved)
  call next_move(Brd,Trgt,N,input,solved)
  if(solved) then
    r = 1+2.0D0*dble(N)*rand() - 1.0D-17
    if(floor(r).le.N) then
      do j = 1,N
        Trgt(floor(r),j) = .NOT.Trgt(floor(r),j)
      end do
    else
      r = r-N
      do j = 1,N
        Trgt(j,floor(r)) = .NOT.Trgt(j,floor(r))
      end do
    end if
  else
    exit
  end if
end do

write(*,*) 'Welcome to the Flipping Bits game
write(*,*) 'You have the current position'

moves = 0
call display(Brd,Trgt,N)
input = N
do
  write(*,*) 'Number of moves so far:', moves
  write(*,*) 'Select the column or row you wish to flip: '
  read(*,*,iostat=io) input
  if(io.eq.0 .and. input.gt.0 .and. input.le.(2*N)) then
    moves = moves+1
    write(*,*) 'Flipping ', input
    call next_move(Brd,Trgt,N,input,solved)
    call display(Brd,Trgt,N)
    if(solved) exit
  else
    write(*,*) 'Please enter a valid column or row number. To quit, press Ctrl+C
  end if
end do

write(*,*) 'Congratulations
write(*,ifmt,advance='no') moves
write(*,*) ' moves were taken by you
deallocate(Brd,Trgt)
end program

subroutine display(Brd,Trgt,N)
implicit none

integer :: N
logical :: Brd(N,N), Trgt(N,N)

character(len=*), parameter :: cfmt = "(A3)", ifmt = "(I3)"
integer :: i, j
write(*,*) 'Current Configuration: '
do i = 0,N
  if(i.eq.0) then
    write(*,cfmt,advance='no') 'R/C'
    write(*,cfmt,advance='no') ' | '
  else
    write(*,ifmt,advance='no') i
  end if
end do
write(*,*) 
do i = 0,N
  if(i.eq.0) then
    do j = 0,N+2
      write(*,cfmt,advance='no') '---'
    end do
  else
    write(*,ifmt,advance='no') i+N
    write(*,cfmt,advance='no') ' | '
    do j = 1,N
      if(Brd(i,j)) then
        write(*,ifmt,advance='no') 1
      else
        write(*,ifmt,advance='no') 0
      end if
    end do
  end if
  write(*,*)
end do

write(*,*)
write(*,*)

write(*,*) 'Target Configuration'
do i = 0,N
  if(i.eq.0) then
    write(*,cfmt,advance='no') 'R/C'
    write(*,cfmt,advance='no') ' | '
  else
    write(*,ifmt,advance='no') i
  end if
end do
write(*,*) 
do i = 0,N
  if(i.eq.0) then
    do j = 0,N+2
      write(*,cfmt,advance='no') '---'
    end do
  else
    write(*,ifmt,advance='no') i+N
    write(*,cfmt,advance='no') ' | '
    do j = 1,N
      if(Trgt(i,j)) then
        write(*,ifmt,advance='no') 1
      else
        write(*,ifmt,advance='no') 0
      end if
    end do
  end if
  write(*,*)
end do
write(*,*)
write(*,*)
end subroutine

subroutine next_move(Brd,Trgt,N,input,solved)
implicit none

integer :: N, input
logical :: Brd(N,N), Trgt(N,N), solved

integer :: i,j

if(input.gt.N) then
  input = input-N
  do i = 1,N
    Brd(input,i) = .not.Brd(input,i)
  end do
else
  do i = 1,N
    Brd(i,input) = .not.Brd(i,input)
  end do
end if
solved = .TRUE.
do i = 1,N
  do j = 1,N
    if( (.not.Brd(i,j).and.Trgt(i,j)) .or. (Brd(i,j).and..not.Trgt(i,j)) ) then
      solved = .FALSE.
      exit
    end if
  end do
  if(.not.solved) exit
end do
end subroutine