Shaylee  Lemke

Shaylee Lemke

1597432860

Modeling Ticket to Ride in C# Part 4: Player Claiming Routes

Our game is set up and ready to play! But now we face the challenge of needing to model how our players would play an actual game.

We can start solving that challenge by determining how players will keep track of the routes they want to claim, the color of the cards they need, and how they can actually make those claims. Let’s get going!

I think I can I think I can I think I can I think I can! Photo by Michał Parzuchowski / Unsplash

The Sample Project

You might want to check out the sample repository over on GitHub to follow along with this post.

exceptionnotfound/TicketToRideModelingPractice

The Player’s Choices

Let’s remind ourselves what a player can do when it is their turn.

I swear, if you take that Nashville to Atlanta route again… DAMMIT KEVIN!

Players have three choices:

  1. The Player can claim an existing route. But in order for them to do this, they have to know what routes they want; they should not just claim random routes, because that won’t help them win.
  2. The Player can draw new destination cards. But if they don’t complete these cards, they count against the player’s point total, so they player should not just draw these at any time.
  3. The Player can draw new train cards. But do they want to draw from the shown cards pile, or off the deck? To make this decision, they need to know what colors they want.

But there’s also one more major feature we need in order to implement these three scenarios: we need to know what routes and colors the Player wants at any given time! We’re going to call this Scenario 0.

We’re going to tackle each of these scenarios separately. In this post, we will deal with Scenarios 0 and 1. The next post will deal with Scenarios 2 and 3.

The Basic Player Class

We first need a Player class. This object will have several properties, and all of them will be used in this post.

public class Player
{
    //The player's name
    public string Name { get; set; }

    //The player's current collection of destination cards.
    public List<DestinationCard> DestinationCards { get; set; } = new List<DestinationCard>();

    //The routes the player wants to claim at any given time.
    public List<BoardRoute> TargetedRoutes { get; set; } = new List<BoardRoute>();

    //All the cities this Player has already connected.
    public List<City> ConnectedCities { get; set; } = new List<City>();

    //The player's color (e.g. red, blue, black, green, or yellow)
    public PlayerColor Color { get; set; }

    //The Player's current collection of train cards.
    public List<TrainCard> Hand { get; set; } = new List<TrainCard>();

    //When one player has < 2 train cars the remaining, the final turn begins.
    public int RemainingTrainCars { get; set; } = 48;

    //The train card colors this Player wants to draw.
    public List<TrainColor> DesiredColors { get; set; } = new List<TrainColor>();

    //A reference to the game board
    public Board Board { get; set; }

    public void TakeTurn()
    {
        //...Implementation in this post and the next
    }
}

Scenario 0: Finding Targeted Routes

In order for the players to know what routes they’d like to claim, we are going to make them “target” these routes by storing a collection of them. Not surprisingly, this is the TargetedRoutes property in the base Player object.

Let’s pretend our player starts the game with two destination cards: Duluth to Houston, and Winnipeg to New Orleans.

Can you tell me how to get, how to get to Sesame Street?

The ideal routes algorithm will find the following routes for these destination cards.

Duluth -> Omaha -> Kansas City -> Oklahoma City -> Dallas -> Houston

and

Winnipeg -> Duluth -> Omaha -> Kansas City -> Oklahoma City -> Little Rock -> New Orleans

Those two routes share a lot of the same route segments. Therefore, it is more important to the player to claim the ones that are shared amongst different destination card ideal routes, rather than routes that are only used for one card. We will need to make sure the “common” route segments are claimed first, lest another player claim them and our destination cards get more difficult to complete.

(IMPORTANT NOTE: There are many different ways we could say what is “important” to the player; claiming common routes is just one of them. For example, we could say that access to the cities is more important than common routes, and make the Player claim a route leading into the origin and destination cities before worrying about how to connect them. One of the reasons why Ticket to Ride is such a fun game is that there are multiple ways to assess the core problem of connecting city A to city B.)

To accomplish all this, let’s create a CalculateTargetedRoutes() method in the Player object that accepts a Destination Card and returns the ideal routes for that card:

public class Player
{
    //...Properties

    public List<BoardRoute> CalculateTargetedRoutes(DestinationCard card)
    { }
}

#modeling practice #c# #csharp #programming-c

What is GEEK

Buddha Community

Modeling Ticket to Ride in C# Part 4: Player Claiming Routes
Shaylee  Lemke

Shaylee Lemke

1597432860

Modeling Ticket to Ride in C# Part 4: Player Claiming Routes

