我是一个初学者程序员,寻找我的简单战争卡游戏程序,我所做的评论。每个玩家得到一副牌,你一次抽一张牌,然后比较2。最高值获胜。这样做,直到比赛结束,谁得到最多的分数,谁就赢。如有任何建议,敬请谅解!谢谢你花时间看这个!
enum Suit
{
Hearts,
Diamonds,
Spades,
Clovers
}
enum Face
{
Two,
Three,
Four,
Five,
Six,
Seven,
Eight,
Nine,
Ten,
Jack,
Queen,
King,
Ace
}
// MAKING WAR CARD GAME
class Program
{
public static bool isPlaying = true;
public static Player human = new Player();
public static Player cpu = new Player();
public static int round = 1;
static void Main(string[] args)
{
GameFlow.Start(human, cpu);
while (isPlaying)
{
for (int i = 0; i < 52; i++)
{
GameFlow.Gameplay(human, cpu, round);
round++;
}
round = 1;
GameFlow.Ending(human, cpu);
}
}
}
class Player
{
public string name = "CPU";
public Card currentCard = new Card(); // the current card in play
public int wins = 0 , drawCount = 0;
public Deck myDeck = new Deck();
public void DrawOne()
{
currentCard = myDeck.CurrentlyInDeck[drawCount];
drawCount++;
if (drawCount == 52)
{
drawCount = 0;
}
}
public void SetName()
{
while (name == "CPU" || name == "")
{
Console.WriteLine("What is your name human?");
name = Console.ReadLine();
if(name == "CPU" || name == "")
{
Console.WriteLine("Invalid name!! Try a real name you assclown!");
Console.ReadLine();
}
Console.Clear();
}
}
class Card
{
public Suit suit;
public Face face;
public void PrintCard()
{
Console.Write("{0} of {1}", face, suit);
}
}
class Deck
{
public List<Card> CurrentlyInDeck;
public void GenerateDeck() // Must use this to populate deck
{
CurrentlyInDeck = new List<Card>(52);
int place = 0; // tracks which card number
for (int i = 0; i < 4; i++)
{
for (int f = 0; f < 13; f++)
{
Card card = new Card();
CurrentlyInDeck.Add(card);
CurrentlyInDeck[place].suit = (Suit)i;
CurrentlyInDeck[place].face = (Face)f;
place++;
}
}
}
private static readonly Random rand = new Random();
public void Shuffle()
{
Card holder = new Card();
int random;
for (int i = 0; i < 52; i++)
{
random = rand.Next(0, 51);
holder = CurrentlyInDeck[i];
CurrentlyInDeck[i] = CurrentlyInDeck[random];
CurrentlyInDeck[random] = holder;
}
}
public void PrintDeck() // prints all cards in the deck , used for testing
{
foreach (var card in CurrentlyInDeck)
{
card.PrintCard();
}
}
}
static class Create
{
public static void Name(Player a)
{
a.SetName();
}
public static void TheirDecks(Player hum , Player cpu)
{
hum.myDeck.GenerateDeck();
cpu.myDeck.GenerateDeck();
hum.myDeck.Shuffle();
cpu.myDeck.Shuffle();
}
}
static class GameFlow
{
static public void Start(Player hum, Player cpu) //Creates initial situation
{
Words.Begin();
Create.TheirDecks(hum, cpu);
Create.Name(hum);
}
static public void ShuffleDecks(Player hum, Player cpu)
{
hum.myDeck.Shuffle();
cpu.myDeck.Shuffle();
}
static public void DrawCards(Player hum, Player cpu) // changes the current card
{
hum.DrawOne();
cpu.DrawOne();
}
static public void Gameplay(Player hum, Player cpu, int round) // The normal gameplay loop
{
GameFlow.DrawCards(hum, cpu);
Words.Template(hum, cpu, round);
GameFlow.CheckWin(hum, cpu);
}
static public void Ending(Player hum, Player cpu) // Once all the cards have been played
{
string answer = "";
bool correctForm = false;
Words.LastWords(hum, cpu);
while (!correctForm)
{
Console.WriteLine("Would you like to play again? Enter y for yes or n for no.");
answer = Console.ReadLine();
answer = answer.ToLower();
if(answer != "y" && answer != "n")
{
Console.WriteLine("Thats not a valid option you idiot!");
Console.WriteLine("Press enter to continue.");
Console.ReadLine();
Console.Clear();
Words.LastWords(hum, cpu);
}
if(answer == "y" || answer == "n")
{
correctForm = true;
}
}
if (answer == "y")
{
PlayingAgain(hum ,cpu);
Console.Clear();
}
if (answer == "n")
{
Console.WriteLine("Thanks for playing!");
Console.WriteLine("Press enter to exit.");
Environment.Exit(0);
}
}
static public void PlayingAgain(Player hum , Player cpu)
{
ShuffleDecks(hum, cpu);
hum.wins = 0;
cpu.wins = 0;
}
static public void CheckWin(Player hum , Player cpu)
{
Console.WriteLine("");
if ((int)hum.currentCard.face > (int)cpu.currentCard.face)
{
hum.wins++;
Console.WriteLine();
Console.WriteLine("You win this one! Nice!");
Console.WriteLine("Press enter to keep going.");
Console.ReadLine();
Console.Clear();
}
else if ((int)hum.currentCard.face < (int)cpu.currentCard.face)
{
cpu.wins++;
Console.WriteLine();
Console.WriteLine("Looks like the CPU won this one. You suck!");
Console.WriteLine("Press enter to keep going.");
Console.ReadLine();
Console.Clear();
}
else
{
Console.WriteLine();
Console.WriteLine("Its a draw!");
Console.WriteLine("Press enter to keep going.");
Console.ReadLine();
Console.Clear();
}
}
}
static class Words // The dialogue of the program
{
public static void Begin()
{
Console.WriteLine("Hello , welcome to war!");
Console.WriteLine("The rules are simple. Its you vs a cpu");
Console.WriteLine("You each pull 1 card from your decks and see which is highest.");
Console.WriteLine("Your card will be the one under your name , while the other is the CPUs.");
Console.WriteLine("The one with the most points at the end wins all the glory!");
Console.WriteLine("Understand?");
Console.WriteLine("Press enter if you're ready for the showdown.");
Console.ReadLine();
Console.Clear();
}
public static void Template(Player hum , Player cpu , int round) //Prints the normal screen
{
int distance = 17; //distance between the 2 names
Console.Write("{0} wins = {1}", hum.name, hum.wins);
Console.Write(" R{0}", round);
distance -= hum.name.Length;
while (distance > 0)
{
Console.Write(" ");
distance--;
}
Console.Write("{0} wins = {1}" , cpu.name , cpu.wins);
Console.WriteLine();
Console.WriteLine();
hum.currentCard.PrintCard();
Console.Write(" vs ");
cpu.currentCard.PrintCard();
}
public static void LastWords(Player hum , Player cpu)
{
Console.WriteLine("Thats all the cards!");
Console.WriteLine("So this is the final score: {0} = {1} and {2} = {3}" , hum.name, hum.wins, cpu.name, cpu.wins);
if(hum.wins > cpu.wins)
{
Console.WriteLine("You have beaten the CPU in this game of luck!!!! Congrats!!!");
}
else if(cpu.wins > hum.wins)
{
Console.WriteLine("The CPU has detroyed you and everything you have loved. Congrats!!!");
}
else
{
Console.WriteLine("Oh my! Its a draw. You both are equal warriors of luck.");
}
}
}发布于 2018-09-20 10:07:04
另一个答案已经提到了费舍-耶茨洗牌,这绝对是您想要使用的。我想我会把你的洗牌分解一下,让你知道它为什么有缺陷。
这是我认为是整个互联网上最好的网页之一,它有一个关于洗牌的章节,你可能会觉得有趣:迈克的可视化算法。
迈克还创建了这个资源:它会洗牌吗?转到这个页面并将选择更改为“天真的交换(i↦随机)”,这就是您已经实现的。它会告诉你洗牌是相当有偏见的:

如果这还不够糟糕的话,你会意外地增加了一种额外的偏见。我已经将您的算法翻译为JS,并为您运行了它:

你看到右下角那个深紫色的正方形了吗?这表明了对最后一个元素的非常负面的偏见。让我们来看看为什么:
public void Shuffle()
{
Card holder = new Card();
int random;
for (int i = 0; i < 52; i++)
{
random = rand.Next(0, 51); // !!!
holder = CurrentlyInDeck[i];
CurrentlyInDeck[i] = CurrentlyInDeck[random];
CurrentlyInDeck[random] = holder;
}
}Random.Next的文档说(强调我的):
大于或等于minValue且小于maxValue的32位有符号整数;也就是说,返回值的范围包括minValue,而不是maxValue。
这意味着您只生成0到50之间的随机数。这意味着您永远不能在原来的位置得到最后一项,因为它只在循环的最后一次迭代中被交换。这对洗牌来说是很糟糕的。
发布于 2018-09-21 17:20:33
让我补充一点其他人似乎没有提到过的东西。您不应该使用公共字段,除非它是常量或只读的,而是应该使用公共属性。例如,考虑一下Card类,但是您对其他类感到内疚。
class Card
{
public Suit suit;
public Face face;
public void PrintCard()
{
Console.Write("{0} of {1}", face, suit);
}
}我希望看到:
PrintCard可以简化为Print,但实际上可以是ToString或Name属性。因此,这将改写为:
public class Card
{
public Suit Suit { get; }
public Face Face { get; }
public Card(Face face, Suit suit)
{
Face = face;
Suit = suit;
}
public string Name => $"{Face}{Suit}";
public override string ToString() => Name;
}您不需要根据神奇的数字或甲板大小来填充它们。而是直接设置它们。示例:
public void GenerateDeck()
{
CurrentlyInDeck = new List<Card>(); // Not concerned with count.
var suits = Enum.GetValues(typeof(Suit)).Cast<Suit>().ToList();
var faces = Enum.GetValues(typeof(Face)).Cast<Face>().ToList();
foreach (var suit in suits)
{
foreach (var face in faces)
{
CurrentlyInDeck.Add(new Card(face, suit));
}
}
}https://codereview.stackexchange.com/questions/203971
复制相似问题