using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using TTT;
namespace TTTConsole {
class Program {
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr LoadLibrary(string lib);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern void FreeLibrary(IntPtr module);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetProcAddress(IntPtr module, string proc);
private delegate void GetNameDelegate(StringBuilder s, Int32 bufsize);
private delegate bool IsHumanDelegate();
private delegate int MyTurnDelegate(IntPtr board);
static string[] PLAYER_STR = new string[] { "", "先手", "後手" };
static string[] PLAYER_MARK = new string[] { " ", "○", "×" };
static List<string> names = new List<string>();
static int[] thinkers;
static bool showNumber = false;
/// <summary>
/// プログラム開始点
/// </summary>
/// <param name="args"></param>
static void Main(string[] args) {
Console.WriteLine(new string('*', 30));
Console.WriteLine("拡張○×ゲーム");
Console.WriteLine(new string('*', 30));
Console.WriteLine("");
var ttt = new TicTacToe();
// プラグインDLLを開く
var pluginFiles = new List<string>() { "TPIHuman.dll", "TPIRandom.dll" };
var modules = new List<IntPtr>();
var GetName = new List<GetNameDelegate>();
var IsHuman = new List<IsHumanDelegate>();
var MyTurn = new List<MyTurnDelegate>();
foreach (var file in pluginFiles) {
var module = LoadLibrary(file);
if (module == IntPtr.Zero) // error handling
{
Console.WriteLine($"Could not load library: {Marshal.GetLastWin32Error()}");
continue;
}
IntPtr method = GetProcAddress(module, "GetName");
if (method == IntPtr.Zero) // error handling
{
Console.WriteLine($"Could not load 'GetName' method: {Marshal.GetLastWin32Error()}");
FreeLibrary(module); // unload library
continue;
}
GetName.Add((GetNameDelegate)Marshal.GetDelegateForFunctionPointer(method, typeof(GetNameDelegate)));
method = GetProcAddress(module, "IsHuman");
if (method == IntPtr.Zero) // error handling
{
Console.WriteLine($"Could not load 'IsHuman' method: {Marshal.GetLastWin32Error()}");
FreeLibrary(module); // unload library
continue;
}
IsHuman.Add((IsHumanDelegate)Marshal.GetDelegateForFunctionPointer(method, typeof(IsHumanDelegate)));
method = GetProcAddress(module, "MyTurn");
if (method == IntPtr.Zero) // error handling
{
Console.WriteLine($"Could not load 'MyTurn' method: {Marshal.GetLastWin32Error()}");
FreeLibrary(module); // unload library
continue;
}
MyTurn.Add((MyTurnDelegate)Marshal.GetDelegateForFunctionPointer(method, typeof(MyTurnDelegate)));
modules.Add(module);
}
// プラグイン名の取得
System.Text.StringBuilder sb = new System.Text.StringBuilder(256);
foreach (var gn in GetName) {
gn(sb, sb.Capacity);
names.Add(sb.ToString());
}
//GetName[0](sb, sb.Capacity);
//names[0] = sb.ToString();
//GetName[1](sb, sb.Capacity);
//names[1] = sb.ToString();
// プレイヤーの選択
Console.WriteLine("プレイヤーの選択");
thinkers = new int[ttt.PLAYERS];
for (var pl=0; pl< ttt.PLAYERS; pl++) {
for (var i = 0; i < names.Count; i++) {
Console.WriteLine($"({i + 1}) {names[i]}");
}
Console.Write($"{PLAYER_STR[pl + 1]} を選んでください: ");
var input = Console.ReadLine();
if (!int.TryParse(input, out thinkers[pl])) return;
if (thinkers[pl] < 1 || thinkers[pl] > names.Count) return;
--thinkers[pl];
}
// 数字表示の選択
Console.Write("○×の順番を表示しますか? 1:しない 2:する ");
showNumber = int.Parse(Console.ReadLine()) == 2 ? true : false;
// 対戦開始
ttt.Init();
do {
Console.WriteLine("");
ShowBoard(ttt);
Console.Write($"{PlayerStr(ttt.Player)} の番");
switch (thinkers[(int)ttt.Player - 1]) {
case 0:
Console.WriteLine("");
//ttt.Set(MyTurnH(ttt.GetBoard()));
break;
case 1:
//ttt.Set(MyTurnR(ttt.GetBoard()));
//if (!IsHumanR()) Console.WriteLine($" --> {ttt.LastSet + 1}");
break;
}
} while (ttt.Judge == JUDGE.None);
// 結果表示
Console.WriteLine("");
Console.WriteLine(new string('*', 30));
ShowBoard(ttt);
Console.WriteLine("");
switch (ttt.Judge) {
case JUDGE.WIN:
Console.WriteLine($"{PlayerStr(ttt.Winner)} の勝利");
break;
case JUDGE.DRAW:
Console.WriteLine($"引き分け");
break;
case JUDGE.OUT_OF_RANGE:
Console.WriteLine($"{PlayerStr(ttt.Player)} の反則負け(範囲外)");
break;
case JUDGE.OVERLAP:
Console.WriteLine($"{PlayerStr(ttt.Player)} の反則負け(重ね置き)");
break;
}
Console.WriteLine(new string('*', 30));
// 終了
Console.Write("Press [Enter] to exit.");
Console.ReadLine();
foreach (var module in modules) FreeLibrary(module);
}
/// <summary>
/// 盤の表示
/// </summary>
/// <param name="ttt"></param>
static void ShowBoard(TicTacToe ttt) {
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>
/// <param name="p">プレイヤー</param>
/// <returns>表示文字列</returns>
static string PlayerStr(PLAYER p) {
return $"{PLAYER_STR[(int)p]}({names[thinkers[(int)p - 1]]})";
}
}
}