Our game is set up and ready to play! But now we face the challenge of needing to model how our players would play an actual game.

We can start solving that challenge by determining how players will keep track of the routes they want to claim, the color of the cards they need, and how they can actually make those claims. Let’s get going!

I think I can I think I can I think I can I think I can! Photo by Michał Parzuchowski / Unsplash

The Sample Project

You might want to check out the sample repository over on GitHub to follow along with this post.

exceptionnotfound/TicketToRideModelingPractice

The Player’s Choices

Let’s remind ourselves what a player can do when it is their turn.

I swear, if you take that Nashville to Atlanta route again… DAMMIT KEVIN!

Players have three choices:

  1. The Player can claim an existing route. But in order for them to do this, they have to know what routes they want; they should not just claim random routes, because that won’t help them win.
  2. The Player can draw new destination cards. But if they don’t complete these cards, they count against the player’s point total, so they player should not just draw these at any time.
  3. The Player can draw new train cards. But do they want to draw from the shown cards pile, or off the deck? To make this decision, they need to know what colors they want.

But there’s also one more major feature we need in order to implement these three scenarios: we need to know what routes and colors the Player wants at any given time! We’re going to call this Scenario 0.

We’re going to tackle each of these scenarios separately. In this post, we will deal with Scenarios 0 and 1. The next post will deal with Scenarios 2 and 3.

The Basic Player Class

We first need a Player class. This object will have several properties, and all of them will be used in this post.

public class Player
{
    //The player's name
    public string Name { get; set; }

    //The player's current collection of destination cards.
    public List<DestinationCard> DestinationCards { get; set; } = new List<DestinationCard>();

    //The routes the player wants to claim at any given time.
    public List<BoardRoute> TargetedRoutes { get; set; } = new List<BoardRoute>();

    //All the cities this Player has already connected.
    public List<City> ConnectedCities { get; set; } = new List<City>();

    //The player's color (e.g. red, blue, black, green, or yellow)
    public PlayerColor Color { get; set; }

    //The Player's current collection of train cards.
    public List<TrainCard> Hand { get; set; } = new List<TrainCard>();

    //When one player has < 2 train cars the remaining, the final turn begins.
    public int RemainingTrainCars { get; set; } = 48;

    //The train card colors this Player wants to draw.
    public List<TrainColor> DesiredColors { get; set; } = new List<TrainColor>();

    //A reference to the game board
    public Board Board { get; set; }

    public void TakeTurn()
    {
        //...Implementation in this post and the next
    }
}

Scenario 0: Finding Targeted Routes

In order for the players to know what routes they’d like to claim, we are going to make them “target” these routes by storing a collection of them. Not surprisingly, this is the TargetedRoutes property in the base Player object.

Let’s pretend our player starts the game with two destination cards: Duluth to Houston, and Winnipeg to New Orleans.

Can you tell me how to get, how to get to Sesame Street?

The ideal routes algorithm will find the following routes for these destination cards.

Duluth -> Omaha -> Kansas City -> Oklahoma City -> Dallas -> Houston

and

Winnipeg -> Duluth -> Omaha -> Kansas City -> Oklahoma City -> Little Rock -> New Orleans

Those two routes share a lot of the same route segments. Therefore, it is more important to the player to claim the ones that are shared amongst different destination card ideal routes, rather than routes that are only used for one card. We will need to make sure the “common” route segments are claimed first, lest another player claim them and our destination cards get more difficult to complete.

(IMPORTANT NOTE: There are many different ways we could say what is “important” to the player; claiming common routes is just one of them. For example, we could say that access to the cities is more important than common routes, and make the Player claim a route leading into the origin and destination cities before worrying about how to connect them. One of the reasons why Ticket to Ride is such a fun game is that there are multiple ways to assess the core problem of connecting city A to city B.)

To accomplish all this, let’s create a CalculateTargetedRoutes() method in the Player object that accepts a Destination Card and returns the ideal routes for that card:

public class Player
{
    //...Properties

    public List<BoardRoute> CalculateTargetedRoutes(DestinationCard card)
    { }
}

#modeling practice #c# #csharp #programming-c

Shaylee  Lemke

Shaylee Lemke

1597522860

Modeling Ticket to Ride in C# Part 5: Player Drawing Cards

Our players have the ability to claim routes and determine which ones they want, but they cannot yet draw cards efficiently. In this post, we will make them have the ability to both draw new destination cards when they need them, and draw new train cards according to their desired colors.

