Initial Commit
This commit is contained in:
parent
14960a7fc6
commit
666687a47f
6
.gitignore
vendored
6
.gitignore
vendored
@ -1,6 +1,6 @@
|
||||
*/bin/*
|
||||
*/obj/*
|
||||
*/.vs/*
|
||||
*\bin\*
|
||||
*\obj\*
|
||||
*\.vs\*
|
||||
Cs*Apps/*/bin/*
|
||||
Cs*Apps/*/obj/*
|
||||
Cs*Apps/*/.vs/*
|
||||
|
53
Cs3Apps/Airline/Airline.csproj
Normal file
53
Cs3Apps/Airline/Airline.csproj
Normal file
@ -0,0 +1,53 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{204522AA-27C2-49AC-BA28-BE82547473C9}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>Airline</RootNamespace>
|
||||
<AssemblyName>Airline</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
6
Cs3Apps/Airline/App.config
Normal file
6
Cs3Apps/Airline/App.config
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
|
||||
</startup>
|
||||
</configuration>
|
254
Cs3Apps/Airline/Program.cs
Normal file
254
Cs3Apps/Airline/Program.cs
Normal file
@ -0,0 +1,254 @@
|
||||
/* Shaun Marquardt
|
||||
* TINFO 200
|
||||
* CS3: Airline
|
||||
* ****************************************************
|
||||
* Change History
|
||||
* Date Developer Description
|
||||
* 2020-02-18 marqusa File creation and initial implementation.
|
||||
* I decided to split PurchaseFirstClassTicket
|
||||
* and PurchaseEconomyTicket into two seperate functions to make it easier to call
|
||||
* if one class of ticket was full and it was acceptable to buy the other seats.
|
||||
* Created a SeatsRemaining function to inform the
|
||||
* user if the flight's all booked up and check seats remaining in a given class
|
||||
* if one type is full.
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Airline
|
||||
{
|
||||
class Program
|
||||
{
|
||||
//Make the seating chart a more globally available variable.
|
||||
//REQ 1: Use a one-dimensional array of type bool
|
||||
//to represent the 10 seats of the plane
|
||||
static bool[] seatingChart = new bool[10];
|
||||
|
||||
/* This is a program for a small airline to manage its new
|
||||
* reservation system. This program assigns seats on each
|
||||
* flight of the airline's only plane (capacity: 10 seats).
|
||||
* The user will be presented with a menu to choose
|
||||
* first class (seats 1-5) or economy (seats 6-10).
|
||||
*
|
||||
* Requirements:
|
||||
* 1) Use a one-dimensional array of type bool to represent
|
||||
* the seating chart of the plane, initialized to false to
|
||||
* indicate all seats are empty.
|
||||
* 2) As each seat is assigned, set the corresponding element
|
||||
* to true to indicate the seat is no longer available.
|
||||
* 3) The program should never assign a seat that is already
|
||||
* assigned.
|
||||
* 4) When the economy section is full, the app should ask the
|
||||
* person if it's acceptable to sit in first class or vice/versa.
|
||||
* 4a) If acceptable, make the seat assignment. If not acceptable
|
||||
* then display the message "Next flight leaves in 3 hours".
|
||||
*/
|
||||
static void Main(string[] args)
|
||||
{
|
||||
string mainMenuChoice;
|
||||
|
||||
//Initialize each seat to false.
|
||||
for (int i = 0; i < seatingChart.Length; i++)
|
||||
{
|
||||
seatingChart[i] = false;
|
||||
}
|
||||
|
||||
// user interface
|
||||
// 1 - sell the user of the software to the user
|
||||
// 2 - instructions (basic) on how to use the software
|
||||
Console.WriteLine(@"
|
||||
****************************************************
|
||||
**** Welcome to the Airline Reservation System *****
|
||||
****************************************************
|
||||
This is a program for Small Airlines Incorporated
|
||||
to assign seats for all flights on the airline's
|
||||
only plane (capacity, 10 seats -- book now!).
|
||||
|
||||
You will be presented with a menu if you would like
|
||||
to fly First Class or Economy. After choosing, you
|
||||
will be assigned a seat if it is available. If no
|
||||
seat is available, you will be asked if you would
|
||||
like a seat in the other class of seats. If that is
|
||||
still not satisfactory for your flying needs or all
|
||||
seats are taken, we will inform you of our next flight
|
||||
departure time.
|
||||
|
||||
Please watch the printed warnings about input types
|
||||
carefully so that you don't crash the program!
|
||||
****************************************************
|
||||
");
|
||||
//Enter main program loop to keep purchasing tickets
|
||||
//like a ticketing agent.
|
||||
do
|
||||
{
|
||||
//Input
|
||||
//Display the menu.
|
||||
Console.WriteLine("1) First Class");
|
||||
Console.WriteLine("2) Economy");
|
||||
Console.WriteLine("3) Exit Program");
|
||||
Console.Write("What tickets would you like to purchase (1, 2, or 3): ");
|
||||
|
||||
//Get the input from the user and store it as a string
|
||||
//as C# allows us to switch on a string, and does not
|
||||
//risk crashing the program on int.Parse()
|
||||
mainMenuChoice = Console.ReadLine();
|
||||
|
||||
switch (mainMenuChoice)
|
||||
{
|
||||
case "1":
|
||||
PurchaseFirstClassTicket();
|
||||
break;
|
||||
case "2":
|
||||
PurchaseEconomyTicket();
|
||||
break;
|
||||
case "3":
|
||||
break;
|
||||
default:
|
||||
Console.WriteLine("Sorry, that's not a valid selection.");
|
||||
break;
|
||||
} //end switch mainMenuChoice
|
||||
} //end do... while
|
||||
while (mainMenuChoice != "3");
|
||||
|
||||
//salutation
|
||||
Console.WriteLine("\nThank you for using this program! Good bye!");
|
||||
} //END main
|
||||
|
||||
private static void PurchaseEconomyTicket()
|
||||
{
|
||||
string userAcceptsSeatClassChange = String.Empty;
|
||||
|
||||
//If there are seats remaining in the Economy class.
|
||||
if (SeatsRemaining("Economy") > 0)
|
||||
{
|
||||
for (int i = 5; i < seatingChart.Length; i++)
|
||||
{
|
||||
/* Assign the next empty seat.
|
||||
* Unfortunately I use break here because
|
||||
* I don't know where the next index of False is
|
||||
* in the range of seating area. Normally this is
|
||||
* done with while, but since I am working in the
|
||||
* middle of an array, it can't be done like that.
|
||||
*/
|
||||
if (!seatingChart[i])
|
||||
{
|
||||
seatingChart[i] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Console.WriteLine("Thank you for booking an Economy class ticket with us.");
|
||||
}
|
||||
else if(SeatsRemaining("First Class") > 0) //Economy is full, but First Class has seats.
|
||||
{
|
||||
Console.Write("Sorry, Economy section is full. " +
|
||||
"Is it acceptable to be seated in First Class? (Y/N): ");
|
||||
|
||||
userAcceptsSeatClassChange = Console.ReadLine();
|
||||
if(userAcceptsSeatClassChange.ToUpper() == "Y" )
|
||||
{
|
||||
PurchaseFirstClassTicket();
|
||||
}
|
||||
else //User does not want first class seats.
|
||||
{
|
||||
Console.WriteLine("Next flight leaves in 3 hours.");
|
||||
}
|
||||
}
|
||||
else //The flight is full.
|
||||
{
|
||||
Console.WriteLine("Sorry, we're all booked up. Next flight leaves in 3 hours.");
|
||||
}
|
||||
|
||||
} //END PurchaseEconomyTicket
|
||||
|
||||
private static void PurchaseFirstClassTicket()
|
||||
{
|
||||
string userAcceptsSeatClassChange = String.Empty;
|
||||
|
||||
//If there are seats remaining in First Class.
|
||||
if (SeatsRemaining("First Class") > 0)
|
||||
{
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
/* Assign the next empty seat.
|
||||
* Unfortunately I use break here because
|
||||
* I don't know where the next index of False is
|
||||
* in the range of seating area. Normally this is
|
||||
* done with while, but since I am working in the
|
||||
* middle of an array, it can't be done like that.
|
||||
*/
|
||||
if (!seatingChart[i])
|
||||
{
|
||||
seatingChart[i] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Console.WriteLine("Thank you for booking a First Class ticket with us.");
|
||||
}
|
||||
else if (SeatsRemaining("Economy") > 0) //First Class is full, but economy has seats.
|
||||
{
|
||||
Console.Write("Sorry, First Class section is full. " +
|
||||
"Is it acceptable to be seated in Economy? (Y/N): ");
|
||||
|
||||
userAcceptsSeatClassChange = Console.ReadLine();
|
||||
if (userAcceptsSeatClassChange.ToUpper() == "Y")
|
||||
{
|
||||
PurchaseEconomyTicket();
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Next flight leaves in 3 hours.");
|
||||
}
|
||||
}
|
||||
else //The flight is full.
|
||||
{
|
||||
Console.WriteLine("Sorry, we're all booked up. Next flight leaves in 3 hours.");
|
||||
}
|
||||
} //END PurchaseFirstClassTicket
|
||||
|
||||
/* Gets the number of seats remaining in
|
||||
* a given seating class, "Economy" or "First Class"
|
||||
*
|
||||
* Preconditions: not yet
|
||||
* Inputs: string seatClass as "Economy" or "First Class"
|
||||
* Outputs: integer
|
||||
* Postconditions: not yet
|
||||
*/
|
||||
private static int SeatsRemaining(string seatClass)
|
||||
{
|
||||
//Setup variables.
|
||||
int countOfSeatsRemaining = 0;
|
||||
int start_index = 0;
|
||||
int end_index = 0;
|
||||
|
||||
//Depending on seat class, we change where we
|
||||
//start and end our for-loop to count the
|
||||
//number of seats remaining in a given class.
|
||||
switch(seatClass)
|
||||
{
|
||||
case "Economy":
|
||||
start_index = 5;
|
||||
end_index = 9;
|
||||
break;
|
||||
case "First Class":
|
||||
start_index = 0;
|
||||
end_index = 4;
|
||||
break;
|
||||
}
|
||||
|
||||
//For loop to count the number of seats remaining, seatClass agnostic.
|
||||
for(int i=start_index; i<=end_index; i++)
|
||||
{
|
||||
if (!seatingChart[i])
|
||||
countOfSeatsRemaining++;
|
||||
}
|
||||
|
||||
//Return the number of seats remaining.
|
||||
return countOfSeatsRemaining;
|
||||
} //END SeatsRemaining
|
||||
} //END class Program
|
||||
}
|
36
Cs3Apps/Airline/Properties/AssemblyInfo.cs
Normal file
36
Cs3Apps/Airline/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("Airline")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Airline")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2020")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("204522aa-27c2-49ac-ba28-be82547473c9")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
37
Cs3Apps/Cs3Apps.sln
Normal file
37
Cs3Apps/Cs3Apps.sln
Normal file
@ -0,0 +1,37 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.29728.190
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elimination", "Elimination\Elimination.csproj", "{6C32EC6B-CF2B-4032-B536-28900D5D52F0}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Airline", "Airline\Airline.csproj", "{204522AA-27C2-49AC-BA28-BE82547473C9}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TicTacToe", "TicTacToe\TicTacToe.csproj", "{6DA041E1-08F7-4FEB-8201-252D03BE5D34}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{6C32EC6B-CF2B-4032-B536-28900D5D52F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6C32EC6B-CF2B-4032-B536-28900D5D52F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6C32EC6B-CF2B-4032-B536-28900D5D52F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6C32EC6B-CF2B-4032-B536-28900D5D52F0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{204522AA-27C2-49AC-BA28-BE82547473C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{204522AA-27C2-49AC-BA28-BE82547473C9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{204522AA-27C2-49AC-BA28-BE82547473C9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{204522AA-27C2-49AC-BA28-BE82547473C9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6DA041E1-08F7-4FEB-8201-252D03BE5D34}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6DA041E1-08F7-4FEB-8201-252D03BE5D34}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6DA041E1-08F7-4FEB-8201-252D03BE5D34}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6DA041E1-08F7-4FEB-8201-252D03BE5D34}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {01C3A74D-113A-49E8-9AC1-D323643747A6}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
6
Cs3Apps/Elimination/App.config
Normal file
6
Cs3Apps/Elimination/App.config
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
|
||||
</startup>
|
||||
</configuration>
|
53
Cs3Apps/Elimination/Elimination.csproj
Normal file
53
Cs3Apps/Elimination/Elimination.csproj
Normal file
@ -0,0 +1,53 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{6C32EC6B-CF2B-4032-B536-28900D5D52F0}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>Elimination</RootNamespace>
|
||||
<AssemblyName>Elimination</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
162
Cs3Apps/Elimination/Program.cs
Normal file
162
Cs3Apps/Elimination/Program.cs
Normal file
@ -0,0 +1,162 @@
|
||||
/* Shaun Marquardt
|
||||
* TINFO 200
|
||||
* CS3: Elimination
|
||||
* ****************************************************
|
||||
* Change History
|
||||
* Date Developer Description
|
||||
* 2020-02-18 marqusa File creation and initial implementation, Microsoft
|
||||
*
|
||||
* REFERENCES
|
||||
* https://docs.microsoft.com/en-us/dotnet/api/system.array.resize?view=netframework-4.8
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Elimination
|
||||
{
|
||||
class Program
|
||||
{
|
||||
/* This is a program that asks the user for five numbers
|
||||
* between 1 and 100 inclusive to be input.
|
||||
* It uses a one-dimensional array, and as the number is read,
|
||||
* the program will display the number only if it's not a duplicate
|
||||
* of a number already read.
|
||||
*
|
||||
* This program has the following requirements:
|
||||
* 1) There must be 5 input values that are ultimately accepted
|
||||
* by the program before it is halted.
|
||||
* 2) To be accepted, the value must be between 10-100 inclusive.
|
||||
* 3) To be accepted, the value must be unique having never been
|
||||
* entered BEFORE that point in time.
|
||||
* 4) As each value is accepted, the program displays the contents
|
||||
* of the unique set of values gathered so far.
|
||||
*/
|
||||
static void Main(string[] args)
|
||||
{
|
||||
//Initialize variables.
|
||||
int[] eliminationArray = new int[0];
|
||||
int userInputNumber;
|
||||
|
||||
// user interface
|
||||
// 1 - sell the user of the software to the user
|
||||
// 2 - instructions (basic) on how to use the software
|
||||
Console.WriteLine(@"
|
||||
****************************************************
|
||||
********** Welcome to the Elimination App **********
|
||||
****************************************************
|
||||
This program will ask you, the user, for five numbers
|
||||
to be input and display only the unique values that
|
||||
were provided. It can be used to deduplicate
|
||||
PIN numbers, combination locks, or anywhere where
|
||||
a sequence of 1 to 5 unique values is required.
|
||||
|
||||
You will be asked to provide five whole numbers between
|
||||
1 and 100 inclusively, such as 12, 42, 39, 98, etc.
|
||||
|
||||
Please watch the printed warnings about input types
|
||||
carefully so that you don't crash the program!
|
||||
****************************************************
|
||||
");
|
||||
/* This for loop will prompt and ask the user for
|
||||
* input a total of five times.
|
||||
*
|
||||
* Implements Requirement 1:
|
||||
* There must be 5 input values that are ultimately accepted
|
||||
* by the program before it is halted.
|
||||
*/
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
//INPUT
|
||||
//Requirement 2 (10-100 inclusive)
|
||||
//is implemented in GetNumber.
|
||||
userInputNumber = GetNumber();
|
||||
|
||||
//PROCESSING
|
||||
/* If-check to implement requirement 3:
|
||||
* To be accepted, the value must be unique having never been
|
||||
* entered BEFORE that point in time.
|
||||
* So if the eliminationArray DOES NOT contain the
|
||||
* input number, add it to the array.
|
||||
*/
|
||||
if (!eliminationArray.Contains(userInputNumber))
|
||||
{
|
||||
//Add one more element to the elimination array
|
||||
//ensuring we use the smallest possible array for each
|
||||
//run of the program.
|
||||
//Ref: Microsoft
|
||||
Array.Resize(ref eliminationArray, eliminationArray.Length + 1);
|
||||
|
||||
//Insert the unique number into the end of the array.
|
||||
eliminationArray[eliminationArray.Length - 1] = userInputNumber;
|
||||
}
|
||||
|
||||
//OUTPUT
|
||||
/* Implement Requirement 4: As each value is accepted,
|
||||
* the program displays the contents of the unique set
|
||||
* of values gathered so far.
|
||||
*/
|
||||
Console.Write($"The current unique values are: ");
|
||||
|
||||
//Instead of writing a standard loop, I can write it
|
||||
//as an expression-bodied lamda statement.
|
||||
//Convert the eliminationArray ToList, and iterate using ForEach method.
|
||||
//"item" goes to "console.write <current unique integer in the array>"
|
||||
eliminationArray.ToList().ForEach(item => Console.Write($"{item.ToString()} "));
|
||||
|
||||
//Insert some space bewtween the output and our next prompt.
|
||||
Console.WriteLine();
|
||||
} //end for
|
||||
|
||||
//salutation
|
||||
Console.WriteLine("\nThank you for using this program! Good bye!");
|
||||
} //end main
|
||||
|
||||
/* Gets a number from the user on the console.
|
||||
* Implements Requirement 2: To be accepted, the
|
||||
* value must be between 10-100 inclusive.
|
||||
*
|
||||
* Preconditions: not yet
|
||||
* Inputs: no args
|
||||
* Outputs: integer
|
||||
* Postconditions: not yet
|
||||
* Ref: marqusa / cs2 barchart
|
||||
*/
|
||||
private static int GetNumber()
|
||||
{
|
||||
//PROCESSING SECTION
|
||||
|
||||
//setup variables
|
||||
bool isValidNumber = false;
|
||||
int userInputNumber;
|
||||
|
||||
//Loop to check for valid input between 10-100.
|
||||
do
|
||||
{
|
||||
//Prompt the user for input.
|
||||
Console.Write("Please enter a whole number from 10-100: ");
|
||||
|
||||
//Store the input as an integer in the userInputNumber variable.
|
||||
userInputNumber = int.Parse(Console.ReadLine());
|
||||
|
||||
//If the number is between 10 and 100 inclusive
|
||||
//the input is valid. Set the isValidNumber boolean value
|
||||
//to true to break out of the while loop.
|
||||
if (userInputNumber >= 10 && userInputNumber <= 100)
|
||||
isValidNumber = true;
|
||||
|
||||
//If the number is not valid, inform the user and return to the start of do..while
|
||||
if (!isValidNumber)
|
||||
Console.WriteLine("Sorry, that's not a valid number.");
|
||||
}
|
||||
while (!isValidNumber);
|
||||
|
||||
//Return the valid input number, between 10 and 100 inclusive.
|
||||
return userInputNumber;
|
||||
} //END GetNumber
|
||||
} // END class Program
|
||||
}
|
36
Cs3Apps/Elimination/Properties/AssemblyInfo.cs
Normal file
36
Cs3Apps/Elimination/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("Elimination")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Elimination")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2020")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("6c32ec6b-cf2b-4032-b536-28900d5d52f0")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
21
Cs3Apps/TicTacToe/App.config
Normal file
21
Cs3Apps/TicTacToe/App.config
Normal file
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<configSections>
|
||||
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
|
||||
<section name="TicTacToe.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
|
||||
</sectionGroup>
|
||||
</configSections>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
|
||||
</startup>
|
||||
<userSettings>
|
||||
<TicTacToe.Properties.Settings>
|
||||
<setting name="PlayVsCPU" serializeAs="String">
|
||||
<value>False</value>
|
||||
</setting>
|
||||
<setting name="CPUAsPlayer" serializeAs="String">
|
||||
<value>2</value>
|
||||
</setting>
|
||||
</TicTacToe.Properties.Settings>
|
||||
</userSettings>
|
||||
</configuration>
|
332
Cs3Apps/TicTacToe/Form1.Designer.cs
generated
Normal file
332
Cs3Apps/TicTacToe/Form1.Designer.cs
generated
Normal file
@ -0,0 +1,332 @@
|
||||
/* The 'codebehind' the Form1.cs GUI interface.
|
||||
* This is Microsoft Visual Studio generated code.
|
||||
* It has not been mucked with by hand, all the code
|
||||
* seen here was generated by Visual Studio.
|
||||
*/
|
||||
namespace TicTacToe
|
||||
{
|
||||
partial class frmTicTacToe
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.components = new System.ComponentModel.Container();
|
||||
this.tlpProgramControls = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.mainMenuStrip = new System.Windows.Forms.MenuStrip();
|
||||
this.gameToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.newGameToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.playVsCPUToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.cPUAsPlayer1ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.cPUAsPlayer2ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.quitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.lblPlayerTurn = new System.Windows.Forms.Label();
|
||||
this.tlpMainGame = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.lbl22 = new System.Windows.Forms.Label();
|
||||
this.lbl21 = new System.Windows.Forms.Label();
|
||||
this.lbl12 = new System.Windows.Forms.Label();
|
||||
this.lbl11 = new System.Windows.Forms.Label();
|
||||
this.lbl20 = new System.Windows.Forms.Label();
|
||||
this.lbl10 = new System.Windows.Forms.Label();
|
||||
this.lbl02 = new System.Windows.Forms.Label();
|
||||
this.lbl01 = new System.Windows.Forms.Label();
|
||||
this.lbl00 = new System.Windows.Forms.Label();
|
||||
this.CPUTurnTimer = new System.Windows.Forms.Timer(this.components);
|
||||
this.tlpProgramControls.SuspendLayout();
|
||||
this.mainMenuStrip.SuspendLayout();
|
||||
this.tlpMainGame.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// tlpProgramControls
|
||||
//
|
||||
this.tlpProgramControls.ColumnCount = 2;
|
||||
this.tlpProgramControls.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
|
||||
this.tlpProgramControls.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
|
||||
this.tlpProgramControls.Controls.Add(this.mainMenuStrip, 0, 0);
|
||||
this.tlpProgramControls.Controls.Add(this.lblPlayerTurn, 1, 0);
|
||||
this.tlpProgramControls.Dock = System.Windows.Forms.DockStyle.Top;
|
||||
this.tlpProgramControls.Location = new System.Drawing.Point(0, 0);
|
||||
this.tlpProgramControls.Name = "tlpProgramControls";
|
||||
this.tlpProgramControls.RowCount = 1;
|
||||
this.tlpProgramControls.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tlpProgramControls.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 41F));
|
||||
this.tlpProgramControls.Size = new System.Drawing.Size(800, 41);
|
||||
this.tlpProgramControls.TabIndex = 2;
|
||||
//
|
||||
// mainMenuStrip
|
||||
//
|
||||
this.mainMenuStrip.GripMargin = new System.Windows.Forms.Padding(2, 2, 0, 2);
|
||||
this.mainMenuStrip.ImageScalingSize = new System.Drawing.Size(24, 24);
|
||||
this.mainMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.gameToolStripMenuItem});
|
||||
this.mainMenuStrip.Location = new System.Drawing.Point(0, 0);
|
||||
this.mainMenuStrip.Name = "mainMenuStrip";
|
||||
this.mainMenuStrip.Size = new System.Drawing.Size(400, 36);
|
||||
this.mainMenuStrip.TabIndex = 0;
|
||||
this.mainMenuStrip.Text = "mainMenuStrip";
|
||||
//
|
||||
// gameToolStripMenuItem
|
||||
//
|
||||
this.gameToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.newGameToolStripMenuItem,
|
||||
this.playVsCPUToolStripMenuItem,
|
||||
this.quitToolStripMenuItem});
|
||||
this.gameToolStripMenuItem.Name = "gameToolStripMenuItem";
|
||||
this.gameToolStripMenuItem.Size = new System.Drawing.Size(74, 32);
|
||||
this.gameToolStripMenuItem.Text = "&Game";
|
||||
//
|
||||
// newGameToolStripMenuItem
|
||||
//
|
||||
this.newGameToolStripMenuItem.Name = "newGameToolStripMenuItem";
|
||||
this.newGameToolStripMenuItem.Size = new System.Drawing.Size(213, 34);
|
||||
this.newGameToolStripMenuItem.Text = "&New Game";
|
||||
this.newGameToolStripMenuItem.Click += new System.EventHandler(this.newGameToolStripMenuItem_Click);
|
||||
//
|
||||
// playVsCPUToolStripMenuItem
|
||||
//
|
||||
this.playVsCPUToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.cPUAsPlayer1ToolStripMenuItem,
|
||||
this.cPUAsPlayer2ToolStripMenuItem});
|
||||
this.playVsCPUToolStripMenuItem.Name = "playVsCPUToolStripMenuItem";
|
||||
this.playVsCPUToolStripMenuItem.Size = new System.Drawing.Size(213, 34);
|
||||
this.playVsCPUToolStripMenuItem.Text = "Play vs &CPU";
|
||||
this.playVsCPUToolStripMenuItem.Click += new System.EventHandler(this.playVsCPUToolStripMenuItem_Click);
|
||||
//
|
||||
// cPUAsPlayer1ToolStripMenuItem
|
||||
//
|
||||
this.cPUAsPlayer1ToolStripMenuItem.Name = "cPUAsPlayer1ToolStripMenuItem";
|
||||
this.cPUAsPlayer1ToolStripMenuItem.Size = new System.Drawing.Size(236, 34);
|
||||
this.cPUAsPlayer1ToolStripMenuItem.Text = "CPU as Player 1";
|
||||
this.cPUAsPlayer1ToolStripMenuItem.Click += new System.EventHandler(this.cPUAsPlayer1ToolStripMenuItem_Click);
|
||||
//
|
||||
// cPUAsPlayer2ToolStripMenuItem
|
||||
//
|
||||
this.cPUAsPlayer2ToolStripMenuItem.Name = "cPUAsPlayer2ToolStripMenuItem";
|
||||
this.cPUAsPlayer2ToolStripMenuItem.Size = new System.Drawing.Size(236, 34);
|
||||
this.cPUAsPlayer2ToolStripMenuItem.Text = "CPU as Player 2";
|
||||
this.cPUAsPlayer2ToolStripMenuItem.Click += new System.EventHandler(this.cPUAsPlayer2ToolStripMenuItem_Click);
|
||||
//
|
||||
// quitToolStripMenuItem
|
||||
//
|
||||
this.quitToolStripMenuItem.Name = "quitToolStripMenuItem";
|
||||
this.quitToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Alt | System.Windows.Forms.Keys.F4)));
|
||||
this.quitToolStripMenuItem.Size = new System.Drawing.Size(213, 34);
|
||||
this.quitToolStripMenuItem.Text = "&Quit";
|
||||
this.quitToolStripMenuItem.Click += new System.EventHandler(this.quitToolStripMenuItem_Click);
|
||||
//
|
||||
// lblPlayerTurn
|
||||
//
|
||||
this.lblPlayerTurn.AutoSize = true;
|
||||
this.lblPlayerTurn.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.lblPlayerTurn.Location = new System.Drawing.Point(403, 0);
|
||||
this.lblPlayerTurn.Name = "lblPlayerTurn";
|
||||
this.lblPlayerTurn.Size = new System.Drawing.Size(394, 41);
|
||||
this.lblPlayerTurn.TabIndex = 1;
|
||||
this.lblPlayerTurn.Text = "Player Turn: **GAME OVER **\nClick to Start";
|
||||
this.lblPlayerTurn.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
||||
//
|
||||
// tlpMainGame
|
||||
//
|
||||
this.tlpMainGame.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.Outset;
|
||||
this.tlpMainGame.ColumnCount = 3;
|
||||
this.tlpMainGame.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F));
|
||||
this.tlpMainGame.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F));
|
||||
this.tlpMainGame.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F));
|
||||
this.tlpMainGame.Controls.Add(this.lbl22, 2, 2);
|
||||
this.tlpMainGame.Controls.Add(this.lbl21, 1, 2);
|
||||
this.tlpMainGame.Controls.Add(this.lbl12, 2, 1);
|
||||
this.tlpMainGame.Controls.Add(this.lbl11, 1, 1);
|
||||
this.tlpMainGame.Controls.Add(this.lbl20, 0, 2);
|
||||
this.tlpMainGame.Controls.Add(this.lbl10, 0, 1);
|
||||
this.tlpMainGame.Controls.Add(this.lbl02, 2, 0);
|
||||
this.tlpMainGame.Controls.Add(this.lbl01, 1, 0);
|
||||
this.tlpMainGame.Controls.Add(this.lbl00, 0, 0);
|
||||
this.tlpMainGame.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tlpMainGame.Location = new System.Drawing.Point(0, 41);
|
||||
this.tlpMainGame.Name = "tlpMainGame";
|
||||
this.tlpMainGame.RowCount = 3;
|
||||
this.tlpMainGame.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 33.33333F));
|
||||
this.tlpMainGame.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 33.33333F));
|
||||
this.tlpMainGame.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 33.33333F));
|
||||
this.tlpMainGame.Size = new System.Drawing.Size(800, 409);
|
||||
this.tlpMainGame.TabIndex = 3;
|
||||
//
|
||||
// lbl22
|
||||
//
|
||||
this.lbl22.AutoSize = true;
|
||||
this.lbl22.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.lbl22.Font = new System.Drawing.Font("Microsoft Sans Serif", 20F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.lbl22.Location = new System.Drawing.Point(537, 272);
|
||||
this.lbl22.Name = "lbl22";
|
||||
this.lbl22.Size = new System.Drawing.Size(258, 135);
|
||||
this.lbl22.TabIndex = 8;
|
||||
this.lbl22.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||
this.lbl22.Click += new System.EventHandler(this.GameBoardLbl_Click);
|
||||
//
|
||||
// lbl21
|
||||
//
|
||||
this.lbl21.AutoSize = true;
|
||||
this.lbl21.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.lbl21.Font = new System.Drawing.Font("Microsoft Sans Serif", 20F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.lbl21.Location = new System.Drawing.Point(271, 272);
|
||||
this.lbl21.Name = "lbl21";
|
||||
this.lbl21.Size = new System.Drawing.Size(258, 135);
|
||||
this.lbl21.TabIndex = 7;
|
||||
this.lbl21.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||
this.lbl21.Click += new System.EventHandler(this.GameBoardLbl_Click);
|
||||
//
|
||||
// lbl12
|
||||
//
|
||||
this.lbl12.AutoSize = true;
|
||||
this.lbl12.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.lbl12.Font = new System.Drawing.Font("Microsoft Sans Serif", 20F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.lbl12.Location = new System.Drawing.Point(537, 137);
|
||||
this.lbl12.Name = "lbl12";
|
||||
this.lbl12.Size = new System.Drawing.Size(258, 133);
|
||||
this.lbl12.TabIndex = 6;
|
||||
this.lbl12.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||
this.lbl12.Click += new System.EventHandler(this.GameBoardLbl_Click);
|
||||
//
|
||||
// lbl11
|
||||
//
|
||||
this.lbl11.AutoSize = true;
|
||||
this.lbl11.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.lbl11.Font = new System.Drawing.Font("Microsoft Sans Serif", 20F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.lbl11.Location = new System.Drawing.Point(271, 137);
|
||||
this.lbl11.Name = "lbl11";
|
||||
this.lbl11.Size = new System.Drawing.Size(258, 133);
|
||||
this.lbl11.TabIndex = 5;
|
||||
this.lbl11.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||
this.lbl11.Click += new System.EventHandler(this.GameBoardLbl_Click);
|
||||
//
|
||||
// lbl20
|
||||
//
|
||||
this.lbl20.AutoSize = true;
|
||||
this.lbl20.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.lbl20.Font = new System.Drawing.Font("Microsoft Sans Serif", 20F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.lbl20.Location = new System.Drawing.Point(5, 272);
|
||||
this.lbl20.Name = "lbl20";
|
||||
this.lbl20.Size = new System.Drawing.Size(258, 135);
|
||||
this.lbl20.TabIndex = 4;
|
||||
this.lbl20.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||
this.lbl20.Click += new System.EventHandler(this.GameBoardLbl_Click);
|
||||
//
|
||||
// lbl10
|
||||
//
|
||||
this.lbl10.AutoSize = true;
|
||||
this.lbl10.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.lbl10.Font = new System.Drawing.Font("Microsoft Sans Serif", 20F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.lbl10.Location = new System.Drawing.Point(5, 137);
|
||||
this.lbl10.Name = "lbl10";
|
||||
this.lbl10.Size = new System.Drawing.Size(258, 133);
|
||||
this.lbl10.TabIndex = 3;
|
||||
this.lbl10.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||
this.lbl10.Click += new System.EventHandler(this.GameBoardLbl_Click);
|
||||
//
|
||||
// lbl02
|
||||
//
|
||||
this.lbl02.AutoSize = true;
|
||||
this.lbl02.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.lbl02.Font = new System.Drawing.Font("Microsoft Sans Serif", 20F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.lbl02.Location = new System.Drawing.Point(537, 2);
|
||||
this.lbl02.Name = "lbl02";
|
||||
this.lbl02.Size = new System.Drawing.Size(258, 133);
|
||||
this.lbl02.TabIndex = 2;
|
||||
this.lbl02.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||
this.lbl02.Click += new System.EventHandler(this.GameBoardLbl_Click);
|
||||
//
|
||||
// lbl01
|
||||
//
|
||||
this.lbl01.AutoSize = true;
|
||||
this.lbl01.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.lbl01.Font = new System.Drawing.Font("Microsoft Sans Serif", 20F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.lbl01.Location = new System.Drawing.Point(271, 2);
|
||||
this.lbl01.Name = "lbl01";
|
||||
this.lbl01.Size = new System.Drawing.Size(258, 133);
|
||||
this.lbl01.TabIndex = 1;
|
||||
this.lbl01.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||
this.lbl01.Click += new System.EventHandler(this.GameBoardLbl_Click);
|
||||
//
|
||||
// lbl00
|
||||
//
|
||||
this.lbl00.AutoSize = true;
|
||||
this.lbl00.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.lbl00.Font = new System.Drawing.Font("Microsoft Sans Serif", 20F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.lbl00.Location = new System.Drawing.Point(5, 2);
|
||||
this.lbl00.Name = "lbl00";
|
||||
this.lbl00.Size = new System.Drawing.Size(258, 133);
|
||||
this.lbl00.TabIndex = 0;
|
||||
this.lbl00.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||
this.lbl00.Click += new System.EventHandler(this.GameBoardLbl_Click);
|
||||
//
|
||||
// CPUTurnTimer
|
||||
//
|
||||
this.CPUTurnTimer.Tick += new System.EventHandler(this.CPUTurnTimer_Tick);
|
||||
//
|
||||
// frmTicTacToe
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(800, 450);
|
||||
this.Controls.Add(this.tlpMainGame);
|
||||
this.Controls.Add(this.tlpProgramControls);
|
||||
this.Name = "frmTicTacToe";
|
||||
this.Text = "Tic Tac Toe";
|
||||
this.Load += new System.EventHandler(this.frmTicTacToe_Load);
|
||||
this.tlpProgramControls.ResumeLayout(false);
|
||||
this.tlpProgramControls.PerformLayout();
|
||||
this.mainMenuStrip.ResumeLayout(false);
|
||||
this.mainMenuStrip.PerformLayout();
|
||||
this.tlpMainGame.ResumeLayout(false);
|
||||
this.tlpMainGame.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.TableLayoutPanel tlpProgramControls;
|
||||
private System.Windows.Forms.MenuStrip mainMenuStrip;
|
||||
private System.Windows.Forms.ToolStripMenuItem gameToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem newGameToolStripMenuItem;
|
||||
private System.Windows.Forms.TableLayoutPanel tlpMainGame;
|
||||
private System.Windows.Forms.Label lbl10;
|
||||
private System.Windows.Forms.Label lbl02;
|
||||
private System.Windows.Forms.Label lbl01;
|
||||
private System.Windows.Forms.Label lbl00;
|
||||
private System.Windows.Forms.Label lbl22;
|
||||
private System.Windows.Forms.Label lbl21;
|
||||
private System.Windows.Forms.Label lbl12;
|
||||
private System.Windows.Forms.Label lbl11;
|
||||
private System.Windows.Forms.Label lbl20;
|
||||
private System.Windows.Forms.ToolStripMenuItem playVsCPUToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem quitToolStripMenuItem;
|
||||
private System.Windows.Forms.Label lblPlayerTurn;
|
||||
private System.Windows.Forms.ToolStripMenuItem cPUAsPlayer1ToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem cPUAsPlayer2ToolStripMenuItem;
|
||||
private System.Windows.Forms.Timer CPUTurnTimer;
|
||||
}
|
||||
}
|
||||
|
472
Cs3Apps/TicTacToe/Form1.cs
Normal file
472
Cs3Apps/TicTacToe/Form1.cs
Normal file
@ -0,0 +1,472 @@
|
||||
/* Shaun Marquardt
|
||||
* TINFO 200
|
||||
* CS3: TicTacToe
|
||||
* ****************************************************
|
||||
* Change History
|
||||
* Date Developer Description
|
||||
* 2020-02-18 marqusa File creation and initial implementation,
|
||||
* Martyr2 (Coders Lexicon), Microsoft, Chuck Costarella L5Life
|
||||
* 2020-02-22 marqusa Add functionality to clear the game board labels.
|
||||
* Implement Winner and Draw Game.
|
||||
* Completed program, add documentation.
|
||||
* 2020-02-23 marqusa Add functionality to have CPU play as player 1 or player 2.
|
||||
* Moved winner stuff out of GameLbl_Click
|
||||
* 2020-02-24 marqusa Fixed the form menu system for Play vs CPU checkboxes,
|
||||
* they were acting funky. Split PlayVsCPU(int turn) into new function.
|
||||
* Also updated the CPUTimer_Tick to do nothing
|
||||
* if the game is over.
|
||||
*
|
||||
* The Form1.cs class acts as the primary driver for the TicTacToe class
|
||||
* which actually plays the game proper. Most of my comments regarding how
|
||||
* the game actually works will be in the TicTacToe.cs file.
|
||||
*
|
||||
* Recieves a delegate event from TicTacToe to update the label in the cell
|
||||
* that was clicked after the 3x3 2d array called 'gameBoard' in the
|
||||
* TicTacToe class gets updated
|
||||
*
|
||||
* REFERENCES
|
||||
* https://www.coderslexicon.com/passing-data-between-forms-using-delegates-and-events/
|
||||
* https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.control.controlcollection.find?view=netframework-4.8
|
||||
* https://docs.microsoft.com/en-us/dotnet/api/system.eventargs?view=netframework-4.8
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace TicTacToe
|
||||
{
|
||||
public partial class frmTicTacToe : Form
|
||||
{
|
||||
/* This is a program to play the classic game,
|
||||
* Tic-Tac-Toe. The form you see displayed (and this class)
|
||||
* is primarily a driver for the TicTacToe class
|
||||
* which actually plays the game behind the scenes.
|
||||
*
|
||||
* Requirements:
|
||||
* 1) Class TicTacToe enables us to create a complete app to play
|
||||
* the game of Tic-Tac-Toe.
|
||||
* 2) This class contains a private 3x3 rectangular array of integers.
|
||||
* 3) The constructor initializes the empty board.
|
||||
* 4) Each move should be in an empty square.
|
||||
* 5) Determine win, lose, or draw.
|
||||
*
|
||||
* Extra Credit:
|
||||
* The app is developed using a Windows Form application.
|
||||
* It is possible to play vs CPU with CPU as Player 1 or Player 2.
|
||||
*
|
||||
* Extra Fun Stuff:
|
||||
* The game actively tracks the current player's turn.
|
||||
* I used an enum for both player turn and X and O.
|
||||
* I included a delegate and custom event args to pass
|
||||
* data from the TicTacToe class and update the correct label.
|
||||
* The game is really handled by basically everything in the
|
||||
* TicTacToe class with the form as a GUI frontend.
|
||||
*/
|
||||
|
||||
//Create a new instance of the TicTacToe class
|
||||
// and store it as a new object called 'game'.
|
||||
TicTacToe game;
|
||||
|
||||
//Visual studio generated code.
|
||||
public frmTicTacToe()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
/* Update the label in a given row/column with X or O
|
||||
* according to what XorO enum value was placed using a delegate.
|
||||
* Ref: Martyr2, Coders Lexicon'
|
||||
* Preconditions: not yet
|
||||
* Inputs: object sender, TicTacToe.RowColumnEventArgs e
|
||||
* Outputs: void return
|
||||
* Postconditions: not yet
|
||||
*/
|
||||
public void MessageReceived(object sender, EventArgs e)
|
||||
{
|
||||
//Ref: Microsoft, EventArgs
|
||||
TicTacToe.RowColumnEventArgs args = (TicTacToe.RowColumnEventArgs)e;
|
||||
|
||||
//DEBUGGING:
|
||||
//MessageBox.Show($"row: {args.row} col: {args.col}");
|
||||
|
||||
//Construct the label name we need.
|
||||
string lblName = $"lbl{args.row}{args.col}";
|
||||
|
||||
//Get the label by constructed name.
|
||||
//ref: microsoft, Controls.Find
|
||||
Label theLabel = (Label)this.Controls.Find(lblName, true)[0];
|
||||
|
||||
//Place an X or an O in the square.
|
||||
//Not playing against CPU is the easy case.
|
||||
//Player 1 is always X. Player 2 is O
|
||||
if (!Properties.Settings.Default.PlayVsCPU)
|
||||
{
|
||||
if (game.CurrentPlayerTurn == TicTacToe.PlayerTurn.Player1)
|
||||
theLabel.Text = TicTacToe.XorO.x.ToString();
|
||||
else
|
||||
theLabel.Text = TicTacToe.XorO.o.ToString();
|
||||
}
|
||||
else //We are playing against CPU.
|
||||
{
|
||||
//If it's the CPU turn, place the CPU move.
|
||||
if (game.CurrentPlayerTurn == TicTacToe.PlayerTurn.CPU)
|
||||
{
|
||||
if (Properties.Settings.Default.CPUAsPlayer == 1)
|
||||
{
|
||||
theLabel.Text = TicTacToe.XorO.x.ToString();
|
||||
}
|
||||
else //CPU as player 2.
|
||||
{
|
||||
theLabel.Text = TicTacToe.XorO.o.ToString();
|
||||
}
|
||||
}
|
||||
else //It's the player's turn
|
||||
{
|
||||
//The CPU is player 1, place an O for human's move.
|
||||
if (Properties.Settings.Default.CPUAsPlayer == 1)
|
||||
theLabel.Text = TicTacToe.XorO.o.ToString();
|
||||
else //The CPU is player 2, place an X for human's move.
|
||||
theLabel.Text = TicTacToe.XorO.x.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Visual studio generated delegate
|
||||
* on form load. Instansiates a new TicTacToe class
|
||||
* and stores it into the game object.
|
||||
* Preconditions: not yet
|
||||
* Inputs: object sender, EventArgs e
|
||||
* Outputs: void return
|
||||
* Postconditions: not yet
|
||||
*/
|
||||
private void frmTicTacToe_Load(object sender, EventArgs e)
|
||||
{
|
||||
//Pass the current TicTacToe form into the TicTacToe class
|
||||
//so the event handler delegate can be hooked in and we
|
||||
//can change the label in the tableGridView from the TicTacToe class.
|
||||
game = new TicTacToe(this);
|
||||
|
||||
//If we are playing as CPU
|
||||
if (Properties.Settings.Default.PlayVsCPU)
|
||||
{
|
||||
playVsCPUToolStripMenuItem.Checked = true;
|
||||
|
||||
//Check the CPU as player 1 tool strip menu item
|
||||
if (Properties.Settings.Default.CPUAsPlayer == 1)
|
||||
{
|
||||
cPUAsPlayer1ToolStripMenuItem.Checked = true;
|
||||
}
|
||||
else //Check the CPU as player 2 tool strip menu item.
|
||||
{
|
||||
cPUAsPlayer2ToolStripMenuItem.Checked = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Start the timer to watch for CPU Turn.
|
||||
* This must be outside the if statement
|
||||
* as "Play vs CPU" can be checked (or unchecked) anytime
|
||||
* there is a "Game Over" status.
|
||||
*/
|
||||
CPUTurnTimer.Start();
|
||||
}
|
||||
|
||||
/* Starts a new game on Game > New Game click.
|
||||
* Visual Studio Generated Delegate.
|
||||
* Preconditions: not yet
|
||||
* Inputs: object sender, EventArgs e
|
||||
* Outputs: void return
|
||||
* Postconditions: not yet
|
||||
*/
|
||||
private void newGameToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
game.StartNewGame();
|
||||
ClearGameLabels();
|
||||
|
||||
//Must set GameOver to true here
|
||||
//so if the user clicks the new game menu item
|
||||
//it is also possible to click the "Play vs CPU"
|
||||
//menu item/option.
|
||||
game.GameOver = true;
|
||||
}
|
||||
|
||||
/* Clear all the labels on the board of X or O.
|
||||
* Preconditions: not yet
|
||||
* Inputs: no args
|
||||
* Outputs: void return
|
||||
* Postconditions: not yet
|
||||
*/
|
||||
private void ClearGameLabels()
|
||||
{
|
||||
//Loop through each control docked in the
|
||||
//table main game layout panel that holds all
|
||||
//the labels for Xs and Os to go into.
|
||||
foreach (var tlpControl in tlpMainGame.Controls)
|
||||
{
|
||||
Label label = (Label)tlpControl;
|
||||
label.Text = string.Empty;
|
||||
}
|
||||
|
||||
//Reset the player turn to Game Over.
|
||||
lblPlayerTurn.Text = "Player Turn: **GAME OVER **\nClick to Start";
|
||||
}
|
||||
|
||||
/* Quit the game and exits the application.
|
||||
* Visual Studio generated delegate.
|
||||
* Preconditions: not yet
|
||||
* Inputs: object sender, EventArgs e
|
||||
* Outputs: void return
|
||||
* Postconditions: not yet
|
||||
*/
|
||||
private void quitToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
//Salutation
|
||||
MessageBox.Show("Thank you for playing! Good bye!");
|
||||
Environment.Exit(0);
|
||||
}
|
||||
|
||||
/* This is the main delegate that is called when a player
|
||||
* clicks a position on the game board to play the game.
|
||||
* Visual Studio generated delegate.
|
||||
* Preconditions: not yet
|
||||
* Inputs: object sender, EventArgs e
|
||||
* Outputs: void return
|
||||
* Postconditions: not yet
|
||||
*/
|
||||
private void GameBoardLbl_Click(object sender, EventArgs e)
|
||||
{
|
||||
//If the game is over, start a new game.
|
||||
if (game.GameOver)
|
||||
{
|
||||
game.StartNewGame();
|
||||
ClearGameLabels();
|
||||
|
||||
//If the player is playing against CPU
|
||||
//and CPU is player 1, adjust the turn to CPU turn.
|
||||
if (Properties.Settings.Default.PlayVsCPU
|
||||
&& Properties.Settings.Default.CPUAsPlayer == 1)
|
||||
game.CurrentPlayerTurn = TicTacToe.PlayerTurn.CPU;
|
||||
}
|
||||
|
||||
//If the player is playing against the CPU
|
||||
//and it is not their CurrentPlayerTurn, do nothing.
|
||||
if (Properties.Settings.Default.PlayVsCPU && game.CurrentPlayerTurn == TicTacToe.PlayerTurn.CPU)
|
||||
return;
|
||||
|
||||
//Get the name of the label and parse it to find out our indexes.
|
||||
Label clickedGamePosition = (Label)sender;
|
||||
|
||||
//Do not allow placing a move in a taken position.
|
||||
if (clickedGamePosition.Text != "")
|
||||
return;
|
||||
|
||||
//Each label is named 'lblXX' where XX is the row and column
|
||||
//that was clicked. So first pick off 'lbl', to leave 'xx'
|
||||
string rowColumn = clickedGamePosition.Name.Remove(0, 3);
|
||||
|
||||
//Now get the row and column.
|
||||
//ToString() must be called as rowColumn[x] returns type char.
|
||||
int row = int.Parse(rowColumn[0].ToString());
|
||||
int col = int.Parse(rowColumn[1].ToString());
|
||||
|
||||
//Take the current player's CurrentPlayerTurn.
|
||||
game.TakePlayerTurn(game.CurrentPlayerTurn, row, col);
|
||||
|
||||
//Swap to the next player's CurrentPlayerTurn.
|
||||
TicTacToe.XorO winningPlayer = game.TogglePlayerTurn(game.CurrentPlayerTurn);
|
||||
|
||||
//Update the player turn label
|
||||
string playerStr = (game.CurrentPlayerTurn.ToString() == TicTacToe.PlayerTurn.CPU.ToString()) ? "CPU (THINKING...)" : game.CurrentPlayerTurn.ToString();
|
||||
lblPlayerTurn.Text = $"Player turn: {playerStr}";
|
||||
|
||||
//Update winner
|
||||
//Check for a winner which will overwrite the turn label.
|
||||
UpdateWinner(winningPlayer);
|
||||
} //GameBoardLbl_Click
|
||||
|
||||
/* Update the form label if there is a winner.
|
||||
* Preconditions: not yet
|
||||
* Inputs: XorO enum winningPlayer
|
||||
* Outputs: void return
|
||||
* Postconditions: not yet
|
||||
*/
|
||||
private void UpdateWinner(TicTacToe.XorO winningPlayer)
|
||||
{
|
||||
//Check for a winner which will overwrite the turn label.
|
||||
if (game.GameOver) //There is a winner
|
||||
{
|
||||
string winningPlayerText = "**WINNER**: ";
|
||||
|
||||
//Not playing against CPU, easy case.
|
||||
if (!Properties.Settings.Default.PlayVsCPU)
|
||||
{
|
||||
if (winningPlayer == TicTacToe.XorO.x) //Player 1 wins.
|
||||
winningPlayerText += "Player 1";
|
||||
else if (winningPlayer == TicTacToe.XorO.o)
|
||||
winningPlayerText += "Player 2"; //Player 2 wins.
|
||||
else
|
||||
winningPlayerText = "**DRAW GAME!**";
|
||||
}
|
||||
else // (PLAY VS CPU)
|
||||
{
|
||||
//Player 1 CPU Wins
|
||||
if (winningPlayer == TicTacToe.XorO.x && Properties.Settings.Default.CPUAsPlayer == 1)
|
||||
winningPlayerText += "CPU";
|
||||
else if (winningPlayer == TicTacToe.XorO.x) //Player 1 Wins
|
||||
winningPlayerText += "Player 1";
|
||||
else if (winningPlayer == TicTacToe.XorO.o && Properties.Settings.Default.CPUAsPlayer == 2) //player 2 cpu wins
|
||||
winningPlayerText += "CPU";
|
||||
else if (winningPlayer == TicTacToe.XorO.o) // player 2 wins
|
||||
winningPlayerText += "Player 2";
|
||||
else //Draw Game.
|
||||
winningPlayerText = "**DRAW GAME!**";
|
||||
} //end else
|
||||
|
||||
//Add Game Over text.
|
||||
winningPlayerText += "\n **GAME OVER** - Click to Start";
|
||||
|
||||
//Update the player turn label with the winner.
|
||||
lblPlayerTurn.Text = winningPlayerText;
|
||||
} // if GameOver
|
||||
} //UpdateWinner
|
||||
|
||||
/* Sets CPU as Player 1
|
||||
* Visual Studio generated delegate.
|
||||
* Preconditions: not yet
|
||||
* Inputs: object sender, EventArgs e
|
||||
* Outputs: void return
|
||||
* Postconditions: not yet
|
||||
*/
|
||||
private void cPUAsPlayer1ToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
//If we are playing vs CPU and If the current box for
|
||||
//P1 CPU is checked, Clear PlayVsCPU options.
|
||||
if (Properties.Settings.Default.PlayVsCPU && cPUAsPlayer1ToolStripMenuItem.Checked == true)
|
||||
{
|
||||
SetPlayVsCPU(0);
|
||||
}
|
||||
else //We are not currently playing vs CPU. Start doing so with CPU as player 1.
|
||||
{
|
||||
SetPlayVsCPU(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Sets CPU as Player 2
|
||||
* Visual Studio generated delegate.
|
||||
* Preconditions: not yet
|
||||
* Inputs: object sender, EventArgs e
|
||||
* Outputs: void return
|
||||
* Postconditions: not yet
|
||||
*/
|
||||
private void cPUAsPlayer2ToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
//If we are playing vs CPU and If the current box for
|
||||
//P2 CPU is checked, Clear PlayVsCPU options.
|
||||
if (Properties.Settings.Default.PlayVsCPU && cPUAsPlayer2ToolStripMenuItem.Checked == true)
|
||||
{
|
||||
SetPlayVsCPU(0);
|
||||
}
|
||||
else //We are not currently playing vs CPU. Start doing so with CPU as player 2.
|
||||
{
|
||||
SetPlayVsCPU(2);
|
||||
}
|
||||
}
|
||||
|
||||
/* Clears playing vs CPU if set.
|
||||
* Visual Studio generated delegate.
|
||||
* Preconditions: not yet
|
||||
* Inputs: object sender, EventArgs e
|
||||
* Outputs: void return
|
||||
* Postconditions: not yet
|
||||
*/
|
||||
private void playVsCPUToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
if(Properties.Settings.Default.PlayVsCPU)
|
||||
SetPlayVsCPU(0);
|
||||
}
|
||||
|
||||
/* Set the correct menu checkboxes and application settings.
|
||||
* called from the menu tool strip delegate events.
|
||||
* Preconditions: not yet
|
||||
* Inputs: int cpuAsPlayer
|
||||
* Outputs: void return
|
||||
* Postconditions: not yet
|
||||
*/
|
||||
private void SetPlayVsCPU(int cpuAsPlayer)
|
||||
{
|
||||
//If the game is not over, alert the player.
|
||||
if (!game.GameOver)
|
||||
{
|
||||
MessageBox.Show("A game is already underway, start a new one.");
|
||||
return;
|
||||
}
|
||||
|
||||
//Set the correct menu checkboxes and application settings.
|
||||
Properties.Settings.Default.CPUAsPlayer = cpuAsPlayer;
|
||||
switch (cpuAsPlayer)
|
||||
{
|
||||
case 0:
|
||||
Properties.Settings.Default.PlayVsCPU = false;
|
||||
playVsCPUToolStripMenuItem.Checked = false;
|
||||
cPUAsPlayer1ToolStripMenuItem.Checked = false;
|
||||
cPUAsPlayer2ToolStripMenuItem.Checked = false;
|
||||
break;
|
||||
case 1: //CPU as player 1
|
||||
Properties.Settings.Default.PlayVsCPU = true;
|
||||
playVsCPUToolStripMenuItem.Checked = true;
|
||||
cPUAsPlayer1ToolStripMenuItem.Checked = true;
|
||||
cPUAsPlayer2ToolStripMenuItem.Checked = false;
|
||||
break;
|
||||
case 2: //CPU as player 2
|
||||
Properties.Settings.Default.PlayVsCPU = true;
|
||||
playVsCPUToolStripMenuItem.Checked = true;
|
||||
cPUAsPlayer1ToolStripMenuItem.Checked = false;
|
||||
cPUAsPlayer2ToolStripMenuItem.Checked = true;
|
||||
break;
|
||||
}
|
||||
//Save the settings.
|
||||
Properties.Settings.Default.Save();
|
||||
} //SetPlayVsCPU
|
||||
|
||||
/* Game timer delegate to watch for the CPU Turn.
|
||||
* Visual studio generated delegate.
|
||||
* Preconditions: not yet
|
||||
* Inputs: object sender, EventArgs e
|
||||
* Outputs: void return
|
||||
* Postconditions: not yet
|
||||
*/
|
||||
private void CPUTurnTimer_Tick(object sender, EventArgs e)
|
||||
{
|
||||
//If the game is over, do not take a CPU turn.
|
||||
if (game.GameOver)
|
||||
return;
|
||||
|
||||
TicTacToe.XorO winningPlayer;
|
||||
string playerStr = string.Empty;
|
||||
|
||||
//Take the CPU turn.
|
||||
if (game.CurrentPlayerTurn == TicTacToe.PlayerTurn.CPU)
|
||||
{
|
||||
//Row and col can be 0,0 here as TakeCPUTurn will be called
|
||||
//which will randomly pick a row/col to play in.
|
||||
game.TakeCPUTurn();
|
||||
|
||||
//Swap to the next player's turn
|
||||
winningPlayer = game.TogglePlayerTurn(game.CurrentPlayerTurn);
|
||||
|
||||
//Update the player turn label after CPU turn.
|
||||
playerStr = (game.CurrentPlayerTurn.ToString() == TicTacToe.PlayerTurn.CPU.ToString()) ? "CPU (THINKING...)" : game.CurrentPlayerTurn.ToString();
|
||||
lblPlayerTurn.Text = $"Player turn: {playerStr}";
|
||||
|
||||
UpdateWinner(winningPlayer);
|
||||
}
|
||||
} //CPUTurnTimer_Tick
|
||||
} // frmTicTacToe
|
||||
}
|
126
Cs3Apps/TicTacToe/Form1.resx
Normal file
126
Cs3Apps/TicTacToe/Form1.resx
Normal file
@ -0,0 +1,126 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<metadata name="mainMenuStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>18, 13</value>
|
||||
</metadata>
|
||||
<metadata name="CPUTurnTimer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>205, 13</value>
|
||||
</metadata>
|
||||
</root>
|
22
Cs3Apps/TicTacToe/Program.cs
Normal file
22
Cs3Apps/TicTacToe/Program.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace TicTacToe
|
||||
{
|
||||
static class Program
|
||||
{
|
||||
/// <summary>
|
||||
/// The main entry point for the application.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
static void Main()
|
||||
{
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
Application.Run(new frmTicTacToe());
|
||||
}
|
||||
}
|
||||
}
|
36
Cs3Apps/TicTacToe/Properties/AssemblyInfo.cs
Normal file
36
Cs3Apps/TicTacToe/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("TicTacToe")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("TicTacToe")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2020")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("6da041e1-08f7-4feb-8201-252d03be5d34")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
71
Cs3Apps/TicTacToe/Properties/Resources.Designer.cs
generated
Normal file
71
Cs3Apps/TicTacToe/Properties/Resources.Designer.cs
generated
Normal file
@ -0,0 +1,71 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace TicTacToe.Properties
|
||||
{
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources
|
||||
{
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager
|
||||
{
|
||||
get
|
||||
{
|
||||
if ((resourceMan == null))
|
||||
{
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("TicTacToe.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture
|
||||
{
|
||||
get
|
||||
{
|
||||
return resourceCulture;
|
||||
}
|
||||
set
|
||||
{
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
117
Cs3Apps/TicTacToe/Properties/Resources.resx
Normal file
117
Cs3Apps/TicTacToe/Properties/Resources.resx
Normal file
@ -0,0 +1,117 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
50
Cs3Apps/TicTacToe/Properties/Settings.Designer.cs
generated
Normal file
50
Cs3Apps/TicTacToe/Properties/Settings.Designer.cs
generated
Normal file
@ -0,0 +1,50 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace TicTacToe.Properties {
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.4.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
|
||||
public static Settings Default {
|
||||
get {
|
||||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("False")]
|
||||
public bool PlayVsCPU {
|
||||
get {
|
||||
return ((bool)(this["PlayVsCPU"]));
|
||||
}
|
||||
set {
|
||||
this["PlayVsCPU"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("2")]
|
||||
public int CPUAsPlayer {
|
||||
get {
|
||||
return ((int)(this["CPUAsPlayer"]));
|
||||
}
|
||||
set {
|
||||
this["CPUAsPlayer"] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
12
Cs3Apps/TicTacToe/Properties/Settings.settings
Normal file
12
Cs3Apps/TicTacToe/Properties/Settings.settings
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="TicTacToe.Properties" GeneratedClassName="Settings">
|
||||
<Profiles />
|
||||
<Settings>
|
||||
<Setting Name="PlayVsCPU" Type="System.Boolean" Scope="User">
|
||||
<Value Profile="(Default)">False</Value>
|
||||
</Setting>
|
||||
<Setting Name="CPUAsPlayer" Type="System.Int32" Scope="User">
|
||||
<Value Profile="(Default)">2</Value>
|
||||
</Setting>
|
||||
</Settings>
|
||||
</SettingsFile>
|
426
Cs3Apps/TicTacToe/TicTacToe.cs
Normal file
426
Cs3Apps/TicTacToe/TicTacToe.cs
Normal file
@ -0,0 +1,426 @@
|
||||
/* Shaun Marquardt
|
||||
* TINFO 200
|
||||
* CS3: TicTacToe
|
||||
* ****************************************************
|
||||
* Change History
|
||||
* Date Developer Description
|
||||
* 2020-02-18 marqusa File creation and initial implementation,
|
||||
* Martyr2 (Coders Lexicon), Microsoft, Chuck Costarella L5Life
|
||||
* 2020-02-22 marqusa Implement TakeCPUTurn.
|
||||
* Implement draw game scenario (Thanks, Wargames).
|
||||
* 2020-02-23 marqusa Add functionality to have CPU play as player 1 or player 2.
|
||||
*
|
||||
* REFERENCES
|
||||
* https://www.coderslexicon.com/passing-data-between-forms-using-delegates-and-events/
|
||||
* https://docs.microsoft.com/en-us/dotnet/api/system.eventargs?view=netframework-4.8
|
||||
*
|
||||
* AND NOW In English, a more descriptive part of what is going on here.
|
||||
* -----------------
|
||||
* So the first thing that happens on Form1_Load, is the form will instantiate
|
||||
* a new TicTacToe class and pass in the form to the constructor.
|
||||
* The constructor will attach the form delegate and initialize the game board
|
||||
* along with setting the GameOver variable to False.
|
||||
*
|
||||
* When a label is clicked, a specific row and column is passed to TakePlayerTurn
|
||||
* along with the current player's turn identifier (by PlayerTurn enum type).
|
||||
*
|
||||
* TakePlayerTurn will check for a winner using CheckForWinner.
|
||||
*
|
||||
* CheckForWinner will set GameOver to TRUE if win or draw.
|
||||
* if win, returns winning player's X or O symbol using XorO enum type.
|
||||
* If draw, still sets GameOver to TRUE, but returns NONE XorO enum type.
|
||||
*
|
||||
* After that, the player turn will be toggled using TogglePlayerTurn, to
|
||||
* signal to the players and the game whose turn it is.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace TicTacToe
|
||||
{
|
||||
class TicTacToe
|
||||
{
|
||||
|
||||
/* This is the class to play the classic game,
|
||||
* Tic-Tac-Toe. The form you see displayed (Form1.cs)
|
||||
* is primarily a driver for this TicTacToe class
|
||||
* which actually plays the game behind the scenes.
|
||||
*
|
||||
* Requirements:
|
||||
* 1) Class TicTacToe enables us to create a complete app to play
|
||||
* the game of Tic-Tac-Toe.
|
||||
* 2) This class contains a private 3x3 rectangular array of integers.
|
||||
* 3) The constructor initializes the empty board.
|
||||
* 4) Each move should be in an empty square.
|
||||
* 5) Determine win, lose, or draw.
|
||||
*
|
||||
* Extra Credit:
|
||||
* The app is developed using a Windows Form application.
|
||||
* It is possible to play vs CPU as CPU player 1 or player 2.
|
||||
*
|
||||
* Extra Fun Stuff:
|
||||
* The game actively tracks the current player's turn.
|
||||
* I used an enum for both player turn and X and O.
|
||||
* I included a delegate and custom event args to pass
|
||||
* data from the TicTacToe class and update the correct label.
|
||||
* The game is really handled by basically everything in this
|
||||
* TicTacToe class with the form as a GUI frontend.
|
||||
*/
|
||||
|
||||
//Game Over auto-implemented property
|
||||
//with internal set
|
||||
public bool GameOver { get; internal set; }
|
||||
|
||||
//Current player turn is of type enum PlayerTurn.
|
||||
//with internal set
|
||||
//This helps the game track whose turn it currently is.
|
||||
public PlayerTurn CurrentPlayerTurn { get; internal set; }
|
||||
|
||||
//The class contains a private 3-by-3 rectangular array of integers.
|
||||
private int[,] gameBoard;
|
||||
|
||||
//Enum XorO describes X as 1, O as 2, and none as 0.
|
||||
//We need a 'none' value to help pass along 'nothing'
|
||||
//or the winning player back to the form on TogglePlayerTurn.
|
||||
public enum XorO
|
||||
{
|
||||
none = 0,
|
||||
x = 1,
|
||||
o = 2
|
||||
}
|
||||
|
||||
//Enum PlayerTurn helps track which player's turn it is
|
||||
//using Player 1=1, Player2=2, and CPU=3.
|
||||
public enum PlayerTurn
|
||||
{
|
||||
Player1 = 1,
|
||||
Player2 = 2,
|
||||
CPU = 3
|
||||
}
|
||||
|
||||
//Delegates to pass data to the GUI Form. Ref: Coder's Lexicon
|
||||
public delegate void SendMessage(object obj, EventArgs e);
|
||||
public event SendMessage OnSendMessage;
|
||||
|
||||
//An eventarg class to send to the GUI form via the delegate. Ref: Microsoft
|
||||
public class RowColumnEventArgs : EventArgs
|
||||
{
|
||||
public int row { get; set; }
|
||||
public int col { get; set; }
|
||||
}
|
||||
|
||||
// Class constructor
|
||||
// 1 - Create the object - chunk out memory on the heap for the actual storage.
|
||||
// 2 - initialize all relevant variables to reasonable defaults.
|
||||
public TicTacToe(frmTicTacToe frm)
|
||||
{
|
||||
//Construct a 3x3 game board.
|
||||
gameBoard = new int[3, 3];
|
||||
|
||||
//The constructor should initialize the empty board to all blank's.
|
||||
InitializeGameBoard();
|
||||
|
||||
//Set the game to be "over"
|
||||
GameOver = true;
|
||||
|
||||
//form driver, says "attach its MessageReceived function to the event"
|
||||
OnSendMessage += frm.MessageReceived;
|
||||
}
|
||||
|
||||
//Initializes the game board to the start state of raw storage
|
||||
//Preconditions: not yet
|
||||
//Inputs: no args
|
||||
//Outputs: void return
|
||||
//Postconditions: not yet
|
||||
//ref: Chuck Costarella, L5Life
|
||||
private void InitializeGameBoard()
|
||||
{
|
||||
//iterate through each row
|
||||
for (int r = 0; r < 3; r++)
|
||||
{
|
||||
//iterate through each column in an individual row
|
||||
for (int c = 0; c < 3; c++)
|
||||
{
|
||||
//init all cells in the game board to the init start status - none
|
||||
gameBoard[r,c] = (int)XorO.none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Starts a new game.
|
||||
* Preconditions: not yet
|
||||
* Inputs: no args
|
||||
* Outputs: void return
|
||||
* Postconditions: not yet
|
||||
*/
|
||||
internal void StartNewGame()
|
||||
{
|
||||
//Start the game.
|
||||
GameOver = false;
|
||||
|
||||
//Reset the game board.
|
||||
InitializeGameBoard();
|
||||
|
||||
//Set to the first player's CurrentPlayerTurn.
|
||||
CurrentPlayerTurn = PlayerTurn.Player1;
|
||||
}
|
||||
|
||||
/* Take a given player's turn.
|
||||
* Preconditions: not yet
|
||||
* Inputs: PlayerTurn, row, col
|
||||
* Outputs: void return
|
||||
* Postconditions: not yet
|
||||
*/
|
||||
internal void TakePlayerTurn(PlayerTurn playerTurn, int row, int col)
|
||||
{
|
||||
//If the game's over, don't take any more turns.
|
||||
if (GameOver)
|
||||
return;
|
||||
|
||||
//If the requested row or column is already taken, don't make a move.
|
||||
//Do not allow placing a move in a spot that already has been placed.
|
||||
if (gameBoard[row,col] != 0)
|
||||
return;
|
||||
|
||||
//ref: Microsoft
|
||||
RowColumnEventArgs args = new RowColumnEventArgs();
|
||||
args.row = row;
|
||||
args.col = col;
|
||||
|
||||
switch (playerTurn)
|
||||
{
|
||||
case PlayerTurn.Player1: //Take the first player's CurrentPlayerTurn.
|
||||
if(gameBoard[row,col] == (int)XorO.none)
|
||||
{
|
||||
gameBoard[row, col] = (int)XorO.x; //The first player is X.
|
||||
OnSendMessage?.Invoke(this, args); //ref: Coder's Lexicon
|
||||
}
|
||||
break;
|
||||
case PlayerTurn.Player2: //Take the second player's turn.
|
||||
if (gameBoard[row, col] == (int)XorO.none)
|
||||
{
|
||||
gameBoard[row, col] = (int)XorO.o; //The second player is O.
|
||||
OnSendMessage?.Invoke(this, args); //ref: Coder's Lexicon
|
||||
}
|
||||
break;
|
||||
case PlayerTurn.CPU: //Take the CPU's turn.
|
||||
TakeCPUTurn();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Take the CPU's turn. Uses Random.Next
|
||||
* which automatically seeds the random number generator
|
||||
* to the current system time.
|
||||
* Preconditions: not yet
|
||||
* Inputs: no args
|
||||
* Outputs: void return
|
||||
* Postconditions: not yet
|
||||
*/
|
||||
public void TakeCPUTurn()
|
||||
{
|
||||
//If the game is over, do nothing.
|
||||
if (GameOver)
|
||||
return;
|
||||
|
||||
//Create a new instance of the System.Random class.
|
||||
//It is automatically seeded with the current system time.
|
||||
Random rnd = new Random();
|
||||
|
||||
//Create a string list of available indexes.
|
||||
//as I won't know how big the collection will be.
|
||||
List<string> availableIndexes = new List<string>();
|
||||
|
||||
//Parse through the gameBoard and find all
|
||||
//the indexes that are still 0.
|
||||
//For each row in the gameboard
|
||||
for (int r = 0; r < 3; r++)
|
||||
{
|
||||
//Iterate through each column.
|
||||
for(int c = 0; c < 3; c++)
|
||||
{
|
||||
//If there is nothing in the current position
|
||||
if(gameBoard[r,c] == 0)
|
||||
{
|
||||
//add it to the availableIndexes list collection.
|
||||
availableIndexes.Add($"{r}{ c}");
|
||||
}
|
||||
}
|
||||
} //end for
|
||||
|
||||
//no more spaces left on the game board.
|
||||
if (availableIndexes.Count == 0)
|
||||
{
|
||||
GameOver = true;
|
||||
return;
|
||||
}
|
||||
|
||||
//Now determine where the computer is going to
|
||||
//place the move.
|
||||
int randomIndex = rnd.Next(0, availableIndexes.Count);
|
||||
string computerMove = availableIndexes[randomIndex];
|
||||
int row = int.Parse(computerMove[0].ToString());
|
||||
int col = int.Parse(computerMove[1].ToString());
|
||||
|
||||
//Setup the event args to pass back
|
||||
//to the main game form.
|
||||
//ref: Microsoft
|
||||
RowColumnEventArgs args = new RowColumnEventArgs();
|
||||
args.row = row;
|
||||
args.col = col;
|
||||
|
||||
//Now place the computer move in the determined
|
||||
//row and column of the game board
|
||||
//and update the form.
|
||||
if(Properties.Settings.Default.CPUAsPlayer == 1)
|
||||
gameBoard[row, col] = (int)XorO.x;
|
||||
else
|
||||
gameBoard[row, col] = (int)XorO.o; //The second player is O.
|
||||
|
||||
OnSendMessage?.Invoke(this, args); //ref: Coder's Lexicon
|
||||
} //TakeCPUTurn
|
||||
|
||||
/* Toggles a player turn between player 1 and player 2
|
||||
* or player 1 and CPU.
|
||||
* Also runs the CheckForWinner function before toggling player turn.
|
||||
* Preconditions: not yet
|
||||
* Inputs: PlayerTurn enum type
|
||||
* Outputs: XorO enum type
|
||||
* Postconditions: not yet
|
||||
*/
|
||||
internal XorO TogglePlayerTurn(PlayerTurn playerTurn)
|
||||
{
|
||||
//Check for winning player before toggling player turn.
|
||||
XorO winningPlayer = CheckForWinner(playerTurn);
|
||||
|
||||
//If we do not have a winner
|
||||
if (!GameOver)
|
||||
{
|
||||
//Swap the player turns.
|
||||
//First is the easy case: If we are not playing vs CPU
|
||||
//simply swap player turn.
|
||||
if(!Properties.Settings.Default.PlayVsCPU)
|
||||
{
|
||||
if (CurrentPlayerTurn == PlayerTurn.Player1)
|
||||
CurrentPlayerTurn = PlayerTurn.Player2;
|
||||
else
|
||||
CurrentPlayerTurn = PlayerTurn.Player1;
|
||||
}
|
||||
else //We are playing against CPU.
|
||||
{
|
||||
//Determine if CPU is Player 1 or Player 2.
|
||||
if(Properties.Settings.Default.CPUAsPlayer == 1) //CPU is player 1.
|
||||
{
|
||||
if (CurrentPlayerTurn == PlayerTurn.Player2)
|
||||
{
|
||||
CurrentPlayerTurn = PlayerTurn.CPU;
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentPlayerTurn = PlayerTurn.Player2;
|
||||
}
|
||||
}
|
||||
else //CPU is player 2.
|
||||
{
|
||||
if (CurrentPlayerTurn == PlayerTurn.Player1)
|
||||
{
|
||||
CurrentPlayerTurn = PlayerTurn.CPU;
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentPlayerTurn = PlayerTurn.Player1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} //end if !GameOver
|
||||
|
||||
//Return 'none' if no winning player,
|
||||
//else return the winning player.
|
||||
return winningPlayer;
|
||||
} // TogglePlayerTurn
|
||||
|
||||
/* Checks for a winner.
|
||||
* If we have a winner, set GameOver to True
|
||||
* and return the winning player's game piece.
|
||||
* Preconditions: not yet
|
||||
* Inputs: PlayerTurn enum
|
||||
* Outputs: XorO enum
|
||||
* Postconditions: not yet
|
||||
*/
|
||||
private XorO CheckForWinner(PlayerTurn playerTurn)
|
||||
{
|
||||
//chicken dinner
|
||||
bool bWinnerWinner = true;
|
||||
XorO winningPlayer = XorO.none;
|
||||
|
||||
//Draw Game. In this foreach loop,
|
||||
//bWinnerWinner is most likely set false.
|
||||
foreach (var value in gameBoard)
|
||||
{
|
||||
//It's not a draw game.
|
||||
if (value == 0)
|
||||
{
|
||||
bWinnerWinner = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Winner on a column.
|
||||
for (int row = 0; row < 3; row++)
|
||||
{
|
||||
if(gameBoard[row,0] != 0 //rowN col0 has something in it
|
||||
&& gameBoard[row,0] == gameBoard[row,1] //rowN col0 is equal to col1
|
||||
&& gameBoard[row,0] == gameBoard[row,2])//and rowN col0 is equal to col2
|
||||
{
|
||||
bWinnerWinner = true;
|
||||
|
||||
//ref: chuck
|
||||
Enum.TryParse<XorO>(gameBoard[row, 0].ToString(), out winningPlayer);
|
||||
}
|
||||
}
|
||||
|
||||
//Winner on a row.
|
||||
for(int col = 0; col < 3; col++)
|
||||
{
|
||||
if (gameBoard[0, col] != 0 //rowN col0 has something in it
|
||||
&& gameBoard[0, col] == gameBoard[1, col] //colN row0 is equan to row1
|
||||
&& gameBoard[0, col] == gameBoard[2, col])//and colN row0 is equal to row2
|
||||
{
|
||||
bWinnerWinner = true;
|
||||
|
||||
//ref: chuck
|
||||
Enum.TryParse<XorO>(gameBoard[0, col].ToString(), out winningPlayer);
|
||||
}
|
||||
}
|
||||
|
||||
//Winner diagonally.
|
||||
if(gameBoard[1,1] != 0 //the middle has something in it.
|
||||
&& ( (gameBoard[0,0] == gameBoard[1,1] //Winner from top left to btm right
|
||||
&& gameBoard[1,1] == gameBoard[2,2])
|
||||
||(gameBoard[0,2] == gameBoard[1,1] //OR winner from top rt to btm lft
|
||||
&& gameBoard[2,0] == gameBoard[1,1]) )
|
||||
) //end if
|
||||
{
|
||||
bWinnerWinner = true;
|
||||
Enum.TryParse<XorO>(gameBoard[1, 1].ToString(), out winningPlayer);
|
||||
}
|
||||
|
||||
//We have a winner or draw game.
|
||||
if (bWinnerWinner)
|
||||
{
|
||||
//Set the game to be over.
|
||||
GameOver = true;
|
||||
|
||||
//Return the winning player's piece.
|
||||
return winningPlayer;
|
||||
}
|
||||
|
||||
//Return no game piece as the game is not over.
|
||||
return XorO.none;
|
||||
}
|
||||
} //CheckForWinner()
|
||||
}
|
84
Cs3Apps/TicTacToe/TicTacToe.csproj
Normal file
84
Cs3Apps/TicTacToe/TicTacToe.csproj
Normal file
@ -0,0 +1,84 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{6DA041E1-08F7-4FEB-8201-252D03BE5D34}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<RootNamespace>TicTacToe</RootNamespace>
|
||||
<AssemblyName>TicTacToe</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Deployment" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Form1.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Form1.Designer.cs">
|
||||
<DependentUpon>Form1.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="TicTacToe.cs" />
|
||||
<EmbeddedResource Include="Form1.resx">
|
||||
<DependentUpon>Form1.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
<Compile Include="Properties\Settings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
6
GLife/App.config
Normal file
6
GLife/App.config
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
|
||||
</startup>
|
||||
</configuration>
|
54
GLife/GLife.csproj
Normal file
54
GLife/GLife.csproj
Normal file
@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{07CD2938-EF48-458A-AAD8-8EA66D5724AF}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>GLife</RootNamespace>
|
||||
<AssemblyName>GLife</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Game.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
25
GLife/GLife.sln
Normal file
25
GLife/GLife.sln
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.29613.14
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GLife", "GLife.csproj", "{07CD2938-EF48-458A-AAD8-8EA66D5724AF}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{07CD2938-EF48-458A-AAD8-8EA66D5724AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{07CD2938-EF48-458A-AAD8-8EA66D5724AF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{07CD2938-EF48-458A-AAD8-8EA66D5724AF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{07CD2938-EF48-458A-AAD8-8EA66D5724AF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {1C933385-BCD4-4180-8D3F-994BF291729E}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
392
GLife/Game.cs
Normal file
392
GLife/Game.cs
Normal file
@ -0,0 +1,392 @@
|
||||
/*
|
||||
* Change History
|
||||
* Date Developer Description
|
||||
* 2020-01-16 marqusa File creation and initial implementation -- Charles Costarella
|
||||
* 2020-01-28 marqusa Game Board Initialization --Charles Costarella
|
||||
* Process game board, determine if cell is dead or alive
|
||||
* Add main game rule logic & count neighbors.
|
||||
* Add a StreamWriter to write out the gameboard per generation to a file.
|
||||
*/
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace GLife
|
||||
{
|
||||
//ref: Chuck Costarella
|
||||
public class Game
|
||||
{
|
||||
public StreamWriter outfile;
|
||||
|
||||
//const has to be assigned immediately and can never be changed.
|
||||
//Readonly does not need to be assigned immediately.
|
||||
// once readonly is assigned, can never be changed.
|
||||
|
||||
// size the game boards
|
||||
public const int ROW_SIZE = 32;
|
||||
public const int COL_SIZE = 120;
|
||||
|
||||
//Define characters for dead or alive cells.
|
||||
public const char DEAD = '-';
|
||||
public const char LIVE = 'o';
|
||||
|
||||
// game boards
|
||||
//initialize board as two dimentional array
|
||||
private char[,] gameBoard;
|
||||
private char[,] tempBoard;
|
||||
|
||||
// Class constructor
|
||||
// 1 - Create the object - chunk out memory on the heap for the actual storage.
|
||||
// 2 - initialize all relevant variables to reasonable defaults.
|
||||
public Game()
|
||||
{
|
||||
//Create a new file with a name.
|
||||
//StreamWriter will make a text file.
|
||||
outfile = new StreamWriter("OUTPUT.txt");
|
||||
|
||||
// construct the two gameboards.
|
||||
gameBoard = new char[ROW_SIZE, COL_SIZE];
|
||||
tempBoard = new char[ROW_SIZE, COL_SIZE];
|
||||
|
||||
// playing the game consists of
|
||||
// step 1 - initializing the gameboard to some start pattern
|
||||
// superimposed over the field
|
||||
// the initial field will be all DEAD
|
||||
InitializeBoards();
|
||||
|
||||
// superimpose some start patterns over the initial board.
|
||||
InsertStartPatterns();
|
||||
}
|
||||
|
||||
// main processing loop for the game
|
||||
// plays the game by setting a number of generations to display
|
||||
// and then looping for each generation
|
||||
// each generation
|
||||
// 1 - displays the results of the current generation
|
||||
// 2 - processes the next gen to the results board (tempBoard)
|
||||
// 3 - swaps the 2 boards
|
||||
//Preconditions: not yet
|
||||
//Inputs: no args
|
||||
//Outputs: void return
|
||||
//Postconditions: not yet
|
||||
//ref: Chuck Costarella
|
||||
public void PlayGame()
|
||||
{
|
||||
// get the number of generations to display from the user
|
||||
Console.Write("Enter the number of generations: ");
|
||||
int numberOfGenerations = int.Parse(Console.ReadLine());
|
||||
|
||||
for (int generation = 1; generation <= numberOfGenerations; generation++)
|
||||
{
|
||||
// 1 - displays the results of the current generation
|
||||
DisplayBoard(generation);
|
||||
|
||||
// 2 - processes the next gen to the results board (tempBoard)
|
||||
ProcessGameBoard();
|
||||
|
||||
// 3 - swaps the 2 boards
|
||||
char[,] tempLocation = gameBoard;
|
||||
gameBoard = tempBoard;
|
||||
tempBoard = tempLocation;
|
||||
}
|
||||
|
||||
//release resource
|
||||
outfile.Close();
|
||||
}
|
||||
|
||||
//Processes the game board according to
|
||||
//Conway's Game of Life rules
|
||||
//Iterate through the current gameboard and
|
||||
//determine if that cell will live or die (in the next gen)
|
||||
//store the results back into the results board (tempBoard)
|
||||
//Preconditions: not yet
|
||||
//Inputs: no args
|
||||
//Outputs: void return
|
||||
//Postconditions: not yet
|
||||
//ref: Chuck Costarella
|
||||
private void ProcessGameBoard()
|
||||
{
|
||||
// 2 - processes the next gen to the results board (tempBoard)
|
||||
// Count the neighbors for each cell
|
||||
for (int r = 0; r < ROW_SIZE; r++)
|
||||
{
|
||||
for (int c = 0; c < COL_SIZE; c++)
|
||||
{
|
||||
// determine if [r,c[ will live or die
|
||||
//store the results back into the results board (tempBoard)
|
||||
tempBoard[r, c] = DetermineDeadOrAlive(r,c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Determine if a specific cell is dead or alive in the next gen by doing the following
|
||||
//count the neighbors to get a total
|
||||
//apply the rules of the game.
|
||||
//Preconditions: not yet
|
||||
//Inputs: int row, int column
|
||||
//Outputs: char DEAD or char ALIVE.
|
||||
//Postconditions: not yet
|
||||
//ref: Chuck Costarella
|
||||
private char DetermineDeadOrAlive(int r, int c)
|
||||
{
|
||||
//YOU SPIN ME RIGHT ROUND BABY
|
||||
//RIGHT ROUND
|
||||
//LIKE A RECORD BABY RIGHT ROUND ROUND ROUND
|
||||
|
||||
//count the neighbors to get a total
|
||||
int count = CountNeighbors(r, c);
|
||||
|
||||
//apply the rules of the game
|
||||
|
||||
//Any live cell with fewer than two live neighbours dies, as if by underpopulation.
|
||||
//Any live cell with two or three live neighbours lives on to the next generation.
|
||||
//Any live cell with more than three live neighbours dies, as if by overpopulation.
|
||||
//Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
|
||||
|
||||
if (count == 2) return gameBoard[r, c]; //status quo rule
|
||||
else if (count == 3) return LIVE; //spontaneous birth
|
||||
else return DEAD; //It's dead, Jim.
|
||||
}
|
||||
|
||||
//Inserts start patterns to both game boards
|
||||
//Preconditions: not yet
|
||||
//Inputs: int row, int column
|
||||
//Outputs: void return
|
||||
//Postconditions: not yet
|
||||
//ref: Chuck Costarella
|
||||
private int CountNeighbors(int r, int c)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
if(r == 0 && c == 0)
|
||||
{
|
||||
//EXCEPTIONAL CASE -- Top Left corner
|
||||
//if (gameBoard[r - 1, c - 1] == LIVE) count++;
|
||||
//if (gameBoard[r - 1, c] == LIVE) count++;
|
||||
//if (gameBoard[r - 1, c + 1] == LIVE) count++;
|
||||
//if (gameBoard[r, c - 1] == LIVE) count++;
|
||||
if (gameBoard[r, c + 1] == LIVE) count++;
|
||||
//if (gameBoard[r + 1, c - 1] == LIVE) count++;
|
||||
if (gameBoard[r + 1, c] == LIVE) count++;
|
||||
if (gameBoard[r + 1, c + 1] == LIVE) count++;
|
||||
}
|
||||
else if(r==0 && c==COL_SIZE-1)
|
||||
{
|
||||
//EXCEPTIONAL CASE -- Top Right corner
|
||||
//if (gameBoard[r - 1, c - 1] == LIVE) count++;
|
||||
//if (gameBoard[r - 1, c] == LIVE) count++;
|
||||
//if (gameBoard[r - 1, c + 1] == LIVE) count++;
|
||||
if (gameBoard[r, c - 1] == LIVE) count++;
|
||||
//if (gameBoard[r, c + 1] == LIVE) count++;
|
||||
if (gameBoard[r + 1, c - 1] == LIVE) count++;
|
||||
if (gameBoard[r + 1, c] == LIVE) count++;
|
||||
//if (gameBoard[r + 1, c + 1] == LIVE) count++;
|
||||
}
|
||||
else if (r==ROW_SIZE-1 && c==0)
|
||||
{
|
||||
//EXCEPTIONAL CASE -- Bottom Left corner
|
||||
//if (gameBoard[r - 1, c - 1] == LIVE) count++;
|
||||
if (gameBoard[r - 1, c] == LIVE) count++;
|
||||
if (gameBoard[r - 1, c + 1] == LIVE) count++;
|
||||
//if (gameBoard[r, c - 1] == LIVE) count++;
|
||||
if (gameBoard[r, c + 1] == LIVE) count++;
|
||||
//if (gameBoard[r + 1, c - 1] == LIVE) count++;
|
||||
//if (gameBoard[r + 1, c] == LIVE) count++;
|
||||
//if (gameBoard[r + 1, c + 1] == LIVE) count++;
|
||||
}
|
||||
else if (r==ROW_SIZE-1 && c==COL_SIZE-1)
|
||||
{
|
||||
//EXCEPTIONAL CASE -- Bottom Right corner
|
||||
if (gameBoard[r - 1, c - 1] == LIVE) count++;
|
||||
if (gameBoard[r - 1, c] == LIVE) count++;
|
||||
//if (gameBoard[r - 1, c + 1] == LIVE) count++;
|
||||
if (gameBoard[r, c - 1] == LIVE) count++;
|
||||
//if (gameBoard[r, c + 1] == LIVE) count++;
|
||||
//if (gameBoard[r + 1, c - 1] == LIVE) count++;
|
||||
//if (gameBoard[r + 1, c] == LIVE) count++;
|
||||
//if (gameBoard[r + 1, c + 1] == LIVE) count++;
|
||||
}
|
||||
else if (r==0)
|
||||
{
|
||||
//EXCEPTIONAL CASE -- Top Edge
|
||||
//if (gameBoard[r - 1, c - 1] == LIVE) count++;
|
||||
//if (gameBoard[r - 1, c] == LIVE) count++;
|
||||
//if (gameBoard[r - 1, c + 1] == LIVE) count++;
|
||||
if (gameBoard[r, c - 1] == LIVE) count++;
|
||||
if (gameBoard[r, c + 1] == LIVE) count++;
|
||||
if (gameBoard[r + 1, c - 1] == LIVE) count++;
|
||||
if (gameBoard[r + 1, c] == LIVE) count++;
|
||||
if (gameBoard[r + 1, c + 1] == LIVE) count++;
|
||||
}
|
||||
else if (c==COL_SIZE-1)
|
||||
{
|
||||
//EXCEPTIONAL CASE -- Right Edge
|
||||
if (gameBoard[r - 1, c - 1] == LIVE) count++;
|
||||
if (gameBoard[r - 1, c] == LIVE) count++;
|
||||
//if (gameBoard[r - 1, c + 1] == LIVE) count++;
|
||||
if (gameBoard[r, c - 1] == LIVE) count++;
|
||||
//if (gameBoard[r, c + 1] == LIVE) count++;
|
||||
if (gameBoard[r + 1, c - 1] == LIVE) count++;
|
||||
if (gameBoard[r + 1, c] == LIVE) count++;
|
||||
//if (gameBoard[r + 1, c + 1] == LIVE) count++;
|
||||
}
|
||||
else if (r==ROW_SIZE-1)
|
||||
{
|
||||
//EXCEPTIONAL CASE -- Bottom Edge
|
||||
if (gameBoard[r - 1, c - 1] == LIVE) count++;
|
||||
if (gameBoard[r - 1, c] == LIVE) count++;
|
||||
if (gameBoard[r - 1, c + 1] == LIVE) count++;
|
||||
if (gameBoard[r, c - 1] == LIVE) count++;
|
||||
if (gameBoard[r, c + 1] == LIVE) count++;
|
||||
//if (gameBoard[r + 1, c - 1] == LIVE) count++;
|
||||
//if (gameBoard[r + 1, c] == LIVE) count++;
|
||||
//if (gameBoard[r + 1, c + 1] == LIVE) count++;
|
||||
}
|
||||
else if (c==0)
|
||||
{
|
||||
//EXCEPTIONAL CASE -- Left Edge
|
||||
//if (gameBoard[r - 1, c - 1] == LIVE) count++;
|
||||
if (gameBoard[r - 1, c] == LIVE) count++;
|
||||
if (gameBoard[r - 1, c + 1] == LIVE) count++;
|
||||
//if (gameBoard[r, c - 1] == LIVE) count++;
|
||||
if (gameBoard[r, c + 1] == LIVE) count++;
|
||||
//if (gameBoard[r + 1, c - 1] == LIVE) count++;
|
||||
if (gameBoard[r + 1, c] == LIVE) count++;
|
||||
if (gameBoard[r + 1, c + 1] == LIVE) count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
//No edges, no corners.
|
||||
if (gameBoard[r - 1, c - 1] == LIVE) count++;
|
||||
if (gameBoard[r - 1, c] == LIVE) count++;
|
||||
if (gameBoard[r - 1, c + 1] == LIVE) count++;
|
||||
if (gameBoard[r, c - 1] == LIVE) count++;
|
||||
if (gameBoard[r, c + 1] == LIVE) count++;
|
||||
if (gameBoard[r + 1, c - 1] == LIVE) count++;
|
||||
if (gameBoard[r + 1, c] == LIVE) count++;
|
||||
if (gameBoard[r + 1, c + 1] == LIVE) count++;
|
||||
}
|
||||
return count;
|
||||
} //end CountNeighbors
|
||||
|
||||
//Inserts start patterns to both game boards
|
||||
//Preconditions: not yet
|
||||
//Inputs: no args
|
||||
//Outputs: void return
|
||||
//Postconditions: not yet
|
||||
//ref: Chuck Costarella
|
||||
private void InsertStartPatterns()
|
||||
{
|
||||
//row, column
|
||||
InsertStartPattern1(20,25);
|
||||
}
|
||||
|
||||
//Initializes the game boards to the start state of raw storage
|
||||
//Preconditions: not yet
|
||||
//Inputs: no args
|
||||
//Outputs: void return
|
||||
//Postconditions: not yet
|
||||
//ref: Chuck Costarella
|
||||
private void InitializeBoards()
|
||||
{
|
||||
//iterate through each row
|
||||
for (int r = 0; r < ROW_SIZE; r++)
|
||||
{
|
||||
//iterate through each column in an individual row
|
||||
for (int c = 0; c < COL_SIZE; c++)
|
||||
{
|
||||
//init all cells in boath boards to the init start status - DEAD
|
||||
gameBoard[r, c] = DEAD;
|
||||
tempBoard[r, c] = DEAD;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Initializes the game boards to the start state of raw storage
|
||||
//Preconditions: not yet
|
||||
//Inputs: integer number of the current generation
|
||||
//Outputs: void return
|
||||
//Postconditions: not yet
|
||||
//ref: Chuck Costarella
|
||||
public void DisplayBoard(int generation)
|
||||
{
|
||||
//Move the cursor to overwrite the old gameboard.
|
||||
Console.SetCursorPosition(0, Console.WindowTop + 1);
|
||||
|
||||
Console.WriteLine($"GENERATION #: {generation}");
|
||||
outfile.WriteLine($"GENERATION #: {generation}");
|
||||
|
||||
//iterate through each row
|
||||
for (int r = 0; r < ROW_SIZE; r++)
|
||||
{
|
||||
//iterate through each column in an individual row
|
||||
for (int c = 0; c < COL_SIZE; c++)
|
||||
{
|
||||
//Write the cell [DEAD OR LIVE] to the console.
|
||||
Console.Write(gameBoard[r, c]);
|
||||
outfile.Write(gameBoard[r, c]);
|
||||
}
|
||||
|
||||
//insert CRLF at the end of every row
|
||||
Console.WriteLine();
|
||||
outfile.WriteLine();
|
||||
}
|
||||
}
|
||||
|
||||
//Inserts start patterns to both game boards
|
||||
//Preconditions: not yet
|
||||
//Inputs: integer row, integer column
|
||||
//Outputs: void return
|
||||
//Postconditions: not yet
|
||||
//ref: Chuck Costarella
|
||||
private void InsertStartPattern1(int r, int c)
|
||||
{
|
||||
//8 LIVE cells
|
||||
gameBoard[r, c + 1] = LIVE;
|
||||
gameBoard[r, c + 2] = LIVE;
|
||||
gameBoard[r, c + 3] = LIVE;
|
||||
gameBoard[r, c + 4] = LIVE;
|
||||
gameBoard[r, c + 5] = LIVE;
|
||||
gameBoard[r, c + 6] = LIVE;
|
||||
gameBoard[r, c + 7] = LIVE;
|
||||
gameBoard[r, c + 8] = LIVE;
|
||||
|
||||
//1 DEAD SPACE - c == 9
|
||||
|
||||
//5 LIVE cells
|
||||
gameBoard[r, c + 10] = LIVE;
|
||||
gameBoard[r, c + 11] = LIVE;
|
||||
gameBoard[r, c + 12] = LIVE;
|
||||
gameBoard[r, c + 13] = LIVE;
|
||||
gameBoard[r, c + 14] = LIVE;
|
||||
|
||||
//3 DEAD cells - c == 15,16,17
|
||||
|
||||
//3 LIVE cells
|
||||
gameBoard[r, c + 18] = LIVE;
|
||||
gameBoard[r, c + 19] = LIVE;
|
||||
gameBoard[r, c + 20] = LIVE;
|
||||
|
||||
//6 DEAD cells - c == 21-26
|
||||
|
||||
//7 LIVE cells
|
||||
gameBoard[r, c + 27] = LIVE;
|
||||
gameBoard[r, c + 28] = LIVE;
|
||||
gameBoard[r, c + 29] = LIVE;
|
||||
gameBoard[r, c + 30] = LIVE;
|
||||
gameBoard[r, c + 31] = LIVE;
|
||||
gameBoard[r, c + 32] = LIVE;
|
||||
gameBoard[r, c + 33] = LIVE;
|
||||
|
||||
//1 DEAD cell c==34
|
||||
|
||||
//5 LIVE cells
|
||||
gameBoard[r, c + 35] = LIVE;
|
||||
gameBoard[r, c + 36] = LIVE;
|
||||
gameBoard[r, c + 37] = LIVE;
|
||||
gameBoard[r, c + 38] = LIVE;
|
||||
gameBoard[r, c + 39] = LIVE;
|
||||
|
||||
} //END InsertStartPattern1
|
||||
|
||||
} // END class
|
||||
} // END namespace
|
29
GLife/Program.cs
Normal file
29
GLife/Program.cs
Normal file
@ -0,0 +1,29 @@
|
||||
/* Shaun Marquardt
|
||||
* TINFO 200
|
||||
* Game of Life simulation
|
||||
* ****************************************************
|
||||
* Change History
|
||||
* Date Developer Description
|
||||
* 2020-01-16 marqusa File creation and initial implementation -- Charles Costarella
|
||||
* 2020-01-28 marqusa --Charles Costarella
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GLife
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
// create a top level object that represents the game
|
||||
Game game = new Game();
|
||||
|
||||
// start the main game simulation
|
||||
game.PlayGame();
|
||||
}
|
||||
}
|
||||
}
|
36
GLife/Properties/AssemblyInfo.cs
Normal file
36
GLife/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("GLife")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("GLife")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2020")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("07cd2938-ef48-458a-aad8-8ea66d5724af")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
6
StudentDB/App.config
Normal file
6
StudentDB/App.config
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
|
||||
</startup>
|
||||
</configuration>
|
57
StudentDB/GradStudent.cs
Normal file
57
StudentDB/GradStudent.cs
Normal file
@ -0,0 +1,57 @@
|
||||
/* This is the GradStudent class which inherits from Student class.
|
||||
* See StuDB for full change history
|
||||
* It adds tuitionCredit and Faculty Advisor to the student class.
|
||||
*
|
||||
* Change History
|
||||
* Date Developer Description
|
||||
* 2020-02-13 marqusa In-class work on the program, Chuck Costarella
|
||||
* through 25
|
||||
* 2020-02-27 marqusa documentation
|
||||
*/
|
||||
namespace StudentDB
|
||||
{
|
||||
class GradStudent : Student
|
||||
{
|
||||
//Auto-implemented properties of TuitionCredit and FacultyAdvisor
|
||||
public decimal TuitionCredit { get; set; }
|
||||
|
||||
public string FacultyAdvisor { get; set; }
|
||||
|
||||
//GradStudent constructor inherits from Student constructor,
|
||||
//addding the credit and faculty advisor arguments.
|
||||
public GradStudent(string first, string last, double gpa, string email,
|
||||
decimal credit, string advisor)
|
||||
: base(first, last, gpa, email)
|
||||
{
|
||||
TuitionCredit = credit;
|
||||
FacultyAdvisor = advisor;
|
||||
}
|
||||
|
||||
// conversion to a lamda expression - mechanism of functional programming.
|
||||
// lamda operator is "=>" abd reads "goes to"
|
||||
// C# calls this an "expression-bodied method"
|
||||
// This is only used for one-liners or very simple things.
|
||||
public override string ToString() => base.ToString() + $"Credit: {TuitionCredit:C}\n Fac: {FacultyAdvisor}\n";
|
||||
|
||||
//the overriden method in the base class must be marked "virtual"
|
||||
public override string ToStringForOutputFile()
|
||||
{
|
||||
//Prepend the discriminator to the base student information
|
||||
string str = StuDB.GRADSTUDENT + "\n" + base.ToStringForOutputFile();
|
||||
|
||||
// append the "local information"
|
||||
str += $"{TuitionCredit}\n";
|
||||
str += $"{FacultyAdvisor}\n";
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/* This is the "Standard?" way instead of the lamda way.
|
||||
* I am just leaving this in here for my reference.
|
||||
public override string ToString()
|
||||
{
|
||||
return base.ToString() + $"Credit: {TuitionCredit:C}\n Fac: {FacultyAdvisor}\n";
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
42
StudentDB/Program.cs
Normal file
42
StudentDB/Program.cs
Normal file
@ -0,0 +1,42 @@
|
||||
/* Shaun Marquardt
|
||||
* TINFO 200
|
||||
* L6: OOP
|
||||
* ****************************************************
|
||||
* Change History
|
||||
* Date Developer Description
|
||||
* 2020-02-11 marqusa File creation and initial implementation, Chuck Costarella
|
||||
* See StuDB for fuller change history
|
||||
* 2020-02-29 marqusa Removed TestMain as I have [I]nsert test driver data in the menu.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StudentDB
|
||||
{
|
||||
class Program
|
||||
{
|
||||
/* This is a program for a student database application.
|
||||
* This program has the capability to read/write to a plain
|
||||
* ascii text file to save the data to disk. When the data is read
|
||||
* it loads each type of student, UNDERGRAD or GRADSTUDENT into a
|
||||
* new list of students. The program operates on this list until
|
||||
* the QUIT menu choice is selected. At said time, the program
|
||||
* will save the current list of students in memory back out to disk.
|
||||
*/
|
||||
|
||||
|
||||
/* This is the main driver program for the StuDB class.
|
||||
* Simply instantiates a new StuDB object and calls GoDatabase()
|
||||
* which presents the main program to the user proper, starting
|
||||
* with the main menu.
|
||||
*/
|
||||
static void Main(string[] args)
|
||||
{
|
||||
StuDB app = new StuDB();
|
||||
app.GoDatabase();
|
||||
}
|
||||
}
|
||||
}
|
36
StudentDB/Properties/AssemblyInfo.cs
Normal file
36
StudentDB/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("StudentDB")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("StudentDB")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2020")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("767514ee-9c14-4590-8e4f-be06473a5c03")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
774
StudentDB/StuDB.cs
Normal file
774
StudentDB/StuDB.cs
Normal file
@ -0,0 +1,774 @@
|
||||
/*
|
||||
* Change History
|
||||
* Date Developer Description
|
||||
* 2020-02-11 marqusa File creation and initial implementation.
|
||||
* -added student class to start with. Add user input and output to files.
|
||||
* 2020-02-13 marqusa Continue with in-class work on the program, Chuck Costarella
|
||||
* - Implemented and updated new input functionality.
|
||||
* 2020-02-18 marqusa Continue with in-class work on the program, Chuck Costarella
|
||||
* -Made GradStudent and Undergrad classes.
|
||||
* -Implementing reading and writing of student types
|
||||
* 2020-02-20 marqusa Continue with in-class work on the program, Chuck Costarella
|
||||
* -Started coding for find, delete, and modify records
|
||||
* 2020-02-25 marqusa Continue with in-class work on the program, Chuck Costarella
|
||||
* -DeleteStudentRecord(), ListAllEmailAddresses()
|
||||
* 2020-02-26 marqusa Fix the output error when writing to output file in wrong order in undergrad
|
||||
* 2020-02-27 marqusa clean up adding new student.
|
||||
* Wrap deletion in a confirmation.
|
||||
* Move constants to top of StuDB
|
||||
* Add documentation.
|
||||
* Add shell to-do for inserting test student data into DB.
|
||||
* Add GetChoice with a maximum range above 9 as
|
||||
* GetSelectionFromUser only gets a single key, and does not
|
||||
* support numbers above 9. Ref: Microsoft
|
||||
* 2020-02-28 marqusa ModifyStudentRecord.
|
||||
* 2020-02-29 marqusa Finish completely implementing ModifyStudentRecord/ModifyUnderGrad/ModifyGrad
|
||||
* Complete all listed TODO items other than adding more rules for email address.
|
||||
* REFERENCES
|
||||
* https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/strings/how-to-determine-whether-a-string-represents-a-numeric-value
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace StudentDB
|
||||
{
|
||||
internal class StuDB
|
||||
{
|
||||
//Constants.
|
||||
const string STUDENT_DB_DATA_FILE = "STUDENT_DB_DATA_FILE.txt";
|
||||
public const string UNDERGRAD = "UNDERGRAD";
|
||||
public const string GRADSTUDENT = "GRADSTUDENT";
|
||||
|
||||
// the more or less persistent storage for students during runtime
|
||||
private List<Student> students = new List<Student>();
|
||||
|
||||
/* Main entry point to the StuDB application.
|
||||
* Preconditions: not yet
|
||||
* Inputs: no args
|
||||
* Outputs: void return
|
||||
* Postconditions: not yet
|
||||
*/
|
||||
public void GoDatabase()
|
||||
{
|
||||
//read the data in fron the input file
|
||||
ReadDataFromInputFile();
|
||||
|
||||
// setup a loop that will repeatedly prompt the user for an action
|
||||
//CRUD - Create, Read, Update, Delete
|
||||
while (true)
|
||||
{
|
||||
// display a main menu to the user
|
||||
DisplayMainMenu();
|
||||
|
||||
// CRUD - capture the user selection
|
||||
ConsoleKeyInfo selection = GetSelectionFromUser();
|
||||
|
||||
//Add space after reading the key.
|
||||
Console.WriteLine();
|
||||
switch (selection.KeyChar)
|
||||
{
|
||||
case 'I':
|
||||
case 'i':
|
||||
InsertTestStudentsIntoDB();
|
||||
break;
|
||||
case 'L':
|
||||
case 'l':
|
||||
ListAllEmailAddresses();
|
||||
break;
|
||||
case 'M':
|
||||
case 'm':
|
||||
ModifyStudentRecord();
|
||||
break;
|
||||
case 'D':
|
||||
case 'd':
|
||||
DeleteStudentRecord();
|
||||
break;
|
||||
case 'F':
|
||||
case 'f':
|
||||
Console.Write("Enter email ID to search for: ");
|
||||
string email = Console.ReadLine();
|
||||
Student searchStudent = FindStudentRecord(email);
|
||||
if (searchStudent != null)
|
||||
{
|
||||
Console.WriteLine(searchStudent);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"{email} not currently in the database.");
|
||||
}
|
||||
break;
|
||||
case 'N':
|
||||
case 'n':
|
||||
System.Diagnostics.Process.Start("notepad");
|
||||
break;
|
||||
case 'A':
|
||||
case 'a':
|
||||
AddStudentRecord();
|
||||
break;
|
||||
case 'P':
|
||||
case 'p':
|
||||
PrintAllRecords();
|
||||
break;
|
||||
case 'Q':
|
||||
case 'q':
|
||||
case 'X':
|
||||
case 'x':
|
||||
ExitTheDatabaseApp();
|
||||
break;
|
||||
case 'S':
|
||||
case 's':
|
||||
SaveDataToOutputFile();
|
||||
break;
|
||||
default:
|
||||
Console.WriteLine($"... sorry, '{selection.KeyChar}' isn't a valid choice.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* List all email addresses currently in the Student list
|
||||
* Preconditions: not yet
|
||||
* Inputs: no args
|
||||
* Outputs: void return
|
||||
* Postconditions: not yet
|
||||
*/
|
||||
private void ListAllEmailAddresses()
|
||||
{
|
||||
Console.WriteLine("*************************");
|
||||
for (int i = 0; i < students.Count; i++)
|
||||
{
|
||||
Console.WriteLine($"{i + 1}: {students[i].EmailAddress}");
|
||||
}
|
||||
Console.WriteLine("END of email list");
|
||||
}
|
||||
|
||||
/* Deletes a student record out of the in-memory student list
|
||||
* after asking "Are you sure you want to delete?"
|
||||
* The confirmation takes Y or y for yes, and
|
||||
* anything else will not delete the student.
|
||||
* Preconditions: not yet
|
||||
* Inputs: no args
|
||||
* Outputs: void return
|
||||
* Postconditions: not yet
|
||||
*/
|
||||
private void DeleteStudentRecord()
|
||||
{
|
||||
//show the user a list of possible deletions in concise format
|
||||
ListAllEmailAddresses();
|
||||
|
||||
Console.Write("Your selection: ");
|
||||
int recordToDelete = GetChoice(Console.ReadLine(), students.Count);
|
||||
|
||||
//adjust the record to delete to correctly index.
|
||||
//GetChoice returns -1 if choice is not valid, which is checked in the below ifcheck.
|
||||
recordToDelete -= 1;
|
||||
|
||||
//Insert a space to pretty up the formatting.
|
||||
Console.WriteLine();
|
||||
|
||||
// Check to see if recordToDelete is between 0 and <students.Count
|
||||
if (recordToDelete < 0 || recordToDelete > students.Count - 1)
|
||||
{
|
||||
Console.WriteLine("Sorry, you did not make a valid choice.");
|
||||
return;
|
||||
}
|
||||
|
||||
ConsoleKeyInfo confirmDelete = GetSelectionFromUser($"Are you sure you want to delete {students[recordToDelete].EmailAddress} [y/n]? ");
|
||||
Console.WriteLine();
|
||||
|
||||
switch (confirmDelete.KeyChar)
|
||||
{
|
||||
case 'Y':
|
||||
case 'y':
|
||||
students.RemoveAt(recordToDelete);
|
||||
|
||||
//Say something nice and make the user feel all warm and fuzzy
|
||||
Console.WriteLine("After delete, now the list is:");
|
||||
ListAllEmailAddresses();
|
||||
break;
|
||||
default:
|
||||
Console.WriteLine("Record NOT deleted.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Modify a student record.
|
||||
* Preconditions: not yet
|
||||
* Inputs: no args
|
||||
* Outputs: void return
|
||||
* Postconditions: not yet
|
||||
*
|
||||
* NOTE: There is no requirement to be able to modify a student's subtype,
|
||||
* i.e, an Undergrad need not be editable to become a GradStudent, or vice versa
|
||||
*/
|
||||
private void ModifyStudentRecord()
|
||||
{
|
||||
ListAllEmailAddresses();
|
||||
Console.Write("Your selection: ");
|
||||
int choice = GetChoice(Console.ReadLine(), students.Count);
|
||||
|
||||
//Decrement choice to properly index into the student list.
|
||||
choice -= 1;
|
||||
|
||||
//GetChoice returns -1 if choice is not valid.
|
||||
//So any negative choice "index" is not valid.
|
||||
if (choice < 0)
|
||||
{
|
||||
Console.WriteLine("... sorry, that's an invalid choice.");
|
||||
return;
|
||||
}
|
||||
|
||||
//The record is found. Show the record to the user.
|
||||
var studentToModify = students[choice];
|
||||
|
||||
//If this is a grad student, cast studentToModify
|
||||
//into GradStudent type.
|
||||
if (studentToModify is GradStudent)
|
||||
studentToModify = (GradStudent)studentToModify;
|
||||
else
|
||||
studentToModify = (Undergrad)studentToModify;
|
||||
|
||||
//Display a sub-menu for edit
|
||||
DisplayEditMenu(studentToModify);
|
||||
|
||||
// when done editing-
|
||||
// display new version of record
|
||||
Console.WriteLine("\nHere is the new record of that student after modification:");
|
||||
Console.Write(studentToModify);
|
||||
}
|
||||
|
||||
/* Modify student / Edit submenu
|
||||
* Preconditions: not yet
|
||||
* Inputs: Student
|
||||
* Outputs: void return
|
||||
* Postconditions: not yet
|
||||
*/
|
||||
private void DisplayEditMenu(Student studentToModify)
|
||||
{
|
||||
//Must be up here to check on While, below.
|
||||
ConsoleKeyInfo selection;
|
||||
|
||||
//Shows the edit menu until the choice is Q.
|
||||
do
|
||||
{
|
||||
Console.WriteLine(@"
|
||||
********************************
|
||||
******* Edit Student Menu ******
|
||||
********************************
|
||||
");
|
||||
//Display something to the user indicating what type of student this is.
|
||||
if (studentToModify is GradStudent)
|
||||
Console.Write("This is a Grad Student.");
|
||||
else
|
||||
Console.Write("This is an Undergrad Student.");
|
||||
|
||||
Console.Write(@"
|
||||
What data for this student would you like to change?
|
||||
[F]irst name: " + studentToModify.FirstName +
|
||||
"\n [L]ast name: " + studentToModify.LastName +
|
||||
"\n [G]PA: " + studentToModify.GradePtAvg +
|
||||
"\n [E]mail: " + studentToModify.EmailAddress
|
||||
);
|
||||
if (studentToModify is GradStudent)
|
||||
ShowGradStudentEditMenu((GradStudent)studentToModify);
|
||||
else
|
||||
ShowUndergradEditMenu((Undergrad)studentToModify);
|
||||
|
||||
Console.WriteLine(@" [Q]uit editing this student.");
|
||||
|
||||
// capture the user selection
|
||||
selection = GetSelectionFromUser();
|
||||
|
||||
//Add space after reading the key.
|
||||
Console.WriteLine();
|
||||
|
||||
switch (selection.KeyChar)
|
||||
{
|
||||
case 'F': //FirstName
|
||||
case 'f':
|
||||
Console.Write("Enter new first name: ");
|
||||
string newFirstName = Console.ReadLine();
|
||||
studentToModify.FirstName = newFirstName;
|
||||
break;
|
||||
case 'L': //LastName
|
||||
case 'l':
|
||||
Console.Write("Enter new last name: ");
|
||||
string newLastName = Console.ReadLine();
|
||||
studentToModify.LastName = newLastName;
|
||||
break;
|
||||
case 'G': //GPA
|
||||
case 'g':
|
||||
Console.Write("Enter new GPA between 0 and 4.0 inclusive: ");
|
||||
double newGPA = double.Parse(Console.ReadLine());
|
||||
studentToModify.GradePtAvg = newGPA;
|
||||
break;
|
||||
case 'E': //Email Address
|
||||
case 'e':
|
||||
Console.Write("Enter the new valid email address with @ symbol: ");
|
||||
string newEmailAddy = Console.ReadLine();
|
||||
//Check to see if another student has the desired email address.
|
||||
if (FindStudentRecord(newEmailAddy) == null)
|
||||
studentToModify.EmailAddress = newEmailAddy;
|
||||
else
|
||||
Console.WriteLine("Sorry, another student has that email. Try again.");
|
||||
break;
|
||||
//Take care of modifying gradstudents.
|
||||
case 'T': //Tuition credit
|
||||
case 't':
|
||||
if (studentToModify is GradStudent)
|
||||
ModifyGradStudent((GradStudent)studentToModify, 't');
|
||||
break;
|
||||
case 'A': //Faculty [A]dvisor
|
||||
case 'a':
|
||||
if (studentToModify is GradStudent)
|
||||
ModifyGradStudent((GradStudent)studentToModify, 'a');
|
||||
break;
|
||||
//Take care of modifying undergrad students.
|
||||
case 'Y': //YearRank
|
||||
case 'y':
|
||||
if (studentToModify is Undergrad)
|
||||
ModifyUndergrad((Undergrad)studentToModify, 'y');
|
||||
break;
|
||||
case 'D': //DegreeMajor
|
||||
case 'd':
|
||||
if (studentToModify is Undergrad)
|
||||
ModifyUndergrad((Undergrad)studentToModify, 'd');
|
||||
break;
|
||||
case 'Q': //Done editing student.
|
||||
case 'q':
|
||||
break;
|
||||
default: //Invalid selection
|
||||
Console.WriteLine("...Sorry, that was an invalid choice.");
|
||||
break;
|
||||
} //end switch
|
||||
} while (selection.KeyChar.ToString().ToUpper() != "Q"); //Check if the user is done editing.
|
||||
} // end DisplayEditMenu
|
||||
|
||||
/* Modify student
|
||||
* This function is for Grad Students.
|
||||
* Preconditions: not yet
|
||||
* Inputs: GradStudent, char choice as 'T' or 'A'
|
||||
* Outputs: void return
|
||||
* Postconditions: not yet
|
||||
*/
|
||||
private void ModifyGradStudent(GradStudent studentToModify, char choice)
|
||||
{
|
||||
switch (choice)
|
||||
{
|
||||
case 'T': //Modify the TuitionCredit
|
||||
case 't':
|
||||
Console.Write("Enter the amount of the tuition credit without the dollar sign: ");
|
||||
decimal newCredit = decimal.Parse(Console.ReadLine());
|
||||
studentToModify.TuitionCredit = newCredit;
|
||||
break;
|
||||
case 'A': //Modify the faculty advisor
|
||||
case 'a':
|
||||
Console.Write("Enter the name of the faculty advisor: ");
|
||||
studentToModify.FacultyAdvisor = Console.ReadLine();
|
||||
break;
|
||||
default: //We shouldn't get here, but if we do, display an error to the user.
|
||||
Console.WriteLine("**BUG**: ModifyGradStudent got called with an invalid selection. Please contact developer.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Modify student
|
||||
* This function is for Undergrad Students.
|
||||
* Preconditions: not yet
|
||||
* Inputs: Undergrad, choice as 'Y' or 'D'
|
||||
* Outputs: void return
|
||||
* Postconditions: not yet
|
||||
*/
|
||||
private void ModifyUndergrad(Undergrad studentToModify, char choice)
|
||||
{
|
||||
switch (choice)
|
||||
{
|
||||
//Modify the YearRank of the undergrad student.
|
||||
case 'Y':
|
||||
case 'y':
|
||||
YearRank rank;
|
||||
Console.Write("Enter the year in school as Freshman, Sophmore, Junior, or Senior: ");
|
||||
//If it's a valid rank, save to the student.
|
||||
if (Enum.TryParse(Console.ReadLine(), out rank))
|
||||
studentToModify.Rank = rank;
|
||||
else
|
||||
Console.WriteLine("Sorry, that was invalid year, please try again.");
|
||||
break;
|
||||
case 'D':
|
||||
case 'd':
|
||||
Console.Write("Enter the student's Degree Major: ");
|
||||
studentToModify.DegreeMajor = Console.ReadLine();
|
||||
break;
|
||||
default: //We shouldn't get here, but if we do, display an error to the user.
|
||||
Console.WriteLine("**BUG**: ModifyUndergrad got called with an invalid selection. Please contact developer.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Modify student / Edit submenu
|
||||
* This function is for Undergrad Students.
|
||||
* Preconditions: not yet
|
||||
* Inputs: Undergrad
|
||||
* Outputs: void return
|
||||
* Postconditions: not yet
|
||||
*/
|
||||
private void ShowUndergradEditMenu(Undergrad studentToModify)
|
||||
{
|
||||
Console.WriteLine(@"
|
||||
[Y]ear Rank: " + studentToModify.Rank +
|
||||
"\n [D]egree Major: " + studentToModify.DegreeMajor
|
||||
);
|
||||
}
|
||||
|
||||
/* Modify student / Edit submenu
|
||||
* This function is for Grad Students.
|
||||
* Preconditions: not yet
|
||||
* Inputs: GradStudent
|
||||
* Outputs: void return
|
||||
* Postconditions: not yet
|
||||
*/
|
||||
private void ShowGradStudentEditMenu(GradStudent studentToModify)
|
||||
{
|
||||
Console.WriteLine(@"
|
||||
[T]uition Credit: " + studentToModify.TuitionCredit +
|
||||
"\n [A]dvisor (Faculty): " + studentToModify.FacultyAdvisor
|
||||
);
|
||||
}
|
||||
|
||||
/* Gets user integer choice between 1 and maxChoiceNumber
|
||||
* Preconditions: not yet
|
||||
* Inputs: string choice, maxChoiceNumber
|
||||
* Outputs: integer or -1 if not a valid choice.
|
||||
* Postconditions: not yet
|
||||
*/
|
||||
private int GetChoice(string userChoice, int maxChoiceNumber)
|
||||
{
|
||||
int choice;
|
||||
|
||||
//Check if choice is an integer (as a string).
|
||||
//ref: microsoft
|
||||
if (int.TryParse(userChoice, out choice))
|
||||
{
|
||||
//If the choice is not between 0 and range, return -1.
|
||||
if (choice < 0 || choice > maxChoiceNumber)
|
||||
return -1;
|
||||
else
|
||||
return choice;
|
||||
}
|
||||
else //If the choice is not an integer, return -1.
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* searches the list collection for a student and either returns
|
||||
* a reference to the found student or null if not found.
|
||||
* Preconditions: not yet
|
||||
* Inputs: string email address
|
||||
* Outputs: Student or null
|
||||
* Postconditions: not yet
|
||||
*/
|
||||
private Student FindStudentRecord(string email)
|
||||
{
|
||||
//Iterate through each student type in the student list.
|
||||
foreach (var student in students)
|
||||
{
|
||||
//If the currently focused student's email address
|
||||
//is equal to the passed in email argument,
|
||||
//return the student.
|
||||
if (student.EmailAddress == email)
|
||||
{
|
||||
return student;
|
||||
}
|
||||
}
|
||||
|
||||
//Student not found, return null.
|
||||
return null;
|
||||
}
|
||||
|
||||
/* Add a student record.
|
||||
* Preconditions: not yet
|
||||
* Inputs: no args
|
||||
* Outputs: void return
|
||||
* Postconditions: not yet
|
||||
*/
|
||||
private void AddStudentRecord()
|
||||
{
|
||||
//First prompt for the email address as that is the key
|
||||
//discriminator between students in the database --
|
||||
//no two students may have the same email address.
|
||||
Console.Write("Desired email address: ");
|
||||
string email = Console.ReadLine();
|
||||
Student studentToAdd = FindStudentRecord(email);
|
||||
|
||||
// if the key (email address) does not already exist - add the student
|
||||
if (studentToAdd == null)
|
||||
{
|
||||
Console.Write("First Name:");
|
||||
string first = Console.ReadLine();
|
||||
Console.Write("Last Name: ");
|
||||
string last = Console.ReadLine();
|
||||
Console.Write("GPA: ");
|
||||
double gpa = double.Parse(Console.ReadLine());
|
||||
|
||||
//Prompt user for graduate student or not
|
||||
//to add the correct type of student to the list.
|
||||
switch (GetSelectionFromUser("Graduate student[y/n]? ").KeyChar)
|
||||
{
|
||||
case 'Y':
|
||||
case 'y':
|
||||
//Grad student
|
||||
Console.Write("\nTotal amount of tuition credit: ");
|
||||
decimal credit = decimal.Parse(Console.ReadLine());
|
||||
Console.Write("Name of faculty advisor: ");
|
||||
string advisor = Console.ReadLine();
|
||||
|
||||
//now make a GradStudent and add to the list
|
||||
students.Add(new GradStudent(first, last, gpa, email, credit, advisor));
|
||||
break;
|
||||
default:
|
||||
//undergrad student
|
||||
//Tell the user how to enter the year as it is an enum.
|
||||
Console.Write("\nEnter the year in school as Freshman, Sophmore, Junior, or Senior: ");
|
||||
YearRank rank;
|
||||
Enum.TryParse<YearRank>(Console.ReadLine(), out rank);
|
||||
Console.Write("What is the student's major: ");
|
||||
string degree = Console.ReadLine();
|
||||
|
||||
// make a new undergrad stu with the gathered info and insert in the list
|
||||
students.Add(new Undergrad(first, last, gpa, email, rank, degree));
|
||||
break;
|
||||
}
|
||||
}
|
||||
else //A student with that email address was found
|
||||
{
|
||||
//Another student with that email address was found.
|
||||
Console.WriteLine("Sorry, another student with that email address is already in the database.");
|
||||
}
|
||||
}
|
||||
|
||||
/* Prints all the student records in the list.
|
||||
* Preconditions: not yet
|
||||
* Inputs: no args
|
||||
* Outputs: void return
|
||||
* Postconditions: not yet
|
||||
*/
|
||||
private void PrintAllRecords()
|
||||
{
|
||||
//For each type of student in the list,
|
||||
foreach (var student in students)
|
||||
{
|
||||
//call the type of student object's ToString() overridden method.
|
||||
Console.WriteLine(student);
|
||||
}
|
||||
}
|
||||
|
||||
/* Save data to the output file.
|
||||
* Preconditions: not yet
|
||||
* Inputs: no args
|
||||
* Outputs: void return
|
||||
* Postconditions: not yet
|
||||
*/
|
||||
private void SaveDataToOutputFile()
|
||||
{
|
||||
// create a file object to attach to the actual file on disk
|
||||
StreamWriter outfile = new StreamWriter(STUDENT_DB_DATA_FILE);
|
||||
|
||||
//Debugging
|
||||
//StreamWriter outfile = new StreamWriter("OUTPUT.txt");
|
||||
|
||||
// use it - write the contents of the students collection to the file
|
||||
for (int i = 0; i < students.Count; i++)
|
||||
{
|
||||
//There is no CRLF at the end of a student from this code
|
||||
outfile.Write(students[i].ToStringForOutputFile());
|
||||
}
|
||||
|
||||
//release the resource
|
||||
outfile.Close();
|
||||
}
|
||||
|
||||
/* Exits the application.
|
||||
* this method also saves all the current changes that have been made to the list.
|
||||
* Preconditions: not yet
|
||||
* Inputs: no args
|
||||
* Outputs: void return
|
||||
* Postconditions: not yet
|
||||
*/
|
||||
private void ExitTheDatabaseApp()
|
||||
{
|
||||
//salutation
|
||||
Console.WriteLine("Thank you for using the Student Database Application.\n" +
|
||||
"Your work has been saved. Good bye!");
|
||||
|
||||
//save the data.
|
||||
SaveDataToOutputFile();
|
||||
|
||||
// zero typically means no errors- normal exit
|
||||
Environment.Exit(0);
|
||||
}
|
||||
|
||||
/* Get the user selected operation character
|
||||
* Preconditions: not yet
|
||||
* Inputs: string prompt (default "User Selection: ")
|
||||
* Outputs: ConsoleKeyInfo (single key)
|
||||
* Postconditions: not yet
|
||||
*/
|
||||
private ConsoleKeyInfo GetSelectionFromUser(string prompt = "User selection: ")
|
||||
{
|
||||
Console.Write(prompt);
|
||||
return Console.ReadKey();
|
||||
}
|
||||
|
||||
/* Display the main menu of the application.
|
||||
* This is the main user interface of the program.
|
||||
* Preconditions: not yet
|
||||
* Inputs: no args
|
||||
* Outputs: void return
|
||||
* Postconditions: not yet
|
||||
*/
|
||||
private void DisplayMainMenu()
|
||||
{
|
||||
Console.WriteLine(@"
|
||||
********************************
|
||||
***** Student Database App *****
|
||||
********************************
|
||||
[P]rint all records
|
||||
[F]ind a student record
|
||||
[L]ist all email addresses
|
||||
[A]dd a new student record
|
||||
[D]elete a student record
|
||||
[M]odify a student record
|
||||
[N]otes utility
|
||||
[I]nsert test driver student data into DB
|
||||
[S]ave the records and continue
|
||||
[Q]uit database app (includes save)
|
||||
");
|
||||
}
|
||||
|
||||
/* Read in the input file data.
|
||||
* make student objects from the read in data
|
||||
* and store them in a semi-persistent data structure.
|
||||
* Preconditions: not yet
|
||||
* Inputs: no args
|
||||
* Outputs: void return
|
||||
* Postconditions: not yet
|
||||
*/
|
||||
private void ReadDataFromInputFile()
|
||||
{
|
||||
StreamReader infile = null;
|
||||
|
||||
//The student database file exists, read it.
|
||||
if (File.Exists(STUDENT_DB_DATA_FILE))
|
||||
{
|
||||
infile = new StreamReader(STUDENT_DB_DATA_FILE);
|
||||
}
|
||||
else //The file does not yet exist, do not load data.
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string studentType = string.Empty;
|
||||
|
||||
//Boilerplate code to read for a file.
|
||||
//Read the file line by line, until the end of the file.
|
||||
//Once infile.readline() reaches EOF, str becomes NULL.
|
||||
while ((studentType = infile.ReadLine()) != null)
|
||||
{
|
||||
string firstName = infile.ReadLine();
|
||||
string lastName = infile.ReadLine();
|
||||
double grades = double.Parse(infile.ReadLine());
|
||||
string email = infile.ReadLine();
|
||||
|
||||
if (studentType == UNDERGRAD)
|
||||
{
|
||||
//reading into an enum type.
|
||||
//chapter 7, book
|
||||
YearRank rank;
|
||||
Enum.TryParse<YearRank>(infile.ReadLine(), out rank);
|
||||
|
||||
string degree = infile.ReadLine();
|
||||
students.Add(new Undergrad(firstName, lastName, grades,
|
||||
email, rank, degree));
|
||||
|
||||
}
|
||||
else if (studentType == GRADSTUDENT)
|
||||
{
|
||||
decimal credit = decimal.Parse(infile.ReadLine());
|
||||
string advisor = infile.ReadLine();
|
||||
|
||||
//The reason we can put a grad student in a list of students
|
||||
//is because a GradStudent IS A KIND OF student.
|
||||
students.Add(new GradStudent(firstName, lastName, grades,
|
||||
email, credit, advisor));
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"ERROR: Unsupported student type: {studentType}");
|
||||
}
|
||||
|
||||
//Now that we have variables for a student,
|
||||
//Create a student object and add it to our list.
|
||||
//new Student is an anonymous object - it doesn't have a name.
|
||||
|
||||
//now that all data for an obj has been read in - make the object and insert in the list
|
||||
//No longer need this code because of the above switch statement.
|
||||
//students.Add(new Student(firstName, lastName, grades, email));
|
||||
}
|
||||
|
||||
//Release the resource.
|
||||
infile.Close();
|
||||
}
|
||||
|
||||
/* Inserts test students into the student list
|
||||
* if those test students are not already present.
|
||||
* Preconditions: not yet
|
||||
* Inputs: no args
|
||||
* Outputs: void return
|
||||
* Postconditions: not yet
|
||||
*/
|
||||
private void InsertTestStudentsIntoDB()
|
||||
{
|
||||
List<Student> testStudents = new List<Student>();
|
||||
|
||||
//The test driver inserts a list of 8 students
|
||||
//into the Student list, if they are not already present.
|
||||
//First setup the Grad Students -- Pro Wrestlers.
|
||||
GradStudent gs1 = new GradStudent("Hulk", "Hogan", 4.0, "hhogan@uw.edu", (decimal)45000.99, "Dr. Hulkamaiac");
|
||||
testStudents.Add(gs1);
|
||||
|
||||
GradStudent gs2 = new GradStudent("Randy", "Savage", 2.8, "rsavage@uw.edu", (decimal)42350.99, "Dr. Hurtzalot");
|
||||
testStudents.Add(gs2);
|
||||
|
||||
GradStudent gs3 = new GradStudent("Rick", "Flair", 1.2, "rflair@uw.edu", (decimal)23000.99, "Dr. Dirtyplayer");
|
||||
testStudents.Add(gs3);
|
||||
|
||||
GradStudent gs4 = new GradStudent("Bret", "Hart", 1.2, "bhart@uw.edu", (decimal)32975.98, "Dr. Hart");
|
||||
testStudents.Add(gs4);
|
||||
|
||||
//Now setup the Undergrad Students -- Football players with hilarious degrees.
|
||||
Undergrad ug1 = new Undergrad("Tom", "Brady", 3.4, "tbrady@uw.edu", YearRank.Freshman, "BS-Deflategate");
|
||||
testStudents.Add(ug1);
|
||||
|
||||
Undergrad ug2 = new Undergrad("Michael", "Vick", 2.5, "mvick@uw.edu", YearRank.Sophmore, "BS-Dogfighting");
|
||||
testStudents.Add(ug2);
|
||||
|
||||
Undergrad ug3 = new Undergrad("Russel", "Wilson", 1.2, "rwilson@uw.edu", YearRank.Junior, "BS-PaidTooMuch");
|
||||
testStudents.Add(ug3);
|
||||
|
||||
Undergrad ug4 = new Undergrad("Joe", "Montana", 3.9, "jmontana@uw.edu", YearRank.Senior, "BS-BeingTheMan");
|
||||
testStudents.Add(ug4);
|
||||
|
||||
//Now for each of our test students in the list,
|
||||
//If the test student is NOT already in the database, add them.
|
||||
foreach (var student in testStudents)
|
||||
{
|
||||
if (FindStudentRecord(student.EmailAddress) == null)
|
||||
students.Add(student);
|
||||
}
|
||||
|
||||
Console.WriteLine("Test student data has been added if it was not present.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
109
StudentDB/Student.cs
Normal file
109
StudentDB/Student.cs
Normal file
@ -0,0 +1,109 @@
|
||||
/* This is the Student class. Undergrad and GradStudent "is a type of" student.
|
||||
* See StuDB for full change history.
|
||||
*
|
||||
* Change History
|
||||
* Date Developer Description
|
||||
* 2020-02-13 marqusa In-class work on the program, Chuck Costarella
|
||||
* through 25
|
||||
*/
|
||||
namespace StudentDB
|
||||
{
|
||||
internal class Student
|
||||
{
|
||||
// auto implemented props
|
||||
public string FirstName { get; set; }
|
||||
|
||||
public string LastName { get; set; }
|
||||
|
||||
// instance variable
|
||||
private double gradePtAvg;
|
||||
private string emailAddress;
|
||||
|
||||
// 1 - allocate storage for the object
|
||||
// 2 - init all vars to reasonable defaults
|
||||
//If first is not called with a variable, it has a default.
|
||||
//default values have to be piled up on the right side of the constructor
|
||||
public Student(string first,
|
||||
string last = "Last name",
|
||||
double grades = 0.7,
|
||||
string email = "newstudent@uw.edu")
|
||||
{
|
||||
FirstName = first;
|
||||
LastName = last;
|
||||
GradePtAvg = grades;
|
||||
EmailAddress = email;
|
||||
}
|
||||
|
||||
//Public variable to set the private emailAddress instance variable.
|
||||
public string EmailAddress
|
||||
{
|
||||
get
|
||||
{
|
||||
return emailAddress;
|
||||
}
|
||||
set
|
||||
{
|
||||
// TODO: Add more "rules" to what exactly an email can be.
|
||||
// -- ABANDONED --
|
||||
if(value.Contains("@"))
|
||||
{
|
||||
emailAddress = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Public variable to set the private gradePtAvg instance variable.
|
||||
public double GradePtAvg
|
||||
{
|
||||
get
|
||||
{
|
||||
return gradePtAvg;
|
||||
}
|
||||
set
|
||||
{
|
||||
// check if GPA is in valid range
|
||||
if (0.0 <= value && value <= 4.0)
|
||||
{
|
||||
gradePtAvg = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// specifically formatted for the output/input file
|
||||
// no labels on any of the data
|
||||
// The virtual keyword allows for the method to be overriden.
|
||||
public virtual string ToStringForOutputFile()
|
||||
{
|
||||
// mkae an empty string
|
||||
string str = string.Empty;
|
||||
|
||||
// build up the string with data we want to print
|
||||
// note this finishes a student output with a CRLF
|
||||
str += $"{FirstName}\n";
|
||||
str += $"{LastName}\n";
|
||||
str += $"{GradePtAvg}\n";
|
||||
str += $"{EmailAddress}\n";
|
||||
|
||||
// return the string
|
||||
return str;
|
||||
}
|
||||
|
||||
//Data to go to the user
|
||||
//Overrides the ToString method found in "Object".
|
||||
public override string ToString()
|
||||
{
|
||||
// mkae an empty string
|
||||
string str = string.Empty;
|
||||
|
||||
// build up the string with data that you want to print from the object
|
||||
str += "***************************\n";
|
||||
str += $"First: {FirstName}\n";
|
||||
str += $" Last: {LastName}\n";
|
||||
str += $" GPA: {GradePtAvg:0.0}\n";
|
||||
str += $"Email: {EmailAddress}\n";
|
||||
|
||||
// return the string
|
||||
return str;
|
||||
}
|
||||
}
|
||||
}
|
57
StudentDB/StudentDB.csproj
Normal file
57
StudentDB/StudentDB.csproj
Normal file
@ -0,0 +1,57 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{767514EE-9C14-4590-8E4F-BE06473A5C03}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>StudentDB</RootNamespace>
|
||||
<AssemblyName>StudentDB</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="GradStudent.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="StuDB.cs" />
|
||||
<Compile Include="Student.cs" />
|
||||
<Compile Include="Undergrad.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
25
StudentDB/StudentDB.sln
Normal file
25
StudentDB/StudentDB.sln
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.29613.14
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StudentDB", "StudentDB.csproj", "{767514EE-9C14-4590-8E4F-BE06473A5C03}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{767514EE-9C14-4590-8E4F-BE06473A5C03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{767514EE-9C14-4590-8E4F-BE06473A5C03}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{767514EE-9C14-4590-8E4F-BE06473A5C03}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{767514EE-9C14-4590-8E4F-BE06473A5C03}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {D8208617-6FE0-4787-A651-E0832AA80E29}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
1064
StudentDB/Testing Run.txt
Normal file
1064
StudentDB/Testing Run.txt
Normal file
File diff suppressed because it is too large
Load Diff
62
StudentDB/Undergrad.cs
Normal file
62
StudentDB/Undergrad.cs
Normal file
@ -0,0 +1,62 @@
|
||||
/* This is the Undergrad class which inherits from Student class.
|
||||
* See StuDB for full change history.
|
||||
* It adds YearRank enum type and MajorDegree data to a student.
|
||||
*
|
||||
* Change History
|
||||
* Date Developer Description
|
||||
* 2020-02-13 marqusa In-class work on the program, Chuck Costarella
|
||||
* through 25
|
||||
* 2020-02-26 marqusa Fix the output error when writing to output file in wrong order in undergrad
|
||||
*
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StudentDB
|
||||
{
|
||||
public enum YearRank
|
||||
{
|
||||
Freshman = 1,
|
||||
Sophmore = 2,
|
||||
Junior = 3,
|
||||
Senior = 4
|
||||
}
|
||||
|
||||
// The way we indicate inheritance is using a colon, then indicate the base class.
|
||||
class Undergrad : Student
|
||||
{
|
||||
public YearRank Rank { get; set; }
|
||||
|
||||
public string DegreeMajor { get; set; }
|
||||
|
||||
//Must have at least the same constructor as the parent.
|
||||
//use :base() to call the parent constructor and supply the arguments
|
||||
//that the parent class needs.
|
||||
public Undergrad(string first, string last, double gpa, string email, YearRank rank, string degree)
|
||||
: base(first, last, gpa, email)
|
||||
{
|
||||
Rank = rank;
|
||||
DegreeMajor = degree;
|
||||
}
|
||||
|
||||
// conversion to a lamda expression - mechanism of functional programming.
|
||||
// lamda operator is "=>" and reads "goes to"
|
||||
// C# calls this an "expression-bodied method"
|
||||
// This is only used for one-liners or very simple things.
|
||||
public override string ToString() => base.ToString() + $"Year: {Rank}\nDegree: {DegreeMajor}\n";
|
||||
|
||||
public override string ToStringForOutputFile()
|
||||
{
|
||||
string str = StuDB.UNDERGRAD + "\n" + base.ToStringForOutputFile();
|
||||
|
||||
// append the "local information"
|
||||
str += $"{Rank}\n";
|
||||
str += $"{DegreeMajor}\n";
|
||||
|
||||
return str;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user