Click here to Skip to main content
15,891,841 members
Articles / Desktop Programming / Windows Forms

Calcoolation: A Math Puzzle Board Game

Rate me:
Please Sign up or sign in to vote.
5.00/5 (23 votes)
6 Aug 2009CPOL5 min read 120.9K   2.9K   53  
Demo for a math puzzle board game
using System;
using System.Collections.Generic;
using System.Text;

namespace Calcoolation.Core
{
    /// <summary>
    /// Represents the game board. Provides funcionalities for random generation for: numbers, cages and operations
    /// </summary>
    public class Board
    {
        #region attributes
        int currentOperation = 0;
        int size = 0;
        Cell[,] matrix = null;
        List<Cage> cages = new List<Cage>();
        static Board instance;
        #endregion attributes

        #region constructor

        private Board()
        {
            currentOperation = (DateTime.Now.Millisecond % 4) + 1;
        }

        #endregion constructor

        #region properties
        public static Board Instance
        {
            get
            {
                if (instance == null)
                    instance = new Board();
                return instance;
            }
        }
        #endregion properties

        #region methods

        public void GenerateBoard(int size)
        {
            this.size = size;
            this.matrix = new Cell[size, size];
            ResetBoard();
            GenerateNumbers();
            GenerateCages();
        }

        public void PickOperation(Cage cage)
        {
            bool success = false;

            while (!success)
            {
                if (currentOperation == 5)
                    currentOperation = 1;

                switch (currentOperation)
                {
                    case 1:
                        cage.Operation = Operations.Plus;
                        int sum = 0;
                        foreach (Cell cell in cage.CellList)
                        {
                            sum += Convert.ToInt32(cell.CellValue);
                        }
                        cage.Result = sum;
                        success = true;
                        break;
                    case 2:
                        cage.Operation = Operations.Minus;
                        if (cage.CellList.Count == 2)
                        {
                            int sub = Convert.ToInt32(cage.CellList[0].CellValue) - Convert.ToInt32(cage.CellList[1].CellValue);
                            if (sub > 0)
                            {
                                cage.Result = sub;
                                success = true;
                            }
                            else
                            {
                                sub = Convert.ToInt32(cage.CellList[1].CellValue) - Convert.ToInt32(cage.CellList[0].CellValue);
                                if (sub > 0)
                                {
                                    cage.Result = sub;
                                    success = true;
                                }
                            }
                        }
                        break;
                    case 3:
                        cage.Operation = Operations.Multiply;
                        int mult = 1;
                        foreach (Cell cell in cage.CellList)
                        {
                            mult *= Convert.ToInt32(cell.CellValue);
                        }
                        cage.Result = mult;
                        success = true;
                        break;
                    case 4:
                        cage.Operation = Operations.Divide;
                        if (cage.CellList.Count == 2)
                        {
                            int quo = Convert.ToInt32(cage.CellList[0].CellValue) / Convert.ToInt32(cage.CellList[1].CellValue);
                            int rem = Convert.ToInt32(cage.CellList[0].CellValue) - quo * Convert.ToInt32(cage.CellList[1].CellValue);
                            if (rem == 0)
                            {
                                cage.Result = quo;
                                success = true;
                            }
                            else
                            {
                                quo = Convert.ToInt32(cage.CellList[1].CellValue) / Convert.ToInt32(cage.CellList[0].CellValue);
                                rem = Convert.ToInt32(cage.CellList[1].CellValue) - quo * Convert.ToInt32(cage.CellList[0].CellValue);
                                if (rem == 0)
                                {
                                    cage.Result = quo;
                                    success = true;
                                }
                            }
                        }
                        break;
                }

                currentOperation++;
            }
        }

