Task: Flipping bits game


C++: #include <time.h>
#include <iostream>
#include <string>

typedef unsigned char byte;
using namespace std;

class flip
{
public:
    flip() { field = 0; target = 0; }
    void play( int w, int h ) { wid = w; hei = h; createField(); gameLoop(); }

private:
    void gameLoop()
    {
	int moves = 0;
	while( !solved() )
	{
	    display(); string r; cout << "Enter rows letters and/or column numbers: "; cin >> r;
	    for( string::iterator i = r.begin(); i != r.end(); i++ )
	    {
		byte ii = ( *i );
		if( ii - 1 >= '0' && ii - 1 <= '9' ) { flipCol( ii - '1' ); moves++; }
		else if( ii >= 'a' && ii <= 'z' ) { flipRow( ii - 'a' ); moves++; }
	    }
	}
	cout << endl << endl << "** Well done! **" << endl << "Used " << moves << " moves." << endl << endl;
    }

    void display()
    { system( "cls" ); output( "TARGET:", target ); output( "YOU:", field ); }

    void output( string t, byte* f )
    {
	cout << t << endl;
	cout << " "; for( int x = 0; x < wid; x++ ) cout << " " << static_cast<char>( x + '1' ); cout << endl;
	for( int y = 0; y < hei; y++ )
	{
	    cout << static_cast<char>( y + 'a' ) << " ";
	    for( int x = 0; x < wid; x++ )
		cout << static_cast<char>( f[x + y * wid] + 48 ) << " ";
	    cout << endl;
	}
	cout << endl << endl;
    }

    bool solved()
    {
	for( int y = 0; y < hei; y++ )
	    for( int x = 0; x < wid; x++ )
		if( target[x + y * wid] != field[x + y * wid] ) return false;
	return true;
    }

    void createTarget()
    {
	for( int y = 0; y < hei; y++ )
	    for( int x = 0; x < wid; x++ )
		if( frnd() < .5f ) target[x + y * wid] = 1;
	        else target[x + y * wid] = 0;
	memcpy( field, target, wid * hei );
    }

    void flipCol( int c )
    { for( int x = 0; x < hei; x++ ) field[c + x * wid] = !field[c + x * wid]; }
	
    void flipRow( int r )
    { for( int x = 0; x < wid; x++ ) field[x + r * wid] = !field[x + r * wid]; }

    void calcStartPos()
    {
	int flips = ( rand() % wid + wid + rand() % hei + hei ) >> 1;
	for( int x = 0; x < flips; x++ )
	{ if( frnd() < .5f ) flipCol( rand() % wid ); else flipRow( rand() % hei ); }
    }

    void createField()
    {
        if( field ){ delete [] field; delete [] target; }
        int t = wid * hei; field = new byte[t]; target = new byte[t];
	memset( field, 0, t ); memset( target, 0, t ); createTarget();
	while( true ) { calcStartPos(); if( !solved() ) break; }
    }

    float frnd() { return static_cast<float>( rand() ) / static_cast<float>( RAND_MAX ); }

    byte* field, *target; int wid, hei;
};

int main( int argc, char* argv[] )
{ srand( time( NULL ) ); flip g; g.play( 3, 3 ); return system( "pause" ); }




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);
        });
    }
}