One hurdle you can throw in the way is to keep secondary values. A good attacker will simply directly modify values in RAM, and there are tools/techniques to identify where in RAM something like the score is kept. So you can do something like this:
- keep both the actual score, and a second "backup" value derived from the real value. A simple example would be e.g. keep the score * 2, but you'll probably want something significantly more complicated so it's harder to guess.
- have a function to change the actual score. This will set a new score and compute a new backup value.
- whenever you access the score, check the backup value is still correct. If it's wrong, re-set the value, kill the player, end the game etc.
The idea is if the game changes the score, it's accepted, but if any other external source changes the score, it's detected because the backup value wasn't changed.
Obviously this only affects the client side and it's a whole other story if you want to do something like post a score to a server, where it's probably impossible to prevent someone tweaking the value at the network layer, but you could still apply a similar approach there to make it harder again.