Not THAT kind of drawing! Photo by Neven Krcmarek / Unsplash

The Sample Project

As always with my code-heavy posts, there’s a sample project on GitHub that you can use to follow along with this one. Check it out!

exceptionnotfound/TicketToRideModelingPractice

Drawing Destination Cards

In a real game of Ticket to Ride, you can draw new destination cards at any time.

But drawing new destination cards is most commonly done when at least one of the player’s current destination cards is completed. Newer players will most likely wait until all their current cards are either completed or impossible to finish.

So, our players will draw destination cards under the following circumstances:

  1. All their current destination cards are either complete or impossible to finish AND
  2. They currently have 5 or less destination cards already.

The second condition is to prevent the game from running out of destination cards.

We know from calculating the targeted routes that if no targeted routes are found, then the destination cards the player already has are completed or not completable. So, all we do is instruct our player that, if there are no targeted routes for him/her, they should draw destination cards.

public class Player
{
    //...Properties and Other Methods
    public void TakeTurn()
    {
        CalculateTargetedRoutes();

        //The calculation for Desired Routes only returned routes 
        //that can still be claimed.
        //If there are no desired routes, then all routes 
        //the player wants are already claimed
        //(whether by this player or someone else).
        //Therefore, if there are no desired routes, draw new destination cards
        if (!TargetedRoutes.Any())
        {
            if (!Board.DestinationCards.Any())
            {
                Console.WriteLine("No destination cards remain! " 
                                  + Name + " must do something else!");
            }
            else if (DestinationCards.Count < 5)
            {
                DrawDestinationCards(); //This method is implemented later
                                        //in this post.
                return;
            }
        }
    }
}

But exactly how does the player draw new destination cards?

The rules of Ticket to Ride state that when a player does this, they will get three destination cards. They must keep one of them, but they can keep as many as they like.

For our simulation, we’re going to say that the player will only ever keep one of the three destination cards they are dealt, and will return the other two to the pile. The question is: which one?

Some of the criteria here are obvious. For example, if the player is lucky and draws a destination card they have already completed, obviously they’ll keep that one because it is essentially free points. But in order to check if the route is already connected, we’ll need several new methods in the BoardRouteCollection class.

Modifications to BoardRouteCollection

The first new method we need is very similar to one we have already written: we need a variation of the GetConnectedCities method that only returns cities that are connected by a given player. We also need a new method to check for a direct route between two cities.

public List<CityLength> GetConnectingCitiesForPlayer(City origin, PlayerColor color)
{
    var destinations = Routes.Where(x => x.Origin == origin 
                                         && x.IsOccupied 
                                         && x.OccupyingPlayerColor == color)
                             .Select(x => new CityLength() 
                             { 
                                 City = x.Destination, 
                                 Length = x.Length 
                             })
                             .ToList();

    var origins = Routes.Where(x => x.Destination == origin
                                    && x.IsOccupied 
                                    && x.OccupyingPlayerColor == color)
                        .Select(x => new CityLength() 
                        { 
                            City = x.Origin, 
                            Length = x.Length 
                        })
                        .ToList();

    destinations.AddRange(origins);
    return destinations.Distinct().OrderBy(x => x.Length).ToList();
}

public BoardRoute GetDirectRouteForPlayer(City origin, 
                                          City destination, 
                                          PlayerColor color)
{
    var route = Routes.Where(x => (x.Origin == origin 
                                   && x.Destination == destination 
                                   && x.IsOccupied 
                                   && x.OccupyingPlayerColor == color)
                               || (x.Origin == destination 
                                   && x.Destination == origin 
                                   && x.IsOccupied
                                   && x.OccupyingPlayerColor == color))
                        .FirstOrDefault();

    return route;
}

This pattern should look familiar, as we did something very close to this to find the ideal routes back in Part 3.

We also need a brand new method that uses the new GetConnectingCitiesForPlayer() and GetDirectRouteForPlayer() methods to see if two cities are connected by a given player. We call that method IsAlreadyConnected().

#modeling practice #c# #programming-c #csharp

Shaylee  Lemke

Shaylee Lemke

1597343640

Modeling Ticket to Ride in C# Part 3: Finding Ideal Routes

With our rules known and our setup complete, we now need to tackle a difficult problem in solving this game: how do we determine the ideal route between two cities?

The Sample Project

As always, there is a sample project on GitHub that has the code we will use here. Check it out!

exceptionnotfound/TicketToRideModelingPractice

Finding Ideal Routes

