[C#] Informatics Competition - Kassiopeia Reloaded [Part 3]

Hey Mates,

maybe you’ve seen the different topic name? It’s not necessary, but I thought this change is more suitable. However, you remember the challenge we had last time? This part is about evolving our program from last time.


Description

Kassiopeia can’t walk about every field as often as she wants anymore. Now she can only walk about every white field one time! The other rules stay the same. If you want you can add a simple animation, which shows how Kassiopeia crawls through the board.

You can use the same examples as last time. Download them here, if you have not done it already.
Can Kassiopeia rech all fields?
0) Yes

  1. No
  2. No
  3. Yes
  4. No
  5. Yes
  6. No
  7. No

My Solution

I just made some minor changes, because the program is already pretty suitable. The biggest change was the animation part and a new class for storing the global variables, so that we don’t have to give everything everytime (Wow, stylistic device! :sunglasses:) as argument. I’ve also removed the recursion joke :sweat:.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.IO;
using System.Threading;

namespace Kassiopeia
{
    class Program
    {
        static void Main(string[] args)
        {

            globals g = new globals();

            while (true)
            {
                //Get file
                String file = input("\nText File: ");

                //Read file / Fill board
                StreamReader f = new StreamReader(file);
                String line;
                int counter = 0;
                while((line = f.ReadLine()) != null)
                {
                    //First line -> Read rows and columns / Create board
                    if (counter == 0)
                    {
                        g.rows = int.Parse(line.Split(' ')[0]);
                        g.cols = int.Parse(line.Split(' ')[1]);

                        g.board = new Char[g.rows, g.cols];
                    }

                    //Else -> Fill board
                    else
                    {
                        for (int i = 0; i < g.cols; i++)
                        {
                            g.board[counter - 1, i] = line[i];
                        }
                    }

                    counter += 1;
                }

                // Test if every field can be reached by only walking about it once
                if (testBoard(g))
                {
                    Console.WriteLine("[*] Kassiopeia can reach all fields!");
                    String ok = input("[#] Do you want to see a nice animation? (Y/n) ");

                    if (ok.ToLower() == "y")
                        animate(g);
                }

                else
                {
                    Console.WriteLine("[!] Kassiopeia can't reach all fields!");
                }
            }
        }

        /// <summary>
        /// Show a sweet animation of our crawling Kassiopeia
        /// </summary>
        /// <param name="g"></param>
        static void animate(globals g)
        {
            for (int i = 0; i < g.connected.Count; i++)
            {
                //If not first element -> Change Kassiopeias position
                if (i != 0)
                {
                    int row = int.Parse(g.connected[i][0].ToString());
                    int col = int.Parse(g.connected[i][1].ToString());

                    int lastRow = int.Parse(g.connected[i - 1][0].ToString());
                    int lastCol = int.Parse(g.connected[i - 1][1].ToString());

                    g.board[lastRow, lastCol] = '°';
                    g.board[row, col] = 'K';
                }

                showBoard(g, i + 1);
            }
        }

        /// <summary>
        /// Prints out the board
        /// </summary>
        /// <param name="g"></param>
        /// <param name="counter"></param>
        static void showBoard(globals g, int counter)
        {
            Console.Clear();
            Console.WriteLine("-<>-<>-<>- Step " + counter.ToString() + " of " + g.connected.Count.ToString() + " -<>-<>-<>-");
            for (int row = 0; row < g.rows; row++)
            {
                for(int col = 0; col < g.cols; col++)
                {
                    Console.Write("[" + g.board[row, col] + "] ");
                }

                Console.WriteLine();
            }

            Thread.Sleep(650);
        }

        static bool testBoard(globals g)
        {
            //Count all white fields
            g.lenAll = 0;
            for (int row = 0; row < g.rows; row++)
            {
                for (int col = 0; col < g.cols; col++)
                {
                    if (g.board[row, col] == ' ' || g.board[row, col] == 'K')
                    {
                        g.lenAll += 1;
                    }
                }
            }

            //Find Kassiopeias position as starting point / Run recursive test to find all reachable fields
            for (int row = 0; row < g.rows; row++)
            {
                for (int col = 0; col < g.cols; col++)
                {
                    if (g.board[row, col] == 'K')
                    {
                        g.connected = new List<String>();
                        g.connected.Add(toXyString(row, col));
                        recursiveTestOfDoom(g, row, col);
                        break;
                    }
                }
            }

            //Test if all can be reached
            if (g.connected.Count == g.lenAll)
            {
                return true;
            }

            return false;
        }

        /// <summary>
        /// A recursive test of Doooooooom
        /// </summary>
        /// <param name="g"></param>
        /// <param name="row"></param>
        /// <param name="col"></param>
        static void recursiveTestOfDoom(globals g, int row, int col)
        {
            //Test above field
            if (row != 0)
            {
                if (g.board[row - 1, col] == ' ')
                {
                    if (!g.connected.Contains(toXyString(row - 1, col)))
                    {
                        g.connected.Add(toXyString(row - 1, col));
                        recursiveTestOfDoom(g, row - 1, col);
                    }
                }
            }

            //Test right field
            if (col != g.cols - 1)
            {
                if (g.board[row, col + 1] == ' ')
                {
                    if (!g.connected.Contains(toXyString(row, col + 1)))
                    {
                        g.connected.Add(toXyString(row, col + 1));
                        recursiveTestOfDoom(g, row, col + 1);
                    }
                }
            }

            //Test below field
            if (row != g.rows - 1)
            {
                if (g.board[row + 1, col] == ' ')
                {
                    if (!g.connected.Contains(toXyString(row + 1, col)))
                    {
                        g.connected.Add(toXyString(row + 1, col));
                        recursiveTestOfDoom(g, row + 1, col);
                    }
                }
            }

            //Test left field
            if (col != 0)
            {
                if (g.board[row, col - 1] == ' ')
                {
                    if (!g.connected.Contains(toXyString(row, col - 1)))
                    {
                        g.connected.Add(toXyString(row, col - 1));
                        recursiveTestOfDoom(g, row, col - 1);
                    }
                }
            }

            //Test if all fields are reached
            if (g.lenAll == g.connected.Count)
                return;

            //Remove this position from list
            g.connected.Remove(toXyString(row, col));
        }

        /// <summary>
        /// Builds a little String out of the x and y coordinate
        /// </summary>
        /// <param name="row"></param>
        /// <param name="col"></param>
        /// <returns></returns>
        static String toXyString(int row, int col)
        {
            return row.ToString() + col.ToString();
        }

        static String input(String text)
        {
            Console.Write(text);
            return Console.ReadLine();
        }
    }

    /// <summary>
    /// Just to store all globals, so that they don't have to be given everytime as argument
    /// </summary>
    class globals
    {
        public Char[,] board { get; set; }
        public List<String> connected { get; set; }
        public int rows { get; set; }
        public int cols { get; set; }
        public int lenAll { get; set; }
    }
}

Conclusion

This is just a simple upgrade to our program. Maybe it’s not that hard if you have already solved the part before, but it’s a good and simple exercise.

|-TheDoctor-|

1 Like

This topic was automatically closed after 30 days. New replies are no longer allowed.