Small knowledge, big challenge! This article is part of the “Programmer’s Essentials
This article also participated in the “Digitalstar Project” to win a creative gift package and creative incentive money
Fans are the private chat I do a big business, let me in king glory the influence of random pattern card out oneself want to use, I’m sure the fans do not know if this random server control, not the client can operate, if you want to black to the server is a bit harder if I can find again against the bureau to modify the data is really too cow force, I just want to say I can’t, I can’t earn 1000+.
Lottery is almost the standard of every game, but also the most important place of krypton gold, now still remember when a game, can not stop the lottery, now I have written many times of lottery, the specific implementation logic is familiar with the heart, so there is no so much obsession. Write about the lottery today.
1. Requirements of lottery:
The realization of the lottery is different from game to game. How to realize the specific lottery is based on the specific planning needs, which are mostly divided into several categories:
1, lucky draw is divided into free times and paid draw, some games will send a free number of CD time, or how many times to send a lucky draw
2, draw ten consecutive draw (multiple draw) and single draw
3, the lottery is divided into whether a certain reward and do not require a certain, such as ten even draw out a cow forced hero
4. When drawing for many times, whether the reward pool is completely random, repeated rewards can occur, or 10 random rewards in the reward pool
5, some lottery is also divided into whether there is a guaranteed number of times, whether the judgment logic of the first draw, guarantee will be a hero, the first draw fixed hero
2. Sorted out the business logic of lottery
Protocol definition: the project I worked with used Protobuf to communicate, so I chose Protobuf to define the communication format, you can define it according to your project, it’s not important.
C indicates the message sent by the client to the server
S represents the message returned by the server
message C_DRAW{ required int32 rewardType = 1; } message S_DRAW{required int32 rewardType = 1; // Lottery type 1 single lottery 2 10 lottery required String rewardContent = 2; // specialReward = 3; // For example, 10 consecutive draw rewards}Copy the code
Explanation of agreement:
The logic of the interface is simple, the client sends the lottery type to the server, and the server processes the business.
The server logic is divided into the following steps
1, check whether the type of lottery sent by the client is valid, if 1 and 2 are not defined, an error is reported, because someone passed illegal data.
2. Check whether the number of times of the corresponding lottery type is enough. If the number is insufficient, an error will be reported
3. Check whether the resources required by the corresponding lottery type are enough. If the resources are insufficient, an error will be reported to the client.
4. Obtain the basic data configuration of the corresponding lottery type and check whether it is abnormal
5. Implement the corresponding lottery logic
6. Add drawn resources to the player
7. Assemble extracted resources into messages and pass them to the client for page display.
As can be seen from the above logic, any operation on the client side will not affect the final lottery results, big business will not be done!
3. Code implementation
1. Configuration of basic data
Explanation:
Id is the data type,
Cost represents the allocation of resources consumed by the lottery
Data is the lottery pool, a_50a represents one resource, for example, A= 2_100 means resource 2 is given 100. The last value of the underline, 50, is the weight
2. Analysis of basic data
1. Pay attention to the data format
2. Ensure that basic data is completely protected
import javafx.util.Pair; import java.util.*; Public class RewardPoolConfig {Map<Integer, ConfigPair> rewardConfigMap; public RewardPoolConfig config; public RewardPoolConfig() { readConfig(); } private void readConfig() { // TODO readFromSource(); RewardConfigMap = new HashMap<>(); / / under simulated rewardConfigMap. Put (1, new ConfigPair (" A_1 ", "# # # # # A_50 B_50 C_50 D_50 E_50 F_50 # # G_50 H_50")); rewardConfigMap.put(2, new ConfigPair("B_1", "A_50#B_50#C_50#D_50#E_50#F_50#G_50#H_50")); } public RewardPoolConfig getInstance() { if (config == null) { config = new RewardPoolConfig(); } return config; } public Map<Integer, ConfigPair> getRewardConfigMap() { return rewardConfigMap; } /** * static class ConfigPair {// The cost of the resource String cost; WeightList <Pair<String, Integer>> weightList; public ConfigPair(String cost, String data) { this.cost = cost; String[] split = data.split("#"); List<Pair<String, Integer>> tmpList = new ArrayList<>(); for (String itemPair : split) { int i = itemPair.lastIndexOf("_"); String reward = itemPair.substring(0, i); String weightStr = itemPair.substring(i + 1); tmpList.add(new Pair<>(reward, Integer.valueOf(weightStr))); } weightList = Collections.unmodifiableList(tmpList); } public List<Pair<String, Integer>> getWeightList() { return weightList; } public String getCost() { return cost; } } public static void main(String[] args) { ConfigPair a_1 = new ConfigPair("A_1", "A_50#B_50#C_50#D_50#E_50#F_50#G_50#H_50"); System.out.println(); }}Copy the code
1. The data source for loading above should be read from appropriate data sources according to the design of specific projects, such as XML, Excel, or database, Json, etc
2, can be expanded according to the needs, such as other ten even pumping must send, can increase the field, here is just to write the core code.
3. Weight random algorithm
import com.google.common.collect.Lists; import javafx.util.Pair; import java.util.List; import java.util.SortedMap; import java.util.TreeMap; /** * public class WeightRandom<K, V extends Number> { private TreeMap<Double, K> weightMap = new TreeMap<>(); public WeightRandom(List<Pair<K, V>> list) throws Exception { if (list == null || list.size() == 0) { throw new Exception("list is null"); } for (Pair<K, V> pair : list) { if (pair.getValue().doubleValue() <= 0) { throw new Exception("weight is wrong"); } double lastWeight = this.weightMap.size() == 0 ? 0 : this.weightMap.lastKey().doubleValue(); Double this.weightmap.put (pair.getValue().doubleValue() + lastWeight, pair.getKey()); }} public K random() {double randomWeight = this.weightmap.lastkey () * math.random (); SortedMap<Double, K> tailMap = this.weightMap.tailMap(randomWeight, false); return this.weightMap.get(tailMap.firstKey()); } public static void main(String[] args) throws Exception { List<Pair<String, Integer>> weighList = Lists.newArrayList(); weighList.add(new Pair<>("AAA", 10)); weighList.add(new Pair<>("BBB", 10)); weighList.add(new Pair<>("CCC", 10)); weighList.add(new Pair<>("DDD", 10)); String random = new WeightRandom<>(weighList).random(); System.out.println(random); }} 4, import javafx.util.Pair; import java.util.List; import java.util.Map; Public class Aain {public static void main(String[] args) throws Exception {int rewardType = 1; Map<Integer, RewardPoolConfig.ConfigPair> rewardConfigMap = RewardPoolConfig.getInstance().getRewardConfigMap(); // check whether the type of lottery sent by the client is valid. If 1 and 2 are not defined, an error is reported because someone passed illegal data. if (! RewardConfigMap. Either containsKey (rewardType)) {/ / illegal lottery type return; } TODO checkPlayerData(); TODO checkPlayerData(); RewardPoolConfig.ConfigPair configPair = rewardConfigMap.get(rewardType); //3. Check whether the resources required by the corresponding lucky draw type are enough. If the resources are insufficient, an error will be reported to the client. String cost = configPair.getCost(); // TODO checkResource(); // Get the basic data configuration of the corresponding lucky draw type, check whether there is an exception, if there is an exception, the error will be reported. List<Pair<String, Integer>> weightList = configpair.getweightList (); String reward = new WeightRandom<>(weightList).random(); TODO addResource(reward); TODO addResource(reward); //7. Assemble the extracted resources into messages and pass them to the client for page display. // sendResultToClient(reward) System.out.println(reward); }}Copy the code
5. Other functions are completed
5.1 10-row drawing, as long as the lottery cycle is changed 5.2 10-row drawing extra send, as long as the basic data is matched with the sent props, and 5.3 10-row drawing is directly added when the resources are added to the player. As long as the item is removed directly from the pool after drawing 5.4 free times to draw the CD, the player's drawing time can be directly recorded, the next time to judge whether the time interval is longer than the CD timeCopy the code
4. Conclusion:
The logic of lottery is relatively simple, but in the project, it will be associated with other modules, such as the progress of the task system, such as the requirement of not making repeated generals. All these requirements need to be dealt with in advance and the final Weigh can be well dealt with