I have a class called Players that holds various player attributes. I want to use a loop to initialize a list of Players based on certain user input. I will then use the list to play a card game with each of the players. I guess the List needs to be global in scope.
I can't figure out how to initialize the list since I can't seem to user a var
in the name field when trying to create a new Player.
Thanks
class Players
{
public string name;
public double bank;
public Hands playerHands; //A List of hands played
public Players ()
{
name = "Unknown";
bank = 0.0;
playerHands = null;
}
public Players(string name, double bank, Hands playerHands)
{
this.name = name;
this.bank = bank;
this.playerHands = playerHands;
}
}
class Program
{
private static int numOfPlayers;
private static int numOfDecks;
private static List<Cards> shoe;
public static void Main()
{
Console.OutputEncoding = Encoding.UTF8; //required to display special characters
Hands playerHands = new Hands();
Hands dealerHands = new Hands();
SetUpTable();
//Initilize Players
Players player = new Players("Ken", 100.00, playerHands);
Players dealer = new Players("Dealer", 0.0, dealerHands);
int dealerScore = 0, playerScore = 0;
//Deal initial cards
//The deal starts with the dealer who gets the first card face down
Cards dealerUpCard = null;
Hand dealerHand = new Hand();
Hand playerHand = new Hand();
dealer.playerHands.addHand(dealerHand);
player.playerHands.addHand(playerHand);
for (int iii = 1; iii < 3; iii++)
{
//Deal dealer's hand
dealerHand.addCard(shoe[0]);
dealerScore += shoe[0].value;
if (iii == 2) { dealerUpCard = shoe[0]; }
shoe.RemoveAt(0);
//Deal Player's aHand
playerHand.addCard(shoe[0]);
playerScore += shoe[0].value;
shoe.RemoveAt(0);
}
//Print out the test hands
displayHand(dealer);
displayHand(player);
Console.Read();
}
static void displayHand(Players player)
{
//Print out the test hands
for (int i = 0; i < player.playerHands.hands.Count; i++)
{
Console.Write("{0}'s hand: ", player.name);
for (int j = 0; j < player.playerHands.hands[i].hand.Count; j++)
{
Console.Write(" {0}{1} ", player.playerHands.hands[i].hand[j].rank, (char)player.playerHands.hands[i].hand[j].suit);
}
Console.WriteLine();
}
}
static void SetUpTable()
{
//Create players
numOfPlayers = validateUserInput("How many players (1-6)?",1,6);
for (int i = 0; i<numOfPlayers; i++)
{ //get player elements
//initiliz a new unique player in the Players list
//ie: Players player = new Players("Ken", 100.00, playerHands);
}
//Create shoe of cards
numOfDecks = validateUserInput("How many decks of cards (1-8)?", 1, 8);
shoe = Deck.createDeck(numOfDecks);
Deck.shuffleDeck(shoe, numOfDecks);
}
}
public List<Players> ListOfPlayers=new List<Players>();
static void SetUpTable()
{
//Create players
numOfPlayers = 6;
for (int i = 0; i<numOfPlayers; i++)
{
ListOfPlayers.Add(new Players());
//or with initial values with ctor:
ListOfPlayers.Add(new Players("Ken", 100.00, playerHands));
//or
ListOfPlayers.Add(new Players(){name="Ken", bank=100.00, playerHands=_playerHands});
//ie: Players player = new Players("Ken", 100.00, playerHands);
}
}
Related
I am trying to make a high score system for a quiz game I have made. I have got all the scores and their names to read in, sort the scores and put them in rich text boxes (one for scores, one for their names). After I used .Sort() on the integer list (scores), the scores were in the correct order but the names (string list) no longer matched up with the scores.
Here is my code:
public partial class frmhighScore : Form
{
public frmhighScore()
{
InitializeComponent();
this.StartPosition = FormStartPosition.CenterScreen;
this.Name = "High Score";
}
string[] contains;
string[] scorenames;
List<int> scores = new List<int>(){ };
List<string> names = new List<string>(){ };
private void highScore_Load(object sender, EventArgs e)
{
scores.Clear();
names.Clear();
scorenames = File.ReadAllLines(AppDomain.CurrentDomain.BaseDirectory + "scorenames.txt");
foreach (string line in scorenames)
{
gameClass.scorenames.Add(line);
}
for (int x = 0; x < gameClass.scorenames.Count(); x++)
{
contains = gameClass.scorenames[x].Split(':');
names.Add(contains[0]);
scores.Add(Convert.ToInt32(contains[1]));
}
scores.Sort();
scores.Reverse();
for (int a = 0; a < scores.Count; a++)
{
}
for (int y = 0; y < names.Count(); y++)
{
richTextBox1.Text += names[y];
richTextBox1.Text += Environment.NewLine;
}
for (int z = 0; z < scores.Count(); z++)
{
richTextBox2.Text += scores[z];
richTextBox2.Text += Environment.NewLine;
}
}
}
gameClass.scorenames is a string list in my class which is used to read in the details from the text file. All ofther variables are local.
richTextBox1 is for the names and richTextBox2 is for the scores
Here is a screenshot of what the form currently looks like:
Current high score form
And here is the text file that I am reading in from (scorenames.txt):
r:6
bob:10
So as you can see, the names are not matched up with the sorted scores
So my final question is, how would I make it so that the names (bob / r) match up with their scores r is 4, bob is 10?
Any help would be greatly appreciated, thanks.
I think you just need to re model your display entity to bundle both Name and Score together. You might need to change your code somewhat similar to below snippet (I haven't taken care of new line format though)
public class DisplayCard
{
public int Score { get; set; }
public string Name { get; set; }
}
List<DisplayCard> ScoreCard = new List<DisplayCard>();
for (int x = 0; x < gameClass.scorenames.Count(); x++)
{
contains = gameClass.scorenames[x].Split(':');
var name = contains[0];
var score = Convert.ToInt32(contains[1]);
ScoreCard.Add(new DisplayCard { Name = name, Score = score });
}
var sortedCard = ScoreCard.OrderBy(o => o.Score).ToList();
foreach (var card in sortedCard)
{
richTextBox1.Text += card.Name;
richTextBox2.Text += card.Score;
/* take care of new line logic*/
}
You might create objects for each player which includes their score. Then use LINQ to sort them by the score, which will then retain the association with their name: https://msdn.microsoft.com/en-us/library/bb534966.aspx
I have an Gameobject that contains several prefabs, As in the picture below
public SimpleSpriteSequence birds;
Randomizer setBirds;
setBirds = new Randomizer(birds.sprites);
int index = setBirds.getRandom();
birds.setCurrentSpriteIndex(index);
In the image below we see the population of the array
Invoke("Interface", 1f);
Now with the help of the random I get a random bird from the array. But the problem is that the bird can be repeated. All I want is that at least 6 times in a row when the Invoke("Interface", 1f); function does not repeat the bird.So in principle I have to do so 6 times the bird does not repeat itself. To be a random of these birds but 6 times to be different birds. No I know if I explained it properly, but I hope you understand the idea.
Here is code but it is written in console application since i do not have your code and it is writen with custom class of Birds but you will adapt it to your code. If you need help with it i will help you.
class Birds
{
public int birdID;
public string birdName;
//public Sprite birdSprite;
}
class Program
{
static Random rnd = new Random();
static Birds[] birds = new Birds[10];
static int nBirdsSpawned = 0;
static List<int> spawnedBirds = new List<int>();
static void Main(string[] args)
{
//Database of my birds ;)
birds[0] = new Birds();
birds[1] = new Birds();
birds[2] = new Birds();
birds[3] = new Birds();
birds[4] = new Birds();
birds[5] = new Birds();
birds[6] = new Birds();
birds[7] = new Birds();
birds[8] = new Birds();
birds[9] = new Birds();
birds[0].birdID = 0;
birds[0].birdName = "Bird 1";
birds[1].birdID = 1;
birds[1].birdName = "Bird 2";
birds[2].birdID = 2;
birds[2].birdName = "Bird 3";
birds[3].birdID = 3;
birds[3].birdName = "Bird 4";
birds[4].birdID = 4;
birds[4].birdName = "Bird 5";
birds[5].birdID = 5;
birds[5].birdName = "Bird 6";
birds[6].birdID = 6;
birds[6].birdName = "Bird 7";
birds[7].birdID = 7;
birds[7].birdName = "Bird 8";
birds[8].birdID = 8;
birds[8].birdName = "Bird 9";
birds[9].birdID = 9;
birds[9].birdName = "Bird 10";
int i = 0;
while (i < 100)
{
RandomSpawn();
i++;
}
Console.Write("Finished");
Console.ReadKey();
}
static void CheckForBirdSpawn(int birdID)
{
if (nBirdsSpawned <= 6)
{
if (!spawnedBirds.Contains(birdID))
{
spawnedBirds.Add(birdID);
SpawnBird(birdID);
}
else
{
Console.WriteLine("Bird " + birds[birdID].birdName + " is already spawned!");
}
}
else
{
SpawnBird(birdID);
}
}
static void SpawnBird(int birdID)
{
Console.WriteLine(birds[birdID].birdName);
nBirdsSpawned++;
}
static void RandomSpawn()
{
int r = rnd.Next(0, 10);
CheckForBirdSpawn(r);
}
}
Until first 6 birds are spawned it check if bird is already spawned and if it is it doesn't allow it's spawning. After 6 birds are spawned it allows every bird to be spawned.
Here is output in console app:
I know this is a mainly code reply but how about you try something a little like this?
Populate a list of the bird indexes.
Pick a random index within that list.
Decrease all already spawned birds' Values.
If any reach zero, re-add the birds index into the availableBird list.
Spawn the bird, while adding it's index as Key and the amount of spawning delay needed until it can be spawned again as the Value.
Remove the birds index from the list.
Do the spawn whenever necessary, this will spawn every frame since it is found in a Coroutine which has an infinite while loop.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class burd : MonoBehaviour {
public bool spawning;
private System.Random rnd = new System.Random();
private Dictionary<int, int> spawnedBurdies = new Dictionary<int, int>();
private List<int> availableBurdies = new List<int>();
// Use this for initialization
void Start () {
for (int index = 0; index < 10; index++)
{
availableBurdies.Add(index);
}
StartCoroutine(SpawnBurdies());
}
private IEnumerator SpawnBurdies()
{
while (true)
{
if (spawning)
{
int burdIndex = rnd.Next(availableBurdies.Count);
spawnBurd(availableBurdies[burdIndex]);
availableBurdies.RemoveAt(burdIndex);
}
yield return new WaitForFixedUpdate();
}
}
private void spawnBurd(int burdIndex)
{
Debug.Log("Spawned burd #" + burdIndex);
List<int> burdieKeys = new List<int>();
foreach (var burdie in spawnedBurdies) { burdieKeys.Add(burdie.Key); }
foreach (var burdieKey in burdieKeys)
{
spawnedBurdies[burdieKey]--;
if(spawnedBurdies[burdieKey] <= 0)
{
spawnedBurdies.Remove(burdieKey);
availableBurdies.Add(burdieKey);
}
}
spawnedBurdies.Add(burdIndex, 6);
}
}
This solution would save you from attempting to spawn birds that can't be spawned; but if there are less birds than the minimum spawns to wait for, an Argument out of range error would be thrown.
My code works as expected except for when I add a playerHand, which is a list of cards, to a playerHands list, it changes all previous player hands in the list to the current playerHand.
My thought as to what is happening is that there is only one playerHand in memory which is constantly being updated with dealt cards. The items in playerHands list are simply pointing to that single playerHand.
How do I create multiple instances of playerHand so that each item in the playerHands list is unique?
Note: my initial reaction was to use Arrays instead of List, but as far as I can tell Arrays are old-school and deprecated in favor of List.
Solving my problem is my goal here but if there are any thoughts as to the direction I am taking with this program would be accepted.
using System;
using System.Collections.Generic;
namespace Blackjack
{
class Program
{
static void Main()
{
int numOfDecks = 2;
List<Cards> shoe = Deck.createDeck(numOfDecks);
Deck.shuffleDeck(shoe, numOfDecks);
Hand playerHand = new Hand();
Hands playerHands = new Hands();
//Test Hands
//Create ten hands of dealt cards
for (int i = 0 ; i < 10; i++)
{
playerHand.clearHand();
playerHands.addHand(playerHand);
for (int j = 0; j < 5; j++)
{
playerHand.addCard(shoe[j]);
shoe.RemoveAt(0); //delete card delt from shoe
}
}
//Display the cards in each of the hands
for (int i = 0; i < playerHands.hands.Count; i++)
{
Console.Write("Hand {0}: Cards: ", i);
for (int j = 0; j < playerHand.hand.Count; j++)
{
Console.Write("{0}{1}, ", playerHands.hands[i].hand [j].rank, playerHands.hands[i].hand[j].suit);
}
Console.WriteLine();
}
Console.Read();
}
}
}
class Hand
{
/////////////////////////////////////////////////////////////////////
//Hand should contain, at a minimum:
// A List<> of cards that holds the individual cards delt to a player
// Game Number: A game is continues until the player quits
// Hand Number: Sequential hand played during a game
//////////////////////////////////////////////////////////////////////
public List<Cards> hand;
public Hand()
{
hand = new List<Cards>();
}
public void addCard(Cards card)
{
this.hand.Add(card);
}
public void clearHand()
{
hand.Clear();
}
}
class Hands
{
public List<Hand> hands;
public Hands()
{
hands = new List<Hand>();
}
public void addHand(Hand hand)
{
hands.Add(hand);
}
}
The issue is really, really simple: you are not creating enough Hand instances.
You call Hand playerHand = new Hand(); just once.
This means you have only one Hand instance, which you are clearing and filling over and over in your first for loop.
You need to call new Hand() once for each hand instance (just editing the relevant part of your code):
Hands playerHands = new Hands();
//Test Hands
//Create ten hands of dealt cards
for (int i = 0 ; i < 10; i++)
{
Hand playerHand = new Hand();
playerHands.addHand(playerHand);
for (int j = 0; j < 5; j++)
{
playerHand.addCard(shoe[j]);
shoe.RemoveAt(0); //delete card delt from shoe
}
}
Have fun!
I previously created a program for users to play my NumBaseBall Game. I would like to add three more functionalities to it:
(1) Display the number of wins,
(2) Display the frequency played
(3) Display the player's winning %
I have an external class called GameResults that contains a method for calculating strikes or balls that determines the outcome of the game and another that checks to see if the player wants to play again.
How can I achieve these additional three functionalities without having my cumulative data for each erased each time a new instance of GameResults is created if the user decides to play again?
Here is my working code:
class Program
{
static void Main(string[] args)
{
do
{
PlayBall();
}
while (GameResults.PlayAgain());
}
public static void PlayBall()
{
Console.WriteLine("\t\t\t*************************************");
Console.WriteLine("\t\t\t* Let's Have Fun *");
Console.WriteLine("\t\t\t* Welcome To The *");
Console.WriteLine("\t\t\t* Number Baseball Game *");
Console.WriteLine("\t\t\t*************************************\n");
GameResults gameresults = new GameResults();
for (int trysCounter = 1; trysCounter <= 5; trysCounter++)
{
gameresults.Strikes = 0;
Random r = new Random();
var myRange = Enumerable.Range(1, 9);
var computerNumbers = myRange.OrderBy(i => r.Next()).Take(3).ToList();
Console.WriteLine("The Game's Three Random Integers Are: (Hidden from user)");
foreach (int integer in computerNumbers)
{
Console.WriteLine("{0}", integer);
}
List<int> playerNumbers = new List<int>();
Console.WriteLine("Please Enter Three Unique Single Digit Integers and Press ENTER after each:");
for (int i = 0; i < 3; i++)
{
Console.Write("");
int number = Convert.ToInt32(Console.ReadLine());
playerNumbers.Add(number);
}
gameresults.StrikesOrBalls(computerNumbers, playerNumbers);
Console.WriteLine("-----------------------> Computer's Numbers = {0}{1}{2}", computerNumbers[0], computerNumbers[1], computerNumbers[2]);
Console.WriteLine("-----------------------> Player's Numbers = {0}{1}{2}", playerNumbers[0], playerNumbers[1], playerNumbers[2]);
Console.WriteLine("-----------------------> Game Results = {0} STRIKES & {1} BALLS\n", gameresults.Strikes, gameresults.Balls);
Console.WriteLine("You have tried {0} times\n", trysCounter);
gameresults.TotalStrikes = gameresults.TotalStrikes + gameresults.Strikes;
Console.WriteLine("STRIKES = {0} ", gameresults.TotalStrikes);
if (gameresults.TotalStrikes >= 3)
{
Console.WriteLine("-----------------------> YOU ARE A WINNER!!!");
break;
}
}
if (gameresults.TotalStrikes < 3)
{
Console.WriteLine("YOU LOSE :(");
}
}
}
Here are my external methods:
public void StrikesOrBalls(List<int> computer, List<int> player)
{
for (int c = 0; c < 3; c++)
{
for (int p = 0; p < 3; p++)
{
if (computer[c] == player[p] && computer[c] != player[c])
Balls++;
}
}
if(computer[0]== player[0])
Strikes++;
if(computer[1] == player[1])
Strikes++;
if(computer[2] == player[2])
Strikes++;
}
public static bool PlayAgain()
{
while (true)
{
Console.Write("Do you want to play again [YES/NO]?\n");
string answer = Console.ReadLine().ToUpper();
if (answer == "YES")
return true;
if (answer == "NO")
Console.WriteLine("Thanks for playing NumBaseBall :) Goodbye!");
return false;
}
}
I want to create a highscore board for my game.
the score board contain the top 5 scores in the text file
the text file are something like this:
alpha, 3500
beta, 3600
gamma, 2200
delta, 3400
epsilon, 2000
and this is my codes :
[Serializable]
public struct HighScoreData
{
public string[] PlayerName;
public int[] Score;
public int Count;
public HighScoreData(int count)
{
PlayerName = new string[count];
Score = new int[count];
Count = count;
}
}
static HighScoreData highScores;
this codes for reading data from text file and already add sorting in it:
try
{
using (StreamReader sr = new StreamReader("highscore.txt"))
{
string line;
int i = 0;
//file = new StreamReader(filePath);
while ((line = sr.ReadLine()) != null)
{
string[] parts = line.Split(',');
highScores.PlayerName[i] = parts[0].Trim();
highScores.Score[i] = Int32.Parse(parts[1].Trim());
i++;
Array.Sort(highScores.Score);
}
}
}
this is how I draw it :
for (int i = 0; i < 5; i++)
{
spriteBatch.DrawString(spriteFont, i + 1 + ". " + highScores.PlayerName[i].ToString()
, new Vector2(200, 150 + 50 * (i)), Color.Red);
spriteBatch.DrawString(spriteFont, highScores.Score[i].ToString(),
new Vector2(550, 150 + 50 * (i)), Color.Red);
}
the problem is when I run the game, it only sorting the scores and not the player name. and also, the first and secod scores in text file are identified as "0". it displayed like this :
alpha 0
beta 0
gamma 2000
delta 2200
epsilon 3400
what must I do, so the program can sorting all the data in the text file, not only the score...?
Another option without comparers using LINQ based on Blau's sample:
struct PlayerScore
{
public string Player;
public int Score;
public int DataYouWant;
}
then a sample of populating the list and sorting it:
List<PlayerScore> scores = new List<PlayerScore>();
Random rand = new Random();
for (int i = 0; i < 10; i++)
{
scores.Add(new PlayerScore()
{
Player = "Player" + i,
Score = rand.Next(1,1000)
});
}
scores = (from s in scores orderby s.Score descending select s).ToList();
foreach (var score in scores)
{
Debug.WriteLine("Player: {0}, Score: {1}", score.Player, score.Score);
}
Make a struct named PlayerScore
struct PlayerScore
{
public string Player;
public int Score;
public int DataYouWant;
public static int Compare(PlayerScore A, PlayerScore B)
{
return A.Score - B.Score;
}
}
and then to Sort call only one time, (outside the while) to the sort method this way:
Array.Sort<PlayerScore>( yourArray, PlayerScore.Compare );
Do you really need to have more than HighScoreData instance? I think that no.. so you store your highscores this way:
static PlayerScore[] highScores = new PlayerScore[MaxHighScorePlayers];