The most important aspects of Gin Rummy are making melds, reducing the point value of your hand, and knocking as quickly as possible. A meld is a combination of cards with matching face values or a run of sequential cards in the same suit, both of which must include at least three cards. Any cards in a meld are worth zero points, which leads to the next important facet. You want to reduce the point value of your hand as much as possible in case another player ends the game first, as they will get the point value of your hand added to their total. You also need to be below a certain total point value to knock. Knocking is when a player ends the current round of a game after their total hand value has gone low enough, and they then see if they have the lowest value and how many points they get from other players. There are other complexities involved in Gin, but those are essentially the key points.
For the second assignment of my Artificial Opponents programming course, we have to make an AI to play Gin. Some of the added complexities of the game are picking cards to discard, watching if the opponent takes the discarded card, watching what they discard, and monitoring what cards are actually still available in the game. The great thing about programming an AI to play this game is computers are exceptionally good at tracking all of this data and much better than the average human. You can know exactly which cards are still left in the deck based on your hand, the discard, what the other player has taken from the discard, and the combination of cards in the deck. This is how you form a strategy to play the game and ultimately win as often as possible.
I want to keep my Gin playing AI fairly simple, but I want to assure that it wins as much as possible. One of the key points will of course be what you could call counting cards, just tracking probabilities of getting any given card that is needed. Using that as the basis, I will use a technique suggested by the professor and give each card in hand a utility or usefulness value. This value will be based on a number of factors, including what I spoke about as the priorities of the game. Those are if the card adds to a meld or is close to doing so, if it is high value in the hand and not in use, and if getting rid of it or keeping it will get you closer to ending the round by knocking. Beyond that I will include factors such as if the other player seems to want cards of that type which would most likely be to create melds, and based on if getting another matching card to create a meld is still possible given remaining cards. Combining all these factors with a weighting algorithm will give a high chance of making the best choices with cards.
The keys to this strategy in terms of code will rely primarily on a class with functions to track all available cards in the deck, essentially counting the cards. It will also need a series of functions which assess each card based on the criteria given above to determine utility. It will then need to store those utility values for each card in the overarching card tracking class. Once the utility of all cards is determined, there will be a function to pick which card should be discarded, most likely based on its utility value, and then determine if it should try to knock or if the hand has Gin for example, meaning a zero point value. While I am not an expert at Gin, I have also found some strategic references listed below which can help me determine how to weight my algorithm. While the above laid out strategy does not assure optimal Gin playing, it should come close and also allow constant tweaking for the best results.
https://www.gamecolony.com/gin_rummy_game_strategy.shtml
http://dreamquestgames.com/gin-strategy-tips-10-golden-rules/
http://www.rubl.com/rules/gin-rummy-tips.html