using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace Post
{
class Program
{
#region Внутренние переменны - состояния
public const int _tapeSize = 1000;
public const int _commandsSize = 1000;
public static bool[] _tape = new bool[_tapeSize];
public static string[] _commands = new string[_commandsSize];
public static int _tapePointer = _tapeSize/2; // указывает на обозреваемую секцию (текущую ячейку памяти)
public static int _commandPointer = 0; // указывает на текущую команду
#endregion
#region Главный метод
//Гланый метод. Отсюда стартует программа
static void Main(string[] args)
{
do
{
PrintMenu();
}
while (ChooseMenuItem());
}
#endregion
#region Управление лентой - простейшие, атомарные операции
//Отмечаем обозреваемую секцию
public static void Mark()
{
_tape[_tapePointer] = true;
}
//Стираем отметку в обозреваемой секции
public static void Unmark()
{
_tape[_tapePointer] = false;
}
//Сдвигаем каретку влево. (Меняется обозреваемая секция)
public static void Left()
{
_tapePointer--;
}
//Сдвигаем каретку вправо. (Меняется обозреваемая секция)
public static void Right()
{
_tapePointer++;
}
//Передаем два номера команды. Если обозреваемая секция отмечена, то возвращается второй номер, если нет - первый
public static int Jump(int firstCommandAddress, int secondCommandAddress) // верхняя, нижнняя
{
if (_tape[_tapePointer])
return secondCommandAddress;
else
return firstCommandAddress;
}
#endregion
#region Основные методы работы с машиной Поста
// Основной метод. Запускает машину поста в действие
public static void StartPostMachine()
{
while (CommandExecution(_commands[_commandPointer]))
{
}
}
public static bool CommandExecution(string query)
{
if (string.IsNullOrWhiteSpace(query))
return false;
if(!query.Contains(' '))
return false;
string[] queryArray = query.Split(' ');
string command = queryArray[0];
switch (command)
{
case "V":
Mark();
_commandPointer = Int32.Parse(queryArray[1]);
return true;
case "X":
Unmark();
_commandPointer = Int32.Parse(queryArray[1]);
return true;
case "->":
Right();
_commandPointer = Int32.Parse(queryArray[1]);
return true;
case "<-":
Left();
_commandPointer = Int32.Parse(queryArray[1]);
return true;
case "?":
_commandPointer = Jump(Int32.Parse(queryArray[1]), Int32.Parse(queryArray[2]));
return true;
default:
return false;
}
}
// Очистка ленты
public static void TapeClear()
{
for (int i = 0; i < _tapeSize; i++)
{
_tape[i] = false;
}
_tapePointer = _tapeSize/2;
}
//Очистка комманд
public static void СommandsClear()
{
for (int i = 0; i < _commandsSize; i++)
{
_commands[i] = null; ;
}
_commandPointer = 0;
}
// Полная очистка и возвращение к исходным данным
public static void Refresh()
{
TapeClear();
СommandsClear();
}
#endregion
#region Меню и работа с ним
// Печать меню
public static void PrintMenu()
{
Console.WriteLine("Добро пожаловать в симулятор машины Поста, выбирите действия");
Console.WriteLine("\t1. Введите данные на ленту");
Console.WriteLine("\t2. Введите команды");
Console.WriteLine("\t3. Показать состояние машины Поста");
Console.WriteLine("\t4. Запустить машину Поста");
Console.WriteLine("\t5. Краткая справка о машине Поста");
Console.WriteLine("\t6. Загрузить пример прибавления еденицы для машины Поста");
Console.WriteLine("\t7. Загрузить пример программы для машины Поста");
Console.WriteLine("\t8. Загрузить пример программы для машины Поста");
Console.WriteLine("\t9. Выйти");
}
// Функция выбора действия в программе. Связана с меню.
public static bool ChooseMenuItem()
{
string tmpStr = Console.ReadLine();
if (tmpStr == "1")
{
InputIntoTape();
return true;
}
if (tmpStr == "2")
{
InputIntoRulesTable();
return true;
}
if (tmpStr == "3")
{
PrintState();
return true;
}
if (tmpStr == "4")
{
Run();
return true;
}
if (tmpStr == "5")
{
PrintHelp();
return true;
}
if (tmpStr == "9")
{
return false;
}
Console.WriteLine("Введен неверный символ, повторите ввод");
Thread.Sleep(1000);
return true;
}
// Ввод данных с консоли на ленту
public static void InputIntoTape()
{
TapeClear();
Console.WriteLine("Введите данные на ленту. Данные в формате 0 или 1");
string inputTape = Console.ReadLine();
for (int i = 0; i < inputTape.Length; i++)
{
if (inputTape[i] == '0')
{
Unmark();
Right();
}
else if (inputTape[i] == '1')
{
Mark();
Right();
}
}
}
public static void InputIntoRulesTable()
{
TapeClear();
Console.WriteLine("Введите номер команды. Затем укажите команду");
int commandNumber = Int32.Parse(Console.ReadLine());
string command= Console.ReadLine();
_commands[commandNumber] = command;
}
public static void PrintState()
{
for (int i = _tapePointer - 20; i < _tapePointer + 20; i++)
{
if (_tape[i])
Console.Write("1");
else
Console.Write("0");
}
Console.WriteLine();
Console.WriteLine();
Console.WriteLine();
for (int i = 0; i < 20; i++)
{
Console.Write(i + ". ");
Console.WriteLine(_commands[i]);
}
}
public static void PrintHelp()
{
Console.WriteLine("\t1) 'V j' - поставить метку, перейти к j-й строке программы.");
Console.WriteLine("\t2) 'X j' - стереть метку, перейти к j-й строке программы.");
Console.WriteLine("\t3) '<- j' - сдвинуться влево, перейти к j-й строке программы.");
Console.WriteLine("\t4) '-> j' - сдвинуться вправо, перейти к j-й строке программы.");
Console.WriteLine("\t5) '? j1; j2' - если нет метки, прыгаем на j2, иначе j1");
Console.WriteLine("\t6) '!' – конец программы (стоп).");
Console.WriteLine();
Console.WriteLine();
Console.WriteLine();
}
public static void Run()
{
StartPostMachine();
}
#endregion
}
}
|