Let’s imagine that we want to find the best route between San Francisco and Nashville. Both these locations are marked as 1 on the map below.

To start with, let’s determine all the destinations we can reach from each of these cities. From San Francisco, we can reach Portland, Salt Lake City, and Los Angeles. From Nashville, we can reach St. Louis, Pittsburgh, Raleigh, Atlanta, and Little Rock. The “second-order” destinations look like this:

The idea is to continue doing this (i.e. looking at all destinations of all connected cities) until one or more cities show up on both sides.

Continuing this, the “third-order” destinations (i.e. every city connected to each of the second-order cities) would look like this:

Now you might be thinking, “great! On the next order, we will have overlapping cities, and as such can find the connecting routes!” And you’d be right. From the overlapping cities we can isolate routes between San Francisco and Nashville.

Here are all the routes this “naive” algorithm would find:

San Francisco -> Salt Lake City -> Denver -> Kansas City -> Saint Louis -> Nashville (16 spaces)

San Francisco -> Los Angeles -> El Paso -> Dallas -> Little Rock -> Nashville (18 spaces)

San Francisco -> Los Angeles -> El Paso -> Oklahoma City -> Little Rock -> Nashville (19 spaces)

However, we know that these routes are not created equal. The first of these will be easiest to claim because the total length of that route is the smallest of the potential routes. Therefore, the “ideal” route will go through Denver, Kansas City, and Saint Louis.

This kind of algorithm will work perfectly fine if no one has claimed any routes yet. But what if some routes are already claimed?

Finding Best-Possible Routes

Let’s imagine that the game is already well underway, and some routes have already been claimed.

We’re going to try to connect Calgary (top-left of the board, near the number 20) to Denver (middle-left of the board). Note that several routes, including the most direct one, are already claimed by other players (specifically Calgary -> Helena, Helena -> Denver, Helena -> Omaha, and both Duluth -> Omaha routes)

We would prefer to take the routes Calgary -> Helena -> Denver, because that takes the least number of cards and the least number of turns. But that’s impossible now, because those routes are both claimed.

So if our first-order cities are Calgary and Denver, here’s our second order cities, ignoring routes that are already claimed.

From Calgary, our second-order cities are Vancouver, Seattle, and Winnipeg. From Denver, our second-order cities are Salt Lake City, Omaha, Kansas City, Oklahoma City, Santa Fe, and Phoenix.

If we continue this, the algorithm will find the following paths:

Calgary -> Seattle -> Portland -> Salt Lake City -> Denver (14 spaces)

Calgary -> Seattle -> Helena -> Salt Lake City -> Denver (16 spaces)

Calgary -> Winnipeg -> Helena -> Salt Lake City -> Denver (16 spaces)

All these routes will take the same number of turns (4) to claim, However, we know that the first option is the best, because it takes the least amount of trains to claim those routes.

Here’s the secret: the algorithm for both ideal routes and best possible routes is actually the same algorithm! The only difference is that for best-possible routes, the routes which have already been claimed are not even considered. It is like they do not exist in that case.

In short, we expand ever outward from both the origin and destination cities, until the list of cities we can reach from both sides (origin and destination) contains the same city. If there are many of these, we take the one with the least number of total spaces.

With all this in mind, let’s start making this algorithm! Be warned, though: this implementation contains healthy doses of recursion.

#modeling practice #c# #programming-c #csharp

Ari  Bogisich

Ari Bogisich

1590244140

Create a Real Estate Management System Project In C# [ Part 4 ]

C# Real Estate Management Project Step by Step With MySQL Database - Part 4

#c #c# #c++ #programming-c

Tamale  Moses

Tamale Moses

1624240146

How to Run C/C++ in Sublime Text?

C and C++ are the most powerful programming language in the world. Most of the super fast and complex libraries and algorithms are written in C or C++. Most powerful Kernel programs are also written in C. So, there is no way to skip it.

In programming competitions, most programmers prefer to write code in C or C++. Tourist is considered the worlds top programming contestant of all ages who write code in C++.

During programming competitions, programmers prefer to use a lightweight editor to focus on coding and algorithm designing. VimSublime Text, and Notepad++ are the most common editors for us. Apart from the competition, many software developers and professionals love to use Sublime Text just because of its flexibility.

I have discussed the steps we need to complete in this blog post before running a C/C++ code in Sublime Text. We will take the inputs from an input file and print outputs to an output file without using freopen file related functions in C/C++.

#cpp #c #c-programming #sublimetext #c++ #c/c++