约瑟夫环(约瑟夫问题):已知n个人(以编号1,2,3…n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。具有完整的图形用户界面,可以配置程序的运行参数,如:n的值,k的值、m的值、执行动画的速度等;执行过程可以暂停/继续;算法执行的结果(包括中间结果)可以持久化(以自定义数据格式保存到文件中;可从文件中读取数据,实时图形化显示执行结果;
约瑟夫实现参考代码: https://blog.youkuaiyun.com/Czhenya/article/details/78230368
文件导入导出也有参考,但忘了参考哪一个了,找到后再附上源码链接
代码如下
public void start_Click(object sender, EventArgs e)
{
//相关参数不能为空
if (textBox1.Text == "" || textBox2.Text == "" || textBox3.Text == "")
{
MessageBox.Show("请输入相关参数");//用户提示
return ;
}
int n = Convert.ToInt32(textBox1.Text);//获取人数n
int m = Convert.ToInt32(textBox2.Text);//获取计数m
List<int> xData = new List<int>();//图形X数据
List<double> yData = new List<double>();//图形Y数据
for (int k = 0; k <n; k++)
{
xData.Add(k);
yData.Add(100.0/n);//根据总人数不同改变份数
}
chart1.Series[0].Points.DataBindXY(xData, yData);
YueSeFuHuan(n,m);//调用约瑟夫函数
timer1.Enabled = true;//打开定时器
}
//暂停
private void pause_Click(object sender, EventArgs e)
{
timer1.Enabled = false;
}
//继续
private void continue_Click(object sender, EventArgs e)
{
timer1.Enabled = true;
}
/// 约瑟夫环问题求解方法
int[] eliminates = new int[100];
public void YueSeFuHuan(int sum, int num)//sum总人数num第几个人出局
{
int c = Convert.ToInt32(textBox3.Text);//开始位置
int[] arr = new int[sum];
for (int i = 0; i < sum; i++)
{
arr[i] = 1;
}
int count = 0;//计数器
int arrlength = arr.Length;//剩余人数
List<int> eliminates1 = new List<int>(sum);
while (arrlength >= 1)
{
for (int i = 0; i < arr.Length; i++)
{
if (arr[i] == 1)
{
count++;
if (count == num)//如果是规定(第几个人出局)
{
arr[i] = 0;//第i个人出局
arrlength--;
count = 0;
if (i + c < sum)
eliminates1.Add(i + c);//第i+1个人出局,他的编号是i
else
eliminates1.Add(i + c - sum);
eliminates = eliminates1.ToArray();
}
}
}
}
}
int j = 0;
private void timer1_Tick(object sender, EventArgs e)
{
dataGridView1.Rows.Add();
dataGridView1.Rows[j].Cells[1].Value = eliminates[j];//淘汰者
dataGridView1.Rows[j].Cells[0].Value = j + 1;//轮数
foreach (DataPoint point in this.chart1.Series[0].Points)
if (point.XValue == eliminates[j])
point.Color = Color.White;
j++;
if (j == eliminates.Length)
{
timer1.Enabled = false;
MessageBox.Show("全部淘汰");
}
if (comboBox1.Text == "较快")
{ timer1.Interval = 500; }
if (comboBox1.Text == "正常")
{ timer1.Interval = 1000; }
if (comboBox1.Text == "较慢")
{ timer1.Interval = 2000; }
}
private void dataGridView1_RowStateChanged(object sender, DataGridViewRowStateChangedEventArgs e)
{
//显示行号
e.Row.HeaderCell.Value = string.Format("{0}", e.Row.Index + 1);
//让滚动条始终处于最下方显示最新数据
dataGridView1.FirstDisplayedScrollingRowIndex = dataGridView1.Rows.Count -1;
}
private void quit_Click(object sender, EventArgs e)
{
Application.Exit();
}
private void output_Click(object sender, EventArgs e)
{
string strPath = "D://data.txt";//路径
//设置文件流,建立连接
System.IO.FileStream fileStream = new System.IO.FileStream(strPath, FileMode.OpenOrCreate);
StreamWriter streamWriter = new StreamWriter(fileStream, System.Text.Encoding.Unicode);
StringBuilder strBuilder = new StringBuilder();
try
{
for (int i = 0; i < dataGridView1.Rows.Count; i++)//遍历所有行
{
strBuilder = new StringBuilder();
for (int j = 0; j < dataGridView1.Columns.Count; j++)//遍历所有列
{
strBuilder.Append(dataGridView1.Rows[i].Cells[j].Value.ToString() + " ");//空格连接
}
strBuilder.Remove(strBuilder.Length - 1, 1);
streamWriter.WriteLine(strBuilder.ToString());
}
}
catch (Exception ex)
{
string strErrorMessage = ex.Message;//捕捉异常
}
finally
{
//关闭文件流
streamWriter.Close();
fileStream.Close();
}
MessageBox.Show("导出成功!", "提示", MessageBoxButtons.OK);//用户提示
}
private void input_Click(object sender, EventArgs e)
{
//新建一个datatable用于保存读入数据
//DataTable dt = new DataTable();
//dt.Columns.Add("轮数", typeof(string));
//dt.Columns.Add("淘汰者", typeof(string));
//读入文件
string strPath = "D://data.txt";
StreamReader sr = new StreamReader(strPath , Encoding.Default);
while (!sr.EndOfStream)
{
string[] items = sr.ReadLine().Split(' ');
Int32 a= Convert.ToInt32(items[0]);
Int32 b = Convert.ToInt32(items[1]);
dataGridView1.Rows.Add(a,b);
}
}