Hey everyone!
So it's time to stuff some information inside your brain again. So much fun! The game is getting so much better, it actually almost feels like a real, full-fledged game. It's not quite there yet, though.
The other thing to understand is that the deeper we go down the proverbial Rabbit Hole, the more complex the programming becomes. With that in mind, I'm trying to set up the game in small incremental units so that I can devote an entire Post to that addition without becoming too overly large or difficult to follow.
Today is time for showing Scores! and Everyone likes to show off their highest Scores. This Post will start that explanation by showing how to pull the data from files.
Connecting to the Scores
So, with no further ado, let's look at the new Form. This will be the form to show the High Scores. If you recall from the last Post, I was going to be pulling High Scores from a Database Table using SQL Queries. Unfortunately, I was having some issues with my Database access and so I decided to change the method that I collect the High Scores (which at this point are just made-up values).
I thought about how I was doing it before, creating the DataTable object and then populating it from the Database Queries, is no longer going to work. Instead, I decided to create 2 text files on the Root "C" Drive (monsters.txt & hi_scores.txt). Below you will see these changes:
namespace SimpleDungeonCrawlerGame
{
public partial class MapForm : Form
{
//string connection = @"server=500BADGATEWAY\SQLEXPRESS;Trusted_Connection=Yes;database=dungeon_crawler;";
//string monster_query = @"SELECT * FROM dungeon_crawler.dbo.monster_table ";
//string score_query = @"SELECT * FROM dungeon_crawler.dbo.score_table ";
As you can see above, I have commented out the query strings so they will no longer be used. Below you will see the parts of the code that were pulling data from the Database and that is now pulling it from the files:
GetDoors(map);
this.Update();
//using (SqlConnection monster_connection = new SqlConnection(connection))
//{
monster_table.Columns.Add("id");
monster_table.Columns.Add("monster_name");
monster_table.Columns.Add("monster_image_filename");
monster_table.Columns.Add("min_health");
monster_table.Columns.Add("max_health");
monster_table.Columns.Add("min_attack");
monster_table.Columns.Add("max_attack");
monster_table.Columns.Add("min_defense");
monster_table.Columns.Add("max_defense");
monster_table.Columns.Add("min_score_reward");
monster_table.Columns.Add("max_score_reward");
monster_table.Columns.Add("min_treasure_reward");
monster_table.Columns.Add("max_treasure_reward");
// SqlCommand monster_command = new SqlCommand(monster_query, monster_connection);
// monster_connection.Open();
// SqlDataReader monster_reader = monster_command.ExecuteReader();
// monster_table.Load(monster_reader);
//}
char line_end = Environment.NewLine.ToCharArray()[0];
string monster_text = File.ReadAllText(@"C:\monsters.txt");
foreach (string monster_line in monster_text.Split(line_end))
{
string[] monster_columns = monster_line.Split('|');
monster_table.Rows.Add(monster_columns);
}
//using (SqlConnection score_connection = new SqlConnection(connection))
//{
score_table.Columns.Add("score");
score_table.Columns.Add("name");
score_table.Columns.Add("date");
// SqlCommand score_command = new SqlCommand(score_query, score_connection);
// score_connection.Open();
// SqlDataReader score_reader = score_command.ExecuteReader();
// score_table.Load(score_reader);
//}
string hi_scores_text = File.ReadAllText(@"C:\hi_scores.txt");
foreach(string hi_score_line in hi_scores_text.Split(line_end))
{
string[] hi_score_columns = hi_score_line.Split('|');
score_table.Rows.Add(hi_score_columns);
}
}
At a quick glance you will notice that the using statements and the query functionality has been commented out, but I left those lines of code (as can be seen below) that actually set up the DataTable Columns.
example:
score_table.Columns.Add("score");
This basically means that I'm creating the columns for the DataTable but will not be filling them up with data from a Database. With a direct File data-pull, you have to Load the file and Read the data in the file. Since these are .TXT Files, they can be opened and modified directly in any old Text Editor, which is how I created them. Below you will see how this is accomplished and I will explain it in more detail.
Pulling File Data
In the following section, we will go into more depth into how I am actually pulling the data for the scores and monsters from files. You can see the raw code below. Take a look, read through it, and see if you can follow what's going on before you read the explanation.
char line_end = Environment.NewLine.ToCharArray()[0];
string monster_text = File.ReadAllText(@"C:\monsters.txt");
foreach (string monster_line in monster_text.Split(line_end))
{
string[] monster_columns = monster_line.Split('|');
monster_table.Rows.Add(monster_columns);
}
.
.
.
string hi_scores_text = File.ReadAllText(@"C:\hi_scores.txt");
foreach(string hi_score_line in hi_scores_text.Split(line_end))
{
string[] hi_score_columns = hi_score_line.Split('|');
score_table.Rows.Add(hi_score_columns);
}
In the first line above you will see that I set up a new variable called "line_end" of type char. A char variable signifies a single character... in this case, I set it to the string value of Environment.NewLine which represents the [Enter]/[LineFeed] (aka a new line). Afterwards, I use the .ToCharArray() extension function to convert the string data to an array of char variables. The [0] component tells the code to use the first value in the array, which in this case identifies the actual [Enter] and nothing else.
Now, skipping to the lower section of code, I will show how these elements are pulled and set up to be added to the DataTable variables.
string hi_scores_text = File.ReadAllText(@"C:\hi_scores.txt");
foreach(string hi_score_line in hi_scores_text.Split(line_end))
{
string[] hi_score_columns = hi_score_line.Split('|');
score_table.Rows.Add(hi_score_columns);
}
Above, I first take a string variable called "hi_scores_text" and populate it by using the File object and its .ReadAllText extension. Doing this tells the program, "I'm going to read all of the text from the file path inside the parentheses in order to populate from the text file". The @ symbol just before the quotes (inside the parentheses) tells us that this is a string literal and, therefore, does not use any escape sequences (I'll let you look up what escape sequences are, because they are a bit difficult to explain).
After that, I iterate through certain values in the "hi_scores_text" to pull each row. To do so, I use the variable itself and call the .Split function against the "line_end" variable... this splits the entire text into parts using the "line_end" char character to do so. The foreach statement actually tells the code to cycle through each of those values.
Then, within the braces {}, you can see it creates a string[] variable, which is a string array. So when it's done, each of the "hi_score_line" values is split against the pipe ("|") character to identify the "hi_score_columns". To complete the transfer, the code transfers the information by adding a Row to the "score_table" DataTable, passing in the entire "hi_score_columns" array to do so.
It's a bit complex, but if you study it and try it you will start to understand how to do this.
As a last note, I went in more depth than I wanted to, but I thought it was important to show that these extension functions can allow you to do conversions and extra logic functions. I have something even more complex that will show up in the next Post in a day or 2.
Thanks for reading and learning.
Lessons Learned
Here are the links to your lessons learned (or not learned, if you need to go back and learn them):
C# Programming Beginner Tutorial: Basic Concepts and Ideas
C# Programming Beginner Tutorial: A First look at actual code using D&D as the Project
C# Programming Beginner Tutorial: Variables & Data Types to Fuel the Gaming Engine!
C# Programming Beginner Tutorial: Designing the Game with Programming Logic in Mind (Part 1)
C# Programming Beginner Tutorial: Designing the Game with Programming Logic in Mind (Part 2)
C# Programming Beginner Tutorial: Designing the Game with Programming Logic in Mind (Part 3)
C-Sharp Programming Beginner Tutorial: Designing the Game with Programming Logic in Mind (Part 4)
C-Sharp Programming Beginner Tutorial: Rock! Paper! Scissors!
C-Sharp Programming Beginner Tutorial: No-Frills Dungeon Crawler (Part 1)
C-Sharp Programming Beginner Tutorial: No-Frills Dungeon Crawler (Part 2)
C-Sharp Programming Beginner Tutorial: No-Frills Dungeon Crawler (Part 3)