Armadillo AI - completely lost

I am building an Armadillo game using C # .NET. He should use a fairly simple scoring mechanism. No ship crashes, if either the player or the computer scores 17 hits, they win. If you strike, you can take another turn. AI attacks randomly until it strikes, after which it attacks the tile in each direction until it finds a trend, and then continues to attack in a straight line until it finds a dead end (either unallocated space or edge If there were spaces that didn't were deleted in the opposite direction that the computer attacked, it then attacks these spaces, it doesn’t target the spaces that it has already reached, or following the patterns that have already been followed.

Here is my AI so far.

int shipCounter = 0, trend = 0; static Random rnd = new Random(); bool gameOver = false, playerTurn = false; int[] score = { 0, 0 }; struct gameData { public bool occupied, hit, marked; } gameData[,,] data; public void computerMove() { Point target = seekTarget(); try { if (data[1, target.X, target.Y].hit) computerMove(); else { data[1, target.X, target.Y].hit = true; if (data[1, target.X, target.Y].occupied) { attacking = true; score[0]++; computerMove(); } } playerTurn = true; } catch (IndexOutOfRangeException) { computerMove(); } } public Point seekTarget() { Point origin = new Point(-1, -1); //find a point that been hit. int x = 0, y = 0; while (x < gridSize && y < gridSize) { if (data[1, x, y].hit && data[1, x, y].occupied && !data[1, x, y].marked) { origin = new Point(x, y); break; } x++; if (x == gridSize && y != gridSize) { x = 0; y++; } } return findTargets(origin); } public Point findTargets(Point origin) { Point[] lim = { origin, origin, origin, origin }; Point[] possibleTargets = { origin, origin, origin, origin }; //Find the edges. while (lim[0].X >= -1 && ((!data[1, lim[0].X, lim[0].Y].hit && !data[1, lim[0].X, lim[0].Y].occupied) || (data[1, lim[0].X, lim[0].Y].hit && data[1, lim[0].X, lim[0].Y].occupied))) { lim[0].X--; if (lim[0].X == -1) break; } while (lim[1].Y >= -1 && ((!data[1, lim[0].X, lim[0].Y].hit && !data[1, lim[0].X, lim[0].Y].occupied) || (data[1, lim[0].X, lim[0].Y].hit && data[1, lim[0].X, lim[0].Y].occupied))) { lim[1].Y--; if (lim[1].Y == -1) break; } while (lim[2].X <= gridSize && ((!data[1, lim[0].X, lim[0].Y].hit && !data[1, lim[0].X, lim[0].Y].occupied) || (data[1, lim[0].X, lim[0].Y].hit && data[1, lim[0].X, lim[0].Y].occupied))) { lim[2].X++; if (lim[2].X == gridSize) break; } while (lim[3].Y <= gridSize && ((!data[1, lim[0].X, lim[0].Y].hit && !data[1, lim[0].X, lim[0].Y].occupied) || (data[1, lim[0].X, lim[0].Y].hit && data[1, lim[0].X, lim[0].Y].occupied))) { lim[3].Y++; if (lim[3].Y == gridSize) break; } //Cell targeting AI } return new Point(rnd.Next(10), rnd.Next(10)); } 

This became extremely messy due to my inability to figure out what was going wrong. If I quote the findTargets function and just accidentally attack the computer, it works fine. Computer and player trade is rotated, and the computer enters the register.

When findTargets turned findTargets player can make one attack, and the computer never takes its turn. Then it does not return to the player’s turn, even if the player’s interceptor is still visible. If anyone could help, he would greatly appreciate it. Sorry for not including the Paint or mouseDown methods, they have exceeded character limits.

User interface without findTargets (rotation of players and computers).

UI with findTargets (the computer cannot rotate, the player takes only one revolution).

Thanks in advance for your help.

EDIT: I highlighted the problem, it seems that it cannot break out of while loops in findTargets . Even if I solve the problem by stopping it from looping when origin is (-1, -1) , it gets into the loop on the first hit.

EDIT 2: It enters the first cycle and is infinitely cyclical. For some reason, it does not increase lim[0].X at all. When I insert a message in a loop to display some data, it is displayed twice and then does not appear again, although it is still cyclical. Does anyone know why this is?

+4
source share
3 answers

You are using an object oriented language - Java looks to me.

Thus, in order to simplify the code, it is easier to understand, simplify support, simplify the code, try to use some real objects.

For example, you must have the Ship class, definitely have the Grid class, possibly the Shot class, etc. The Ship class should definitely "connect" to your Grid class. The Grid class SHOULD NOT select the entire grid of potential locations, but should only select valid Hit areas, because the Ship instance is connected to them. Each place not populated by a ship’s instance is obviously a pass, so handle all locations that don’t contain a ship in one method -

The Grid class will do all the work - it can have addShipHorizontal (Ship, x, y), addShipVertical (Ship, x, y). It must have hitTest (x, y), which returns either null or Ship. It must support a set of Ship instances, such as an ArrayList, which it will iterate over in the hitTest (x, y) method.

The ship must have a PointCount and a Points collection that are set when the ship is passed to the addShipH () or addShipV () methods. The ship should also have a hitTest (x, y) method, which returns true if the ship lives in the specified x, y. hitTest (x, y) will iterate through the vessels of the collection of points looking for a match.

When it is time to take a picture, select your location in the grid and click test - there is a link to the ship at the selected location, yes, then execute ship.hit (location) and return a new Hit () - otherwise return a new miss ();

Divide it into the objects that you actually think of imitation - this is called the domain model. Then give each class of objects the appropriate methods so that the actual game is just an orchestration among the classes of the domain model and between them.

Do not write down the game code - write classes instead, then class methods - as you create classes, the game will arise due to the interaction between classes through their methods.

Starting at the top, which class will you need 2 instances at the top of the application? The answer is Player. What player class controls? Grid and list of ships. What is a grid? List of ships and their places, as well as hit testing for shots. What does the ship support? Its location on the grid and which of the places in which it is located were not affected.

You will find if you do this in OO style, it will be 1/4 of the code and will have twice as much flexibility. Good luck

+3
source

As @ jorge-Chibante mentioned, please separate your domain code and presentation code and try writing some unit tests to check how you expect your AI to work and then develop your own AI.

In Ships N 'Battles, a game with a battleship, I built an AI with probability and made a probability brain map of each square to have an enemy ship. All with some tests to help test behavior and any futures refactoring.

Keep every part of your code with only one responsibility, and you will make your life easier.

+1
source

AI

There are 3 different strategies in the battleship (I simplify here). Bomb random square Bomb in a circle Bomb in a straight line

First, the computer just needs to find a random square that has not yet been hacked. When he finds the square, he needs to bomb him to try to figure out where the ship is. After that, he assumes that this is the direction of the ship and the bomb in a straight line (on both sides).

Your computer should have a variable indicating what mode it is in.

code

You code is everywhere, hard to read. You must separate your logic from more functions. Thus, it is easier to check / read and find out where the problem is. Also make sure you play the logic and the user interface logic is well separated.

 public bool IsOccuped(Point target) public bool AlreadyBombed(Point target) public bool BombLocation(Point target) public Point FindNewTarget() 

Now your computer will be much nicer

 public void ComputerMove() { Point target; target = FindNewTarget(); BombLocation(target); } // There are more efficient way of doing this but it an example. public Point FindNewTarget() { Point newTarget = new Point(); do { newTarget.x = [get random location from 0 to grid width] newTarget.y = [get random location from 0 to grid height] }while(AlreadyBombed(newTarget)) } 

Even if the function is small, code repeatability can greatly help.

 public bool IsOccuped(Point target) { return data[1, target.X, target.Y].hit; } 
0
source

Source: https://habr.com/ru/post/1481840/


All Articles