前陣子看到某人《關於某道 C# 上機題的 OO》,後來又有人用裝飾模式做這題,這裡我來個策略模式。不習慣廢話,直接上程式碼,不知道算不算策略模式,請高人指點。
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp
{
public class Program
{
static void Main(string[] args)
{
Game game = new Game(17);
// 設定策略
game.Strategy = new StrategyA();
game.GameOver += new EventHandler(game_GameOver);
game.Start();
Console.Read();
}
static void game_GameOver(object sender, EventArgs e)
{
Console.WriteLine("Last Person:" + sender);
}
}
/// 策略介面
public interface IStrategy
{
/// 執行策略
void Work(Game g);
}
/// 策略 A:從第一個人開始報數,報到 3 的倍數退出,直到剩下最後一人
public class StrategyA : IStrategy
{
private List<Person> over = new List<Person>();
private int k = 0;
public void Work(Game game)
{
foreach (Person p in game.Players)
{
p.Say(++k);
if (k % 3 == 0) over.Add(p);
}
game.Players.RemoveAll(o => over.Contains(o));
}
}
public delegate void EventHandler(object sender, EventArgs e);
/// 遊戲
public class Game
{
public Game(int num)
{
Players = new List<Person>();
for (int i = 0; i < num; i++) Players.Add(new Person(i + 1));
}
public IStrategy Strategy { get; set; }
public List<Person> Players { get; set; }
public event EventHandler GameOver;
public void Start()
{
if (Strategy != null)
{
while (Players.Count > 1)
{
Strategy.Work(this);
}
GameOver(this.Players.First().Id, new EventArgs());
}
}
}
/// 玩家
public class Person
{
public Person(int id) { this.Id = id; }
public int Id { get; set; }
public void Say(int num)
{
Console.WriteLine(string.Format("{0}:{1}", Id, num));
}
}
}
StrategyA 實作介面 IStrategy 遵循開閉原則,若要換規則只要新增一個實作 IStrategy 的類別即可。之前還有用循環鏈結串列完成這道題,晚上再發上來。