using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 五子棋
{
class Program
{
///
/// 游戏规则
///
public static string[] Gz = new string[]
{
" 游戏规则:",
" 1.双方分别使用黑白两色的棋子,空棋盘开局。",
" 2.黑色棋子先下,白色棋子后下,每次只能下一子。",
" 3.先形成5子连线者获胜",
" 操作简介:",
" 1.黑子通过wasd键移动选择落子点,空格键落子",
" 2.白子通过↑↓←→键移动选择落子点,空格键落子"
};
/// <summary>
/// 操作记录
/// </summary>
public static List<CzjlModel> Czjl = new List<CzjlModel>();
/// <summary>
/// 棋子集合.
/// </summary>
public static List<QzModel> QzList = new List<QzModel>();
/// <summary>
/// 棋盘大小
/// </summary>
public static int size = 16;
/// <summary>
/// 当前回合数
/// </summary>
public static int huihe = 1;
/// <summary>
/// 当前落子方,0白棋1黑棋
/// </summary>
public static int type = 0;
/// <summary>
/// 光标输入位置x
/// </summary>
public static int index_X = 0;
/// <summary>
/// 光标输入位置y
/// </summary>
public static int index_Y = 0;
/// <summary>
/// 程序入口
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
//定义结束状态bool变量
bool is_end = true;
// 初始化光标位置到棋盘中央
index_X = size;// 棋盘由字符■组成,由于■占两个字符位置,所以用/2处理
index_Y = size / 2;
// 循环检测游戏是否结束
while (is_end)
{
// 清空控制台内容,达到刷新效果
Console.Clear();
// 绘制棋盘
Draw_Qp(size);
//打印落子记录
if (type == 0)
{
Draw_Czjl("白子");
}
else
{
Draw_Czjl("黑子");
}
// 设置光标输入点位置
Console.SetCursorPosition(index_X, index_Y);
// 定义落子状态
bool is_lz = true;
// 检测落子状态
while (is_lz)
{
// 接收键盘按键信息
if (DownKey(Console.ReadKey(true).Key))
{
is_lz = false;
}
else
{
is_lz = true;
}
}
//获取白棋集合
List<QzModel> bqList = QzList.Where(r => r.Type == 0).ToList();
//获取黑棋集合
List<QzModel> hqList = QzList.Where(r => r.Type == 1).ToList();
//落子后进行胜负检测
if (IsWin(bqList))
{
Console.WriteLine("白棋胜");
is_end = false;
}
if (IsWin(hqList))
{
Console.WriteLine("黑棋胜");
is_end = false;
}
}
Console.Read();
}
/// <summary>
/// 绘制棋盘
/// </summary>
/// <param name="size">棋盘大小</param>
public static void Draw_Qp(int size)
{
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
//当棋盘上有棋子时绘制棋子
if (QzList.Where(r => r.Y == i && r.X / 2 == j).ToList().Count > 0)
{
if (QzList.Where(r => r.Y == i && r.X / 2 == j).ToList().Last().Type == 1)
{
Console.Write("○");
}
else
{
Console.Write("●");
}
continue;
}
//没有棋子时绘制棋盘
Console.Write("■");
}
//打印游戏规则
if (Gz.Length > i)
{
Console.Write(Gz[i]);
}
//换行
Console.WriteLine();
}
}
/// <summary>
/// 打印落子记录
/// </summary>
/// <param name="content">操作内容</param>
/// <param name="type">操作人</param>
public static void Draw_Czjl(string type)
{
// 按序号对落子记录排序,只打印最新的三条
var Czjl_sort = Czjl.OrderByDescending(r => r.Sort).ToList().Take(3).ToList();
// 打印系统消息
if (type == "白子")
{
if (Czjl_sort.Count > 0)
{
Console.WriteLine("第" + huihe + "回合,请白棋落子!");
}
else
{
Console.WriteLine("第1回合,请白棋落子!");
}
}
else
{
if (Czjl_sort.Count > 0)
{
Console.WriteLine("第" + huihe + "回合,请黑棋落子!");
}
else
{
Console.WriteLine("第1回合,请黑棋落子!");
}
}
Console.WriteLine();
Console.WriteLine();
//打印落子记录
foreach (var i in Czjl_sort)
{
Console.WriteLine(i.Content);
}
}
/// <summary>
/// 胜负校验
/// </summary>
/// <param name="QzList">棋子集合</param>
public static bool IsWin(List<QzModel> QzList)
{
bool is_win = false;// 胜负状态
int lx_number = 1;//连珠数量
//当棋子数不够时不进行检测
if (QzList.Count() < 5)
{
return false;
}
QzModel qzModel = QzList.Last();// 获取最新落子点
// 过滤无效棋子
var QzList_Jc = QzList.Where(r =>
(r.X + 8 <= qzModel.X || r.X - 8 <= qzModel.X)
&&
(r.Y - 5 <= qzModel.Y || r.Y + 5 <= qzModel.Y)).ToList();
//当有效棋子数不够时不进行检测
if (QzList_Jc.Count() <= 0)
{
return false;
}
// 竖向检测
// 按x坐标进行分组获取和落子点x坐标相同的棋子,进行竖向检测
var QzList_jc = QzList_Jc.Where(r => r.X == qzModel.X).OrderByDescending(s => s.Y).ToList();
for (int i = 0; i < QzList_jc.Count; i++)
{
// 防止下标溢出
if (i + 1 >= QzList_jc.Count())
{
continue;
}
//检查棋子是否相连
if (QzList_jc[i].Y == QzList_jc[i + 1].Y)
{
lx_number++;
}
else
{
lx_number = 0;
}
//相连棋子超过5或者等于5时判胜
if (lx_number >= 5)
{
is_win = true;
}
}
// 横向检测
// 按y坐标进行分组获取和落子点y坐标相同的棋子,进行横向检测
var QzList_jc_X = QzList_Jc.Where(r => r.Y == qzModel.Y).OrderByDescending(s => s.X).ToList();
for (int i = 0; i < QzList_jc_X.Count; i++)
{
if (i + 1 >= QzList_jc_X.Count())
{
continue;
}
if (QzList_Jc[i].X == QzList_jc_X[i + 1].X + 2)
{
lx_number++;
}
else
{
lx_number = 0;
}
if (lx_number >= 5)
{
is_win = true;
}
}
// 左斜向检测\
for (int i = 0; i < 9; i++)
{
int x = 0;
int y = 0;
if (i < 4)
{
x = qzModel.X / 2 - (4 - i);
y = qzModel.Y - (4 - i);
}
else if (i == 4)
{
x = qzModel.X / 2;
x = qzModel.Y;
}
else
{
x = qzModel.X / 2 + (i - 4);
x = qzModel.Y + (i - 4);
}
if (QzList_Jc.Where(r => r.X == x * 2 && r.Y == y).Count() == 1)
{
lx_number++;
}
else
{
lx_number = 0;
}
if (lx_number >= 5)
{
is_win = true;
}
}
// 右斜向检测/
for (int i = 0; i < 9; i++)
{
int x = 0;
int y = 0;
if (i < 4)
{
x = qzModel.X / 2 - (4 - i);
y = qzModel.Y + (4 - i);
}
else if (i == 4)
{
x = qzModel.X / 2;
x = qzModel.Y;
}
else
{
x = qzModel.X / 2 + (i - 4);
x = qzModel.Y - (i - 4);
}
if (QzList_Jc.Where(r => r.X == x * 2 && r.Y == y).Count() == 1)
{
lx_number++;
}
else
{
lx_number = 0;
}
if (lx_number >= 5)
{
is_win = true;
}
}
return is_win;
}
/// <summary>
/// 按键检测光标移动
/// </summary>
/// <param name="key">按键值</param>
public static bool DownKey(ConsoleKey key)
{
//检测按键,对不同按键进行不同操作
switch (key)
{
// 光标上移
case ConsoleKey.W:
case ConsoleKey.UpArrow:
index_Y -= 1;
Console.SetCursorPosition(index_X, index_Y);
break;
// 光标左移
case ConsoleKey.A:
case ConsoleKey.LeftArrow:
index_X -= 2;
Console.SetCursorPosition(index_X, index_Y);
break;
// 光标下移
case ConsoleKey.S:
case ConsoleKey.DownArrow:
index_Y += 1;
Console.SetCursorPosition(index_X, index_Y);
break;
// 光标右移
case ConsoleKey.D:
case ConsoleKey.RightArrow:
index_X += 2;
Console.SetCursorPosition(index_X, index_Y);
break;
// 落子
case ConsoleKey.Spacebar:
//检测是否已经有棋子存在
var count = QzList.Where(r => r.X == index_X && r.Y == index_Y).ToList().Count;
if (count > 0)
{
CzjlModel czjlModel = new CzjlModel()
{
Content = "此处已经有棋子了,请重新落子!",
Sort = QzList.Count + 1,
};
Czjl.Add(czjlModel);
Console.SetCursorPosition(0, 16);
if (type == 0)
{
Draw_Czjl("白子");
}
else
{
Draw_Czjl("黑子");
}
// 落子失败返回false,提示玩家重新落子
return false;
}
//生成对应棋子,添加到棋子集合
if (type == 0)
{
Console.Write("●");
QzModel qzModel = new QzModel()
{
Type = 0,
X = index_X,
Y = index_Y,
};
QzList.Add(qzModel);
}
else
{
Console.Write("○");
QzModel qzModel = new QzModel()
{
Type = 1,
X = index_X,
Y = index_Y,
};
QzList.Add(qzModel);
}
Console.SetCursorPosition(0, 16);
// 生成落子记录,添加到记录集合
if (type == 0)
{
CzjlModel czjlModel = new CzjlModel()
{
Content = "白棋在" + "[" + index_X / 2 + "," + index_Y + "] 处" + "落子",
Sort = QzList.Count + 1,
};
Czjl.Add(czjlModel);
Draw_Czjl("黑子");
type = 1;
}
else
{
CzjlModel czjlModel = new CzjlModel()
{
Content = "黑棋在" + "[" + index_X / 2 + "," + index_Y + "] 处" + "落子",
Sort = QzList.Count + 1,
};
Czjl.Add(czjlModel);
Draw_Czjl("白子");
huihe++;
type = 0;
}
return true;
}
return false;
}
}
/// <summary>
/// 操作记录model
/// </summary>
public class CzjlModel
{
/// <summary>
/// 内容
/// </summary>
public string Content { get; set; }
/// <summary>
/// 序号
/// </summary>
public int Sort { get; set; }
}
/// <summary>
/// 棋子model
/// </summary>
public class QzModel
{
/// <summary>
/// 棋子类型,0白棋1黑棋
/// </summary>
public int Type { get; set; }
/// <summary>
/// 棋子X坐标
/// </summary>
public int X { get; set; }
/// <summary>
/// 棋子Y坐标
/// </summary>
public int Y { get; set; }
}
}