C# Trouble wiith Blackjack Game - c#

I'm having trouble with the counter variable. Every time I leave each method, count is re-initialized to 0. I haven't completed the Stay() method the Hit() method is killing. After every Hit I need to display all of the user's cards. I do not know how to do this. There has to be a more efficient way. I think all my problems arise from the problem with the Count variable.
Thanks for any help.
Below is my main class. Below that is my Deck class.
I left out the Card, Suit and Rank class.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BlkJack
{
class Program
{
static void Main(string[] args)
{
string name;
int Chips = 500;
int Wage;
int count = 0;
string HS;
Card pCard1, dCard1, pCard2, dCard2;
int playerHand, dealerHand;
//int chipsWon;
Console.WriteLine("Welcome to Johnny's BlackJack!");
Console.WriteLine("You are given $500 to play with.");
Console.WriteLine("Table Limit is $250 per hand. <Enter a 0 to quit>");
name = GetName("Enter name: ");
Console.WriteLine("Hello {0}, you are ${1} ahead.", name, Chips);
Wage = getWager("What is your wager?: ", 1, 250, "?Value must be an integer.", "Max bet is 250!");
Deck d = new Deck();
startingHand(count, d, out pCard1, out dCard1, out pCard2, out dCard2, out playerHand, out dealerHand);
Console.WriteLine("Your hand: {0}, {1} <{2}> ", pCard1, pCard2, playerHand);
Console.WriteLine("<Dealer's show card is {0}>", dCard1);
count = count + 4;
HS = HitorStay("Do you want to <H>it or <S>tay?: ", count, playerHand, d);
while (HS == "H" || HS == "HIT")
{
HS = HitorStay("Do you want to <H>it or <S>tay?: ", count, playerHand, d);
Console.WriteLine("Your cards: {0} {1} <{2}>", pCard1, pCard2, playerHand);
//Console.WriteLine("{0}", count);
}
}
static string GetString(string prompt, string[] valid, string error)
{
string response;
bool OK = false;
do
{
Console.Write(prompt);
response = Console.ReadLine().ToUpper();
foreach (string s in valid) if (response == s) OK = true;
if (!OK) Console.WriteLine(error);
}
while (!OK);
return response;
}
static string GetName(string prompt)
{
string response;
Console.Write(prompt);
response = Console.ReadLine();
while (response == "0")
{
Environment.Exit(0);
}
return response;
}
static bool GetYesNo(string prompt)
{
string[] valid = { "YES", "Y", "NO", "N" };
string ans = GetString(prompt, valid, "Invalid response. Please reenter.");
return (ans == "YES" || ans == "Y");
}
static int getWager(string prompt, int low, int high, string errorInt, string errorRange)
{
int Wager;
string userInput;
bool OKInt = false, OKRange = false;
do
{
Console.Write(prompt);
userInput = Console.ReadLine();
OKInt = Int32.TryParse(userInput, out Wager);
if (OKInt)
{
OKRange = low <= Wager && Wager <= high;
if (!OKRange) Console.WriteLine(errorRange);
}
else
Console.WriteLine(errorInt);
}
while (!OKInt || !OKRange);
return Wager;
}
public static int startingHand(int count, Deck d, out Card pCard1, out Card dCard1, out Card pCard2, out Card dCard2, out int playerHand, out int dealerHand)
{
playerHand = 0; dealerHand = 0;
if (count == 0 || count >= 42) d.Shuffle();
for (int i = 0; i < 52; i++)
Console.Write("{0},", d.GetCard(i));
pCard1 = d.GetCard(count);
count++;
dCard1 = d.GetCard(count);
count++;
pCard2 = d.GetCard(count);
count++;
dCard2 = d.GetCard(count);
count++;
playerHand = pCard1.GetValue() + pCard2.GetValue();
dealerHand = dCard1.GetValue() + dCard2.GetValue();
return count;
}
static string HitorStay(string prompt, int count, int playerHand, Deck d)
{
string[] valid = { "HIT", "H", "STAY", "S" };
string HS = GetString(prompt, valid, "?Invalid Response. (H)it or (S)tay?");
if (HS == "HIT" || HS == "H")
{
Hit(count, playerHand, d);
}
//else if (HS == "STAY" || HS == "S")
//{
//Stay(count, playerHand, dealerHand, out chipStay);
//}
else Environment.Exit(0);
return HS;
}
public static int Hit(int count, int playerHand, Deck d)
{
count += 1;
playerHand += d.GetCard(count).GetValue();
return playerHand;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BlkJack
{
class Deck
{
private Card[] cards = new Card[52];
public Deck()
{
for (int suitVal=0; suitVal<4; suitVal++)
{
for (int rankVal = 0; rankVal < 13; rankVal++)
{
cards[suitVal * 13 + rankVal] =
new Card((Suit)suitVal, (Rank)(rankVal));
cards[suitVal * 13 + rankVal].SetValue(rankVal);
if (rankVal > 9) cards[suitVal * 13 + rankVal].SetValue(10);
if (rankVal == 1) cards[suitVal * 13 + rankVal].SetValue(11);
if (rankVal == 0) cards[suitVal * 13 + rankVal].SetValue(10);
}
}
}
public Card GetCard(int cardNum)
{
return cards[cardNum];
}
public void Shuffle()
{
Card[] newDeck = new Card[52]; // cards randomly assigned to locs in newDeck
bool[] assigned = new bool[52]; // keep track of what locs used in newDeck
int seed = 0;
Console.Write("Enter seed: ");
seed = Convert.ToInt32(Console.ReadLine()); // yes, stupid user can break
Random rGen = new Random(seed);
for (int i=0; i<52; i++)
{
int destCard = 0; // where card is going to be put
bool foundCard = false;
while (foundCard == false)
{
destCard = rGen.Next(52);
if (assigned[destCard] == false)
foundCard = true;
}
assigned[destCard] = true;
newDeck[destCard] = cards[i];
}
newDeck.CopyTo(cards, 0); //.CopyTo(destination, start index)
}
}
}

Look at this code
public static int Hit(int count, int playerHand, Deck d)
{
count += 1;
You are passing in a copy of count and incrementing that copy. The original value you passed in is never affected. Straightforward fixes include
Pass count by reference ref int count.
Make count a static class field rather than a local variable in Main()
A much better way would be to encapsulate your logic in a class and make count a field or property of that class, so that class methods can see and change it.

Related

C# Sliding Window Algorithm

So i have to sent a message from a Sender to a Destination(Shown in main class) by specifing how many letters i wanna sent (the size variable).When the laters left are less than letters i wanna sent,it automaticaly sent how many i have left,and after the algorithm stops;
The problem is when the message i supossely sent is 9 characters long,and when i wanna sent 6 characters and another 3 it throws me an error (System.IndexOutOfRangeException: 'Index was outside the bounds of the array.'
)
using System;
using System.Text;
using System.Threading;
namespace homework
{
internal class slidingWindow
{
private string name;
private StringBuilder message = new StringBuilder();
private bool isSource = false;
private int fin = 0;
public slidingWindow(string name, bool isSource)
{
this.name = name;
this.isSource = isSource;
}
public void messageSet(string _message)
{
if (isSource == true) message.Append(_message);
else Console.WriteLine("Is not source");
}
public void sendMessage(slidingWindow destination)
{
int counter= 0;
Console.WriteLine("Specify the size of data sent: ");
int size = Convert.ToInt32(Console.ReadLine()); //the size of how manny letters i should send
int countCharacterSent=size;
for (int x = 0; x < message.Length+(message.Length%size); x = x + size)
{
counter++;
for (int y = 0; y < size; y++)
{
if (x + size > message.Length + (message.Length % size)) { size=size-(message.Length%size); countCharacterSent = message.Length; }
else {destination.message.Append(message[x + y]); }
}
Console.WriteLine("Sennder---- " + destination.message + " ----->Destination" + " (" + counter+ ")"+ " Characters sent: "+size+ " Characters received: "+countCharacterSent+ '\n');
Thread.Sleep(TimeSpan.FromSeconds(1));
countCharacterSent = countCharacterSent + size;
}
fin = 1;
if (message.Length % size != 0) destination.fin = 1;
destination.print();
}
public void print()
{
Console.WriteLine("Destination has receveid the message: " + message+" FIN: "+fin);
}
}
and the main class
using System;
namespace homework
{
class main
{
static void Main(string[] args)
{
while (true)
{
int option = 0;
slidingWindow a = new slidingWindow("Sender", true);
a.messageSet("exampless");
slidingWindow b = new slidingWindow("Destination", false);
a.sendMessage(b);
Console.WriteLine("If you want to exit write 1:"+'\n');
option = Convert.ToInt32(Console.ReadLine());
if (option == 1) break;
}
}
}
example:
input:
message='example'
size=3;
output:
exa
mpl
e
Honestly I can see you try hard (too hard) to handle the limit case of the last block that can just not meet the expect size.
Since you do this in dotnet C#, and depending on the version you will see you have many different options....
Especially to create a batch of x out of a simple sequence....
here is a homemade version of things you will find for free in libraries like moreLinq and probably in latest Linq lib..
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Linq;
public static class LinqExtensions
{
public static IEnumerable<IEnumerable<T>> Batch<T>(this IEnumerable<T> source, int size)
{
return source
.Select( (c, i) => (c, index : i))
.Aggregate(
new List<List<T>>(),
(res, c) =>
{
if (c.index % size == 0)
res.Add(new List<T> { c.c });
else
res.Last().Add(c.c);
return res;
});
}
}
public class Program
{
public static void Main(string[] args)
{
var test = "xxxxxxxxxxx".AsEnumerable();
var blocks = test
.Batch(3)
.Select(b=> new string(b.ToArray()));
blocks.ToList().ForEach(System.Console.WriteLine);
}
}

How to save C# output to a file?

My code finds prime numbers in a given range. I want to make a menu in the end of it that will ask if i want to save output numbers to a file and then save it. I would really appreciate any help.
using System;
public class Exercise34
{
public static void Main()
{
int num,i,ctr,stno,enno;
Console.Write("\n\n");
Console.Write("Find the prime numbers within a range of numbers:\n");
Console.Write("---------------------------------------------------");
Console.Write("\n\n");
Console.Write("Input starting number of range: ");
stno = Convert.ToInt32(Console.ReadLine());
Console.Write("Input ending number of range : ");
enno = Convert.ToInt32(Console.ReadLine());
Console.Write("The prime numbers between {0} and {1} are : \n",stno,enno);
for(num = stno;num<=enno;num++)
{
ctr = 0;
for(i=2;i<=num/2;i++)
{
if(num%i==0){
ctr++;
break;
}
}
if(ctr==0 && num!= 1)
Console.Write("{0} ",num);
}
Console.Write("\n");
}
}
I suggest extracting method(s): do not cram everything into single Main, decompose the solution into easy to read and debug routines
private static bool IsPrime(int value) {
if (value <= 1)
return false;
if (value % 2 == 0)
return value == 2;
int n = (int) (Math.Sqrt(value) + 0.5);
for (int i = 3; i <= n; i += 2)
if (value % i == 0)
return false;
}
private static IEnumerable<int> Primes(int from, int to) {
if (to <= 1)
yield break;
if (from < 2)
from = 2;
for (int value = from; value <= to; ++value)
if (IsPrime(value))
yield return value;
}
And then you put it as simple as (output to Console)
public static void Main() {
...
Console.Write("The prime numbers between {0} and {1} are : \n",stno,enno);
foreach (int value in Primes(stno, enno))
Console.WriteLine(value);
}
or (output to File)
using System.IO;
using System.Linq;
...
public static void Main() {
...
Console.Write("The prime numbers between {0} and {1} are : \n",stno,enno);
File.WriteAllLines(#"c:\MyFile.txt", Primes(stno, enno)
.Select(value => value.ToString()));
}

C# problems with a for loop

Can someone tell me why this doesnt work. When I enter the loop it prints everything instead of one line and get the users input. It prints Enter the integer the account numberEnter the integer the account balanceEnter the account holder lastname
Got it working thanks everyone, but now the searchaccounts doesnt work
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class accounts
{
private int[] accountnum = new int[5]; //private accountnum array of five integer account numbers
private int[] accountbal = new int[5];//private balance array of five balance amounts
private string[] accountname = new string[5];//private accntname array to hold five last names
public void fillAccounts()
{
int bal;
int accountnumber;
string name;
for (int x = 0; x < 5; ++x)
{
Console.Write("Enter the integer the account number");
accountnumber = Console.Read();
Console.Write("Enter the integer the account balance");
bal = Console.Read();
Console.Write("Enter the account holder lastname");
name = Console.ReadLine();
accountnum[x] = accountnumber;
accountbal[x] = bal;
accountname[x] = name;
}
}
public void searchAccounts()
{
Console.WriteLine("Enter the account number");
int acctnum = Console.Read();
for (int x = 0; x < 6; ++x)
{
if (x < 5)
{
if (accountnum[x] == acctnum)
{
Console.WriteLine("Account #{0} has a balance of {1} for customer {2}", acctnum, accountbal[x].ToString("C"), accountname[x]);
break;
}
}
else
{
Console.WriteLine("You entered invalid account number");
}
}
}
public void averageAccounts()
{
int sum = 0;
int avg;
for (int x = 0; x < 5; ++x)
{
sum = accountbal[x] + sum;
}
avg = sum / 5;
Console.WriteLine("The average dollar amount is {0}", avg.ToString("c"));
}
}
class assignment3_alt
{
static void Main(string[] args)
{
accounts myclass = new accounts();
string userin;
myclass.fillAccounts();
int i = 0;
while (i != 1)
{//use the following menu:
Console.WriteLine("*****************************************");
Console.WriteLine("enter an a or A to search account numbers");
Console.WriteLine("enter a b or B to average the accounts");
Console.WriteLine("enter an x or X to exit program");
Console.WriteLine("*****************************************");
Console.Write("Enter option-->");
userin = Console.ReadLine();
if (userin == "a" || userin == "A")
{
myclass.searchAccounts();
}
else if (userin == "b" || userin == "B")
{
myclass.averageAccounts();
}
else if (userin == "x" || userin == "X")
{
break;
}
else
{
Console.WriteLine("You entered an invalid option");
}
}
}
}
}
Console.Read only reads a single character. You need to use Console.ReadLine.
Console.Write("Enter the integer the account number");
accountnumber = int.Parse(Console.ReadLine());
Console.Write("Enter the integer the account balance");
bal = int.Parse(Console.ReadLine());
Console.Write("Enter the account holder lastname");
name = Console.ReadLine();
You might also want to consider using int.TryParse instead of int.Parse so that you can better handle invalid input.
For your new question it is the same error. Just replace:
int acctnum = Console.Read();
with
int acctnum = int.Parse(Console.ReadLine());
or (preferably)
int acctnum;
if (!int.TryParse(Console.ReadLine(), out acctnum))
{
Console.WriteLine("You need to enter a number");
return;
}
The first will fail if the user doesn't enter a valid integer the second will print out a nice error message and return to the loop.
This is not an answer, as other have already put up some good ones. These are just a few tips about your code.
Instead of looping with while (i != 1), never changing the value of i and terminating the loop with break, it would be better to use a do-while loop, like this:
do
{
// blah blah
} while(userin != "x" || userin != "X")
It is less confusing than having a variable with no use at all.

C# : Console.Read() does not get the "right" input

I have the following code:
The actual problem is the "non-quoted" code.
I want to get the player amount (max = 4), but when I ask via Console.Read() and I enter any Int from 1 to 4 I get as value: 48 + Console.Read().
They only thing how I can get the "real" input is using Console.ReadLine(), but this does not give me an Integer, no it returns a string, and actually do not know how to convert String (Numbers) to Integers in C#, because I am new, and because I only found ToString() and not ToNumber.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace eve_calc_tool
{
class Program
{
int players;
int units;
int active_units;
int inactive_units;
int finished_units;
int lastDiceNumber = 0;
bool game_state;
public static void Main(string[] args)
{
int count_game = 0;
//Console.Title = "Mensch ärger dich nicht";
//Console.WriteLine("\tNeues Spiel wird");
//Console.WriteLine("\t...geladen");
//System.Threading.Thread.Sleep(5000);
//Console.Clear();
//Console.WriteLine("Neues Spiel wird gestartet, bitte haben sie etwas Geduld");
//Console.Title = "Spiel " + count_game.ToString();
//Console.Clear();
//string prevText = "Anzahl der Spieler: ";
//Console.WriteLine(prevText);
string read = Console.ReadLine();
/*Program game = new Program();
game.players = read;
game.setPlayers(game.players);
if (game.players > 0 && 5 > game.players)
{
game.firstRound();
}*/
string readagain = read;
Console.ReadLine();
}
/*
bool setPlayers(int amount)
{
players = amount;
if (players > 0)
{
return true;
}
else
{
return false;
}
}
bool createGame()
{
inactive_units = units = getPlayers() * 4;
active_units = 0;
finished_units = 0;
game_state = true;
if (game_state == true)
{
return true;
}
else
{
return false;
}
}
int getPlayers()
{
return players;
}
private static readonly Random random = new Random();
private static readonly object syncLock = new object();
public static int RandomNumber(int min, int max)
{
lock (syncLock)
{ // synchronize
return random.Next(min, max);
}
}
int rollDice()
{
lastDiceNumber = RandomNumber(1,6);
return lastDiceNumber;
}
int firstRound()
{
int[] results = new int[getPlayers()];
for (int i = 0; i < getPlayers(); i++)
{
results[i] = rollDice();
}
Array.Sort(results);
return results[3];
}
*/
}
}
You can use
int convertedNumber = int.parse(stringToConvert)
or
int convertedNumber;
int.TryParse(stringToConvert, out covertedNumber)
to convert strings to integers.
You should really use TryParse instead so that you can catch if the user doesn't input a number. int.Parse will throw an exception if it tries to convert a string that is not numeric.
int convertedNumber = 0;
if (!int.TryParse(stringToConvert, out convertedNumber))
{
// this code will execute if the user did not put
// in an actual number. For example, if the user entered "a".
}
The TryParse method returns a boolean value which will tell you whether the conversion was successful. If it was successful, the converted value will be passed through the out parameter.
To convert your string to an integer, use int.Parse(yourString).
The reason you get "48 + Console.ReadKey" is that Console.ReadKey returns the code of the key that was pressed - in this case, the ANSI value of the number character that was pressed.

getting the best record from a file

I have a file with the following text inside
mimi,m,70
tata,f,60
bobo,m,100
soso,f,30
I did the reading from file thing and many many other methods and functions, but how I can get the best male name and his grade according to the grade.
here is the code I wrote. Hope it's not so long
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace practice_Ex
{
class Program
{
public static int[] ReadFile(string FileName, out string[] Name, out char[] Gender)
{
Name = new string[1];
int[] Mark = new int[1];
Gender = new char[1];
if (File.Exists(FileName))
{
FileStream Input = new FileStream(FileName, FileMode.Open, FileAccess.Read);
StreamReader SR = new StreamReader(Input);
string[] Current;
int Counter = 0;
string Str = SR.ReadLine();
while (Str != null)
{
Current = Str.Split(',');
Name[Counter] = Current[0];
Mark[Counter] = int.Parse(Current[2]);
Gender[Counter] = char.Parse(Current[1].ToUpper());
Counter++;
Array.Resize(ref Name, Counter + 1);
Array.Resize(ref Mark, Counter + 1);
Array.Resize(ref Gender, Counter + 1);
Str = SR.ReadLine();
}
}
return Mark;
}
public static int MostFreq(int[] M, out int Frequency)
{
int Counter = 0;
int Frequent = 0;
Frequency = 0;
for (int i = 0; i < M.Length; i++)
{
Counter = 0;
for (int j = 0; j < M.Length; j++)
if (M[i] == M[j])
Counter++;
if (Counter > Frequency)
{
Frequency = Counter;
Frequent = M[i];
}
}
return Frequent;
}
public static int Avg(int[] M)
{
int total = 0;
for (int i = 0; i < M.Length; i++)
total += M[i];
return total / M.Length;
}
public static int AvgCond(char[] G, int[] M, char S)
{
int total = 0;
int counter = 0;
for (int i = 0; i < G.Length; i++)
if (G[i] == S)
{
total += M[i];
counter++;
}
return total / counter;
}
public static int BelowAvg(int[] M, out int AboveAvg)
{
int Bcounter = 0;
AboveAvg = 0;
for (int i = 0; i < M.Length; i++)
{
if (M[i] < Avg(M))
Bcounter++;
else
AboveAvg++;
}
return Bcounter;
}
public static int CheckNames(string[] Name, char C)
{
C = char.Parse(C.ToString().ToLower());
int counter = 0;
string Str;
for (int i = 0; i < Name.Length - 1; i++)
{
Str = Name[i].ToLower();
if (Str[0] == C || Str[Str.Length - 1] == C)
counter++;
}
return counter;
}
public static void WriteFile(string FileName, string[] Output)
{
FileStream FS = new FileStream(FileName, FileMode.OpenOrCreate, FileAccess.Write);
StreamWriter SW = new StreamWriter(FS);
for (int i = 0; i < Output.Length; i++)
SW.WriteLine(Output[i]);
}
static void Main(string[] args)
{
int[] Mark;
char[] Gender;
string[] Name;
string[] Output = new string[8];
int Frequent, Frequency, AvgAll, MaleAvg, FemaleAvg, BelowAverage, AboveAverage, NamesCheck;
Mark = ReadFile("c:\\IUST1.txt", out Name, out Gender);
Frequent = MostFreq(Mark, out Frequency);
AvgAll = Avg(Mark);
MaleAvg = AvgCond(Gender, Mark, 'M');
FemaleAvg = AvgCond(Gender, Mark, 'F');
BelowAverage = BelowAvg(Mark, out AboveAverage);
NamesCheck = CheckNames(Name, 'T');
Output [0]= "Frequent Mark = " + Frequent.ToString();
Output [1]= "Frequency = " + Frequency.ToString();
Output [2]= "Average Of All = " + AvgAll.ToString();
Output [3]= "Average Of Males = " + MaleAvg.ToString();
Output [4]= "Average Of Females = " + FemaleAvg.ToString();
Output [5]= "Below Average = " + BelowAverage.ToString();
Output [6]= "Above Average = " + AboveAverage.ToString();
Output [7]= "Names With \"T\" = " + NamesCheck.ToString();
WriteFile("c:\\Output.txt", Output);
}
}
}
Well, I like LINQ (update: excluded via comments) for querying, especially if I can do it without buffering the data (so I can process a huge file efficiently). For example below (update: removed LINQ); note the use of iterator blocks (yield return) makes this fully "lazy" - only one record is held in memory at a time.
This also shows separation of concerns: one method deals with reading a file line by line; one method deals with parsing a line into a typed data record; one (or more) method(s) work with those data record(s).
using System;
using System.Collections.Generic;
using System.IO;
enum Gender { Male, Female, Unknown }
class Record
{
public string Name { get; set; }
public Gender Gender { get; set; }
public int Score { get; set; }
}
static class Program
{
static IEnumerable<string> ReadLines(string path)
{
using (StreamReader reader = File.OpenText(path))
{
string line;
while ((line = reader.ReadLine()) != null)
{
yield return line;
}
}
}
static IEnumerable<Record> Parse(string path)
{
foreach (string line in ReadLines(path))
{
string[] segments = line.Split(',');
Gender gender;
switch(segments[1]) {
case "m": gender = Gender.Male; break;
case "f": gender = Gender.Female; break;
default: gender = Gender.Unknown; break;
}
yield return new Record
{
Name = segments[0],
Gender = gender,
Score = int.Parse(segments[2])
};
}
}
static void Main()
{
Record best = null;
foreach (Record record in Parse("data.txt"))
{
if (record.Gender != Gender.Male) continue;
if (best == null || record.Score > best.Score)
{
best = record;
}
}
Console.WriteLine("{0}: {1}", best.Name, best.Score);
}
}
The advantage of writing things as iterators is that you can easily use either streaming or buffering - for example, you can do:
List<Record> data = new List<Record>(Parse("data.txt"));
and then manipulate data all day long (assuming it isn't too large) - useful for multiple aggregates, mutating data, etc.
This question asks how to find a maximal element by a certain criterion. Combine that with Marc's LINQ part and you're away.
In the real world, of course, these would be records in a database, and you would use one line of SQL to select the best record, ie:
SELECT Name, Score FROM Grades WHERE Score = MAX(Score)
(This returns more than one record where there's more than one best record, of course.) This is an example of the power of using the right tool for the job.
I think the fastest and least-code way would be to transform the txt to xml and then use Linq2Xml to select from it. Here's a link.
Edit: That might be more work than you'd like to do. Another option is to create a class called AcademicRecord that has properties for the persons name gender etc. Then when you read the file, add to a List for each line in the file. Then use a Sort predicate to sort the list; the highest record would then be the first one in the list. Here's a link.
Your assignment might have different requirements, but if you only want to get "best male name and grade" from a file you described, a compact way is:
public String FindRecord()
{
String[] lines = File.ReadAllLines("MyFile.csv");
Array.Sort(lines, CompareByBestMaleName);
return lines[0];
}
int SortByBestMaleName(String a, String b)
{
String[] ap = a.Split();
String[] bp = b.Split();
// Always rank male higher
if (ap[1] == "m" && bp[1] == "f") { return 1; }
if (ap[1] == "f" && bp[1] == "m") { return -1; }
// Compare by score
return int.Parse(ap[2]).CompareTo(int.Parse(bp[2]));
}
Note that this is neither fast nor robust.

Categories