        public bool TestResult()
        {
            bool success = true;

            string testString = "";
            for (int i = 1; i <= size; i++)
            {
                testString += i.ToString();
            }

            List<int> userList = new List<int>();
            string userString = "";

            //Testing row numbers
            for (int row = 0; row < size; row++)
            {
                userList = new List<int>();
                userString = "";

                for (int column = 0; column < size; column++)
                    userList.Add(matrix[column, row].UserValue);

                userList.Sort();

                for (int i = 0; i < size; i++)
                    userString += userList[i].ToString();
                
                success = success && userString.Equals(testString);
            }

            //Testing column numbers
            for (int column = 0; column < size; column++)
            {
                userList = new List<int>();
                userString = "";
                
                for (int row = 0; row < size; row++)
                    userList.Add(matrix[column, row].UserValue);

                userList.Sort();

                for (int i = 0; i < size; i++)
                    userString += userList[i].ToString();

                success = success && userString.Equals(testString);
            }

            //Testing each cage
            foreach (Cage cage in cages)
            {
                success = success && cage.TestResult();
            }

            return success;
        }

        private void GenerateNumbers()
        {
            ResetBoard();

            Random rnd = new Random();

            string number = "0";

            int minSize = size;
            int maxSize = 0;
            bool someSolved = true;

            while (someSolved)
            {
                someSolved = false;

                //Search for naked pairs in rows
                if (!someSolved)
                {
                    for (int row = 0; row < size; row++)
                    {
                        string nakedPairValue = "";
                        Point nakedPair1 = new Point(0,0);
                        Point nakedPair2 = new Point(0, 0);
                        int nakedPairCount = 0;

                        for (int column = 0; column < size - 1; column++)
                        {
                            //if (matrix[column, row].CellValidValues.Length == 2)
                            if (matrix[column, row].CellValidValues.Length == 2)
                            {
                                nakedPair1 = new Point(column, row);
                                nakedPairValue = matrix[column, row].CellValidValues;
                                nakedPairCount = 1;

                                for (int c = column + 1; c < size; c++)
                                {
                                    if (matrix[c, row].CellValidValues.Length == 2 && matrix[c, row].CellValidValues == nakedPairValue && c != column)
                                    {
                                        nakedPair2 = new Point(c, row);
                                        nakedPairCount++;
                                    }
                                }

                                //2 naked pairs found?
                                if (nakedPairCount == 2)
                                {
                                    //remove naked pairs values from the other cells in the same row
                                    for (int c = 0; c < size; c++)
                                    {
                                        if (c != nakedPair1.X && c != nakedPair2.X && matrix[c, row].CellValidValues.Length > 1)
                                        {
                                            if (matrix[c, row].CellValidValues.Contains(nakedPairValue[0].ToString()))
                                            {
                                                matrix[c, row].CellValidValues = matrix[c, row].CellValidValues.Replace(nakedPairValue[0].ToString(), "");
                                            }

                                            if (matrix[c, row].CellValidValues.Contains(nakedPairValue[1].ToString()))
                                            {
                                                matrix[c, row].CellValidValues = matrix[c, row].CellValidValues.Replace(nakedPairValue[1].ToString(), "");
                                            }
                                        }
                                    }
                                }
                            }                            
                        }
                    }
                }

                //Search for naked pairs in columns
                if (!someSolved)
                {
                    for (int column = 0; column < size; column++)
                    {
                        string nakedPairValue = "";
                        Point nakedPair1 = new Point(0, 0);
                        Point nakedPair2 = new Point(0, 0);
                        int nakedPairCount = 0;

                        for (int row = 0; row < size - 1; row++)
                        {
                            if (matrix[column, row].CellValidValues.Length == 2)
                            {
                                nakedPair1 = new Point(column, row);
                                nakedPairValue = matrix[column, row].CellValidValues;
                                nakedPairCount = 1;

                                for (int r = row + 1; r < size; r++)
                                {
                                    if (matrix[column, r].CellValidValues.Length == 2 && matrix[column, r].CellValidValues == nakedPairValue && r != row)
                                    {
                                        nakedPair2 = new Point(column, r);
                                        nakedPairCount++;
                                    }
                                }

                                //2 naked pairs found?
                                if (nakedPairCount == 2)
                                {
                                    //remove naked pairs values from the other cells in the same column
                                    for (int r = 0; r < size; r++)
                                    {
                                        if (r != nakedPair1.Y && r != nakedPair2.Y && matrix[column, r].CellValidValues.Length > 1)
                                        {
                                            if (matrix[column, r].CellValidValues.Contains(nakedPairValue[0].ToString()))
                                            {
                                                matrix[column, r].CellValidValues = matrix[column, r].CellValidValues.Replace(nakedPairValue[0].ToString(), "");
                                            }

                                            if (matrix[column, r].CellValidValues.Contains(nakedPairValue[1].ToString()))
                                            {
                                                matrix[column, r].CellValidValues = matrix[column, r].CellValidValues.Replace(nakedPairValue[1].ToString(), "");
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                //Search for naked triplets in rows
                for (int row = 0; row < size; row++)
                {
                    string nakedTripletValue = "";
                    Point nakedTriplet1 = new Point(0, 0);
                    Point nakedTriplet2 = new Point(0, 0);
                    Point nakedTriplet3 = new Point(0, 0);
                    int nakedTripletCount = 0;

                    for (int column = 0; column < size - 1; column++)
                    {
                        if (matrix[column, row].CellValidValues.Length == 3)
                        {
                            nakedTriplet1 = new Point(column, row);
                            nakedTriplet2 = new Point(0, 0);
                            nakedTriplet3 = new Point(0, 0);

                            nakedTripletValue = matrix[column, row].CellValidValues;
                            char char1 = nakedTripletValue[0];
                            char char2 = nakedTripletValue[1];
                            char char3 = nakedTripletValue[2];
                            nakedTripletCount = 1;

                            for (int c = 0; c < size; c++)
                            {
                                if (matrix[c, row].CellValidValues.Length > 1 && 
                                    (
                                        matrix[c, row].CellValidValues == (char1.ToString() + char2.ToString() + char3.ToString()) ||
                                        matrix[c, row].CellValidValues == (char1.ToString() + char2.ToString()) ||
                                        matrix[c, row].CellValidValues == (char1.ToString() + char3.ToString()) ||
                                        matrix[c, row].CellValidValues == (char2.ToString() + char3.ToString())
                                    )
                                    && c != nakedTriplet1.X && c != nakedTriplet2.X && c != nakedTriplet3.X)
                                {
                                    if (nakedTriplet2.X == 0)
                                        nakedTriplet2 = new Point(c, row);
                                    else
                                        nakedTriplet3 = new Point(c, row);

                                    nakedTripletCount++;
                                }
                            }

                            //3 naked Triplets found?
                            if (nakedTripletCount == 3)
                            {
                                //remove naked Triplets values from the other cells in the same row
                                for (int c = 0; c < size; c++)
                                {
                                    if (c != nakedTriplet1.X && c != nakedTriplet2.X && c != nakedTriplet3.X)
                                    {
                                        if (matrix[c, row].CellValidValues.Contains(char1.ToString()))
                                        {
                                            matrix[c, row].CellValidValues = matrix[c, row].CellValidValues.Replace(char1.ToString(), "");
                                        }

                                        if (matrix[c, row].CellValidValues.Contains(char2.ToString()))
                                        {
                                            matrix[c, row].CellValidValues = matrix[c, row].CellValidValues.Replace(char2.ToString(), "");
                                        }

                                        if (matrix[c, row].CellValidValues.Contains(char3.ToString()))
                                        {
                                            matrix[c, row].CellValidValues = matrix[c, row].CellValidValues.Replace(char3.ToString(), "");
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                //Search for cells with a unique solution possible
                for (int row = 0; row < size; row++)
                {
                    for (int column = 0; column < size; column++)
                    {
                        if (matrix[column, row].CellValidValues.Length == 1 && matrix[column, row].CellValue == "0")
                        {
                            number = matrix[column, row].CellValidValues;
                            SetValue(number, column, row);
                            someSolved = true;
                        }
                    }
                }

                //Random selection
                if (!someSolved)
                {
                    minSize = size;
                    for (int row = 0; row < size; row++)
                    {
                        for (int column = 0; column < size; column++)
                        {
                            if (matrix[column, row].CellValidValues.Length < minSize && matrix[column, row].CellValidValues.Length > 1)
                            {
                                minSize = matrix[column, row].CellValidValues.Length;
                            }

                            if (matrix[column, row].CellValidValues.Length > maxSize)
                                maxSize = matrix[column, row].CellValidValues.Length;
                        }
                    }

                    for (int row = 0; row < size; row++)
                    {
                        for (int column = 0; column < size; column++)
                        {
                            number = "0";

                            if (matrix[column, row].CellValue == "0" && matrix[column, row].CellValidValues.Length == minSize)
                            {
                                int pos = rnd.Next(1, matrix[column, row].CellValidValues.Length + 1);
                                number = matrix[column, row].CellValidValues.Substring(pos - 1, 1);

                                SetValue(number, column, row);

                                someSolved = true;
                                break;
                            }
                        }

                        if (someSolved)
                            break;
                    }
                }
            }
        }

        private void GenerateCages()
        {
            cages = new List<Cage>();

            bool success = false;
            int orientation = 0;
            int c2 = 0;
            int r2 = 0;

            Random rnd = new Random();

            for (int r = 0; r < size; r++)
            {
                for (int c = 0; c < size; c++)
                {
                    if (matrix[c, r].Cage == null)
                    {
                        success = false;
                        while (!success)
                        {
                            orientation = rnd.Next(1, 5);

                            switch (orientation)
                            {
                                case 1: // W
                                    c2 = c - 1;
                                    r2 = r;
                                    break;
                                case 2: // E
                                    c2 = c + 1;
                                    r2 = r;
                                    break;
                                case 3: // N
                                    c2 = c;
                                    r2 = r - 1;
                                    break;
                                case 4: // S
                                    c2 = c;
                                    r2 = r + 1;
                                    break;
                            }

                            if (c2 >= 0 && c2 < size && r2 >= 0 && r2 < size)
                            {
                                Cage cage = matrix[c2, r2].Cage;
                                if (cage == null)
                                {
                                    cage = new Cage();
                                    cage.CellList.Add(matrix[c2, r2]);
                                    matrix[c2, r2].Cage = cage;
                                }
                                else
                                {
                                    if (cage.CellList.Count > 3 && (c != size - 1 || r != size - 1))
                                    {
                                        continue;
                                    }
                                }

                                cage.CellList.Add(matrix[c, r]);
                                matrix[c, r].Cage = cage;
                                cages.Add(cage);
                                success = true;
                            }
                        }
                    }
                }
            }

            foreach (Cage cage in cages)
            {
                PickOperation(cage);
            }
        }

        private void ResetBoard()
        {
            string s = "";

            for (int c = 1; c <= size; c++)
                s += c.ToString();

            for (int row = 0; row < size; row++)
            {
                for (int column = 0; column < size; column++)
                {
                    matrix[column, row] = new Cell();
                    matrix[column, row].CellValue = "0";
                    matrix[column, row].CellValidValues = s;
                    matrix[column, row].Column = column;
                    matrix[column, row].Row = row;
                    matrix[column, row].UserValue = 0;
                }
            }
        }

        private void SetValue(string number, int column, int row)
        {
            for (int c = 0; c < size; c++)
            {
                matrix[c, row].CellValidValues = matrix[c, row].CellValidValues.Replace(number, "");
            }

            for (int r = 0; r < size; r++)
            {
                matrix[column, r].CellValidValues = matrix[column, r].CellValidValues.Replace(number, "");
            }

            matrix[column, row].CellValidValues = number;
            matrix[column, row].CellValue = number;
        }

        #endregion methods

        #region properties
        public Cell[,] Matrix
        {
            get { return matrix; }
        }

        public List<Cage> Cages
        {
            get { return cages; }
        }
        #endregion properties
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Instructor / Trainer Alura Cursos Online
Brazil Brazil

Comments and Discussions