LINQ和集合框架
目录
04. LINQ和集合框架
C#集合框架和LINQ查询完全指南 - 游戏开发中的数据操作
📌 本章导航
集合框架概览
集合框架层次结构
C#的集合框架提供了丰富的数据结构,适用于不同的使用场景:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
// 集合框架主要接口
// IEnumerable<T> - 可枚举的集合
// ICollection<T> - 可计数、添加、删除的集合
// IList<T> - 可索引访问的列表
// IDictionary<TKey, TValue> - 键值对集合
// 主要集合类型对比
public class CollectionOverview
{
public static void CompareCollections()
{
// List<T> - 动态数组,适合频繁随机访问
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
// Dictionary<TKey, TValue> - 键值对,适合快速查找
Dictionary<string, int> scores = new Dictionary<string, int>
{
{"Player1", 100},
{"Player2", 85},
{"Player3", 92}
};
// HashSet<T> - 无重复元素,适合成员检查
HashSet<string> uniqueItems = new HashSet<string> { "Sword", "Shield", "Potion" };
// Queue<T> - 先进先出
Queue<string> gameMessages = new Queue<string>();
gameMessages.Enqueue("Game started");
gameMessages.Enqueue("Player joined");
// Stack<T> - 后进先出
Stack<GameState> gameStates = new Stack<GameState>();
gameStates.Push(GameState.Menu);
gameStates.Push(GameState.Playing);
// LinkedList<T> - 双向链表,适合频繁插入删除
LinkedList<int> linkedList = new LinkedList<int>();
Console.WriteLine("集合类型对比:");
Console.WriteLine($"List: 适合随机访问, O(1) 索引访问");
Console.WriteLine($"Dictionary: 适合键值查找, O(1) 平均查找");
Console.WriteLine($"HashSet: 适合唯一性检查, O(1) 查找");
Console.WriteLine($"Queue: 适合任务队列, O(1) 入队出队");
Console.WriteLine($"Stack: 适合状态管理, O(1) 入栈出栈");
}
}
集合选择指南
| 场景 | 推荐集合 | 原因 |
|---|---|---|
| 频繁随机访问 | List |
O(1) 索引访问 |
| 快速查找 | Dictionary<TKey, TValue> | O(1) 平均查找时间 |
| 唯一性约束 | HashSet |
自动去重,快速成员检查 |
| 任务队列 | Queue |
FIFO顺序处理 |
| 状态管理 | Stack |
LIFO状态回退 |
| 频繁插入/删除 | LinkedList |
O(1) 中间插入删除 |
常用集合类型
List - 动态数组
using System;
using System.Collections.Generic;
public class ListDemo
{
public static void DemonstrateList()
{
// 创建和初始化
List<int> numbers = new List<int>();
List<string> names = new List<string> { "Alice", "Bob", "Charlie" };
List<Player> players = new List<Player>(10); // 预设容量
// 添加元素
numbers.Add(10);
numbers.AddRange(new[] { 20, 30, 40 });
// 访问元素
Console.WriteLine($"第一个元素: {numbers[0]}");
Console.WriteLine($"最后一个元素: {numbers.Last()}"); // 需要using System.Linq
// 查找元素
int index = numbers.IndexOf(20);
bool contains = numbers.Contains(30);
// 插入和删除
numbers.Insert(1, 15); // 在索引1处插入
numbers.RemoveAt(0); // 删除索引0的元素
numbers.Remove(30); // 删除值为30的元素
// 排序
numbers.Sort();
numbers.Reverse();
// 转换为数组
int[] array = numbers.ToArray();
// 遍历
foreach (int num in numbers)
{
Console.WriteLine(num);
}
// 使用索引遍历
for (int i = 0; i < numbers.Count; i++)
{
Console.WriteLine($"[{i}]: {numbers[i]}");
}
}
}
// 游戏中的玩家列表示例
public class PlayerManager
{
private List<Player> players = new List<Player>();
public void AddPlayer(Player player)
{
players.Add(player);
}
public Player FindPlayerByName(string name)
{
return players.FirstOrDefault(p => p.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
}
public List<Player> GetPlayersByLevel(int minLevel)
{
return players.Where(p => p.Level >= minLevel).ToList();
}
public void RemoveInactivePlayers(TimeSpan maxInactivity)
{
players.RemoveAll(p => DateTime.Now - p.LastActivity > maxInactivity);
}
public int GetTotalScore()
{
return players.Sum(p => p.Score);
}
}
Dictionary<TKey, TValue> - 键值对集合
using System;
using System.Collections.Generic;
using System.Linq;
public class DictionaryDemo
{
public static void DemonstrateDictionary()
{
// 创建和初始化
Dictionary<string, int> scores = new Dictionary<string, int>();
Dictionary<int, Player> playerLookup = new Dictionary<int, Player>
{
{ 1, new Player("Player1") },
{ 2, new Player("Player2") }
};
// 添加/更新
scores["Alice"] = 100;
scores["Bob"] = 85;
scores["Charlie"] = 92;
// 安全添加 (避免键重复异常)
if (!scores.ContainsKey("Alice"))
{
scores.Add("Alice", 100);
}
// 安全更新
scores["Alice"] = 105; // 直接赋值会更新
scores["Alice"] += 10; // 复合赋值
// 访问元素
if (scores.TryGetValue("Alice", out int aliceScore))
{
Console.WriteLine($"Alice's score: {aliceScore}");
}
// 检查键存在
bool hasAlice = scores.ContainsKey("Alice");
bool hasDavid = scores.ContainsKey("David");
// 遍历
foreach (var kvp in scores)
{
Console.WriteLine($"{kvp.Key}: {kvp.Value}");
}
// 遍历键和值
foreach (string name in scores.Keys)
{
Console.WriteLine($"Player: {name}");
}
foreach (int score in scores.Values)
{
Console.WriteLine($"Score: {score}");
}
// 删除
scores.Remove("Bob");
scores.Clear();
}
}
// 游戏配置管理示例
public class GameConfigManager
{
private Dictionary<string, object> config = new Dictionary<string, object>();
public void SetConfig<T>(string key, T value)
{
config[key] = value;
}
public T GetConfig<T>(string key, T defaultValue = default(T))
{
if (config.TryGetValue(key, out object value))
{
if (value is T result)
{
return result;
}
try
{
return (T)Convert.ChangeType(value, typeof(T));
}
catch
{
return defaultValue;
}
}
return defaultValue;
}
public bool HasConfig(string key)
{
return config.ContainsKey(key);
}
// 批量设置配置
public void SetConfigs(Dictionary<string, object> newConfigs)
{
foreach (var kvp in newConfigs)
{
config[kvp.Key] = kvp.Value;
}
}
// 获取所有配置
public Dictionary<string, T> GetConfigsOfType<T>()
{
return config
.Where(kvp => kvp.Value is T)
.ToDictionary(kvp => kvp.Key, kvp => (T)kvp.Value);
}
}
// 使用示例
public class ConfigUsage
{
public static void Example()
{
GameConfigManager config = new GameConfigManager();
// 设置配置
config.SetConfig("MaxPlayers", 10);
config.SetConfig("GameMode", "Deathmatch");
config.SetConfig("TimeLimit", 1800); // 30分钟
config.SetConfig("EnablePowerUps", true);
// 获取配置
int maxPlayers = config.GetConfig("MaxPlayers", 8);
string gameMode = config.GetConfig("GameMode", "Default");
bool powerUpsEnabled = config.GetConfig("EnablePowerUps", false);
Console.WriteLine($"Max players: {maxPlayers}");
Console.WriteLine($"Game mode: {gameMode}");
Console.WriteLine($"Power-ups: {(powerUpsEnabled ? "Enabled" : "Disabled")}");
}
}
HashSet - 集合操作
using System;
using System.Collections.Generic;
using System.Linq;
public class HashSetDemo
{
public static void DemonstrateHashSet()
{
// 创建和初始化
HashSet<string> uniqueItems = new HashSet<string>();
HashSet<int> numbers = new HashSet<int> { 1, 2, 3, 4, 5 };
// 添加元素 (自动去重)
uniqueItems.Add("Sword");
uniqueItems.Add("Shield");
uniqueItems.Add("Sword"); // 重复元素,不会添加
uniqueItems.Add("Potion");
Console.WriteLine($"Unique items count: {uniqueItems.Count}");
// 检查成员
bool hasSword = uniqueItems.Contains("Sword");
bool hasBow = uniqueItems.Contains("Bow");
// 集合操作
HashSet<int> set1 = new HashSet<int> { 1, 2, 3, 4 };
HashSet<int> set2 = new HashSet<int> { 3, 4, 5, 6 };
// 并集
HashSet<int> union = new HashSet<int>(set1);
union.UnionWith(set2);
Console.WriteLine($"Union: [{string.Join(", ", union)}]");
// 交集
HashSet<int> intersection = new HashSet<int>(set1);
intersection.IntersectWith(set2);
Console.WriteLine($"Intersection: [{string.Join(", ", intersection)}]");
// 差集
HashSet<int> difference = new HashSet<int>(set1);
difference.ExceptWith(set2);
Console.WriteLine($"Difference (set1 - set2): [{string.Join(", ", difference)}]");
// 对称差集 (XOR)
HashSet<int> symmetricDiff = new HashSet<int>(set1);
symmetricDiff.SymmetricExceptWith(set2);
Console.WriteLine($"Symmetric difference: [{string.Join(", ", symmetricDiff)}]");
// 遍历
foreach (string item in uniqueItems)
{
Console.WriteLine(item);
}
}
}
// 游戏物品管理示例
public class InventoryManager
{
private HashSet<string> uniqueItems = new HashSet<string>();
private Dictionary<string, int> stackableItems = new Dictionary<string, int>();
private const int MAX_STACK_SIZE = 99;
public bool AddItem(string itemName, int quantity = 1)
{
if (IsUniqueItem(itemName))
{
// 独特物品,只能有一个
if (uniqueItems.Contains(itemName))
{
return false; // 已存在
}
uniqueItems.Add(itemName);
return true;
}
else
{
// 可堆叠物品
if (stackableItems.ContainsKey(itemName))
{
stackableItems[itemName] = Math.Min(
stackableItems[itemName] + quantity,
MAX_STACK_SIZE
);
}
else
{
stackableItems[itemName] = Math.Min(quantity, MAX_STACK_SIZE);
}
return true;
}
}
public bool RemoveItem(string itemName, int quantity = 1)
{
if (uniqueItems.Contains(itemName))
{
return uniqueItems.Remove(itemName);
}
else if (stackableItems.TryGetValue(itemName, out int currentQuantity))
{
int newQuantity = currentQuantity - quantity;
if (newQuantity <= 0)
{
return stackableItems.Remove(itemName);
}
else
{
stackableItems[itemName] = newQuantity;
return true;
}
}
return false;
}
public bool HasItem(string itemName)
{
return uniqueItems.Contains(itemName) || stackableItems.ContainsKey(itemName);
}
public int GetItemCount(string itemName)
{
if (uniqueItems.Contains(itemName))
return 1;
else if (stackableItems.TryGetValue(itemName, out int count))
return count;
else
return 0;
}
private bool IsUniqueItem(string itemName)
{
// 根据物品名称或类型判断是否为独特物品
// 这里简化为以"Unique"开头的物品为独特物品
return itemName.StartsWith("Unique");
}
public List<string> GetAllItems()
{
var allItems = new List<string>(uniqueItems);
allItems.AddRange(stackableItems.Where(kvp => kvp.Value > 0).Select(kvp => kvp.Key));
return allItems;
}
}
Queue 和 Stack - 有序集合
using System;
using System.Collections.Generic;
public class QueueStackDemo
{
public static void DemonstrateQueue()
{
// 队列 - 先进先出 (FIFO)
Queue<string> messageQueue = new Queue<string>();
// 入队
messageQueue.Enqueue("Message 1");
messageQueue.Enqueue("Message 2");
messageQueue.Enqueue("Message 3");
Console.WriteLine($"队列大小: {messageQueue.Count}");
Console.WriteLine($"下一个消息: {messageQueue.Peek()}"); // 查看但不移除
// 出队
while (messageQueue.Count > 0)
{
string message = messageQueue.Dequeue();
Console.WriteLine($"处理消息: {message}");
}
}
public static void DemonstrateStack()
{
// 栈 - 后进先出 (LIFO)
Stack<GameAction> actionStack = new Stack<GameAction>();
// 入栈
actionStack.Push(new GameAction("Move", new Vector3(1, 0, 0)));
actionStack.Push(new GameAction("Jump", null));
actionStack.Push(new GameAction("Attack", new Weapon()));
Console.WriteLine($"栈大小: {actionStack.Count}");
Console.WriteLine($"最近操作: {actionStack.Peek().Type}"); // 查看但不移除
// 出栈 (撤销操作)
while (actionStack.Count > 0)
{
GameAction action = actionStack.Pop();
Console.WriteLine($"撤销操作: {action.Type}");
}
}
}
// 游戏事件系统示例
public class GameEventManager
{
private Queue<GameEvent> eventQueue = new Queue<GameEvent>();
private Stack<GameEvent> eventHistory = new Stack<GameEvent>();
private const int MAX_HISTORY = 50;
public void QueueEvent(GameEvent gameEvent)
{
eventQueue.Enqueue(gameEvent);
}
public void ProcessEvents()
{
while (eventQueue.Count > 0)
{
GameEvent gameEvent = eventQueue.Dequeue();
ProcessEvent(gameEvent);
// 保存到历史记录
eventHistory.Push(gameEvent);
if (eventHistory.Count > MAX_HISTORY)
{
eventHistory = new Stack<GameEvent>(eventHistory.Take(MAX_HISTORY));
}
}
}
private void ProcessEvent(GameEvent gameEvent)
{
// 处理游戏事件
switch (gameEvent.Type)
{
case EventType.PlayerMove:
HandlePlayerMove(gameEvent);
break;
case EventType.PlayerAttack:
HandlePlayerAttack(gameEvent);
break;
case EventType.EnemySpawn:
HandleEnemySpawn(gameEvent);
break;
}
}
public void UndoLastEvent()
{
if (eventHistory.Count > 0)
{
GameEvent lastEvent = eventHistory.Pop();
ReverseEvent(lastEvent);
}
}
private void ReverseEvent(GameEvent gameEvent)
{
// 反转事件效果
Console.WriteLine($"撤销事件: {gameEvent.Type}");
}
private void HandlePlayerMove(GameEvent gameEvent)
{
Console.WriteLine("处理玩家移动事件");
}
private void HandlePlayerAttack(GameEvent gameEvent)
{
Console.WriteLine("处理玩家攻击事件");
}
private void HandleEnemySpawn(GameEvent gameEvent)
{
Console.WriteLine("处理敌人生成事件");
}
}
public class GameEvent
{
public EventType Type { get; set; }
public object Data { get; set; }
public DateTime Timestamp { get; set; }
public GameEvent(EventType type, object data)
{
Type = type;
Data = data;
Timestamp = DateTime.Now;
}
}
public enum EventType
{
PlayerMove,
PlayerAttack,
EnemySpawn,
ItemPickup,
PlayerDeath
}
public class GameAction
{
public string Type { get; set; }
public object Data { get; set; }
public GameAction(string type, object data)
{
Type = type;
Data = data;
}
}
LINQ查询语法
查询语法基础
using System;
using System.Collections.Generic;
using System.Linq;
public class LinqQuerySyntax
{
public static void DemonstrateQuerySyntax()
{
List<Player> players = new List<Player>
{
new Player { Name = "Alice", Level = 15, Score = 2500, Class = "Warrior" },
new Player { Name = "Bob", Level = 8, Score = 1200, Class = "Mage" },
new Player { Name = "Charlie", Level = 22, Score = 3800, Class = "Archer" },
new Player { Name = "Diana", Level = 18, Score = 3100, Class = "Warrior" },
new Player { Name = "Eve", Level = 5, Score = 800, Class = "Mage" }
};
// 基本查询 - 找出等级大于10的玩家
var highLevelPlayers = from p in players
where p.Level > 10
select p;
Console.WriteLine("等级大于10的玩家:");
foreach (var player in highLevelPlayers)
{
Console.WriteLine($" {player.Name} - Level {player.Level}");
}
// 多条件查询
var warriorHighScorers = from p in players
where p.Class == "Warrior" && p.Score > 2000
select new { p.Name, p.Score, p.Level };
Console.WriteLine("\n高分战士玩家:");
foreach (var player in warriorHighScorers)
{
Console.WriteLine($" {player.Name} - Score: {player.Score}, Level: {player.Level}");
}
// 排序查询
var topPlayers = from p in players
orderby p.Score descending, p.Level descending
select p;
Console.WriteLine("\n按分数排序的玩家:");
foreach (var player in topPlayers.Take(3))
{
Console.WriteLine($" {player.Name} - Score: {player.Score}");
}
// 投影查询 (选择特定字段)
var playerStats = from p in players
where p.Level >= 10
select new
{
Name = p.Name,
PowerLevel = p.Level * 10 + p.Score / 100
};
Console.WriteLine("\n玩家实力评级:");
foreach (var stat in playerStats)
{
Console.WriteLine($" {stat.Name}: {stat.PowerLevel}");
}
// 分组查询
var playersByClass = from p in players
group p by p.Class into g
select new { Class = g.Key, Count = g.Count(), AverageLevel = g.Average(p => p.Level) };
Console.WriteLine("\n按职业分组:");
foreach (var group in playersByClass)
{
Console.WriteLine($" {group.Class}: {group.Count}人, 平均等级 {group.AverageLevel:F1}");
}
}
}
复杂查询语法
public class ComplexLinqQueries
{
public static void DemonstrateComplexQueries()
{
// 模拟游戏数据
var players = new List<Player>
{
new Player { Name = "Alice", Level = 15, Score = 2500, Class = "Warrior", Guild = "Lions" },
new Player { Name = "Bob", Level = 8, Score = 1200, Class = "Mage", Guild = "Wolves" },
new Player { Name = "Charlie", Level = 22, Score = 3800, Class = "Archer", Guild = "Lions" },
new Player { Name = "Diana", Level = 18, Score = 3100, Class = "Warrior", Guild = "Eagles" },
new Player { Name = "Eve", Level = 5, Score = 800, Class = "Mage", Guild = "Wolves" }
};
var items = new List<Item>
{
new Item { Name = "Sword", Type = "Weapon", Value = 100, Owner = "Alice" },
new Item { Name = "Shield", Type = "Armor", Value = 80, Owner = "Alice" },
new Item { Name = "Staff", Type = "Weapon", Value = 120, Owner = "Bob" },
new Item { Name = "Bow", Type = "Weapon", Value = 150, Owner = "Charlie" },
new Item { Name = "Potion", Type = "Consumable", Value = 20, Owner = "Diana" }
};
// JOIN查询 - 玩家和物品
var playerItems = from p in players
join i in items on p.Name equals i.Owner
select new { Player = p.Name, Item = i.Name, ItemType = i.Type };
Console.WriteLine("玩家物品列表:");
foreach (var result in playerItems)
{
Console.WriteLine($" {result.Player} 拥有 {result.Item} ({result.ItemType})");
}
// 嵌套查询
var richPlayers = from p in players
where (from i in items where i.Owner == p.Name select i.Value).Sum() > 150
select p;
Console.WriteLine("\n拥有贵重物品的玩家:");
foreach (var player in richPlayers)
{
Console.WriteLine($" {player.Name}");
}
// let子句 - 创建临时变量
var playerWealth = from p in players
let totalItemValue = (from i in items where i.Owner == p.Name select i.Value).Sum()
let wealthLevel = totalItemValue > 100 ? "Rich" : totalItemValue > 50 ? "Medium" : "Poor"
select new { p.Name, TotalValue = totalItemValue, WealthLevel = wealthLevel };
Console.WriteLine("\n玩家财富等级:");
foreach (var player in playerWealth)
{
Console.WriteLine($" {player.Name}: {player.TotalValue} ({player.WealthLevel})");
}
// 量词操作
bool allHighLevel = players.All(p => p.Level >= 5); // 所有玩家等级都>=5
bool anyHighScorer = players.Any(p => p.Score > 3000); // 是否有高分玩家
Console.WriteLine($"\n所有玩家等级>=5: {allHighLevel}");
Console.WriteLine($"有高分玩家(>3000): {anyHighScorer}");
}
}
public class Player
{
public string Name { get; set; }
public int Level { get; set; }
public int Score { get; set; }
public string Class { get; set; }
public string Guild { get; set; }
public DateTime LastLogin { get; set; } = DateTime.Now;
}
public class Item
{
public string Name { get; set; }
public string Type { get; set; }
public int Value { get; set; }
public string Owner { get; set; }
}
LINQ方法语法
基础方法操作
using System;
using System.Collections.Generic;
using System.Linq;
public class LinqMethodSyntax
{
public static void DemonstrateMethodSyntax()
{
List<Player> players = new List<Player>
{
new Player { Name = "Alice", Level = 15, Score = 2500, Class = "Warrior" },
new Player { Name = "Bob", Level = 8, Score = 1200, Class = "Mage" },
new Player { Name = "Charlie", Level = 22, Score = 3800, Class = "Archer" },
new Player { Name = "Diana", Level = 18, Score = 3100, Class = "Warrior" },
new Player { Name = "Eve", Level = 5, Score = 800, Class = "Mage" }
};
// Where - 过滤
var highLevelPlayers = players.Where(p => p.Level > 10);
Console.WriteLine("等级大于10的玩家:");
highLevelPlayers.ToList().ForEach(p => Console.WriteLine($" {p.Name}"));
// Select - 投影
var playerNames = players.Select(p => p.Name);
Console.WriteLine($"\n所有玩家名字: [{string.Join(", ", playerNames)}]");
// SelectMany - 扁平化
var nameLengths = players.SelectMany(p => p.Name.ToCharArray()).Count();
Console.WriteLine($"所有玩家名字字符总数: {nameLengths}");
// OrderBy/ThenBy - 排序
var sortedPlayers = players
.OrderByDescending(p => p.Score)
.ThenByDescending(p => p.Level);
Console.WriteLine("\n按分数和等级排序:");
sortedPlayers.ToList().ForEach(p => Console.WriteLine($" {p.Name}: {p.Score}"));
// Take/Skip - 分页
var top3 = players.OrderByDescending(p => p.Score).Take(3);
var afterTop3 = players.OrderByDescending(p => p.Score).Skip(3);
Console.WriteLine("\n前三名:");
top3.ToList().ForEach(p => Console.WriteLine($" {p.Name}: {p.Score}"));
}
public static void DemonstrateAggregation()
{
List<Player> players = new List<Player>
{
new Player { Name = "Alice", Level = 15, Score = 2500 },
new Player { Name = "Bob", Level = 8, Score = 1200 },
new Player { Name = "Charlie", Level = 22, Score = 3800 },
new Player { Name = "Diana", Level = 18, Score = 3100 },
new Player { Name = "Eve", Level = 5, Score = 800 }
};
// 聚合操作
Console.WriteLine($"玩家总数: {players.Count()}");
Console.WriteLine($"平均等级: {players.Average(p => p.Level):F2}");
Console.WriteLine($"最高等级: {players.Max(p => p.Level)}");
Console.WriteLine($"总分数: {players.Sum(p => p.Score)}");
Console.WriteLine($"最高分数: {players.Max(p => p.Score)}");
// 条件聚合
var avgHighLevelScore = players
.Where(p => p.Level >= 10)
.Average(p => p.Score);
Console.WriteLine($"高等级玩家平均分数: {avgHighLevelScore:F2}");
// 元素操作
var firstHighScorer = players.FirstOrDefault(p => p.Score > 3000);
Console.WriteLine($"第一个高分玩家: {firstHighScorer?.Name ?? "无"}");
var lastPlayer = players.LastOrDefault();
Console.WriteLine($"最后加入的玩家: {lastPlayer?.Name ?? "无"}");
var playerAt3 = players.ElementAtOrDefault(2); // 索引从0开始
Console.WriteLine($"第三个玩家: {playerAt3?.Name ?? "无"}");
}
}
高级方法操作
public class AdvancedLinqMethods
{
public static void DemonstrateAdvancedMethods()
{
List<Player> players = new List<Player>
{
new Player { Name = "Alice", Level = 15, Score = 2500, Class = "Warrior", Guild = "Lions" },
new Player { Name = "Bob", Level = 8, Score = 1200, Class = "Mage", Guild = "Wolves" },
new Player { Name = "Charlie", Level = 22, Score = 3800, Class = "Archer", Guild = "Lions" },
new Player { Name = "Diana", Level = 18, Score = 3100, Class = "Warrior", Guild = "Eagles" },
new Player { Name = "Eve", Level = 5, Score = 800, Class = "Mage", Guild = "Wolves" }
};
// GroupBy - 分组
var playersByClass = players.GroupBy(p => p.Class);
Console.WriteLine("按职业分组:");
foreach (var group in playersByClass)
{
Console.WriteLine($" {group.Key}: {string.Join(", ", group.Select(p => p.Name))}");
}
// ToDictionary - 转换为字典
var playerDict = players.ToDictionary(p => p.Name, p => p.Score);
Console.WriteLine($"\n玩家分数字典 - Alice: {playerDict["Alice"]}");
// ToLookup - 创建查找表 (与GroupBy类似,但立即执行)
var playersByGuild = players.ToLookup(p => p.Guild);
Console.WriteLine("\n按公会分组:");
foreach (var guild in playersByGuild)
{
Console.WriteLine($" {guild.Key}: {string.Join(", ", guild.Select(p => p.Name))}");
}
// Join - 连接操作
var items = new List<Item>
{
new Item { Name = "Sword", Type = "Weapon", Value = 100, Owner = "Alice" },
new Item { Name = "Staff", Type = "Weapon", Value = 120, Owner = "Bob" },
new Item { Name = "Bow", Type = "Weapon", Value = 150, Owner = "Charlie" }
};
var playerItems = players
.Join(items,
player => player.Name,
item => item.Owner,
(player, item) => new { Player = player.Name, Item = item.Name, Value = item.Value })
.ToList();
Console.WriteLine("\n玩家物品连接:");
playerItems.ForEach(pi => Console.WriteLine($" {pi.Player} - {pi.Item} (价值: {pi.Value})"));
// GroupJoin - 组连接
var playersWithItems = players
.GroupJoin(items,
player => player.Name,
item => item.Owner,
(player, playerItems) => new {
Player = player.Name,
Items = playerItems.ToList()
})
.ToList();
Console.WriteLine("\n玩家及其物品:");
foreach (var pw in playersWithItems)
{
var itemsList = pw.Items.Count > 0 ?
string.Join(", ", pw.Items.Select(i => i.Name)) : "无物品";
Console.WriteLine($" {pw.Player}: {itemsList}");
}
}
public static void DemonstrateSetOperations()
{
// 集合操作
var activePlayers = new List<string> { "Alice", "Bob", "Charlie", "Diana" };
var premiumPlayers = new List<string> { "Alice", "Charlie", "Eve", "Frank" };
// Union - 并集
var allPlayers = activePlayers.Union(premiumPlayers);
Console.WriteLine($"所有玩家 (并集): [{string.Join(", ", allPlayers)}]");
// Intersect - 交集
var premiumActive = activePlayers.Intersect(premiumPlayers);
Console.WriteLine($"既活跃又高级的玩家 (交集): [{string.Join(", ", premiumActive)}]");
// Except - 差集
var activeNotPremium = activePlayers.Except(premiumPlayers);
Console.WriteLine($"活跃但非高级玩家 (差集): [{string.Join(", ", activeNotPremium)}]");
// Concat - 连接
var allNames = activePlayers.Concat(premiumPlayers);
Console.WriteLine($"连接所有名字 (有重复): [{string.Join(", ", allNames)}]");
// Distinct - 去重
var uniqueNames = activePlayers.Concat(premiumPlayers).Distinct();
Console.WriteLine($"连接所有名字 (去重): [{string.Join(", ", uniqueNames)}]");
}
public static void DemonstrateGenerationMethods()
{
// 生成方法
// Range - 生成数字序列
var levels = Enumerable.Range(1, 10); // 1到10
Console.WriteLine($"等级序列: [{string.Join(", ", levels)}]");
// Repeat - 重复值
var defaultScores = Enumerable.Repeat(0, 5); // 重复0五次
Console.WriteLine($"默认分数: [{string.Join(", ", defaultScores)}]");
// Empty - 空集合
var emptyList = Enumerable.Empty<Player>();
Console.WriteLine($"空列表数量: {emptyList.Count()}");
// DefaultIfEmpty - 空时提供默认值
var withDefault = emptyList.DefaultIfEmpty(new Player { Name = "DefaultPlayer" });
Console.WriteLine($"空列表默认值: {withDefault.First().Name}");
}
}
游戏数据查询示例
public class GameDataQueries
{
private List<Player> players;
private List<Enemy> enemies;
private List<Item> items;
public GameDataQueries()
{
// 初始化游戏数据
players = new List<Player>
{
new Player { Name = "Hero1", Level = 25, Score = 5000, Class = "Warrior", Health = 100, LastLogin = DateTime.Now.AddDays(-1) },
new Player { Name = "Hero2", Level = 18, Score = 3200, Class = "Mage", Health = 85, LastLogin = DateTime.Now.AddDays(-2) },
new Player { Name = "Hero3", Level = 30, Score = 6800, Class = "Archer", Health = 90, LastLogin = DateTime.Now },
new Player { Name = "Hero4", Level = 12, Score = 1800, Class = "Warrior", Health = 70, LastLogin = DateTime.Now.AddDays(-5) },
new Player { Name = "Hero5", Level = 22, Score = 4500, Class = "Mage", Health = 95, LastLogin = DateTime.Now.AddDays(-1) }
};
enemies = new List<Enemy>
{
new Enemy { Name = "Goblin", Level = 5, Health = 30, Type = "Melee", SpawnArea = "Forest" },
new Enemy { Name = "Orc", Level = 12, Health = 80, Type = "Melee", SpawnArea = "Mountain" },
new Enemy { Name = "Skeleton", Level = 8, Health = 45, Type = "Melee", SpawnArea = "Cave" },
new Enemy { Name = "Skeleton Archer", Level = 10, Health = 40, Type = "Ranged", SpawnArea = "Cave" },
new Enemy { Name = "Dragon", Level = 25, Health = 500, Type = "Boss", SpawnArea = "Castle" }
};
items = new List<Item>
{
new Item { Name = "Health Potion", Type = "Consumable", Value = 50, Rarity = "Common", Owner = "Hero1" },
new Item { Name = "Mana Potion", Type = "Consumable", Value = 40, Rarity = "Common", Owner = "Hero2" },
new Item { Name = "Sword of Light", Type = "Weapon", Value = 500, Rarity = "Epic", Owner = "Hero3" },
new Item { Name = "Shield", Type = "Armor", Value = 200, Rarity = "Rare", Owner = "Hero1" },
new Item { Name = "Mystic Orb", Type = "Artifact", Value = 1000, Rarity = "Legendary", Owner = "Hero5" }
};
}
// 玩家相关查询
public List<Player> GetActivePlayers(TimeSpan activityThreshold)
{
return players
.Where(p => DateTime.Now - p.LastLogin <= activityThreshold)
.OrderByDescending(p => p.Score)
.ToList();
}
public Dictionary<string, double> GetAverageLevelByClass()
{
return players
.GroupBy(p => p.Class)
.ToDictionary(g => g.Key, g => g.Average(p => p.Level));
}
public Player GetTopPlayer()
{
return players
.OrderByDescending(p => p.Score)
.ThenByDescending(p => p.Level)
.FirstOrDefault();
}
public List<string> GetInactivePlayerNames(TimeSpan inactivityThreshold)
{
return players
.Where(p => DateTime.Now - p.LastLogin > inactivityThreshold)
.Select(p => p.Name)
.ToList();
}
// 敌人相关查询
public List<Enemy> GetEnemiesByArea(string area)
{
return enemies.Where(e => e.SpawnArea.Equals(area, StringComparison.OrdinalIgnoreCase)).ToList();
}
public Dictionary<string, int> GetEnemyCountByType()
{
return enemies
.GroupBy(e => e.Type)
.ToDictionary(g => g.Key, g => g.Count());
}
public Enemy GetStrongestEnemy()
{
return enemies.OrderByDescending(e => e.Health).FirstOrDefault();
}
// 物品相关查询
public List<Item> GetItemsByRarity(string rarity)
{
return items.Where(i => i.Rarity.Equals(rarity, StringComparison.OrdinalIgnoreCase)).ToList();
}
public Dictionary<string, int> GetItemCountByType()
{
return items
.GroupBy(i => i.Type)
.ToDictionary(g => g.Key, g => g.Count());
}
public List<Item> GetMostValuableItems(int count)
{
return items.OrderByDescending(i => i.Value).Take(count).ToList();
}
// 综合查询
public var GetPlayerStatsSummary()
{
return new
{
TotalPlayers = players.Count,
AverageLevel = players.Average(p => p.Level),
AverageScore = players.Average(p => p.Score),
ActivePlayers = players.Count(p => DateTime.Now - p.LastLogin <= TimeSpan.FromDays(7)),
HighestLevelPlayer = players.OrderByDescending(p => p.Level).First().Name,
HighestScoringPlayer = players.OrderByDescending(p => p.Score).First().Name
};
}
public void RunAllQueries()
{
Console.WriteLine("=== 游戏数据分析 ===");
// 活跃玩家 (一周内登录)
var activePlayers = GetActivePlayers(TimeSpan.FromDays(7));
Console.WriteLine($"活跃玩家: {string.Join(", ", activePlayers.Select(p => p.Name))}");
// 各职业平均等级
var avgLevels = GetAverageLevelByClass();
Console.WriteLine("各职业平均等级:");
foreach (var kvp in avgLevels)
{
Console.WriteLine($" {kvp.Key}: {kvp.Value:F1}");
}
// 顶级玩家
var topPlayer = GetTopPlayer();
Console.WriteLine($"顶级玩家: {topPlayer.Name} (分数: {topPlayer.Score})");
// 非活跃玩家 (超过3天未登录)
var inactivePlayers = GetInactivePlayerNames(TimeSpan.FromDays(3));
Console.WriteLine($"非活跃玩家: {string.Join(", ", inactivePlayers)}");
// 按区域分组的敌人
var enemiesByArea = enemies.GroupBy(e => e.SpawnArea);
Console.WriteLine("各区域敌人分布:");
foreach (var area in enemiesByArea)
{
Console.WriteLine($" {area.Key}: {string.Join(", ", area.Select(e => e.Name))}");
}
// 稀有度物品统计
var itemsByRarity = items.GroupBy(i => i.Rarity);
Console.WriteLine("各稀有度物品数量:");
foreach (var rarity in itemsByRarity)
{
Console.WriteLine($" {rarity.Key}: {rarity.Count()} 件");
}
// 游戏统计摘要
var stats = GetPlayerStatsSummary();
Console.WriteLine($"游戏统计: 总玩家 {stats.TotalPlayers}, 平均等级 {stats.AverageLevel:F1}, 平均分数 {stats.AverageScore:F0}");
}
}
public class Enemy
{
public string Name { get; set; }
public int Level { get; set; }
public int Health { get; set; }
public string Type { get; set; }
public string SpawnArea { get; set; }
}
// 扩展Item类
public class Item
{
public string Name { get; set; }
public string Type { get; set; }
public int Value { get; set; }
public string Owner { get; set; }
public string Rarity { get; set; } // Common, Rare, Epic, Legendary
}
游戏开发中的应用
玩家管理系统
using System;
using System.Collections.Generic;
using System.Linq;
public class PlayerManagementSystem
{
private List<Player> players = new List<Player>();
private Dictionary<string, Player> playerLookup = new Dictionary<string, Player>();
private Dictionary<string, List<Player>> guildMembers = new Dictionary<string, List<Player>>();
public void AddPlayer(Player player)
{
if (!playerLookup.ContainsKey(player.Name))
{
players.Add(player);
playerLookup[player.Name] = player;
// 添加到公会
if (!string.IsNullOrEmpty(player.Guild))
{
if (!guildMembers.ContainsKey(player.Guild))
{
guildMembers[player.Guild] = new List<Player>();
}
guildMembers[player.Guild].Add(player);
}
}
}
public Player FindPlayer(string name)
{
return playerLookup.GetValueOrDefault(name);
}
public List<Player> FindPlayersByLevelRange(int minLevel, int maxLevel)
{
return players.Where(p => p.Level >= minLevel && p.Level <= maxLevel).ToList();
}
public List<Player> FindPlayersByClass(string playerClass)
{
return players.Where(p => p.Class.Equals(playerClass, StringComparison.OrdinalIgnoreCase)).ToList();
}
public List<Player> GetTopPlayers(int count, string sortBy = "Score")
{
switch (sortBy.ToLower())
{
case "level":
return players.OrderByDescending(p => p.Level).Take(count).ToList();
case "score":
return players.OrderByDescending(p => p.Score).Take(count).ToList();
default:
return players.OrderByDescending(p => p.Score).ThenByDescending(p => p.Level).Take(count).ToList();
}
}
public List<Player> GetOnlinePlayers(TimeSpan recentThreshold = default)
{
if (recentThreshold == default)
recentThreshold = TimeSpan.FromMinutes(10); // 默认10分钟内
return players
.Where(p => DateTime.Now - p.LastLogin <= recentThreshold)
.ToList();
}
public Dictionary<string, int> GetClassDistribution()
{
return players
.GroupBy(p => p.Class)
.ToDictionary(g => g.Key, g => g.Count());
}
public double GetAverageLevel()
{
return players.Any() ? players.Average(p => p.Level) : 0;
}
public double GetAverageScore()
{
return players.Any() ? players.Average(p => p.Score) : 0;
}
public List<Player> GetPlayersForLeaderboard(int page = 1, int pageSize = 10)
{
return players
.OrderByDescending(p => p.Score)
.ThenByDescending(p => p.Level)
.Skip((page - 1) * pageSize)
.Take(pageSize)
.ToList();
}
public List<Player> GetPlayersByGuild(string guildName)
{
return guildMembers.GetValueOrDefault(guildName, new List<Player>());
}
public Dictionary<string, double> GetAverageStatsByGuild()
{
return guildMembers.ToDictionary(
kvp => kvp.Key,
kvp => kvp.Value.Any() ? kvp.Value.Average(p => p.Score) : 0
);
}
public List<Player> SearchPlayers(string searchTerm)
{
return players.Where(p =>
p.Name.Contains(searchTerm, StringComparison.OrdinalIgnoreCase) ||
p.Class.Contains(searchTerm, StringComparison.OrdinalIgnoreCase) ||
(!string.IsNullOrEmpty(p.Guild) && p.Guild.Contains(searchTerm, StringComparison.OrdinalIgnoreCase))
).ToList();
}
public void RemoveInactivePlayers(TimeSpan inactivityThreshold)
{
var inactivePlayers = players.Where(p => DateTime.Now - p.LastLogin > inactivityThreshold).ToList();
foreach (var player in inactivePlayers)
{
players.Remove(player);
playerLookup.Remove(player.Name);
// 从公会中移除
if (!string.IsNullOrEmpty(player.Guild) && guildMembers.ContainsKey(player.Guild))
{
guildMembers[player.Guild].Remove(player);
if (guildMembers[player.Guild].Count == 0)
{
guildMembers.Remove(player.Guild);
}
}
}
}
public void UpdatePlayerStats(string playerName, int scoreIncrease, int levelIncrease = 0)
{
if (playerLookup.TryGetValue(playerName, out Player player))
{
player.Score += scoreIncrease;
if (levelIncrease > 0)
{
player.Level += levelIncrease;
}
player.LastLogin = DateTime.Now; // 更新活跃时间
}
}
public void PrintSystemStats()
{
Console.WriteLine("=== 玩家系统统计 ===");
Console.WriteLine($"总玩家数: {players.Count}");
Console.WriteLine($"平均等级: {GetAverageLevel():F2}");
Console.WriteLine($"平均分数: {GetAverageScore():F2}");
Console.WriteLine("职业分布:");
foreach (var kvp in GetClassDistribution())
{
Console.WriteLine($" {kvp.Key}: {kvp.Value} 人");
}
Console.WriteLine("公会统计:");
foreach (var kvp in guildMembers)
{
Console.WriteLine($" {kvp.Key}: {kvp.Value.Count} 人");
}
}
}
物品和背包系统
public class InventorySystem
{
private Dictionary<string, List<Item>> playerInventories = new Dictionary<string, List<Item>>();
private Dictionary<string, Item> itemDatabase = new Dictionary<string, Item>();
public void InitializeItemDatabase()
{
// 初始化物品数据库
var defaultItems = new List<Item>
{
new Item { Name = "Health Potion", Type = "Consumable", Value = 50, Rarity = "Common", MaxStack = 99 },
new Item { Name = "Mana Potion", Type = "Consumable", Value = 40, Rarity = "Common", MaxStack = 99 },
new Item { Name = "Iron Sword", Type = "Weapon", Value = 200, Rarity = "Common", MaxStack = 1 },
new Item { Name = "Leather Armor", Type = "Armor", Value = 150, Rarity = "Common", MaxStack = 1 },
new Item { Name = "Magic Scroll", Type = "Consumable", Value = 100, Rarity = "Uncommon", MaxStack = 10 },
new Item { Name = "Dragon Scale", Type = "Material", Value = 50, Rarity = "Rare", MaxStack = 99 }
};
foreach (var item in defaultItems)
{
itemDatabase[item.Name] = item;
}
}
public bool AddItemToPlayer(string playerName, string itemName, int quantity = 1)
{
if (!itemDatabase.ContainsKey(itemName))
return false;
if (!playerInventories.ContainsKey(playerName))
{
playerInventories[playerName] = new List<Item>();
}
var inventory = playerInventories[playerName];
var templateItem = itemDatabase[itemName];
// 对于可堆叠物品,尝试合并到现有堆栈
if (templateItem.MaxStack > 1)
{
var existingItem = inventory.FirstOrDefault(i => i.Name == itemName && i.Quantity < templateItem.MaxStack);
if (existingItem != null)
{
int spaceAvailable = templateItem.MaxStack - existingItem.Quantity;
int toAdd = Math.Min(quantity, spaceAvailable);
existingItem.Quantity += toAdd;
quantity -= toAdd;
}
}
// 如果还有剩余数量,添加新堆栈
while (quantity > 0)
{
int stackSize = Math.Min(quantity, templateItem.MaxStack);
inventory.Add(new Item
{
Name = templateItem.Name,
Type = templateItem.Type,
Value = templateItem.Value,
Rarity = templateItem.Rarity,
MaxStack = templateItem.MaxStack,
Quantity = stackSize
});
quantity -= stackSize;
}
return true;
}
public bool RemoveItemFromPlayer(string playerName, string itemName, int quantity = 1)
{
if (!playerInventories.ContainsKey(playerName))
return false;
var inventory = playerInventories[playerName];
var itemsToRemove = new List<Item>();
int remainingToRemove = quantity;
// 从后往前遍历,避免索引问题
for (int i = inventory.Count - 1; i >= 0 && remainingToRemove > 0; i--)
{
var item = inventory[i];
if (item.Name == itemName)
{
if (item.Quantity <= remainingToRemove)
{
// 移除整个堆栈
itemsToRemove.Add(item);
remainingToRemove -= item.Quantity;
}
else
{
// 部分移除
item.Quantity -= remainingToRemove;
remainingToRemove = 0;
}
}
}
// 实际移除项目
foreach (var item in itemsToRemove)
{
inventory.Remove(item);
}
return remainingToRemove == 0;
}
public List<Item> GetPlayerInventory(string playerName)
{
return playerInventories.GetValueOrDefault(playerName, new List<Item>());
}
public List<Item> GetItemsByType(string playerName, string itemType)
{
return GetPlayerInventory(playerName)
.Where(i => i.Type.Equals(itemType, StringComparison.OrdinalIgnoreCase))
.ToList();
}
public int GetItemCount(string playerName, string itemName)
{
return GetPlayerInventory(playerName)
.Where(i => i.Name == itemName)
.Sum(i => i.Quantity);
}
public List<Item> GetItemsByRarity(string playerName, string rarity)
{
return GetPlayerInventory(playerName)
.Where(i => i.Rarity.Equals(rarity, StringComparison.OrdinalIgnoreCase))
.ToList();
}
public bool HasItem(string playerName, string itemName, int minQuantity = 1)
{
return GetItemCount(playerName, itemName) >= minQuantity;
}
public Dictionary<string, int> GetItemCountByType(string playerName)
{
return GetPlayerInventory(playerName)
.GroupBy(i => i.Type)
.ToDictionary(g => g.Key, g => g.Sum(i => i.Quantity));
}
public Dictionary<string, int> GetItemCountByRarity(string playerName)
{
return GetPlayerInventory(playerName)
.GroupBy(i => i.Rarity)
.ToDictionary(g => g.Key, g => g.Sum(i => i.Quantity));
}
public List<Item> GetMostValuableItems(string playerName, int count = 5)
{
return GetPlayerInventory(playerName)
.OrderByDescending(i => i.Value * i.Quantity)
.Take(count)
.ToList();
}
public void SortInventory(string playerName, string sortBy = "Name")
{
if (!playerInventories.ContainsKey(playerName))
return;
var inventory = playerInventories[playerName];
switch (sortBy.ToLower())
{
case "name":
inventory.Sort((a, b) => string.Compare(a.Name, b.Name));
break;
case "type":
inventory.Sort((a, b) => string.Compare(a.Type, b.Type));
break;
case "value":
inventory.Sort((a, b) => b.Value.CompareTo(a.Value)); // 降序
break;
case "rarity":
var rarityOrder = new Dictionary<string, int>
{
["Common"] = 0, ["Uncommon"] = 1, ["Rare"] = 2, ["Epic"] = 3, ["Legendary"] = 4
};
inventory.Sort((a, b) => rarityOrder.GetValueOrDefault(b.Rarity, 0).CompareTo(rarityOrder.GetValueOrDefault(a.Rarity, 0)));
break;
}
}
public void PrintInventory(string playerName)
{
var inventory = GetPlayerInventory(playerName);
if (!inventory.Any())
{
Console.WriteLine($"{playerName} 的背包是空的");
return;
}
Console.WriteLine($"{playerName} 的背包:");
var grouped = inventory.GroupBy(i => i.Name);
foreach (var group in grouped)
{
int totalQuantity = group.Sum(i => i.Quantity);
var firstItem = group.First();
Console.WriteLine($" {firstItem.Name} x{totalQuantity} ({firstItem.Type}, {firstItem.Rarity}) - 总值: {firstItem.Value * totalQuantity}");
}
}
}
// 扩展Item类以支持库存系统
public class Item
{
public string Name { get; set; }
public string Type { get; set; }
public int Value { get; set; }
public string Rarity { get; set; }
public int MaxStack { get; set; } = 1;
public int Quantity { get; set; } = 1;
}
战斗和技能系统
public class BattleSystem
{
public class BattleUnit
{
public string Name { get; set; }
public int Level { get; set; }
public int Health { get; set; }
public int MaxHealth { get; set; }
public int Attack { get; set; }
public int Defense { get; set; }
public int Speed { get; set; }
public List<Skill> Skills { get; set; } = new List<Skill>();
public bool IsAlive => Health > 0;
public BattleUnit(string name, int level)
{
Name = name;
Level = level;
MaxHealth = Level * 50;
Health = MaxHealth;
Attack = Level * 5;
Defense = Level * 2;
Speed = Level * 3;
}
}
public class Skill
{
public string Name { get; set; }
public int BaseDamage { get; set; }
public int ManaCost { get; set; }
public int Cooldown { get; set; }
public int CurrentCooldown { get; set; }
public SkillType Type { get; set; }
public bool IsAvailable => CurrentCooldown <= 0;
}
public enum SkillType
{
Damage,
Heal,
Buff,
Debuff
}
public class BattleResult
{
public BattleUnit Winner { get; set; }
public List<BattleAction> Actions { get; set; } = new List<BattleAction>();
public TimeSpan Duration { get; set; }
}
public class BattleAction
{
public BattleUnit Actor { get; set; }
public BattleUnit Target { get; set; }
public string Action { get; set; }
public int Damage { get; set; }
public int HealthChange { get; set; }
public DateTime Time { get; set; }
}
public BattleResult SimulateBattle(BattleUnit attacker, BattleUnit defender)
{
var result = new BattleResult();
var startTime = DateTime.Now;
// 确保单位处于初始状态
attacker.Health = attacker.MaxHealth;
defender.Health = defender.MaxHealth;
// 重置技能冷却
foreach (var skill in attacker.Skills.Concat(defender.Skills))
{
skill.CurrentCooldown = 0;
}
// 战斗循环
while (attacker.IsAlive && defender.IsAlive)
{
// 根据速度决定行动顺序
var first = attacker.Speed >= defender.Speed ? attacker : defender;
var second = first == attacker ? defender : attacker;
// 第一个单位行动
var action1 = ExecuteTurn(first, second);
result.Actions.Add(action1);
if (!second.IsAlive) break;
// 第二个单位行动
var action2 = ExecuteTurn(second, first);
result.Actions.Add(action2);
}
result.Winner = attacker.IsAlive ? attacker : defender.IsAlive ? defender : null;
result.Duration = DateTime.Now - startTime;
return result;
}
private BattleAction ExecuteTurn(BattleUnit attacker, BattleUnit defender)
{
// 选择技能或普通攻击
var availableSkills = attacker.Skills.Where(s => s.IsAvailable).ToList();
Skill usedSkill = null;
if (availableSkills.Any())
{
// 随机选择一个可用技能
var random = new Random();
usedSkill = availableSkills[random.Next(availableSkills.Count)];
}
if (usedSkill != null)
{
return UseSkill(attacker, defender, usedSkill);
}
else
{
return NormalAttack(attacker, defender);
}
}
private BattleAction UseSkill(BattleUnit attacker, BattleUnit defender, Skill skill)
{
int damage = 0;
int healthChange = 0;
string action = skill.Name;
switch (skill.Type)
{
case SkillType.Damage:
damage = Math.Max(0, skill.BaseDamage + attacker.Attack - defender.Defense);
defender.Health = Math.Max(0, defender.Health - damage);
break;
case SkillType.Heal:
healthChange = skill.BaseDamage; // 对于治疗技能,BaseDamage表示治疗量
attacker.Health = Math.Min(attacker.MaxHealth, attacker.Health + healthChange);
action = $"{skill.Name} (治疗)";
break;
case SkillType.Buff:
// 简单的增益效果
attacker.Attack += skill.BaseDamage / 10;
action = $"{skill.Name} (增益)";
break;
case SkillType.Debuff:
// 简单的减益效果
defender.Defense = Math.Max(0, defender.Defense - skill.BaseDamage / 20);
action = $"{skill.Name} (减益)";
break;
}
// 设置冷却
skill.CurrentCooldown = skill.Cooldown;
// 更新所有技能的冷却
foreach (var s in attacker.Skills)
{
s.CurrentCooldown = Math.Max(0, s.CurrentCooldown - 1);
}
return new BattleAction
{
Actor = attacker,
Target = defender,
Action = action,
Damage = damage,
HealthChange = healthChange,
Time = DateTime.Now
};
}
private BattleAction NormalAttack(BattleUnit attacker, BattleUnit defender)
{
int damage = Math.Max(1, attacker.Attack - defender.Defense / 2);
defender.Health = Math.Max(0, defender.Health - damage);
return new BattleAction
{
Actor = attacker,
Target = defender,
Action = "普通攻击",
Damage = damage,
Time = DateTime.Now
};
}
public List<BattleUnit> GetUnitsByStatus(List<BattleUnit> units, bool aliveOnly = true)
{
return aliveOnly ?
units.Where(u => u.IsAlive).ToList() :
units.Where(u => !u.IsAlive).ToList();
}
public Dictionary<string, double> GetAverageStats(List<BattleUnit> units)
{
if (!units.Any()) return new Dictionary<string, double>();
return new Dictionary<string, double>
{
["AverageLevel"] = units.Average(u => u.Level),
["AverageHealth"] = units.Average(u => u.MaxHealth),
["AverageAttack"] = units.Average(u => u.Attack),
["AverageDefense"] = units.Average(u => u.Defense),
["AverageSpeed"] = units.Average(u => u.Speed)
};
}
public BattleUnit GetStrongestUnit(List<BattleUnit> units)
{
return units
.OrderByDescending(u => u.MaxHealth + u.Attack * 2 + u.Defense + u.Speed)
.FirstOrDefault();
}
public List<BattleUnit> SortUnitsByPower(List<BattleUnit> units)
{
return units
.OrderByDescending(u => u.MaxHealth + u.Attack * 2 + u.Defense + u.Speed)
.ToList();
}
public void PrintBattleResult(BattleResult result)
{
Console.WriteLine("=== 战斗结果 ===");
Console.WriteLine($"获胜者: {result.Winner?.Name ?? "平局"}");
Console.WriteLine($"战斗持续: {result.Duration.TotalMilliseconds:F0}ms");
Console.WriteLine($"行动次数: {result.Actions.Count}");
Console.WriteLine("\n战斗过程:");
foreach (var action in result.Actions.Take(10)) // 只显示前10个行动
{
if (action.Damage > 0)
{
Console.WriteLine($"{action.Actor.Name} 对 {action.Target.Name} 使用 {action.Action}, 造成 {action.Damage} 点伤害");
}
else if (action.HealthChange != 0)
{
Console.WriteLine($"{action.Actor.Name} 使用 {action.Action}, 改变生命值 {action.HealthChange:+#;-#;0}");
}
else
{
Console.WriteLine($"{action.Actor.Name} 对 {action.Target.Name} 使用 {action.Action}");
}
}
if (result.Actions.Count > 10)
{
Console.WriteLine($"... 还有 {result.Actions.Count - 10} 个行动");
}
}
}
性能优化技巧
LINQ性能优化
using System;
using System.Collections.Generic;
using System.Linq;
public class LinqPerformance
{
public static void PerformanceTips()
{
// 1. 避免在循环中使用LINQ
var players = new List<Player>();
for (int i = 0; i < 1000; i++)
{
players.Add(new Player { Name = $"Player{i}", Level = i % 50, Score = i * 10 });
}
// ❌ 错误: 在循环中使用LINQ (性能差)
// for (int i = 0; i < 100; i++)
// {
// var highScorers = players.Where(p => p.Score > 5000).ToList(); // 每次都重新计算
// }
// ✅ 正确: 预先计算或使用索引
var highScorers = players.Where(p => p.Score > 5000).ToList(); // 只计算一次
// 2. 使用IList避免重复枚举
var query = players.Where(p => p.Level > 10); // 延迟执行
// 如果需要多次访问结果,转换为列表
var list = query.ToList(); // 立即执行
// 3. 选择合适的数据结构
// ❌ 使用List进行频繁查找
// var player = players.First(p => p.Name == "Alice");
// ✅ 使用Dictionary进行快速查找
var playerDict = players.ToDictionary(p => p.Name, p => p);
var player = playerDict.GetValueOrDefault("Alice");
// 4. 使用IEqualityComparer优化
var uniquePlayers = players
.GroupBy(p => p.Name, StringComparer.OrdinalIgnoreCase)
.Select(g => g.First())
.ToList();
// 5. 避免Select不必要的投影
// ❌ 不必要的投影
// var names = players.Select(p => p.Name).Where(name => name.Length > 5);
// ✅ 先过滤再投影
var names = players.Where(p => p.Name.Length > 5).Select(p => p.Name);
// 6. 使用Any代替Count > 0
// ❌ 性能差
// bool hasHighLevel = players.Count(p => p.Level > 20) > 0;
// ✅ 性能好
bool hasHighLevel = players.Any(p => p.Level > 20);
// 7. 使用FirstOrDefault避免异常
// ❌ 可能抛出异常
// var first = players.Where(p => p.Level > 100).First();
// ✅ 安全
var first = players.FirstOrDefault(p => p.Level > 100);
}
public static void DemonstrateEfficientPatterns()
{
var players = new List<Player>();
for (int i = 0; i < 10000; i++)
{
players.Add(new Player { Name = $"Player{i}", Level = i % 50, Score = i * 10 });
}
// 高效的分页查询
int pageNumber = 2;
int pageSize = 20;
var pagedPlayers = players
.OrderByDescending(p => p.Score)
.Skip((pageNumber - 1) * pageSize)
.Take(pageSize)
.ToList();
Console.WriteLine($"第{pageNumber}页玩家数量: {pagedPlayers.Count}");
// 高效的分组统计
var classStats = players
.GroupBy(p => p.Level / 10) // 按等级段分组
.Select(g => new
{
LevelRange = $"{g.Key * 10}-{g.Key * 10 + 9}",
Count = g.Count(),
AverageScore = g.Average(p => p.Score),
MaxScore = g.Max(p => p.Score)
})
.ToList();
Console.WriteLine("等级段统计:");
foreach (var stat in classStats.Take(5))
{
Console.WriteLine($" {stat.LevelRange}: {stat.Count}人, 平均分数{stat.AverageScore:F0}, 最高分{stat.MaxScore}");
}
// 使用HashSet进行快速成员检查
var specialPlayerNames = new HashSet<string> { "Player100", "Player200", "Player500", "Player999" };
var specialPlayers = players
.Where(p => specialPlayerNames.Contains(p.Name))
.ToList();
Console.WriteLine($"特殊玩家数量: {specialPlayers.Count}");
}
public static void MemoryEfficientQueries()
{
var players = new List<Player>();
for (int i = 0; i < 50000; i++)
{
players.Add(new Player { Name = $"Player{i}", Level = i % 50, Score = i * 10 });
}
// 对于大数据集,考虑使用迭代方式
var highScorers = new List<Player>();
foreach (var player in players)
{
if (player.Score > 400000) // 直接遍历,避免LINQ开销
{
highScorers.Add(player);
}
}
Console.WriteLine($"高分玩家数量: {highScorers.Count}");
// 使用Span<T>和ReadOnlySpan<T>进行高性能操作 (C# 7.2+)
// 注意: 这里仅作示例,实际使用需要适当的场景
var playerArray = players.Take(1000).ToArray();
var span = playerArray.AsSpan();
// 对于字符串操作,使用StringBuilder
var names = string.Join(", ", players.Take(100).Select(p => p.Name));
Console.WriteLine($"前100个玩家名字长度: {names.Length}");
}
}
集合性能优化
public class CollectionPerformance
{
public static void OptimizeCollections()
{
// 1. 预设容量
var players = new List<Player>(1000); // 预设容量避免频繁重分配
// 2. 使用Dictionary进行快速查找
var playerLookup = new Dictionary<string, Player>();
// 3. 使用HashSet进行成员检查
var bannedPlayers = new HashSet<string>();
// 4. 选择合适的集合类型
// 频繁随机访问 -> List<T>
// 快速键值查找 -> Dictionary<TKey, TValue>
// 唯一性约束 -> HashSet<T>
// 队列处理 -> Queue<T>
// 栈操作 -> Stack<T>
// 5. 使用Concurrent集合进行多线程操作
// 注意: 需要using System.Collections.Concurrent;
// var threadSafePlayers = new ConcurrentDictionary<string, Player>();
// 6. 批量操作
var newPlayers = new List<Player>
{
new Player { Name = "Player1" },
new Player { Name = "Player2" },
new Player { Name = "Player3" }
};
players.AddRange(newPlayers); // 批量添加比逐个添加高效
// 7. 使用Span<T>进行高性能操作
var playerArray = players.Take(100).ToArray();
var span = playerArray.AsSpan();
// 8. 避免装箱拆箱
// ❌ 值类型装箱
// var objectList = new List<object> { 1, 2, 3, 4, 5 };
// ✅ 使用泛型
var intList = new List<int> { 1, 2, 3, 4, 5 };
// 9. 使用ReadOnlyCollection<T>保护数据
var readOnlyPlayers = new ReadOnlyCollection<Player>(players);
// 10. 使用Collection Initializer
var quickList = new List<Player>
{
new Player { Name = "Quick1" },
new Player { Name = "Quick2" }
};
}
public static void CompareCollectionPerformance()
{
const int size = 100000;
// 测试List<T>性能
var list = new List<int>();
var sw = System.Diagnostics.Stopwatch.StartNew();
for (int i = 0; i < size; i++)
{
list.Add(i);
}
sw.Stop();
Console.WriteLine($"List.Add {size} 个元素耗时: {sw.ElapsedMilliseconds}ms");
// 测试预分配容量的List<T>性能
var listWithCapacity = new List<int>(size);
sw.Restart();
for (int i = 0; i < size; i++)
{
listWithCapacity.Add(i);
}
sw.Stop();
Console.WriteLine($"预分配List.Add {size} 个元素耗时: {sw.ElapsedMilliseconds}ms");
// 测试Dictionary查找性能
var dict = new Dictionary<int, int>();
for (int i = 0; i < size; i++)
{
dict[i] = i * 2;
}
sw.Restart();
for (int i = 0; i < 1000; i++)
{
var value = dict[size / 2]; // 查找中间元素
}
sw.Stop();
Console.WriteLine($"Dictionary查找1000次耗时: {sw.ElapsedMilliseconds}ms");
// 测试List查找性能
var listForSearch = new List<int>();
for (int i = 0; i < size; i++)
{
listForSearch.Add(i * 2);
}
sw.Restart();
for (int i = 0; i < 1000; i++)
{
var index = listForSearch.IndexOf(size); // O(n) 查找
}
sw.Stop();
Console.WriteLine($"List.IndexOf查找1000次耗时: {sw.ElapsedMilliseconds}ms");
}
}
实践练习
练习1: 游戏排行榜系统
public class LeaderboardSystem
{
private List<Player> players = new List<Player>();
private Dictionary<string, int> playerScores = new Dictionary<string, int>();
public void AddOrUpdatePlayer(string playerName, int score)
{
if (playerScores.ContainsKey(playerName))
{
playerScores[playerName] = Math.Max(playerScores[playerName], score);
}
else
{
playerScores[playerName] = score;
}
}
public List<Player> GetTopPlayers(int count = 10)
{
return playerScores
.OrderByDescending(kvp => kvp.Value)
.Take(count)
.Select(kvp => new Player { Name = kvp.Key, Score = kvp.Value })
.ToList();
}
public int GetPlayerRank(string playerName)
{
if (!playerScores.ContainsKey(playerName))
return -1;
var sortedScores = playerScores.Values.OrderByDescending(s => s).ToList();
var playerScore = playerScores[playerName];
return sortedScores.IndexOf(playerScore) + 1;
}
public List<Player> GetPlayersInRankRange(int startRank, int endRank)
{
var allPlayers = playerScores
.OrderByDescending(kvp => kvp.Value)
.Select(kvp => new Player { Name = kvp.Key, Score = kvp.Value })
.ToList();
return allPlayers.Skip(startRank - 1).Take(endRank - startRank + 1).ToList();
}
public Dictionary<int, List<Player>> GetPlayersByScoreRange(int rangeSize = 1000)
{
return playerScores
.GroupBy(kvp => (kvp.Value / rangeSize) * rangeSize) // 按分数段分组
.OrderByDescending(g => g.Key)
.ToDictionary(
g => g.Key,
g => g.Select(kvp => new Player { Name = kvp.Key, Score = kvp.Value }).ToList()
);
}
public Player GetPlayerStats(string playerName)
{
if (!playerScores.ContainsKey(playerName))
return null;
var playerScore = playerScores[playerName];
var allScores = playerScores.Values.ToList();
return new Player
{
Name = playerName,
Score = playerScore,
Level = CalculateLevel(playerScore),
Percentile = CalculatePercentile(playerScore, allScores)
};
}
private int CalculateLevel(int score)
{
return (int)Math.Sqrt(score / 100) + 1;
}
private double CalculatePercentile(int playerScore, List<int> allScores)
{
var higherScores = allScores.Count(s => s > playerScore);
return (1.0 - (double)higherScores / allScores.Count) * 100;
}
public void PrintLeaderboard(int count = 10)
{
var topPlayers = GetTopPlayers(count);
Console.WriteLine("=== 排行榜 ===");
for (int i = 0; i < topPlayers.Count; i++)
{
var player = topPlayers[i];
Console.WriteLine($"{i + 1,2}. {player.Name} - {player.Score,8:N0} 分");
}
}
public void PrintScoreDistribution()
{
var distribution = GetPlayersByScoreRange(5000);
Console.WriteLine("\n=== 分数分布 ===");
foreach (var range in distribution.Take(5)) // 显示前5个分数段
{
Console.WriteLine($"{range.Key,6} - {range.Key + 4999,6}: {range.Value.Count,3} 人");
}
}
}
练习2: 游戏数据分析器
public class GameDataAnalyzer
{
private List<GameSession> sessions = new List<GameSession>();
private List<PlayerAction> actions = new List<PlayerAction>();
public void AddSession(GameSession session)
{
sessions.Add(session);
}
public void AddAction(PlayerAction action)
{
actions.Add(action);
}
public AnalysisReport GenerateReport()
{
var report = new AnalysisReport();
// 会话分析
report.TotalSessions = sessions.Count;
report.AverageSessionDuration = sessions.Any() ?
TimeSpan.FromTicks((long)sessions.Average(s => s.Duration.Ticks)) : TimeSpan.Zero;
report.TotalPlayTime = TimeSpan.FromTicks(sessions.Sum(s => s.Duration.Ticks));
// 活跃玩家分析
var uniquePlayers = sessions.Select(s => s.PlayerId).Distinct().ToList();
report.UniquePlayers = uniquePlayers.Count;
// 玩家行为分析
var playerSessions = sessions.GroupBy(s => s.PlayerId);
report.AverageSessionsPerPlayer = playerSessions.Any() ?
playerSessions.Average(g => g.Count()) : 0;
// 操作分析
report.TotalActions = actions.Count;
var actionTypeCount = actions.GroupBy(a => a.ActionType)
.ToDictionary(g => g.Key, g => g.Count());
report.ActionsByType = actionTypeCount;
// 时间分析
if (sessions.Any())
{
var sessionDates = sessions.Select(s => s.StartTime.Date).ToList();
report.FirstSession = sessions.Min(s => s.StartTime);
report.LastSession = sessions.Max(s => s.StartTime);
report.ActiveDays = sessionDates.Distinct().Count();
}
// 离开率分析
var completedSessions = sessions.Count(s => s.IsCompleted);
report.CompletionRate = sessions.Count > 0 ?
(double)completedSessions / sessions.Count * 100 : 0;
return report;
}
public List<PlayerAction> GetPlayerActions(string playerId, DateTime? startDate = null, DateTime? endDate = null)
{
var query = actions.Where(a => a.PlayerId == playerId);
if (startDate.HasValue)
query = query.Where(a => a.Timestamp >= startDate.Value);
if (endDate.HasValue)
query = query.Where(a => a.Timestamp <= endDate.Value);
return query.OrderBy(a => a.Timestamp).ToList();
}
public Dictionary<string, int> GetPlayerActionFrequency(string playerId)
{
return GetPlayerActions(playerId)
.GroupBy(a => a.ActionType)
.ToDictionary(g => g.Key, g => g.Count());
}
public List<string> GetMostActivePlayers(int count = 10)
{
return sessions
.GroupBy(s => s.PlayerId)
.OrderByDescending(g => g.Count())
.Take(count)
.Select(g => g.Key)
.ToList();
}
public TimeSpan GetAverageTimeToComplete(string actionType)
{
var startEvents = actions.Where(a => a.ActionType == $"Start{actionType}");
var completeEvents = actions.Where(a => a.ActionType == $"Complete{actionType}");
var matchingEvents = startEvents.Join(
completeEvents,
start => start.PlayerId,
complete => complete.PlayerId,
(start, complete) => new { Start = start.Timestamp, Complete = complete.Timestamp }
).Where(j => j.Complete > j.Start);
if (!matchingEvents.Any())
return TimeSpan.Zero;
return TimeSpan.FromTicks((long)matchingEvents
.Average(e => (e.Complete - e.Start).Ticks));
}
public void PrintAnalysis()
{
var report = GenerateReport();
Console.WriteLine("=== 游戏数据分析报告 ===");
Console.WriteLine($"总会话数: {report.TotalSessions}");
Console.WriteLine($"总玩家数: {report.UniquePlayers}");
Console.WriteLine($"总操作数: {report.TotalActions}");
Console.WriteLine($"平均会话时长: {report.AverageSessionDuration}");
Console.WriteLine($"总游戏时间: {report.TotalPlayTime}");
Console.WriteLine($"平均每个玩家会话数: {report.AverageSessionsPerPlayer:F2}");
Console.WriteLine($"完成率: {report.CompletionRate:F2}%");
Console.WriteLine($"活跃天数: {report.ActiveDays}");
Console.WriteLine("\n操作类型分布:");
foreach (var action in report.ActionsByType.Take(5))
{
Console.WriteLine($" {action.Key}: {action.Value} 次");
}
Console.WriteLine($"\n最活跃的5名玩家:");
foreach (var player in GetMostActivePlayers(5))
{
Console.WriteLine($" {player}");
}
}
}
public class GameSession
{
public string PlayerId { get; set; }
public DateTime StartTime { get; set; }
public TimeSpan Duration { get; set; }
public bool IsCompleted { get; set; }
public string Level { get; set; }
public int Score { get; set; }
}
public class PlayerAction
{
public string PlayerId { get; set; }
public string ActionType { get; set; }
public DateTime Timestamp { get; set; }
public string Details { get; set; }
}
public class AnalysisReport
{
public int TotalSessions { get; set; }
public int UniquePlayers { get; set; }
public int TotalActions { get; set; }
public TimeSpan AverageSessionDuration { get; set; }
public TimeSpan TotalPlayTime { get; set; }
public double AverageSessionsPerPlayer { get; set; }
public Dictionary<string, int> ActionsByType { get; set; } = new Dictionary<string, int>();
public DateTime FirstSession { get; set; }
public DateTime LastSession { get; set; }
public int ActiveDays { get; set; }
public double CompletionRate { get; set; }
}
常见错误和最佳实践
1. 避免重复枚举
// ❌ 错误: 重复枚举可枚举集合
public void BadExample(IEnumerable<int> numbers)
{
var count = numbers.Count(); // 第一次枚举
var sum = numbers.Sum(); // 第二次枚举
var max = numbers.Max(); // 第三次枚举
}
// ✅ 正确: 转换为列表或数组
public void GoodExample(IEnumerable<int> numbers)
{
var list = numbers.ToList(); // 只枚举一次
var count = list.Count; // O(1)
var sum = list.Sum(); // O(n)
var max = list.Max(); // O(n)
}
2. 正确使用FirstOrDefault vs First
// ❌ 可能抛出异常
var player = players.First(p => p.Level > 100); // 如果没有匹配项会抛异常
// ✅ 安全使用
var player = players.FirstOrDefault(p => p.Level > 100); // 无匹配项返回默认值
if (player != null)
{
// 处理player
}
3. 避免在查询中使用复杂方法
// ❌ 性能差: 在查询中调用复杂方法
var results = players.Where(p => IsEligibleForReward(p)).ToList();
// ✅ 预先计算或简化条件
var eligiblePlayers = players.Where(p => p.Level >= 10 && p.Score > 1000).ToList();
4. 使用索引优化
// 对于频繁的随机访问,使用List<T>
var players = new List<Player> { /* ... */ };
var player = players[5]; // O(1)
// 对于频繁的键值查找,使用Dictionary<TKey, TValue>
var playerLookup = players.ToDictionary(p => p.Name, p => p);
var player = playerLookup["Alice"]; // O(1)
总结
本章我们深入学习了C#的集合框架和LINQ查询:
✅ 集合框架: List
LINQ和集合框架是C#中极其强大的功能,特别适合处理游戏开发中的各种数据操作需求。掌握这些技术可以大大提高代码的可读性和开发效率。
下一步
继续学习 05. 高级特性 →