If they have swam onto a square occupied by a fish, eat the fish and reset the hunger counter.

If the hunger counter has reached the starvation value, the shark dies.

If the reproduction counter has reached the reproduction threshold, another shark is spawned in an adjacent square.

Fish:

Swim in a random direction.

Increment reproduction counter.

If reproduction counter reaches its threshold, another fish is spawned (no pun intended) in an adjacent square.

If the system parameters (fish reproduction time, shark starvation time, shark reproduction time) and initial state (usually a large random sprinkling of fish and a small random sprinkling of sharks) are chosen well, the system should settle into a very convincing (but slightly noisy) predator-prey cycle with occasional unusual events but for the most part running in a stable manner for an arbitrary amount of time.

It is also possible to produce unstable parameter sets, for instance if you allow sharks to reproduce quicker than they starve, they will take over and drive fish into extinction.

It is interresting to watch, and it doesn't take long to code up a version of this program and play with it. It has many realistic and amazingly complex behaviors that are all coded for in that simple set of rules. One can also add variations like overcrowding rules, or allowing starving sharks to eat other sharks if no fish are around, etc... The possibilitis are endless.