Newer
Older
TicTacToe / TTTConsole / ConsolePlay.cs
using System;
using System.Collections.Generic;
using TTT;

namespace TTTConsole {

    class ConsolePlay {

        private readonly string[] PLAYER_STR = new string[] { "", "先手", "後手" };
        private readonly string[] PLAYER_MARK = new string[] { " ", "○", "×" };

        private TicTacToe _ttt = new TicTacToe();
        private List<Plugin> _plugins = new List<Plugin>();
        private List<Plugin> _player = new List<Plugin>();
        static bool _showNumber = false;

        /// <summary>
        /// 実行
        /// </summary>
        /// <param name="pluginFiles"></param>
        public void Run(string[] pluginFiles) {
            ShowTitle();
            if (!LoadPlugin(pluginFiles)) {
                Console.WriteLine("プラグインがありません.");
                return;
            }
            if (!SelectPlayer()) {
                Console.WriteLine("中断します.");
                return;
            }
            Battle();
            ShowResult();
        }

        /// <summary>
        /// タイトルを表示
        /// </summary>
        private void ShowTitle() {
            Console.WriteLine(new string('*', 30));
            Console.WriteLine("拡張○×ゲーム");
            Console.WriteLine(new string('*', 30));
            Console.WriteLine("");
        }

        /// <summary>
        /// プラグインを読み込む
        /// </summary>
        /// <param name="files"></param>
        private bool LoadPlugin(string[] files) {
            foreach (var file in files) {
                var plugin = new Plugin();
                if (!plugin.Load(file)) continue;
                _plugins.Add(plugin);
            }
            return _plugins.Count > 0;
        }

        /// <summary>
        /// プレイヤーの選択
        /// </summary>
        private bool SelectPlayer() {
            Console.WriteLine("プレイヤーの選択");
            for (var pl = 0; pl < _ttt.PLAYERS; pl++) {
                for (var i = 0; i < _plugins.Count; i++) {
                    Console.WriteLine($"({i + 1}) {_plugins[i].Name}");
                }
                Console.Write($"{PLAYER_STR[pl + 1]} を選んでください: ");
                var input = Console.ReadLine();

                int selID;
                if (!int.TryParse(input, out selID)) return false;
                if (selID < 1 || selID > _plugins.Count) return false;
                _player.Add(_plugins[selID - 1]);
            }

            // 数字表示の選択
            Console.Write("○×の順番を表示しますか? 1:しない 2:する ");
            _showNumber = int.Parse(Console.ReadLine()) == 2 ? true : false;

            return true;
        }

        /// <summary>
        /// 対戦
        /// </summary>
        private void Battle() {
            _ttt.Init();
            do {
                Console.WriteLine("");
                ShowBoard();
                Console.Write($"{PlayerStr()} の番");

                if (_player[(int)_ttt.Player - 1].IsHuman) Console.WriteLine("");
                _ttt.Set(_player[(int)_ttt.Player - 1].MyTurn(_ttt.GetBoard()));
                if (!_player[(int)_ttt.Player - 1].IsHuman) Console.WriteLine($" --> {_ttt.LastSet + 1}");

            } while (_ttt.Judge == JUDGE.None);
        }

        /// <summary>
        /// 結果表示
        /// </summary>
        private void ShowResult() {
            string msg = "";
            switch (_ttt.Judge) {
            case JUDGE.WIN:
                msg = $"{PlayerStr()} の勝利";
                break;
            case JUDGE.DRAW:
                msg = $"引き分け";
                break;
            case JUDGE.OUT_OF_RANGE:
                msg = $"{PlayerStr()} の反則負け(範囲外)";
                break;
            case JUDGE.OVERLAP:
                msg = $"{PlayerStr()} の反則負け(重ね置き)";
                break;
            }

            Console.WriteLine("");
            Console.WriteLine(new string('*', 30));
            ShowBoard();
            Console.WriteLine("");
            Console.WriteLine(msg);
            Console.WriteLine(new string('*', 30));
        }

        /// <summary>
        /// 盤の表示
        /// </summary>
        private void ShowBoard() {
            Console.WriteLine(new string('~', 6) + $" ターン{_ttt.Turn} " + new string('~', 6));

            var flip = _ttt.Player == PLAYER.Second ? -1 : 1;
            for (var row = 0; row < _ttt.BOARD_ROWS; row++) {
                Console.Write("    ");
                for (var col = 0; col < _ttt.BOARD_COLS; col++) {
                    var pos = row * _ttt.BOARD_COLS + col;
                    var pIdx = _ttt.Board[pos] * flip > 0 ? PLAYER.First :
                        _ttt.Board[pos] * flip < 0 ? PLAYER.Second : PLAYER.None;
                    Console.Write(PLAYER_MARK[(int)pIdx]);
                    if (_showNumber) Console.Write(_ttt.Board[pos] == 0 ? "  " :
                        string.Format("{0,2}", Math.Abs(_ttt.Board[pos])));
                    if (col < _ttt.BOARD_COLS - 1) Console.Write(" | ");
                }
                Console.WriteLine("");
                if (row < _ttt.BOARD_ROWS - 1) {
                    if (_showNumber) Console.WriteLine("    -----+------+-----");
                    else Console.WriteLine("    ---+----+---");
                }
            }
        }

        /// <summary>
        /// プレイヤーの表示文字列を生成
        /// </summary>
        /// <returns>表示文字列</returns>
        private string PlayerStr() {
            return $"{PLAYER_STR[(int)_ttt.Player]}({_player[(int)_ttt.Player - 1].Name})";
        }
    }
}